Browse Source

We're on Chaos Calmer now

Matthias Schiffer 9 years ago
parent
commit
ab10be9f50
74 changed files with 220 additions and 37974 deletions
  1. 11 4
      Makefile
  2. 3 3
      docs/dev/i18n.rst
  3. 0 7
      include/Makefile.image
  4. 1 2
      include/Makefile.target
  5. 1 1
      include/config
  6. 2 2
      include/gluon.mk
  7. 4 29
      include/package.mk
  8. 8 7
      modules
  9. 3 3
      package/gluon-announce/files/usr/lib/lua/gluon/announce.lua
  10. 3 2
      package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua
  11. 3 2
      package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua
  12. 1 15
      package/gluon-core/Makefile
  13. 2 2
      package/gluon-core/files/lib/gluon/upgrade/001-upgrade
  14. 1 1
      package/gluon-core/files/lib/gluon/upgrade/010-primary-mac
  15. 1 1
      package/gluon-core/files/lib/gluon/upgrade/999-version
  16. 1 1
      package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm
  17. 0 1
      package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm
  18. 1 1
      package/gluon-mesh-batman-adv-core/Makefile
  19. 1 1
      package/gluon-site/Makefile
  20. 1 1
      package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/status
  21. 7 25
      patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch
  22. 0 31
      patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch
  23. 31 0
      patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch
  24. 0 0
      patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch
  25. 0 26
      patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch
  26. 8 8
      patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch
  27. 0 570
      patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch
  28. 0 471
      patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch
  29. 0 0
      patches/openwrt/0006-base-files-disable-reset-button-handling.patch
  30. 0 72
      patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch
  31. 21 0
      patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch
  32. 0 161
      patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch
  33. 42 0
      patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch
  34. 24 0
      patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch
  35. 0 43
      patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch
  36. 0 28
      patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch
  37. 0 20
      patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch
  38. 0 25
      patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch
  39. 0 42
      patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch
  40. 0 229
      patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch
  41. 0 177
      patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch
  42. 0 33655
      patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch
  43. 0 41
      patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch
  44. 0 20
      patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch
  45. 0 34
      patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch
  46. 0 24
      patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch
  47. 0 35
      patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch
  48. 0 39
      patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch
  49. 0 70
      patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch
  50. 0 180
      patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch
  51. 0 65
      patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch
  52. 0 22
      patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch
  53. 0 57
      patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch
  54. 0 26
      patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch
  55. 0 1111
      patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch
  56. 0 168
      patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch
  57. 0 41
      patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch
  58. 0 20
      patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch
  59. 3 3
      patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch
  60. 6 6
      patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch
  61. 17 0
      patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch
  62. 0 33
      patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch
  63. 0 35
      patches/packages/openwrt/0002-libuecc-update-to-v5.patch
  64. 0 213
      patches/packages/openwrt/0003-fastd-update-to-v17.patch
  65. 0 52
      patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch
  66. 0 0
      patches/packages/routing/0001-alfred-adjust-intervals.patch
  67. 0 0
      patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch
  68. 7 4
      targets/ar71xx-generic/profiles.mk
  69. 1 1
      targets/ar71xx-generic/vermagic
  70. 1 1
      targets/ar71xx-nand/vermagic
  71. 1 1
      targets/mpc85xx-generic/vermagic
  72. 1 1
      targets/ramips-rt305x/vermagic
  73. 1 1
      targets/x86-generic/vermagic
  74. 1 1
      targets/x86-kvm_guest/vermagic

+ 11 - 4
Makefile

@@ -212,7 +212,7 @@ config: FORCE
 		echo 'CONFIG_BUILD_SUFFIX="gluon-$(GLUON_TARGET)"'; \
 		echo '$(patsubst %,CONFIG_PACKAGE_%=m,$(sort $(filter-out -%,$(GLUON_DEFAULT_PACKAGES) $(GLUON_SITE_PACKAGES) $(PROFILE_PACKAGES))))' \
 			| sed -e 's/ /\n/g'; \
-		echo '$(patsubst %,CONFIG_GLUON_LANG_%=y,$(GLUON_LANGS))' \
+		echo '$(patsubst %,CONFIG_LUCI_LANG_%=y,$(GLUON_LANGS))' \
 			| sed -e 's/ /\n/g'; \
 	) > $(BOARD_BUILDDIR)/config.tmp
 	scripts/config/conf --defconfig=$(BOARD_BUILDDIR)/config.tmp Config.in
@@ -281,8 +281,11 @@ packages: $(package/stamp-compile)
 prepare-image: FORCE
 	rm -rf $(BOARD_KDIR)
 	mkdir -p $(BOARD_KDIR)
-	cp $(KERNEL_BUILD_DIR)/vmlinux $(KERNEL_BUILD_DIR)/vmlinux.elf $(BOARD_KDIR)/
-	+$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image -f $(GLUONDIR)/include/Makefile.image prepare KDIR="$(BOARD_KDIR)"
+	$(foreach k, vmlinux vmlinux.elf \
+		$(if $(KERNEL_IMAGES),$(KERNEL_IMAGES),$(filter-out dtbs,$(KERNELNAME))), \
+		$(CP) $(KERNEL_BUILD_DIR)/$(k) $(BOARD_KDIR)/$(k); \
+	)
+	+$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image image_prepare KDIR="$(BOARD_KDIR)"
 
 prepare: FORCE
 	@$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua \
@@ -346,7 +349,7 @@ $(eval $(call merge-lists,INSTALL_PACKAGES,DEFAULT_PACKAGES GLUON_DEFAULT_PACKAG
 
 package_install: FORCE
 	$(OPKG) update
-	$(OPKG) install $(PACKAGE_DIR)/libc_*.ipk
+	$(OPKG) install $(PACKAGE_DIR)/base-files_*.ipk $(PACKAGE_DIR)/libc_*.ipk
 	$(OPKG) install $(PACKAGE_DIR)/kernel_*.ipk
 
 	$(OPKG) install $(INSTALL_PACKAGES)
@@ -354,6 +357,10 @@ package_install: FORCE
 
 	rm -f $(TARGET_DIR)/usr/lib/opkg/lists/* $(TARGET_DIR)/tmp/opkg.lock
 
+# Remove opkg database when opkg is not intalled
+	if [ ! -x $(TARGET_DIR)/bin/opkg ]; then rm -rf $(TARGET_DIR)/usr/lib/opkg; fi
+
+
 ifeq ($(GLUON_OPKG_CONFIG),1)
 include $(INCLUDE_DIR)/version.mk
 endif

+ 3 - 3
docs/dev/i18n.rst

@@ -80,9 +80,9 @@ instead).
 Adding support for new languages
 --------------------------------
 
-A list of all languages supported by LuCI can be found in the ``include/package.mk`` file of
-the Gluon repository. Adding translations for these languages is straightforward using the ``msginit``
-command.
+A list of all languages supported by LuCI can be found in the ``packages/luci/luci.mk`` file after
+Gluon's dependencies have been downloaded using ``make update``. Adding translations for these
+languages is straightforward using the ``msginit`` command.
 
 For other languages, support must be added tu LuCI first, which constitutes completely translating
 the ``base.pot``. Please contact the upstream LuCI maintainers if you'd like to do this.

+ 0 - 7
include/Makefile.image

@@ -1,7 +0,0 @@
-override define BuildImage
-prepare: FORCE
-	$(call Image/Prepare)
-endef
-
-# The Makefile included here is $(TOPDIR)/target/linux/$(BOARD)/image/Makefile
-include Makefile

+ 1 - 2
include/Makefile.target

@@ -7,8 +7,7 @@ override define Kernel/Configure
 	echo "# CONFIG_KALLSYMS_EXTRA_PASS is not set" >> $(LINUX_DIR)/.config.target
 	echo "# CONFIG_KALLSYMS_ALL is not set" >> $(LINUX_DIR)/.config.target
 	echo "# CONFIG_KALLSYMS_UNCOMPRESSED is not set" >> $(LINUX_DIR)/.config.target
-	echo "# CONFIG_KPROBES is not set" >> $(LINUX_DIR)/.config.target
-	$(SCRIPT_DIR)/metadata.pl kconfig $(TMP_DIR)/.packageinfo $(BOARD_BUILDDIR)/config-allmods > $(LINUX_DIR)/.config.override
+	$(SCRIPT_DIR)/metadata.pl kconfig $(TMP_DIR)/.packageinfo $(BOARD_BUILDDIR)/config-allmods $(KERNEL_PATCHVER) > $(LINUX_DIR)/.config.override
 	$(SCRIPT_DIR)/kconfig.pl 'm+' '+' $(LINUX_DIR)/.config.target /dev/null $(LINUX_DIR)/.config.override > $(LINUX_DIR)/.config
 	$(call Kernel/SetNoInitramfs)
 	rm -rf $(KERNEL_BUILD_DIR)/modules

+ 1 - 1
include/config

@@ -19,4 +19,4 @@ CONFIG_ATH_USER_REGD=y
 CONFIG_PACKAGE_ATH_DEBUG=y
 CONFIG_ATH10K_CT_COMMUNITY_FW=y
 
-CONFIG_PACKAGE_luci-base_srcdiet=y
+CONFIG_LUCI_SRCDIET=y

+ 2 - 2
include/gluon.mk

@@ -35,7 +35,7 @@ export GLUON_LANGS
 ifeq ($(OPENWRT_BUILD),1)
 ifeq ($(GLUON_TOOLS),1)
 
-CONFIG_VERSION_REPO := $(shell $(GLUONDIR)/scripts/site.sh opkg_repo || echo http://downloads.openwrt.org/barrier_breaker/14.07/%S/packages)
+CONFIG_VERSION_REPO := $(shell $(GLUONDIR)/scripts/site.sh opkg_repo || echo http://downloads.openwrt.org/chaos_calmer/15.05-rc1/%S/packages)
 export CONFIG_VERSION_REPO
 
 GLUON_SITE_CODE := $(shell $(GLUONDIR)/scripts/site.sh site_code)
@@ -65,7 +65,7 @@ GLUON_TARGET_$$(gluon_target)_BOARD := $(1)
 GLUON_TARGET_$$(gluon_target)_SUBTARGET := $(2)
 endef
 
-GLUON_DEFAULT_PACKAGES := gluon-core kmod-ipv6 firewall ip6tables -uboot-envtools
+GLUON_DEFAULT_PACKAGES := gluon-core kmod-ipv6 firewall ip6tables -uboot-envtools -wpad-mini hostapd-mini
 
 override DEFAULT_PACKAGES.router :=
 

+ 4 - 29
include/package.mk

@@ -7,45 +7,20 @@ $(shell cat $(1) | sed -ne '1h; 1!H; $$ {g; s/@/+@/g; s/\n/-@/g; p}')
 END__GLUON__CHECK__SITE
 endef
 
-
 # Languages supported by LuCi
 GLUON_SUPPORTED_LANGS := ca zh_cn en fr de el he hu it ja ms no pl pt_br pt ro ru es sv uk vi
 
-GLUON_LANG_ca := catalan
-GLUON_LANG_zh_cn := chinese
-GLUON_LANG_en := english
-GLUON_LANG_fr := french
-GLUON_LANG_de := german
-GLUON_LANG_el := greek
-GLUON_LANG_he := hebrew
-GLUON_LANG_hu := hungarian
-GLUON_LANG_it := italian
-GLUON_LANG_ja := japanese
-GLUON_LANG_ms := malay
-GLUON_LANG_no := norwegian
-GLUON_LANG_pl := polish
-GLUON_LANG_pt_br := portuguese-brazilian
-GLUON_LANG_pt := portuguese
-GLUON_LANG_ro := romanian
-GLUON_LANG_ru := russian
-GLUON_LANG_es := spanish
-GLUON_LANG_sv := swedish
-GLUON_LANG_uk := ukrainian
-GLUON_LANG_vi := vietnamese
-
-GLUON_I18N_PACKAGES := $(foreach lang,$(GLUON_SUPPORTED_LANGS),+GLUON_LANG_$(lang):luci-i18n-$(GLUON_LANG_$(lang)))
-GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_GLUON_LANG_$(lang))
-GLUON_ENABLED_LANGS := $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_GLUON_LANG_$(lang)),$(lang)))
-
+GLUON_I18N_PACKAGES := $(foreach lang,$(GLUON_SUPPORTED_LANGS),+LUCI_LANG_$(lang):luci-i18n-base-$(lang))
+GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_LUCI_LANG_$(lang))
+GLUON_ENABLED_LANGS := $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_LUCI_LANG_$(lang)),$(lang)))
 
-GLUON_PO2LMO := $(BUILD_DIR)/luci/build/po2lmo
 
 define GluonBuildI18N
 	mkdir -p $$(PKG_BUILD_DIR)/i18n
 	for lang in $$(GLUON_ENABLED_LANGS); do \
 		if [ -e $(2)/$$$$lang.po ]; then \
 			rm -f $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \
-			$(GLUON_PO2LMO) $(2)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \
+			po2lmo $(2)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \
 		fi; \
 	done
 endef

+ 8 - 7
modules

@@ -1,18 +1,19 @@
 GLUON_FEEDS='openwrt gluon routing luci'
 
-OPENWRT_REPO=git://git.openwrt.org/14.07/openwrt.git
-OPENWRT_COMMIT=179bab8b1700d74b28cc6cd25322f9a1ad670107
+OPENWRT_REPO=git://git.openwrt.org/openwrt.git
+OPENWRT_COMMIT=53a178af743eb1a463c806ee79d1e622969ad6ef
 
 PACKAGES_OPENWRT_REPO=git://github.com/openwrt/packages.git
-PACKAGES_OPENWRT_COMMIT=01fcd1f29174a56d6ddb59901ed8c67ea42c3a8f
-PACKAGES_OPENWRT_BRANCH=for-14.07
+PACKAGES_OPENWRT_COMMIT=914beae80e848c161214464fba7a9826c66bbf26
+PACKAGES_OPENWRT_BRANCH=for-15.05
 
 PACKAGES_GLUON_REPO=git://github.com/freifunk-gluon/packages.git
 PACKAGES_GLUON_COMMIT=e8ee21d116a0abc2e328b0ee181d79845654582e
 
 PACKAGES_ROUTING_REPO=git://github.com/openwrt-routing/packages.git
-PACKAGES_ROUTING_COMMIT=5d4ad63897b435d5df0f39a49bd58962c22c33b8
-PACKAGES_ROUTING_BRANCH=for-14.07
+PACKAGES_ROUTING_COMMIT=b1c3bdfbf47003088198bf8ef699a94cc29e3eca
+PACKAGES_ROUTING_BRANCH=for-15.05
 
 PACKAGES_LUCI_REPO=git://github.com/openwrt/luci.git
-PACKAGES_LUCI_COMMIT=f81be49ae756dab82e1758a6c9de145f0d36960e
+PACKAGES_LUCI_COMMIT=7a54785ea616df1e72f20b9cad2f1a6b3097f7b5
+PACKAGES_LUCI_BRANCH=for-15.05

+ 3 - 3
package/gluon-announce/files/usr/lib/lua/gluon/announce.lua

@@ -2,12 +2,12 @@
 
 module('gluon.announce', package.seeall)
 
-fs = require 'luci.fs'
+fs = require 'nixio.fs'
 uci = require('luci.model.uci').cursor()
 util = require 'luci.util'
 
 local function collect_entry(entry)
-	if fs.isdirectory(entry) then
+	if fs.stat(entry, 'type') == 'dir' then
 		return collect_dir(entry)
 	else
 		return setfenv(loadfile(entry), _M)()
@@ -17,7 +17,7 @@ end
 function collect_dir(dir)
 	local ret = {}
 
-	for _, entry in ipairs(fs.dir(dir)) do
+	for entry in fs.dir(dir) do
 		if entry:sub(1, 1) ~= '.' then
 			local ok, val = pcall(collect_entry, dir .. '/' .. entry)
 			if ok then

+ 3 - 2
package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua

@@ -49,10 +49,11 @@ function action_reboot()
   uci:commit("gluon-setup-mode")
 
   if nixio.fork() ~= 0 then
-    local fs = require "luci.fs"
+    local fs = require "nixio.fs"
+    local util = require "nixio.util"
 
     local parts_dir = "/lib/gluon/config-mode/reboot/"
-    local files = fs.dir(parts_dir)
+    local files = util.consume(fs.dir(parts_dir))
 
     table.sort(files)
 

+ 3 - 2
package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua

@@ -1,11 +1,12 @@
 local wizard_dir = "/lib/gluon/config-mode/wizard/"
 local i18n = luci.i18n
 local uci = luci.model.uci.cursor()
-local fs = require "luci.fs"
+local fs = require "nixio.fs"
+local util = require "nixio.util"
 local f, s
 
 local wizard = {}
-local files = fs.dir(wizard_dir)
+local files = util.consume(fs.dir(wizard_dir))
 
 table.sort(files)
 

+ 1 - 15
package/gluon-core/Makefile

@@ -12,21 +12,7 @@ define Package/gluon-core
   SECTION:=gluon
   CATEGORY:=Gluon
   TITLE:=Base files of Gluon
-  DEPENDS:=+gluon-site +lua-platform-info +luci-lib-nixio +odhcp6c +firewall
-endef
-
-
-define LangConfig
-config GLUON_LANG_$(1)
-	bool "$(GLUON_LANG_$(1)) language support"
-	depends on PACKAGE_gluon-core
-	default n
-
-endef
-
-
-define Package/gluon-core/config
-$(foreach lang,$(GLUON_SUPPORTED_LANGS),$(call LangConfig,$(lang)))
+  DEPENDS:=+gluon-site +lua-platform-info +luci-base +odhcp6c +firewall
 endef
 
 

+ 2 - 2
package/gluon-core/files/lib/gluon/upgrade/001-upgrade

@@ -1,10 +1,10 @@
 #!/usr/bin/lua
 
-local fs = require 'luci.fs'
+local fs = require 'nixio.fs'
 local sysconfig = require 'gluon.sysconfig'
 
 
-if fs.isfile('/lib/gluon/version/core') and not sysconfig.gluon_version then
+if fs.stat('/lib/gluon/version/core') and not sysconfig.gluon_version then
   -- This isn't an initial upgrade, so set gluon_version
   sysconfig.gluon_version = ''
 end

+ 1 - 1
package/gluon-core/files/lib/gluon/upgrade/010-primary-mac

@@ -10,7 +10,7 @@ end
 
 local platform = require 'gluon.platform'
 
-local fs = require 'luci.fs'
+local fs = require 'nixio.fs'
 local util = require 'luci.util'
 
 

+ 1 - 1
package/gluon-core/files/lib/gluon/upgrade/999-version

@@ -2,7 +2,7 @@
 
 local sysconfig = require 'gluon.sysconfig'
 
-local fs = require 'luci.fs'
+local fs = require 'nixio.fs'
 local util = require 'luci.util'
 
 

+ 1 - 1
package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm

@@ -1,5 +1,5 @@
 <%-
-   local fs = require 'luci.fs'
+   local fs = require 'nixio.fs'
    local uci = require('luci.model.uci').cursor()
    local util = require 'luci.util'
    local i18n = require 'luci.i18n'

+ 0 - 1
package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm

@@ -20,7 +20,6 @@ $Id$
 
 	local hostname = sys.hostname()
 	local release = fs.readfile("/lib/gluon/release")
-	local load1, load5, load15 = sys.loadavg()
 
 	local request  = disp.context.path
 	local request2 = disp.context.request

+ 1 - 1
package/gluon-mesh-batman-adv-core/Makefile

@@ -11,7 +11,7 @@ define Package/gluon-mesh-batman-adv-core
   SECTION:=gluon
   CATEGORY:=Gluon
   TITLE:=Support for batman-adv meshing (core)
-  DEPENDS:=+gluon-core +firewall +kmod-ipt-nathelper +libiwinfo-lua
+  DEPENDS:=+gluon-core +firewall +libiwinfo-lua
 endef
 
 define Build/Prepare

+ 1 - 1
package/gluon-site/Makefile

@@ -5,7 +5,7 @@ PKG_VERSION:=$(if $(GLUON_SITE_CODE),$(GLUON_SITE_CODE),1)
 PKG_RELEASE:=$(GLUON_RELEASE)
 
 PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/
-PKG_BUILD_DEPENDS := luci
+PKG_BUILD_DEPENDS := luci-base/host
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 

+ 1 - 1
package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/status

@@ -1,7 +1,7 @@
 #!/usr/bin/lua
 
 local util = require("luci.util")
-local fs = require("luci.fs")
+local fs = require("nixio.fs")
 local ltn12 = require 'luci.ltn12'
 local sys = require("luci.sys")
 local json = require("luci.json")

+ 7 - 25
patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch

@@ -3,10 +3,10 @@ Date: Sat, 26 Jul 2014 06:10:23 +0200
 Subject: tools/Makefile: fix host tools build dependencies
 
 diff --git a/tools/Makefile b/tools/Makefile
-index 13bb028..137ad61 100644
+index 2f516d2..9416069 100644
 --- a/tools/Makefile
 +++ b/tools/Makefile
-@@ -97,10 +97,16 @@ define PrepareStaging
+@@ -95,10 +95,16 @@ define PrepareStaging
  endef
  
  # preparatory work
@@ -23,32 +23,14 @@ index 13bb028..137ad61 100644
  
  $(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build
  	$(call PrepareStaging,$(STAGING_DIR_HOST))
-@@ -112,7 +118,7 @@ $(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build
+@@ -110,8 +116,8 @@ $(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build
  
- 
- define PrepareCommand
--$(STAGING_DIR_HOST)/bin/$(1): $(STAGING_DIR)/.prepared
-+$(STAGING_DIR_HOST)/bin/$(1): $(STAGING_DIR_HOST)/.prepared
- 	@mkdir -p "$$(dir $$@)"; rm -f "$$@"
- 	@export FILE="$$$$(which $(2) 2>/dev/null | grep -v 'not found' | head -n1)"; [ -n "$$$$FILE" ] || { \
- 		echo "Command $(1) not found."; false; \
-@@ -121,7 +127,7 @@ $(STAGING_DIR_HOST)/bin/$(1): $(STAGING_DIR)/.prepared
- endef
  endif
  
--$(STAGING_DIR_HOST)/bin/stat: $(STAGING_DIR)/.prepared
-+$(STAGING_DIR_HOST)/bin/stat: $(STAGING_DIR_HOST)/.prepared
- 	@rm -f $@
- 	@if stat --version > /dev/null 2>&1; then \
- 		ln -s `which stat` $@; \
-@@ -145,8 +151,8 @@ $(eval $(call PrepareCommand,tar,gtar tar))
- $(eval $(call PrepareCommand,diff,gdiff diff))
- 
- $(curdir)/cmddeps = $(patsubst %,$(STAGING_DIR_HOST)/bin/%,md5sum cp stat seq python awk getopt grep tar diff)
--$(curdir)//prepare = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared $($(curdir)/cmddeps)
--$(curdir)//compile = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared $($(curdir)/cmddeps)
-+$(curdir)//prepare = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared $($(curdir)/cmddeps)
-+$(curdir)//compile = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared $($(curdir)/cmddeps)
+-$(curdir)//prepare = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared
+-$(curdir)//compile = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared
++$(curdir)//prepare = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared
++$(curdir)//compile = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared
  
  # prerequisites for the individual targets
  $(curdir)/ := .config prereq

+ 0 - 31
patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch

@@ -1,31 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sat, 16 Aug 2014 17:52:34 +0200
-Subject: ar71xx: correctly detect hardware revision on TP-Link Archer C5 and C7
-
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 18da356..1709356 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -214,6 +214,13 @@ tplink_board_detect() {
- 	"934100"*)
- 		model="NC-LINK SMART-300"
- 		;;
-+	"c50000"*)
-+		model="TP-Link Archer C5"
-+		;;
-+	"750000"*|\
-+	"c70000"*)
-+		model="TP-Link Archer C7"
-+		;;
- 	*)
- 		hwver=""
- 		;;
-@@ -748,7 +755,7 @@ ar71xx_board_detect() {
- 	esac
- 
- 	case "$machine" in
--	*TL-WR* | *TL-WA* | *TL-MR* | *TL-WD*)
-+	*TL-WR* | *TL-WA* | *TL-MR* | *TL-WD* | *Archer*)
- 		tplink_board_detect "$machine"
- 		;;
- 	esac

+ 31 - 0
patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch

@@ -0,0 +1,31 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Thu, 13 Nov 2014 01:17:24 +0100
+Subject: odhcp6c: always accept RDNSS, independent of the default router lifetime
+
+diff --git a/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch
+new file mode 100644
+index 0000000..cb694ca
+--- /dev/null
++++ b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch
+@@ -0,0 +1,21 @@
++--- a/src/ra.c
+++++ b/src/ra.c
++@@ -438,18 +438,6 @@ bool ra_process(void)
++ 				}
++ 			}
++ 		}
++-
++-		int states[2] = {STATE_RA_DNS, STATE_RA_SEARCH};
++-		for (size_t i = 0; i < 2; ++i) {
++-			size_t ra_dns_len;
++-			uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
++-			for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
++-						(uint8_t*)c < &start[ra_dns_len] && &c->auxtarget[c->auxlen] <= &start[ra_dns_len];
++-						c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]))
++-				if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
++-						c->valid > router_valid)
++-					c->valid = router_valid;
++-		}
++ 	}
++ 
++ 	if (found)

+ 0 - 0
patches/openwrt/0009-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch → patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch


+ 0 - 26
patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch

@@ -1,26 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 13 Nov 2014 01:17:24 +0100
-Subject: odhcp6c: always accept RDNSS, independent of the default router lifetime
-
-diff --git a/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch
-new file mode 100644
-index 0000000..ae4e18d
---- /dev/null
-+++ b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch
-@@ -0,0 +1,16 @@
-+--- a/src/ra.c
-++++ b/src/ra.c
-+@@ -409,13 +409,6 @@ bool ra_process(void)
-+ 				}
-+ 			}
-+ 		}
-+-
-+-		size_t ra_dns_len;
-+-		struct odhcp6c_entry *entry = odhcp6c_get_state(STATE_RA_DNS, &ra_dns_len);
-+-		for (size_t i = 0; i < ra_dns_len / sizeof(*entry); ++i)
-+-			if (IN6_ARE_ADDR_EQUAL(&entry[i].router, &from.sin6_addr) &&
-+-					entry[i].valid > router_valid)
-+-				entry[i].valid = router_valid;
-+ 	}
-+ 
-+ 	if (found)

+ 8 - 8
patches/openwrt/0019-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch → patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch

@@ -3,10 +3,10 @@ Date: Tue, 10 Mar 2015 13:17:14 +0100
 Subject: ath10k: add Candelatech community firmware as an additional choice
 
 diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
-index 629692d..d77842a 100644
+index 2a40bb1..17dbe03 100644
 --- a/package/kernel/mac80211/Makefile
 +++ b/package/kernel/mac80211/Makefile
-@@ -605,6 +605,14 @@ This module adds support for wireless adapters based on
+@@ -604,6 +604,14 @@ This module adds support for wireless adapters based on
  Atheros USB AR9271 and AR7010 family of chipsets.
  endef
  
@@ -21,7 +21,7 @@ index 629692d..d77842a 100644
  define KernelPackage/ath10k
    $(call KernelPackage/mac80211/Default)
    TITLE:=Atheros 802.11ac wireless cards support
-@@ -625,13 +633,31 @@ endef
+@@ -624,13 +632,31 @@ endef
  define KernelPackage/ath10k/config
    if PACKAGE_kmod-ath10k
  
@@ -55,14 +55,14 @@ index 629692d..d77842a 100644
    endif
  endef
  
-@@ -1824,14 +1850,20 @@ define KernelPackage/ath10k/install
+@@ -1858,14 +1884,20 @@ define KernelPackage/ath10k/install
  	$(INSTALL_DATA) \
  		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
  		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
 +ifeq ($(CONFIG_ATH10K_AP_FW),y)
 +	$(INSTALL_DATA) \
-+		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2/firmware-3.bin_10.2-00082-4-2 \
-+		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-3.bin
++		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \
++		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin
 +endif
  ifeq ($(CONFIG_ATH10K_STA_FW),y)
  	$(INSTALL_DATA) \
@@ -72,8 +72,8 @@ index 629692d..d77842a 100644
 +endif
 +ifeq ($(CONFIG_ATH10K_CT_COMMUNITY_FW),y)
  	$(INSTALL_DATA) \
--		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2/firmware-3.bin_10.2-00082-4-2 \
--		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-3.bin
+-		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \
+-		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin
 +		$(DL_DIR)/$(ATH10K_CT_COMMUNITY_FW) \
 +		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
  endif

+ 0 - 570
patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch

@@ -1,570 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 26 Nov 2014 19:57:39 +0100
-Subject: firmware-utils: add new tool tplink-safeloader for the new TP-LINK Pharos devices (CPE210/220/510/520)
-
-The new TP-LINK Pharos series uses a new bootloader, the "TP-LINK Safeloader".
-It uses an advanced firmware image format, containing an image partition table
-and a flash partition table (and image partitions are mapped to the
-corresponding flash partitions). The exact image format is documented in the
-source code.
-
-Furthermore, the bootloader expects the kernel image as an ELF executable.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile
-index 4bb53cb..3f9eb56 100644
---- a/tools/firmware-utils/Makefile
-+++ b/tools/firmware-utils/Makefile
-@@ -41,6 +41,7 @@ define Host/Compile
- 	$(call cc,mkplanexfw sha1)
- 	$(call cc,mktplinkfw md5)
- 	$(call cc,mktplinkfw2 md5)
-+	$(call cc,tplink-safeloader md5, -Wall)
- 	$(call cc,pc1crypt)
- 	$(call cc,osbridge-crc)
- 	$(call cc,wrt400n cyg_crc32)
-diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c
-new file mode 100644
-index 0000000..23d703f
---- /dev/null
-+++ b/tools/firmware-utils/src/tplink-safeloader.c
-@@ -0,0 +1,538 @@
-+/*
-+  Copyright (c) 2014, Matthias Schiffer <mschiffer@universe-factory.net>
-+  All rights reserved.
-+
-+  Redistribution and use in source and binary forms, with or without
-+  modification, are permitted provided that the following conditions are met:
-+
-+    1. Redistributions of source code must retain the above copyright notice,
-+       this list of conditions and the following disclaimer.
-+    2. Redistributions in binary form must reproduce the above copyright notice,
-+       this list of conditions and the following disclaimer in the documentation
-+       and/or other materials provided with the distribution.
-+
-+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+*/
-+
-+
-+/*
-+   tplink-safeloader
-+
-+   Image generation tool for the TP-LINK SafeLoader as seen on
-+   TP-LINK Pharos devices (CPE210/220/510/520)
-+*/
-+
-+
-+#include <assert.h>
-+#include <errno.h>
-+#include <error.h>
-+#include <stdbool.h>
-+#include <stdio.h>
-+#include <stdint.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <time.h>
-+#include <unistd.h>
-+
-+#include <arpa/inet.h>
-+
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+
-+#include "md5.h"
-+
-+
-+#define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
-+
-+
-+/** An image partition table entry */
-+struct image_partition_entry {
-+	const char *name;
-+	size_t size;
-+	uint8_t *data;
-+};
-+
-+/** A flash partition table entry */
-+struct flash_partition_entry {
-+	const char *name;
-+	uint32_t base;
-+	uint32_t size;
-+};
-+
-+
-+/** The content of the soft-version structure */
-+struct __attribute__((__packed__)) soft_version {
-+	uint32_t magic;
-+	uint32_t zero;
-+	uint8_t pad1;
-+	uint8_t version_major;
-+	uint8_t version_minor;
-+	uint8_t version_patch;
-+	uint8_t year_hi;
-+	uint8_t year_lo;
-+	uint8_t month;
-+	uint8_t day;
-+	uint32_t rev;
-+	uint8_t pad2;
-+};
-+
-+
-+static const uint8_t jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
-+
-+
-+/**
-+   Salt for the MD5 hash
-+
-+   Fortunately, TP-LINK seems to use the same salt for most devices which use
-+   the new image format.
-+*/
-+static const uint8_t md5_salt[16] = {
-+	0x7a, 0x2b, 0x15, 0xed,
-+	0x9b, 0x98, 0x59, 0x6d,
-+	0xe5, 0x04, 0xab, 0x44,
-+	0xac, 0x2a, 0x9f, 0x4e,
-+};
-+
-+
-+/** Vendor information for CPE210/220/510/520 */
-+static const unsigned char cpe510_vendor[] = "\x00\x00\x00\x1f""CPE510(TP-LINK|UN|N300-5):1.0\r\n";
-+
-+
-+/**
-+    The flash partition table for CPE210/220/510/520;
-+    it is the same as the one used by the stock images.
-+*/
-+static const struct flash_partition_entry cpe510_partitions[] = {
-+	{"fs-uboot", 0x00000, 0x20000},
-+	{"partition-table", 0x20000, 0x02000},
-+	{"default-mac", 0x30000, 0x00020},
-+	{"product-info", 0x31100, 0x00100},
-+	{"signature", 0x32000, 0x00400},
-+	{"os-image", 0x40000, 0x170000},
-+	{"soft-version", 0x1b0000, 0x00100},
-+	{"support-list", 0x1b1000, 0x00400},
-+	{"file-system", 0x1c0000, 0x600000},
-+	{"user-config", 0x7c0000, 0x10000},
-+	{"default-config", 0x7d0000, 0x10000},
-+	{"log", 0x7e0000, 0x10000},
-+	{"radio", 0x7f0000, 0x10000},
-+	{NULL, 0, 0}
-+};
-+
-+/**
-+   The support list for CPE210/220/510/520
-+
-+   The stock images also contain strings for two more devices: BS510 and BS210.
-+   At the moment, there exists no public information about these devices.
-+*/
-+static const unsigned char cpe510_support_list[] =
-+	"\x00\x00\x00\xc8\x00\x00\x00\x00"
-+	"SupportList:\r\n"
-+	"CPE510(TP-LINK|UN|N300-5):1.0\r\n"
-+	"CPE520(TP-LINK|UN|N300-5):1.0\r\n"
-+	"CPE210(TP-LINK|UN|N300-2):1.0\r\n"
-+	"CPE220(TP-LINK|UN|N300-2):1.0\r\n"
-+	"\r\n\xff";
-+
-+
-+/** Allocates a new image partition */
-+struct image_partition_entry alloc_image_partition(const char *name, size_t len) {
-+	struct image_partition_entry entry = {name, len, malloc(len)};
-+	if (!entry.data)
-+		error(1, errno, "malloc");
-+
-+	return entry;
-+}
-+
-+/** Frees an image partition */
-+void free_image_partition(struct image_partition_entry entry) {
-+	free(entry.data);
-+}
-+
-+/** Generates the partition-table partition */
-+struct image_partition_entry make_partition_table(const struct flash_partition_entry *p) {
-+	struct image_partition_entry entry = alloc_image_partition("partition-table", 0x800);
-+
-+	char *s = (char *)entry.data, *end = (char *)(s+entry.size);
-+
-+	*(s++) = 0x00;
-+	*(s++) = 0x04;
-+	*(s++) = 0x00;
-+	*(s++) = 0x00;
-+
-+	size_t i;
-+	for (i = 0; p[i].name; i++) {
-+		size_t len = end-s;
-+		size_t w = snprintf(s, len, "partition %s base 0x%05x size 0x%05x\n", p[i].name, p[i].base, p[i].size);
-+
-+		if (w > len-1)
-+			error(1, 0, "flash partition table overflow?");
-+
-+		s += w;
-+	}
-+
-+	s++;
-+
-+	memset(s, 0xff, end-s);
-+
-+	return entry;
-+}
-+
-+
-+/** Generates a binary-coded decimal representation of an integer in the range [0, 99] */
-+static inline uint8_t bcd(uint8_t v) {
-+	return 0x10 * (v/10) + v%10;
-+}
-+
-+
-+/** Generates the soft-version partition */
-+struct image_partition_entry make_soft_version(uint32_t rev) {
-+	struct image_partition_entry entry = alloc_image_partition("soft-version", sizeof(struct soft_version));
-+	struct soft_version *s = (struct soft_version *)entry.data;
-+
-+	time_t t;
-+	if (time(&t) == (time_t)(-1))
-+		error(1, errno, "time");
-+
-+	struct tm *tm = localtime(&t);
-+
-+	s->magic = htonl(0x0000000c);
-+	s->zero = 0;
-+	s->pad1 = 0xff;
-+
-+	s->version_major = 0;
-+	s->version_minor = 0;
-+	s->version_patch = 0;
-+
-+	s->year_hi = bcd((1900+tm->tm_year)/100);
-+	s->year_lo = bcd(tm->tm_year%100);
-+	s->month = bcd(tm->tm_mon+1);
-+	s->day = bcd(tm->tm_mday);
-+	s->rev = htonl(rev);
-+
-+	s->pad2 = 0xff;
-+
-+	return entry;
-+}
-+
-+/** Generates the support-list partition */
-+struct image_partition_entry make_support_list(const unsigned char *support_list, size_t len) {
-+	struct image_partition_entry entry = alloc_image_partition("support-list", len);
-+	memcpy(entry.data, support_list, len);
-+	return entry;
-+}
-+
-+/** Creates a new image partition with an arbitrary name from a file */
-+struct image_partition_entry read_file(const char *part_name, const char *filename, bool add_jffs2_eof) {
-+	struct stat statbuf;
-+
-+	if (stat(filename, &statbuf) < 0)
-+		error(1, errno, "unable to stat file `%s'", filename);
-+
-+	size_t len = statbuf.st_size;
-+
-+	if (add_jffs2_eof)
-+		len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark);
-+
-+	struct image_partition_entry entry = alloc_image_partition(part_name, len);
-+
-+	FILE *file = fopen(filename, "rb");
-+	if (!file)
-+		error(1, errno, "unable to open file `%s'", filename);
-+
-+	if (fread(entry.data, statbuf.st_size, 1, file) != 1)
-+		error(1, errno, "unable to read file `%s'", filename);
-+
-+	if (add_jffs2_eof) {
-+		uint8_t *eof = entry.data + statbuf.st_size, *end = entry.data+entry.size;
-+
-+		memset(eof, 0xff, end - eof - sizeof(jffs2_eof_mark));
-+		memcpy(end - sizeof(jffs2_eof_mark), jffs2_eof_mark, sizeof(jffs2_eof_mark));
-+	}
-+
-+	fclose(file);
-+
-+	return entry;
-+}
-+
-+
-+/**
-+   Copies a list of image partitions into an image buffer and generates the image partition table while doing so
-+
-+   Example image partition table:
-+
-+     fwup-ptn partition-table base 0x00800 size 0x00800
-+     fwup-ptn os-image base 0x01000 size 0x113b45
-+     fwup-ptn file-system base 0x114b45 size 0x1d0004
-+     fwup-ptn support-list base 0x2e4b49 size 0x000d1
-+
-+   Each line of the partition table is terminated with the bytes 09 0d 0a ("\t\r\n"),
-+   the end of the partition table is marked with a zero byte.
-+
-+   The firmware image must contain at least the partition-table and support-list partitions
-+   to be accepted. There aren't any alignment constraints for the image partitions.
-+
-+   The partition-table partition contains the actual flash layout; partitions
-+   from the image partition table are mapped to the corresponding flash partitions during
-+   the firmware upgrade. The support-list partition contains a list of devices supported by
-+   the firmware image.
-+
-+   The base offsets in the firmware partition table are relative to the end
-+   of the vendor information block, so the partition-table partition will
-+   actually start at offset 0x1814 of the image.
-+
-+   I think partition-table must be the first partition in the firmware image.
-+*/
-+void put_partitions(uint8_t *buffer, const struct image_partition_entry *parts) {
-+	size_t i;
-+	char *image_pt = (char *)buffer, *end = image_pt + 0x800;
-+
-+	size_t base = 0x800;
-+	for (i = 0; parts[i].name; i++) {
-+		memcpy(buffer + base, parts[i].data, parts[i].size);
-+
-+		size_t len = end-image_pt;
-+		size_t w = snprintf(image_pt, len, "fwup-ptn %s base 0x%05x size 0x%05x\t\r\n", parts[i].name, (unsigned)base, (unsigned)parts[i].size);
-+
-+		if (w > len-1)
-+			error(1, 0, "image partition table overflow?");
-+
-+		image_pt += w;
-+
-+		base += parts[i].size;
-+	}
-+
-+	image_pt++;
-+
-+	memset(image_pt, 0xff, end-image_pt);
-+}
-+
-+/** Generates and writes the image MD5 checksum */
-+void put_md5(uint8_t *md5, uint8_t *buffer, unsigned int len) {
-+	MD5_CTX ctx;
-+
-+	MD5_Init(&ctx);
-+	MD5_Update(&ctx, md5_salt, (unsigned int)sizeof(md5_salt));
-+	MD5_Update(&ctx, buffer, len);
-+	MD5_Final(md5, &ctx);
-+}
-+
-+
-+/**
-+   Generates the firmware image in factory format
-+
-+   Image format:
-+
-+     Bytes (hex)  Usage
-+     -----------  -----
-+     0000-0003    Image size (4 bytes, big endian)
-+     0004-0013    MD5 hash (hash of a 16 byte salt and the image data starting with byte 0x14)
-+     0014-1013    Vendor information (4096 bytes, padded with 0xff; there seem to be older
-+                  (VxWorks-based) TP-LINK devices which use a smaller vendor information block)
-+     1014-1813    Image partition table (2048 bytes, padded with 0xff)
-+     1814-xxxx    Firmware partitions
-+*/
-+void * generate_factory_image(const unsigned char *vendor, size_t vendor_len, const struct image_partition_entry *parts, size_t *len) {
-+	*len = 0x1814;
-+
-+	size_t i;
-+	for (i = 0; parts[i].name; i++)
-+		*len += parts[i].size;
-+
-+	uint8_t *image = malloc(*len);
-+	if (!image)
-+		error(1, errno, "malloc");
-+
-+	image[0] = *len >> 24;
-+	image[1] = *len >> 16;
-+	image[2] = *len >> 8;
-+	image[3] = *len;
-+
-+	memcpy(image+0x14, vendor, vendor_len);
-+	memset(image+0x14+vendor_len, 0xff, 4096-vendor_len);
-+
-+	put_partitions(image + 0x1014, parts);
-+	put_md5(image+0x04, image+0x14, *len-0x14);
-+
-+	return image;
-+}
-+
-+/**
-+   Generates the firmware image in sysupgrade format
-+
-+   This makes some assumptions about the provided flash and image partition tables and
-+   should be generalized when TP-LINK starts building its safeloader into hardware with
-+   different flash layouts.
-+*/
-+void * generate_sysupgrade_image(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) {
-+	const struct flash_partition_entry *flash_os_image = &flash_parts[5];
-+	const struct flash_partition_entry *flash_soft_version = &flash_parts[6];
-+	const struct flash_partition_entry *flash_support_list = &flash_parts[7];
-+	const struct flash_partition_entry *flash_file_system = &flash_parts[8];
-+
-+	const struct image_partition_entry *image_os_image = &image_parts[3];
-+	const struct image_partition_entry *image_soft_version = &image_parts[1];
-+	const struct image_partition_entry *image_support_list = &image_parts[2];
-+	const struct image_partition_entry *image_file_system = &image_parts[4];
-+
-+	assert(strcmp(flash_os_image->name, "os-image") == 0);
-+	assert(strcmp(flash_soft_version->name, "soft-version") == 0);
-+	assert(strcmp(flash_support_list->name, "support-list") == 0);
-+	assert(strcmp(flash_file_system->name, "file-system") == 0);
-+
-+	assert(strcmp(image_os_image->name, "os-image") == 0);
-+	assert(strcmp(image_soft_version->name, "soft-version") == 0);
-+	assert(strcmp(image_support_list->name, "support-list") == 0);
-+	assert(strcmp(image_file_system->name, "file-system") == 0);
-+
-+	if (image_os_image->size > flash_os_image->size)
-+		error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size);
-+	if (image_file_system->size > flash_file_system->size)
-+		error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size);
-+
-+	*len = flash_file_system->base - flash_os_image->base + image_file_system->size;
-+
-+	uint8_t *image = malloc(*len);
-+	if (!image)
-+		error(1, errno, "malloc");
-+
-+	memset(image, 0xff, *len);
-+
-+	memcpy(image, image_os_image->data, image_os_image->size);
-+	memcpy(image + flash_soft_version->base - flash_os_image->base, image_soft_version->data, image_soft_version->size);
-+	memcpy(image + flash_support_list->base - flash_os_image->base, image_support_list->data, image_support_list->size);
-+	memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size);
-+
-+	return image;
-+}
-+
-+
-+/** Generates an image for CPE210/220/510/520 and writes it to a file */
-+static void do_cpe510(const char *output, const char *kernel_image, const char *rootfs_image, uint32_t rev, bool add_jffs2_eof, bool sysupgrade) {
-+	struct image_partition_entry parts[6] = {};
-+
-+	parts[0] = make_partition_table(cpe510_partitions);
-+	parts[1] = make_soft_version(rev);
-+	parts[2] = make_support_list(cpe510_support_list, sizeof(cpe510_support_list)-1);
-+	parts[3] = read_file("os-image", kernel_image, false);
-+	parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof);
-+
-+	size_t len;
-+	void *image;
-+	if (sysupgrade)
-+		image = generate_sysupgrade_image(cpe510_partitions, parts, &len);
-+	else
-+		image = generate_factory_image(cpe510_vendor, sizeof(cpe510_vendor)-1, parts, &len);
-+
-+	FILE *file = fopen(output, "wb");
-+	if (!file)
-+		error(1, errno, "unable to open output file");
-+
-+	if (fwrite(image, len, 1, file) != 1)
-+		error(1, 0, "unable to write output file");
-+
-+	fclose(file);
-+
-+	free(image);
-+
-+	size_t i;
-+	for (i = 0; parts[i].name; i++)
-+		free_image_partition(parts[i]);
-+}
-+
-+
-+/** Usage output */
-+void usage(const char *argv0) {
-+	fprintf(stderr,
-+		"Usage: %s [OPTIONS...]\n"
-+		"\n"
-+		"Options:\n"
-+		"  -B <board>      create image for the board specified with <board>\n"
-+		"  -k <file>       read kernel image from the file <file>\n"
-+		"  -r <file>       read rootfs image from the file <file>\n"
-+		"  -o <file>       write output to the file <file>\n"
-+		"  -V <rev>        sets the revision number to <rev>\n"
-+		"  -j              add jffs2 end-of-filesystem markers\n"
-+		"  -S              create sysupgrade instead of factory image\n"
-+		"  -h              show this help\n",
-+		argv0
-+	);
-+};
-+
-+
-+int main(int argc, char *argv[]) {
-+	const char *board = NULL, *kernel_image = NULL, *rootfs_image = NULL, *output = NULL;
-+	bool add_jffs2_eof = false, sysupgrade = false;
-+	unsigned rev = 0;
-+
-+	while (true) {
-+		int c;
-+
-+		c = getopt(argc, argv, "B:k:r:o:V:jSh");
-+		if (c == -1)
-+			break;
-+
-+		switch (c) {
-+		case 'B':
-+			board = optarg;
-+			break;
-+
-+		case 'k':
-+			kernel_image = optarg;
-+			break;
-+
-+		case 'r':
-+			rootfs_image = optarg;
-+			break;
-+
-+		case 'o':
-+			output = optarg;
-+			break;
-+
-+		case 'V':
-+			sscanf(optarg, "r%u", &rev);
-+			break;
-+
-+		case 'j':
-+			add_jffs2_eof = true;
-+			break;
-+
-+		case 'S':
-+			sysupgrade = true;
-+			break;
-+
-+		case 'h':
-+			usage(argv[0]);
-+			return 0;
-+
-+		default:
-+			usage(argv[0]);
-+			return 1;
-+		}
-+	}
-+
-+	if (!board)
-+		error(1, 0, "no board has been specified");
-+	if (!kernel_image)
-+		error(1, 0, "no kernel image has been specified");
-+	if (!rootfs_image)
-+		error(1, 0, "no rootfs image has been specified");
-+	if (!output)
-+		error(1, 0, "no output filename has been specified");
-+
-+	if (strcmp(board, "CPE510") == 0)
-+		do_cpe510(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade);
-+	else
-+		error(1, 0, "unsupported board %s", board);
-+
-+	return 0;
-+}

+ 0 - 471
patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch

@@ -1,471 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 26 Nov 2014 19:57:50 +0100
-Subject: ar71xx: add support for TP-LINK CPE210/220/510/520
-
-This adds support for the TP-LINK CPE210/220/510/520 (Pharos series). These
-devices are very similar to the Ubiquiti NanoStations, but with better specs:
-faster CPU, more RAM, 2x2 MIMO.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh
-index eb96338..d9c7328 100755
---- a/target/linux/ar71xx/base-files/etc/diag.sh
-+++ b/target/linux/ar71xx/base-files/etc/diag.sh
-@@ -43,6 +43,9 @@ get_status_led() {
- 	cap4200ag)
- 		status_led="senao:green:pwr"
- 		;;
-+	cpe510)
-+		status_led="tp-link:green:link4"
-+		;;
- 	db120)
- 		status_led="db120:green:status"
- 		;;
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index 0d085be..a6e6721 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -61,6 +61,16 @@ carambola2)
- 	ucidef_set_led_wlan "wlan" "WLAN" "carambola2:green:wlan" "phy0tpt"
- 	;;
- 
-+cpe510)
-+	ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20"
-+	ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10"
-+	ucidef_set_rssimon "wlan0" "40000" "1"
-+	ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13"
-+	ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13"
-+	ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13"
-+	ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13"
-+	;;
-+
- db120)
- 	ucidef_set_led_usbdev "usb" "USB" "db120:green:usb" "1-1"
- 	;;
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-index 4be30b8..78f4992 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-@@ -62,6 +62,13 @@ tl-wdr4900-v2)
- 	ucidef_add_switch_vlan "switch0" "2" "1 6"
- 	;;
- 
-+cpe510)
-+	ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"
-+	ucidef_add_switch "switch0" "1" "1"
-+	ucidef_add_switch_vlan "switch0" "1" "0t 5"
-+	ucidef_add_switch_vlan "switch0" "2" "0t 4"
-+	;;
-+
- db120 |\
- rb-2011l | \
- rb-2011uas |\
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 1709356..9fb4102 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -229,6 +229,39 @@ tplink_board_detect() {
- 	AR71XX_MODEL="$model $hwver"
- }
- 
-+tplink_pharos_get_model_string() {
-+	local part
-+	part=$(find_mtd_part 'product-info')
-+	[ -z "$part" ] && return 1
-+
-+	# The returned string will end with \r\n, but we don't remove it here
-+	# to simplify matching against it in the sysupgrade image check
-+	dd if=$part bs=1 skip=4360 2>/dev/null | head -n 1
-+}
-+
-+tplink_pharos_board_detect() {
-+	local model_string="$(tplink_pharos_get_model_string | tr -d '\r')"
-+	local oIFS="$IFS"; IFS=":"; set -- $model_string; IFS="$oIFS"
-+	local model
-+
-+	case "$1" in
-+	'CPE210(TP-LINK|UN|N300-2)')
-+		model='TP-Link CPE210'
-+		;;
-+	'CPE220(TP-LINK|UN|N300-2)')
-+		model='TP-Link CPE220'
-+		;;
-+	'CPE510(TP-LINK|UN|N300-5)')
-+		model='TP-Link CPE510'
-+		;;
-+	'CPE520(TP-LINK|UN|N300-5)')
-+		model='TP-Link CPE520'
-+		;;
-+	esac
-+
-+	[ -n "$model" ] && AR71XX_MODEL="$model v$2"
-+}
-+
- ar71xx_board_detect() {
- 	local machine
- 	local name
-@@ -302,6 +335,10 @@ ar71xx_board_detect() {
- 	*CAP4200AG)
- 		name="cap4200ag"
- 		;;
-+	*"CPE210/220/510/520")
-+		name="cpe510"
-+		tplink_pharos_board_detect
-+		;;
- 	*"DB120 reference board")
- 		name="db120"
- 		;;
-@@ -754,11 +791,8 @@ ar71xx_board_detect() {
- 		;;
- 	esac
- 
--	case "$machine" in
--	*TL-WR* | *TL-WA* | *TL-MR* | *TL-WD* | *Archer*)
-+	[ -z "$AR71XX_MODEL" ] && [ "${machine:0:8}" = 'TP-LINK ' ] && \
- 		tplink_board_detect "$machine"
--		;;
--	esac
- 
- 	[ -z "$name" ] && name="unknown"
- 
-diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-index eeaac6a..c583215 100755
---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-@@ -70,6 +70,33 @@ tplink_get_image_boot_size() {
- 	get_image "$@" | dd bs=4 count=1 skip=37 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
- }
- 
-+tplink_pharos_check_image() {
-+	local magic_long="$(get_magic_long "$1")"
-+	[ "$magic_long" != "7f454c46" ] && {
-+		echo "Invalid image magic '$magic_long'"
-+		return 1
-+	}
-+
-+	local model_string="$(tplink_pharos_get_model_string)"
-+	local line
-+
-+	# Here $1 is given to dd directly instead of get_image as otherwise the skip
-+	# will take almost a second (as dd can't seek then)
-+	#
-+	# This will fail if the image isn't local, but that's fine: as the
-+	# read loop won't be executed at all, it will return true, so the image
-+	# is accepted (loading the first 1.5M of a remote image for this check seems
-+	# a bit extreme)
-+	dd if="$1" bs=1 skip=1511432 count=1024 2>/dev/null | while read line; do
-+		[ "$line" == "$model_string" ] && break
-+	done || {
-+		echo "Unsupported image (model not in support-list)"
-+		return 1
-+	}
-+
-+	return 0
-+}
-+
- seama_get_type_magic() {
- 	get_image "$@" | dd bs=1 count=4 skip=53 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
- }
-@@ -214,6 +241,11 @@ platform_check_image() {
- 		return 0
- 		;;
- 
-+	cpe510)
-+		tplink_pharos_check_image "$1" && return 0
-+		return 1
-+		;;
-+
- 	dir-825-b1 | \
- 	tew-673gru)
- 		dir825b_check_image "$1" && return 0
-diff --git a/target/linux/ar71xx/config-3.10 b/target/linux/ar71xx/config-3.10
-index 482914a..14b59f7 100644
---- a/target/linux/ar71xx/config-3.10
-+++ b/target/linux/ar71xx/config-3.10
-@@ -39,6 +39,7 @@ CONFIG_ATH79_MACH_AW_NR580=y
- CONFIG_ATH79_MACH_BHU_BXU2000N2_A=y
- CONFIG_ATH79_MACH_CAP4200AG=y
- CONFIG_ATH79_MACH_CARAMBOLA2=y
-+CONFIG_ATH79_MACH_CPE510=y
- CONFIG_ATH79_MACH_DB120=y
- CONFIG_ATH79_MACH_DIR_505_A1=y
- CONFIG_ATH79_MACH_DIR_600_A1=y
-diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c
-new file mode 100644
-index 0000000..8bf5c0f
---- /dev/null
-+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c
-@@ -0,0 +1,107 @@
-+/*
-+ *  TP-LINK CPE210/220/510/520 board support
-+ *
-+ *  Copyright (C) 2014 Matthias Schiffer <mschiffer@universe-factory.net>
-+ *
-+ *  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/gpio.h>
-+#include <linux/platform_device.h>
-+
-+#include <asm/mach-ath79/ath79.h>
-+#include <asm/mach-ath79/ar71xx_regs.h>
-+
-+#include "common.h"
-+#include "dev-eth.h"
-+#include "dev-gpio-buttons.h"
-+#include "dev-leds-gpio.h"
-+#include "dev-m25p80.h"
-+#include "dev-wmac.h"
-+#include "machtypes.h"
-+
-+
-+#define CPE510_GPIO_LED_LAN0	11
-+#define CPE510_GPIO_LED_LAN1	12
-+#define CPE510_GPIO_LED_L1	13
-+#define CPE510_GPIO_LED_L2	14
-+#define CPE510_GPIO_LED_L3	15
-+#define CPE510_GPIO_LED_L4	16
-+
-+#define CPE510_GPIO_BTN_RESET	4
-+
-+#define CPE510_KEYS_POLL_INTERVAL	20 /* msecs */
-+#define CPE510_KEYS_DEBOUNCE_INTERVAL	(3 * CPE510_KEYS_POLL_INTERVAL)
-+
-+
-+static struct gpio_led cpe510_leds_gpio[] __initdata = {
-+	{
-+		.name		= "tp-link:green:lan0",
-+		.gpio		= CPE510_GPIO_LED_LAN0,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:lan1",
-+		.gpio		= CPE510_GPIO_LED_LAN1,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:link1",
-+		.gpio		= CPE510_GPIO_LED_L1,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:link2",
-+		.gpio		= CPE510_GPIO_LED_L2,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:link3",
-+		.gpio		= CPE510_GPIO_LED_L3,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:link4",
-+		.gpio		= CPE510_GPIO_LED_L4,
-+		.active_low	= 1,
-+	},
-+};
-+
-+static struct gpio_keys_button cpe510_gpio_keys[] __initdata = {
-+	{
-+		.desc		= "Reset button",
-+		.type		= EV_KEY,
-+		.code		= KEY_RESTART,
-+		.debounce_interval = CPE510_KEYS_DEBOUNCE_INTERVAL,
-+		.gpio		= CPE510_GPIO_BTN_RESET,
-+		.active_low	= 1,
-+	}
-+};
-+
-+
-+static void __init cpe510_setup(void)
-+{
-+	u8 *mac = (u8 *) KSEG1ADDR(0x1f830008);
-+	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
-+
-+	/* Disable JTAG, enabling GPIOs 0-3 */
-+	/* Configure OBS4 line, for GPIO 4*/
-+	ath79_gpio_function_setup(AR934X_GPIO_FUNC_JTAG_DISABLE,
-+				  AR934X_GPIO_FUNC_CLK_OBS4_EN);
-+
-+	ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe510_leds_gpio),
-+				 cpe510_leds_gpio);
-+
-+	ath79_register_gpio_keys_polled(1, CPE510_KEYS_POLL_INTERVAL,
-+					ARRAY_SIZE(cpe510_gpio_keys),
-+					cpe510_gpio_keys);
-+
-+	ath79_register_m25p80(NULL);
-+
-+	ath79_register_mdio(1, 0);
-+	ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0);
-+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
-+	ath79_register_eth(1);
-+
-+	ath79_register_wmac(ee, mac);
-+}
-+
-+MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE210/220/510/520",
-+	     cpe510_setup);
-diff --git a/target/linux/ar71xx/generic/profiles/tp-link.mk b/target/linux/ar71xx/generic/profiles/tp-link.mk
-index 78333be..a9d170c 100644
---- a/target/linux/ar71xx/generic/profiles/tp-link.mk
-+++ b/target/linux/ar71xx/generic/profiles/tp-link.mk
-@@ -16,6 +16,17 @@ endef
- $(eval $(call Profile,ARCHERC7))
- 
- 
-+define Profile/CPE510
-+	NAME:=TP-LINK CPE210/220/510/520
-+	PACKAGES:=rssileds
-+endef
-+
-+define Profile/CPE510/Description
-+	Package set optimized for the TP-LINK CPE210/220/510/520.
-+endef
-+$(eval $(call Profile,CPE510))
-+
-+
- define Profile/TLMR10U
- 	NAME:=TP-LINK TL-MR10U
- 	PACKAGES:=kmod-usb-core kmod-usb2
-diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
-index 425fcc5..55f11dc 100644
---- a/target/linux/ar71xx/image/Makefile
-+++ b/target/linux/ar71xx/image/Makefile
-@@ -261,6 +261,7 @@ cameo_ap121_mtdlayout_8M=mtdparts=spi0.0:64k(u-boot)ro,64k(art)ro,64k(mac)ro,64k
- cameo_db120_mtdlayout=mtdparts=spi0.0:64k(uboot)ro,64k(nvram)ro,15936k(firmware),192k(lang)ro,64k(mac)ro,64k(art)ro
- cameo_db120_mtdlayout_8M=mtdparts=spi0.0:64k(uboot)ro,64k(nvram)ro,7872k(firmware),128k(lang)ro,64k(art)ro
- cap4200ag_mtdlayout=mtdparts=spi0.0:256k(u-boot),64k(u-boot-env),320k(custom)ro,1536k(kernel),12096k(rootfs),2048k(failsafe),64k(art),13632k@0xa0000(firmware)
-+cpe510_mtdlayout=mtdparts=spi0.0:128k(u-boot)ro,64k(pation-table)ro,64k(product-info)ro,1536k(kernel),6144k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware)
- eap300v2_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env),320k(custom),13632k(firmware),2048k(failsafe),64k(art)ro
- db120_mtdlayout=mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6336k(rootfs),1408k(kernel),64k(nvram),64k(art)ro,7744k@0x50000(firmware)
- cameo_ap94_mtdlayout=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,6208k(firmware),64k(caldata)ro,1600k(unknown)ro,64k@0x7f0000(caldata_copy)
-@@ -811,6 +812,32 @@ define Image/Build/TPLINK-LZMA/initramfs
- endef
- 
- 
-+Image/Build/TPLINK-SAFELOADER/buildkernel=$(call PatchKernelLzma,$(2),$(3) $(4))
-+
-+define Image/Build/TPLINK-SAFELOADER
-+	-rm -rf $(KDIR)/lzma-loader
-+	$(LOADER_MAKE) LOADER=loader-$(2).elf\
-+		LZMA_TEXT_START=0x80a00000 LOADADDR=0x80060000 \
-+		LOADER_DATA="$(KDIR_TMP)/vmlinux-$(2).bin.lzma" BOARD="$(2)" \
-+		compile loader.elf
-+
-+	-$(STAGING_DIR_HOST)/bin/tplink-safeloader \
-+		-B $(5) \
-+		-k $(KDIR)/loader-$(2).elf \
-+		-r $(KDIR)/root.$(1) \
-+		-V $(REVISION) \
-+		-j \
-+		-o $(call factoryname,$(1),$(2))
-+	-$(STAGING_DIR_HOST)/bin/tplink-safeloader \
-+		-B $(5) \
-+		-k $(KDIR)/loader-$(2).elf \
-+		-r $(KDIR)/root.$(1) \
-+		-V $(REVISION) \
-+		-j -S \
-+		-o $(call sysupname,$(1),$(2))
-+endef
-+
-+
- define Image/Build/CyberTAN
- 	echo -n '' > $(KDIR_TMP)/empty.bin
- 	$(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/image.tmp \
-@@ -1227,6 +1254,8 @@ $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWDR4310V1,tl-wdr4310-v1,TL-WDR4
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWDR4900V2,tl-wdr4900-v2,TL-WDR4900-v2,ttyS0,115200,0x49000002,1,8Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,MW4530RV1,mw4530r-v1,TL-WDR4300,ttyS0,115200,0x45300001,1,8Mlzma))
- 
-+$(eval $(call SingleProfile,TPLINK-SAFELOADER,64kraw,CPE510,cpe210-220-510-520,CPE510,ttyS0,115200,$$(cpe510_mtdlayout),CPE510))
-+
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,SMART-300,smart-300,SMART-300,ttyS0,115200,0x93410001,1,8Mlzma))
- 
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,OOLITE,oolite,GS-OOLITE,ttyATH0,115200,0x3C000101,1,16Mlzma))
-diff --git a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-index 3669f26..516d52d 100644
---- a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-+++ b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-@@ -1,6 +1,6 @@
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -16,22 +16,144 @@
-+@@ -16,22 +16,145 @@
-  
-  enum ath79_mach_type {
-  	ATH79_MACH_GENERIC = 0,
-@@ -24,6 +24,7 @@
- +	ATH79_MACH_BHU_BXU2000N2_A1,	/* BHU BXU2000n-2 A1 */
- +	ATH79_MACH_CAP4200AG,		/* Senao CAP4200AG */
- +	ATH79_MACH_CARAMBOLA2,		/* 8devices Carambola2 */
-++	ATH79_MACH_CPE510,		/* TP-LINK CPE510 */
-  	ATH79_MACH_DB120,		/* Atheros DB120 reference board */
-  	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
- +	ATH79_MACH_DIR_505_A1,		/* D-Link DIR-505 rev. A1 */
-@@ -209,7 +210,7 @@
-  config ATH79_MACH_AP121
-  	bool "Atheros AP121 reference board"
-  	select SOC_AR933X
--@@ -9,64 +64,736 @@ config ATH79_MACH_AP121
-+@@ -9,64 +64,745 @@ config ATH79_MACH_AP121
-  	select ATH79_DEV_GPIO_BUTTONS
-  	select ATH79_DEV_LEDS_GPIO
-  	select ATH79_DEV_M25P80
-@@ -709,6 +710,15 @@
-  
- -config ATH79_MACH_AP81
- -	bool "Atheros AP81 reference board"
-++config ATH79_MACH_CPE510
-++       bool "TP-LINK CPE510 support"
-++       select SOC_AR934X
-++       select ATH79_DEV_ETH
-++       select ATH79_DEV_GPIO_BUTTONS
-++       select ATH79_DEV_LEDS_GPIO
-++       select ATH79_DEV_M25P80
-++       select ATH79_DEV_WMAC
-++
- +config ATH79_MACH_TL_MR11U
- +	bool "TP-LINK TL-MR11U/TL-MR3040 support"
- +	select SOC_AR933X
-@@ -972,7 +982,7 @@
-  
-  config ATH79_MACH_UBNT_XM
-  	bool "Ubiquiti Networks XM/UniFi boards"
--@@ -83,6 +810,65 @@ config ATH79_MACH_UBNT_XM
-+@@ -83,6 +819,65 @@ config ATH79_MACH_UBNT_XM
-  	  Say 'Y' here if you want your kernel to support the
-  	  Ubiquiti Networks XM (rev 1.0) board.
-  
-@@ -1038,7 +1048,7 @@
-  endmenu
-  
-  config SOC_AR71XX
--@@ -132,7 +918,10 @@ config ATH79_DEV_DSA
-+@@ -132,7 +927,10 @@ config ATH79_DEV_DSA
-  config ATH79_DEV_ETH
-  	def_bool n
-  
-@@ -1050,7 +1060,7 @@
-  	def_bool n
-  
-  config ATH79_DEV_GPIO_BUTTONS
--@@ -164,4 +953,7 @@ config ATH79_PCI_ATH9K_FIXUP
-+@@ -164,4 +962,7 @@ config ATH79_PCI_ATH9K_FIXUP
-  config ATH79_ROUTERBOOT
-  	def_bool n
-  
-@@ -1060,7 +1070,7 @@
-  endif
- --- a/arch/mips/ath79/Makefile
- +++ b/arch/mips/ath79/Makefile
--@@ -38,9 +38,90 @@ obj-$(CONFIG_ATH79_ROUTERBOOT)		+= route
-+@@ -38,9 +38,91 @@ obj-$(CONFIG_ATH79_ROUTERBOOT)		+= route
-  #
-  # Machines
-  #
-@@ -1079,6 +1089,7 @@
- +obj-$(CONFIG_ATH79_MACH_AW_NR580)	+= mach-aw-nr580.o
- +obj-$(CONFIG_ATH79_MACH_BHU_BXU2000N2_A)+= mach-bhu-bxu2000n2-a.o
- +obj-$(CONFIG_ATH79_MACH_CAP4200AG)	+= mach-cap4200ag.o
-++obj-$(CONFIG_ATH79_MACH_CPE510)		+= mach-cpe510.o
-  obj-$(CONFIG_ATH79_MACH_DB120)		+= mach-db120.o
- +obj-$(CONFIG_ATH79_MACH_DIR_505_A1)	+= mach-dir-505-a1.o
- +obj-$(CONFIG_ATH79_MACH_DIR_600_A1)	+= mach-dir-600-a1.o

+ 0 - 0
patches/openwrt/0031-base-files-disable-reset-button-handling.patch → patches/openwrt/0006-base-files-disable-reset-button-handling.patch


+ 0 - 72
patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch

@@ -1,72 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 26 Nov 2014 23:20:33 +0100
-Subject: ar71xx: refactor ubnt xw board setup
-
-Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
-
-diff --git a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-index ed2fd24..9413bd8 100644
---- a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-+++ b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-@@ -1,6 +1,8 @@
----- a/arch/mips/ath79/mach-ubnt-xm.c
--+++ b/arch/mips/ath79/mach-ubnt-xm.c
--@@ -332,3 +332,60 @@ static void __init ubnt_uap_pro_setup(vo
-+Index: linux-3.10.49/arch/mips/ath79/mach-ubnt-xm.c
-+===================================================================
-+--- linux-3.10.49.orig/arch/mips/ath79/mach-ubnt-xm.c	2014-08-15 22:55:37.890080659 +0200
-++++ linux-3.10.49/arch/mips/ath79/mach-ubnt-xm.c	2014-08-15 22:58:31.061570912 +0200
-+@@ -332,3 +332,67 @@
-  MIPS_MACHINE(ATH79_MACH_UBNT_UAP_PRO, "UAP-PRO", "Ubiquiti UniFi AP Pro",
-  	     ubnt_uap_pro_setup);
-  
-@@ -29,7 +31,7 @@
- +	},
- +};
- +
--+static void __init ubnt_nano_m_xw_setup(void)
-++static void __init ubnt_xw_init(void)
- +{
- +	u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000);
- +
-@@ -44,26 +46,36 @@
- +	ath79_register_wmac(eeprom + UAP_PRO_WMAC_CALDATA_OFFSET, NULL);
- +	ap91_pci_init(eeprom + UAP_PRO_PCI_CALDATA_OFFSET, NULL);
- +
--+	ath79_register_mdio(0, ~(BIT(0) | BIT(1) | BIT(5)));
- +
- +	ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_MII_GMAC0 | AR934X_ETH_CFG_MII_GMAC0_SLAVE);
- +	ath79_init_mac(ath79_eth0_data.mac_addr,
- +		       eeprom + UAP_PRO_MAC0_OFFSET, 0);
- +
--+	/* GMAC0 is connected to an AR8326 switch */
- +	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII;
-++	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
-++}
-++
-++static void __init ubnt_nano_m_xw_setup(void)
-++{
-++	ubnt_xw_init();
-++
-++	/* GMAC0 is connected to an AR8326 switch */
-++	ath79_register_mdio(0, ~(BIT(0) | BIT(1) | BIT(5)));
- +	ath79_eth0_data.phy_mask = (BIT(0) | BIT(1) | BIT(5));
- +	ath79_eth0_data.speed = SPEED_100;
- +	ath79_eth0_data.duplex = DUPLEX_FULL;
--+	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
- +	ath79_register_eth(0);
- +}
- +
- +MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M_XW, "UBNT-NM-XW", "Ubiquiti Nanostation M XW",
- +	     ubnt_nano_m_xw_setup);
-++
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -124,6 +124,7 @@ enum ath79_mach_type {
-+@@ -121,9 +121,10 @@ enum ath79_mach_type {
-+ 	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
-+ 	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-+ 	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
-  	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
-  	ATH79_MACH_UBNT_LSX,		/* Ubiquiti LSX */
-  	ATH79_MACH_UBNT_NANO_M, 	/* Ubiquiti NanoStation M */

+ 21 - 0
patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch

@@ -0,0 +1,21 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Wed, 20 May 2015 21:56:14 +0200
+Subject: ncurses: fix host build with GCC 5.1
+
+diff --git a/package/libs/ncurses/Makefile b/package/libs/ncurses/Makefile
+index 13c7962..39851a6 100644
+--- a/package/libs/ncurses/Makefile
++++ b/package/libs/ncurses/Makefile
+@@ -82,6 +82,12 @@ HOST_CONFIGURE_ARGS += \
+ 	--without-tests \
+ 	--without-curses-h
+ 
++HOST_CONFIGURE_VARS = \
++        CC="$(HOSTCC)" \
++        CFLAGS="$(HOST_CFLAGS)" \
++        CPPFLAGS="$(HOST_CPPFLAGS) -P" \
++        LDFLAGS="$(HOST_LDFLAGS)" \
++        SHELL="$(SHELL)"
+ 
+ ifeq ($(HOST_OS),FreeBSD)
+ 	CONFIGURE_ARGS +=

+ 0 - 161
patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch

@@ -1,161 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 26 Nov 2014 23:20:46 +0100
-Subject: ar71xx: add board support for ubnt loco m xw
-
-Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
-
-diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh
-index d9c7328..924766d 100755
---- a/target/linux/ar71xx/base-files/etc/diag.sh
-+++ b/target/linux/ar71xx/base-files/etc/diag.sh
-@@ -34,7 +34,7 @@ get_status_led() {
- 	aw-nr580)
- 		status_led="aw-nr580:green:ready"
- 		;;
--	bullet-m | rocket-m | nano-m | nanostation-m | nanostation-m-xw)
-+	bullet-m | rocket-m | nano-m | nanostation-m | nanostation-m-xw | loco-m-xw)
- 		status_led="ubnt:green:link4"
- 		;;
- 	bxu2000n-2-a1)
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index a6e6721..2676b48 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -38,7 +38,8 @@ ap113)
- bullet-m | \
- nanostation-m | \
- rocket-m | \
--nanostation-m-xw)
-+nanostation-m-xw | \
-+loco-m-xw)
- 	ucidef_set_led_rssi "rssilow" "RSSILOW" "ubnt:red:link1" "wlan0" "1" "100" "0" "13"
- 	ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "ubnt:orange:link2" "wlan0" "26" "100" "-25" "13"
- 	ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "ubnt:green:link3" "wlan0" "51" "100" "-50" "13"
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-index 78f4992..c494310 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-@@ -293,6 +293,7 @@ bullet-m |\
- cap4200ag |\
- eap300v2 |\
- eap7660d |\
-+loco-m-xw |\
- mr600 |\
- mr600v2 |\
- rb-411 |\
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 9fb4102..79b6073 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -396,6 +396,9 @@ ar71xx_board_detect() {
- 	*"Bullet M")
- 		name="bullet-m"
- 		;;
-+	*"Loco M XW")
-+		name="loco-m-xw"
-+		;;
- 	*"Nanostation M")
- 		name="nanostation-m"
- 		;;
-diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-index c583215..a566b62 100755
---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-@@ -217,6 +217,7 @@ platform_check_image() {
- 	airgateway | \
- 	airrouter | \
- 	bullet-m | \
-+	loco-m-xw | \
- 	nanostation-m | \
- 	rocket-m | \
- 	nanostation-m-xw | \
-diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
-index 55f11dc..3fdaf47 100644
---- a/target/linux/ar71xx/image/Makefile
-+++ b/target/linux/ar71xx/image/Makefile
-@@ -1276,6 +1276,7 @@ $(eval $(call SingleProfile,UBNTXM,64kraw,UBNTNANOM,ubnt-nano-m,UBNT-NM,ttyS0,11
- $(eval $(call SingleProfile,UBNTXM,64kraw,UBNTUNIFI,ubnt-unifi,UBNT-UF,ttyS0,115200,XM,BZ,ar7240))
- $(eval $(call SingleProfile,UBNTXM,64kraw,UBNTUNIFIOUTDOOR,ubnt-unifi-outdoor,UBNT-U20,ttyS0,115200,XM,BZ,ar7240))
- $(eval $(call SingleProfile,UBNTXM,64kraw,UBNTNANOMXW,ubnt-nano-m-xw,UBNT-NM-XW,ttyS0,115200,XM,XW,ar934x))
-+$(eval $(call SingleProfile,UBNTXM,64kraw,UBNTLOCOXW,ubnt-loco-m-xw,UBNT-LOCO-XW,ttyS0,115200,XM,XW,ar934x))
- $(eval $(call SingleProfile,UBNTXM,64kraw,UBNTAIRGW,ubnt-air-gateway,UBNT-AGW,ttyATH0,115200,XM,AirGW,ar933x))
- 
- $(eval $(call SingleProfile,WHRHPG300N,64kraw,WHRG301N,whr-g301n,WHR-G301N,ttyS0,115200,$$(whrhpg300n_mtdlayout),WHR-G301N))
-@@ -1322,7 +1323,7 @@ $(eval $(call MultiProfile,TLWR941,TLWR941NV2 TLWR941NV3 TLWR941NV4 TLWR941NV6))
- $(eval $(call MultiProfile,TLWR1043,TLWR1043V1 TLWR1043V2))
- $(eval $(call MultiProfile,TLWDR4300,TLWDR3500V1 TLWDR3600V1 TLWDR4300V1 TLWDR4300V1IL TLWDR4310V1 MW4530RV1))
- $(eval $(call MultiProfile,TUBE2H,TUBE2H8M TUBE2H16M))
--$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTNANOM UBNTNANOMXW UBNTUNIFI UBNTUNIFIOUTDOOR UAPPRO UBNTAIRGW))
-+$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTNANOM UBNTNANOMXW UBNTLOCOXW UBNTUNIFI UBNTUNIFIOUTDOOR UAPPRO UBNTAIRGW))
- $(eval $(call MultiProfile,WNDR3700,WNDR3700V1 WNDR3700V2 WNDR3800 WNDR3800CH WNDRMAC WNDRMACV2))
- $(eval $(call MultiProfile,WNR612V2,REALWNR612V2 N150R))
- $(eval $(call MultiProfile,WP543,WP543_2M WP543_4M WP543_8M WP543_16M))
-diff --git a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-index 9413bd8..5e3d4d4 100644
---- a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-+++ b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-@@ -1,8 +1,6 @@
--Index: linux-3.10.49/arch/mips/ath79/mach-ubnt-xm.c
--===================================================================
----- linux-3.10.49.orig/arch/mips/ath79/mach-ubnt-xm.c	2014-08-15 22:55:37.890080659 +0200
--+++ linux-3.10.49/arch/mips/ath79/mach-ubnt-xm.c	2014-08-15 22:58:31.061570912 +0200
--@@ -332,3 +332,67 @@
-+--- a/arch/mips/ath79/mach-ubnt-xm.c
-++++ b/arch/mips/ath79/mach-ubnt-xm.c
-+@@ -332,3 +332,78 @@ static void __init ubnt_uap_pro_setup(vo
-  MIPS_MACHINE(ATH79_MACH_UBNT_UAP_PRO, "UAP-PRO", "Ubiquiti UniFi AP Pro",
-  	     ubnt_uap_pro_setup);
-  
-@@ -67,15 +65,27 @@ Index: linux-3.10.49/arch/mips/ath79/mach-ubnt-xm.c
- +	ath79_register_eth(0);
- +}
- +
-++static void __init ubnt_loco_m_xw_setup(void)
-++{
-++	ubnt_xw_init();
-++
-++	ath79_register_mdio(0, ~BIT(1));
-++	ath79_eth0_data.phy_mask = BIT(1);
-++	ath79_register_eth(0);
-++}
-++
- +MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M_XW, "UBNT-NM-XW", "Ubiquiti Nanostation M XW",
- +	     ubnt_nano_m_xw_setup);
- +
-++MIPS_MACHINE(ATH79_MACH_UBNT_LOCO_M_XW, "UBNT-LOCO-XW", "Ubiquiti Loco M XW",
-++	     ubnt_loco_m_xw_setup);
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -121,9 +121,10 @@ enum ath79_mach_type {
-+@@ -121,9 +121,11 @@ enum ath79_mach_type {
-  	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
-  	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-  	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
-++	ATH79_MACH_UBNT_LOCO_M_XW, 	/* Ubiquiti Loco M XW */
-  	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
-  	ATH79_MACH_UBNT_LSX,		/* Ubiquiti LSX */
-  	ATH79_MACH_UBNT_NANO_M, 	/* Ubiquiti NanoStation M */
-diff --git a/target/linux/ar71xx/patches-3.10/722-MIPS-ath79-add-airGateway-support.patch b/target/linux/ar71xx/patches-3.10/722-MIPS-ath79-add-airGateway-support.patch
-index 0fe62d9..c9d1e1e 100644
---- a/target/linux/ar71xx/patches-3.10/722-MIPS-ath79-add-airGateway-support.patch
-+++ b/target/linux/ar71xx/patches-3.10/722-MIPS-ath79-add-airGateway-support.patch
-@@ -12,10 +12,10 @@
-  #include "dev-ap9x-pci.h"
-  #include "dev-eth.h"
-  #include "dev-gpio-buttons.h"
--@@ -389,3 +391,65 @@ static void __init ubnt_nano_m_xw_setup(
-+@@ -406,3 +408,65 @@ MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M_XW,
-  
-- MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M_XW, "UBNT-NM-XW", "Ubiquiti Nanostation M XW",
-- 	     ubnt_nano_m_xw_setup);
-+ MIPS_MACHINE(ATH79_MACH_UBNT_LOCO_M_XW, "UBNT-LOCO-XW", "Ubiquiti Loco M XW",
-+ 	     ubnt_loco_m_xw_setup);
- +
- +static struct gpio_led ubnt_airgateway_gpio_leds[] __initdata = {
- +	{
-@@ -87,4 +87,4 @@
- +	ATH79_MACH_UBNT_AIRGW,		/* Ubiquiti AirGateway */
-  	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-  	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
-- 	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
-+ 	ATH79_MACH_UBNT_LOCO_M_XW, 	/* Ubiquiti Loco M XW */

+ 42 - 0
patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch

@@ -0,0 +1,42 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Wed, 20 May 2015 23:10:36 +0200
+Subject: mac80211: ath10k: allow simultaneous AP+IBSS
+
+diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
+new file mode 100644
+index 0000000..33b3110
+--- /dev/null
++++ b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
+@@ -0,0 +1,32 @@
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -5264,6 +5264,10 @@ static const struct ieee80211_iface_limi
++ 	.max	= 7,
++ 	.types	= BIT(NL80211_IFTYPE_AP)
++ 	},
+++	{
+++	.max    = 1,
+++	.types  = BIT(NL80211_IFTYPE_ADHOC)
+++	},
++ };
++ 
++ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
++@@ -5271,6 +5275,10 @@ static const struct ieee80211_iface_limi
++ 	.max	= 8,
++ 	.types	= BIT(NL80211_IFTYPE_AP)
++ 	},
+++	{
+++	.max    = 1,
+++	.types  = BIT(NL80211_IFTYPE_ADHOC)
+++	},
++ };
++ 
++ static const struct ieee80211_iface_combination ath10k_if_comb[] = {
++@@ -5575,6 +5583,7 @@ int ath10k_mac_register(struct ath10k *a
++ 		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
++ 		ar->hw->wiphy->n_iface_combinations =
++ 			ARRAY_SIZE(ath10k_10x_if_comb);
+++		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
++ 		break;
++ 	case ATH10K_FW_WMI_OP_VERSION_UNSET:
++ 	case ATH10K_FW_WMI_OP_VERSION_MAX:

+ 24 - 0
patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch

@@ -0,0 +1,24 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Wed, 20 May 2015 23:15:20 +0200
+Subject: iwinfo: update NanoStation (Loco) txpower offsets
+
+diff --git a/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch b/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch
+new file mode 100644
+index 0000000..1e13570
+--- /dev/null
++++ b/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch
+@@ -0,0 +1,14 @@
++--- a/hardware.txt
+++++ b/hardware.txt
++@@ -42,8 +42,9 @@
++ 0x168c 0x0027 0x0777 0x4082    7      0  "Ubiquiti" "SR71"
++ 0x168c 0x0029 0x0777 0x4005    7      0  "Ubiquiti" "SR71-15"
++ 0x168c 0x002a 0x0777 0xe302   12      0  "Ubiquiti" "PicoStation M2" /* ToDo: confirm offset */
++-0x168c 0x002a 0x0777 0xe012   12      0  "Ubiquiti" "NanoStation M2" /* ToDo: confirm offset */
++-0x168c 0x002a 0x0777 0xe005    5      0  "Ubiquiti" "NanoStation M5" /* ToDo: confirm offset */
+++0x168c 0x002a 0x0777 0xe012   11      0  "Ubiquiti" "NanoStation M2"
+++0x168c 0x002e 0x0777 0xe0a2    8      0  "Ubiquiti" "NanoStation Loco M2"
+++0x168c 0x002a 0x0777 0xe005   16      0  "Ubiquiti" "NanoStation M5"
++ 0x168c 0x002a 0x0777 0xe202   12      0  "Ubiquiti" "Bullet M2"
++ 0x168c 0x002a 0x0777 0xe805    5      0  "Ubiquiti" "Bullet M5"
++ 0x168c 0x002a 0x0777 0xe345    0      0  "Ubiquiti" "WispStation M5" /* ToDo: confirm offset */

+ 0 - 43
patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch

@@ -1,43 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sun, 11 Jan 2015 09:14:34 +0100
-Subject: firmware-utils: remove dependency on error.h in tplink-safeloader
-
-Fixes build on Mac OS X
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c
-index 23d703f..9c5bb54 100644
---- a/tools/firmware-utils/src/tplink-safeloader.c
-+++ b/tools/firmware-utils/src/tplink-safeloader.c
-@@ -34,7 +34,6 @@
- 
- #include <assert.h>
- #include <errno.h>
--#include <error.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdint.h>
-@@ -143,6 +142,14 @@ static const unsigned char cpe510_support_list[] =
- 	"CPE220(TP-LINK|UN|N300-2):1.0\r\n"
- 	"\r\n\xff";
- 
-+#define error(_ret, _errno, _str, ...)				\
-+	do {							\
-+		fprintf(stderr, _str ": %s\n", ## __VA_ARGS__,	\
-+			strerror(_errno));			\
-+		if (_ret)					\
-+			exit(_ret);				\
-+	} while (0)
-+
- 
- /** Allocates a new image partition */
- struct image_partition_entry alloc_image_partition(const char *name, size_t len) {
-@@ -200,6 +207,7 @@ struct image_partition_entry make_soft_version(uint32_t rev) {
- 	struct soft_version *s = (struct soft_version *)entry.data;
- 
- 	time_t t;
-+
- 	if (time(&t) == (time_t)(-1))
- 		error(1, errno, "time");
- 

+ 0 - 28
patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch

@@ -1,28 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Fri, 16 Jan 2015 03:49:40 +0100
-Subject: build: explicitly unexport CONFIG_SITE
-
-On systems with CONFIG_SITE in the environment (e.g. OpenSUSE) make will export
-the CONFIG_SITE set in include/package.mk by default. This will cause host
-builds to get the target site configuration, leading to all kinds of weirdness
-(wrong pointer size, wrong endianess).
-
-Fix this by explicitly unexporting CONFIG_SITE. The explicit export for the
-target builds overrides the unexport, so the target builds will still correctly
-get the site config.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/include/package.mk b/include/package.mk
-index 88ec3ef..53ca6de 100644
---- a/include/package.mk
-+++ b/include/package.mk
-@@ -93,7 +93,7 @@ CONFIG_SITE:=$(INCLUDE_DIR)/site/$(REAL_GNU_TARGET_NAME)
- CUR_MAKEFILE:=$(filter-out Makefile,$(firstword $(MAKEFILE_LIST)))
- SUBMAKE:=$(NO_TRACE_MAKE) $(if $(CUR_MAKEFILE),-f $(CUR_MAKEFILE))
- PKG_CONFIG_PATH=$(STAGING_DIR)/usr/lib/pkgconfig:$(STAGING_DIR)/usr/share/pkgconfig
--unexport QUIET
-+unexport QUIET CONFIG_SITE
- 
- ifeq ($(DUMP)$(filter prereq clean refresh update,$(MAKECMDGOALS)),)
-   ifneq ($(if $(QUILT),,$(CONFIG_AUTOREBUILD)),)

+ 0 - 20
patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch

@@ -1,20 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Fri, 16 Jan 2015 19:56:39 +0100
-Subject: ar71xx: fix board detection for TP-LINK TL-WA860RE
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 79b6073..13c5bf2 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -630,6 +630,9 @@ ar71xx_board_detect() {
- 	*TL-WA850RE)
- 		name="tl-wa850re"
- 		;;
-+	*TL-WA860RE)
-+		name="tl-wa860re"
-+		;;
- 	*"TL-WA830RE v2")
- 		name="tl-wa830re-v2"
- 		;;

+ 0 - 25
patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch

@@ -1,25 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 28 Jan 2015 15:02:54 +0100
-Subject: ar71xx: add default LED configuration for D-Link DIR-615 rev. C1
-
-This patch adds an entry in the uci-defaults' led-file to configure the
-WAN and WLAN LEDs by default.
-
-Signed-off-by: Vincent Wiemann <me@bibbl.com>
-
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index 2676b48..ee90c52 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -122,6 +122,11 @@ dir-615-e4)
- 	ucidef_set_led_switch "lan4" "LAN4" "d-link:green:lan4" "switch0" "0x10"
- 	;;
- 
-+dir-615-c1)
-+	ucidef_set_led_netdev "wan" "WAN" "d-link:green:wan" "eth1"
-+	ucidef_set_led_wlan "wlan" "WLAN" "d-link:green:wlan" "phy0tpt"
-+	;;
-+
- dir-825-b1)
- 	ucidef_set_led_usbdev "usb" "USB" "d-link:blue:usb" "1-1"
- 	;;

+ 0 - 42
patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch

@@ -1,42 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 28 Jan 2015 14:56:03 +0100
-Subject: ar71xx: fix D-Link DIR-615 rev. C1 WLAN MAC address
-
-Fix the WLAN MAC address to match the one printed on the label by using the
-correct address from the ART instead of the address of the LAN interface.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c
-index 425be30..e55a43f 100644
---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c
-+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-dir-615-c1.c
-@@ -38,6 +38,8 @@
- #define DIR_615C1_CONFIG_ADDR		0x1f020000
- #define DIR_615C1_CONFIG_SIZE		0x10000
- 
-+#define DIR_615C1_WLAN_MAC_ADDR		0x1f3fffb4
-+
- static struct gpio_led dir_615c1_leds_gpio[] __initdata = {
- 	{
- 		.name		= "d-link:orange:status",
-@@ -96,16 +98,16 @@ static void __init dir_615c1_setup(void)
- {
- 	const char *config = (char *) KSEG1ADDR(DIR_615C1_CONFIG_ADDR);
- 	u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000);
--	u8 mac[6];
--	u8 *wlan_mac = NULL;
-+	u8 mac[ETH_ALEN], wlan_mac[ETH_ALEN];
- 
- 	if (ath79_nvram_parse_mac_addr(config, DIR_615C1_CONFIG_SIZE,
- 				       "lan_mac=", mac) == 0) {
- 		ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0);
- 		ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1);
--		wlan_mac = mac;
- 	}
- 
-+	ath79_parse_ascii_mac((char *) KSEG1ADDR(DIR_615C1_WLAN_MAC_ADDR), wlan_mac);
-+
- 	ath79_register_mdio(0, DIR_615C1_MDIO_MASK);
- 
- 	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII;

+ 0 - 229
patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch

@@ -1,229 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 3 Feb 2015 16:54:22 +0100
-Subject: Add support for the TP-LINK TL-WR941ND v5
-
-This device is very similar to the TL-WR841N v8, only two LED GPIOs are
-different.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh
-index 924766d..f0d5d70 100755
---- a/target/linux/ar71xx/base-files/etc/diag.sh
-+++ b/target/linux/ar71xx/base-files/etc/diag.sh
-@@ -214,7 +214,8 @@ get_status_led() {
- 	tl-wr841n-v8 | \
- 	tl-wa830re-v2 | \
- 	tl-wr842n-v2 | \
--	tl-wr941nd)
-+	tl-wr941nd | \
-+	tl-wr941nd-v5)
- 		status_led="tp-link:green:system"
- 		;;
- 	archer-c5 | \
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index ee90c52..a74b8f4 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -345,7 +345,8 @@ tl-wr741nd-v4)
- 	ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt"
- 	;;
- 
--tl-wr841n-v8)
-+tl-wr841n-v8 | \
-+tl-wr941nd-v5)
- 	ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth0"
- 	ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x04"
- 	ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08"
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-index c494310..3ccb917 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network
-@@ -211,6 +211,7 @@ smart-300 | \
- tl-mr3420-v2 |\
- tl-wr841n-v8 |\
- tl-wr842n-v2 |\
-+tl-wr941nd-v5 |\
- wnr2000-v3 |\
- wnr2200 |\
- wnr612-v2)
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 13c5bf2..5fbca92 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -681,6 +681,9 @@ ar71xx_board_detect() {
- 	*TL-WR941ND)
- 		name="tl-wr941nd"
- 		;;
-+	*"TL-WR941N/ND v5")
-+		name="tl-wr941nd-v5"
-+		;;
- 	*"TL-WR703N v1")
- 		name="tl-wr703n"
- 		;;
-diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-index a566b62..e512f41 100755
---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-@@ -326,6 +326,7 @@ platform_check_image() {
- 	tl-wr841n-v9 | \
- 	tl-wr842n-v2 | \
- 	tl-wr941nd | \
-+	tl-wr941nd-v5 | \
- 	tl-wr1041n-v2 | \
- 	tl-wr1043nd | \
- 	tl-wr1043nd-v2 | \
-diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c
-index 0099b15..73cfdd9 100644
---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c
-+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr841n-v8.c
-@@ -38,6 +38,15 @@
- #define TL_MR3420V2_GPIO_LED_3G	11
- #define TL_MR3420V2_GPIO_USB_POWER	4
- 
-+#define TL_WR941NDV5_GPIO_LED_WLAN	13
-+#define TL_WR941NDV5_GPIO_LED_QSS	15
-+#define TL_WR941NDV5_GPIO_LED_WAN	18
-+#define TL_WR941NDV5_GPIO_LED_LAN1	19
-+#define TL_WR941NDV5_GPIO_LED_LAN2	20
-+#define TL_WR941NDV5_GPIO_LED_LAN3	2
-+#define TL_WR941NDV5_GPIO_LED_LAN4	3
-+#define TL_WR941NDV5_GPIO_LED_SYSTEM	14
-+
- #define TL_WR841NV8_KEYS_POLL_INTERVAL	20	/* msecs */
- #define TL_WR841NV8_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR841NV8_KEYS_POLL_INTERVAL)
- 
-@@ -127,6 +136,42 @@ static struct gpio_keys_button tl_mr3420v2_gpio_keys[] __initdata = {
- 	}
- };
- 
-+static struct gpio_led tl_wr941nd_v5_leds_gpio[] __initdata = {
-+	{
-+		.name		= "tp-link:green:lan1",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_LAN1,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:lan2",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_LAN2,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:lan3",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_LAN3,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:lan4",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_LAN4,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:qss",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_QSS,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:system",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_SYSTEM,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:wan",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_WAN,
-+		.active_low	= 1,
-+	}, {
-+		.name		= "tp-link:green:wlan",
-+		.gpio		= TL_WR941NDV5_GPIO_LED_WLAN,
-+		.active_low	= 1,
-+	},
-+};
-+
- static void __init tl_ap123_setup(void)
- {
- 	u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00);
-@@ -223,3 +268,19 @@ static void __init tl_mr3420v2_setup(void)
- 
- MIPS_MACHINE(ATH79_MACH_TL_MR3420_V2, "TL-MR3420-v2", "TP-LINK TL-MR3420 v2",
- 	     tl_mr3420v2_setup);
-+
-+
-+static void __init tl_wr941nd_v5_setup(void)
-+{
-+	tl_ap123_setup();
-+
-+	ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_v5_leds_gpio),
-+				 tl_wr941nd_v5_leds_gpio);
-+
-+	ath79_register_gpio_keys_polled(1, TL_WR841NV8_KEYS_POLL_INTERVAL,
-+					ARRAY_SIZE(tl_wr841n_v8_gpio_keys),
-+					tl_wr841n_v8_gpio_keys);
-+}
-+
-+MIPS_MACHINE(ATH79_MACH_TL_WR941ND_V5, "TL-WR941ND-v5", "TP-LINK TL-WR941N/ND v5",
-+	     tl_wr941nd_v5_setup);
-diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
-index 3fdaf47..ba16c7b 100644
---- a/target/linux/ar71xx/image/Makefile
-+++ b/target/linux/ar71xx/image/Makefile
-@@ -1242,6 +1242,7 @@ $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWA801NV2,tl-wa801nd-v2,TL-WA801
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWA850,tl-wa850re-v1,TL-WA850RE,ttyS0,115200,0x08500001,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWA860,tl-wa860re-v1,TL-WA860RE,ttyS0,115200,0x08600001,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWA901NV3,tl-wa901nd-v3,TL-WA901ND-v3,ttyS0,115200,0x09010003,1,4Mlzma))
-+$(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWR941NV5,tl-wr941nd-v5,TL-WR941ND-v5,ttyS0,115200,0x09410005,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWR941NV6,tl-wr941nd-v6,TL-WDR3500,ttyS0,115200,0x09410006,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWR1041,tl-wr1041n-v2,TL-WR1041N-v2,ttyS0,115200,0x10410002,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLWR1043V2,tl-wr1043nd-v2,TL-WR1043ND-v2,ttyS0,115200,0x10430002,1,8M))
-@@ -1319,7 +1320,7 @@ $(eval $(call MultiProfile,TLWR741,TLWR741NV1 TLWR741NV2 TLWR741NV4))
- $(eval $(call MultiProfile,TLWR743,TLWR743NV1 TLWR743NV2))
- $(eval $(call MultiProfile,TLWR841,TLWR841NV15 TLWR841NV3 TLWR841NV5 TLWR841NV7 TLWR841NV8 TLWR841NV9))
- $(eval $(call MultiProfile,TLWR842,TLWR842V1 TLWR842V2))
--$(eval $(call MultiProfile,TLWR941,TLWR941NV2 TLWR941NV3 TLWR941NV4 TLWR941NV6))
-+$(eval $(call MultiProfile,TLWR941,TLWR941NV2 TLWR941NV3 TLWR941NV4 TLWR941NV5 TLWR941NV6))
- $(eval $(call MultiProfile,TLWR1043,TLWR1043V1 TLWR1043V2))
- $(eval $(call MultiProfile,TLWDR4300,TLWDR3500V1 TLWDR3600V1 TLWDR4300V1 TLWDR4300V1IL TLWDR4310V1 MW4530RV1))
- $(eval $(call MultiProfile,TUBE2H,TUBE2H8M TUBE2H16M))
-diff --git a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-index 516d52d..3722519 100644
---- a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-+++ b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-@@ -1,6 +1,6 @@
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -16,22 +16,145 @@
-+@@ -16,22 +16,146 @@
-  
-  enum ath79_mach_type {
-  	ATH79_MACH_GENERIC = 0,
-@@ -108,6 +108,7 @@
- +	ATH79_MACH_TL_WR841N_V8,	/* TP-LINK TL-WR841N/ND v8 */
- +	ATH79_MACH_TL_WR842N_V2,	/* TP-LINK TL-WR842N/ND v2 */
- +	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
-++	ATH79_MACH_TL_WR941ND_V5,	/* TP-LINK TL-WR941ND v5 */
-  	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-  	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
- +	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
-diff --git a/target/linux/ar71xx/patches-3.10/720-MIPS-ath79-add-Tube2H-support.patch b/target/linux/ar71xx/patches-3.10/720-MIPS-ath79-add-Tube2H-support.patch
-index c4aa70c..7a3754b 100644
---- a/target/linux/ar71xx/patches-3.10/720-MIPS-ath79-add-Tube2H-support.patch
-+++ b/target/linux/ar71xx/patches-3.10/720-MIPS-ath79-add-Tube2H-support.patch
-@@ -1,13 +1,13 @@
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -141,6 +141,7 @@ enum ath79_mach_type {
-- 	ATH79_MACH_TL_WR841N_V9,	/* TP-LINK TL-WR841N/ND v9 */
-+@@ -143,6 +143,7 @@ enum ath79_mach_type {
-  	ATH79_MACH_TL_WR842N_V2,	/* TP-LINK TL-WR842N/ND v2 */
-  	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
-+ 	ATH79_MACH_TL_WR941ND_V5,	/* TP-LINK TL-WR941ND v5 */
- +	ATH79_MACH_TUBE2H,		/* Alfa Network Tube2H */
-  	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-  	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
-- 	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
-+ 	ATH79_MACH_UBNT_LOCO_M_XW, 	/* Ubiquiti Loco M XW */
- --- a/arch/mips/ath79/Kconfig
- +++ b/arch/mips/ath79/Kconfig
- @@ -29,6 +29,15 @@ config ATH79_MACH_ALFA_NX
-@@ -28,7 +28,7 @@
-  	select SOC_AR724X
- --- a/arch/mips/ath79/Makefile
- +++ b/arch/mips/ath79/Makefile
--@@ -116,6 +116,7 @@ obj-$(CONFIG_ATH79_MACH_TL_WR1043ND_V2)
-+@@ -117,6 +117,7 @@ obj-$(CONFIG_ATH79_MACH_TL_WR1043ND_V2)
-  obj-$(CONFIG_ATH79_MACH_TL_WR2543N)	+= mach-tl-wr2543n.o
-  obj-$(CONFIG_ATH79_MACH_TL_WR703N)	+= mach-tl-wr703n.o
-  obj-$(CONFIG_ATH79_MACH_TL_WR720N_V3)	+= mach-tl-wr720n-v3.o

+ 0 - 177
patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch

@@ -1,177 +0,0 @@
-From: blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>
-Date: Thu, 22 Jan 2015 09:35:46 +0000
-Subject: ar71xx: add support for the UniFi AP Outdoor Plus
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh
-index f0d5d70..6aac86a 100755
---- a/target/linux/ar71xx/base-files/etc/diag.sh
-+++ b/target/linux/ar71xx/base-files/etc/diag.sh
-@@ -244,6 +244,9 @@ get_status_led() {
- 	uap-pro)
- 		status_led="ubnt:white:dome"
- 		;;
-+	unifi-outdoor-plus)
-+		status_led="ubnt:white:front"
-+		;;
- 	airgateway)
- 		status_led="ubnt:white:status"
- 		;;
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 5fbca92..61a7936 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -723,6 +723,9 @@ ar71xx_board_detect() {
- 	*"UniFiAP Outdoor")
- 		name="unifi-outdoor"
- 		;;
-+	*"UniFiAP Outdoor+")
-+		name="unifi-outdoor-plus"
-+		;;
- 	*WP543)
- 		name="wp543"
- 		;;
-diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-index e512f41..49746c4 100755
---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh
-@@ -363,6 +363,7 @@ platform_check_image() {
- 		return 1
- 		;;
- 
-+	unifi-outdoor-plus | \
- 	uap-pro)
- 		[ "$magic_long" != "19852003" ] && {
- 			echo "Invalid image type."
-@@ -467,6 +468,7 @@ platform_do_upgrade() {
- 	om5p)
- 		platform_do_upgrade_openmesh "$ARGV"
- 		;;
-+	unifi-outdoor-plus | \
- 	uap-pro)
- 		MTD_CONFIG_ARGS="-s 0x180000"
- 		default_do_upgrade "$ARGV"
-diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
-index ba16c7b..8505ac4 100644
---- a/target/linux/ar71xx/image/Makefile
-+++ b/target/linux/ar71xx/image/Makefile
-@@ -1262,6 +1262,7 @@ $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,SMART-300,smart-300,SMART-300,tty
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,OOLITE,oolite,GS-OOLITE,ttyATH0,115200,0x3C000101,1,16Mlzma))
- 
- $(eval $(call SingleProfile,UAPPRO,64k,UAPPRO,ubnt-uap-pro,UAP-PRO,ttyS0,115200,BZ,BZ,ar934x))
-+$(eval $(call SingleProfile,UAPPRO,64k,UBNTUNIFIOUTDOORPLUS,ubnt-unifi-outdoor-plus,UBNT-UOP,ttyS0,115200,BZ,BZ,ar7240))
- 
- $(eval $(call SingleProfile,UBDEV,64kraw,UBDEV01,ubdev01,UBNT-UF,ttyS0,115200,XM,XM,ar7240))
- 
-@@ -1324,7 +1325,7 @@ $(eval $(call MultiProfile,TLWR941,TLWR941NV2 TLWR941NV3 TLWR941NV4 TLWR941NV5 T
- $(eval $(call MultiProfile,TLWR1043,TLWR1043V1 TLWR1043V2))
- $(eval $(call MultiProfile,TLWDR4300,TLWDR3500V1 TLWDR3600V1 TLWDR4300V1 TLWDR4300V1IL TLWDR4310V1 MW4530RV1))
- $(eval $(call MultiProfile,TUBE2H,TUBE2H8M TUBE2H16M))
--$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTNANOM UBNTNANOMXW UBNTLOCOXW UBNTUNIFI UBNTUNIFIOUTDOOR UAPPRO UBNTAIRGW))
-+$(eval $(call MultiProfile,UBNT,UBNTAIRROUTER UBNTRS UBNTRSPRO UBNTLSSR71 UBNTBULLETM UBNTROCKETM UBNTNANOM UBNTNANOMXW UBNTLOCOXW UBNTUNIFI UBNTUNIFIOUTDOOR UBNTUNIFIOUTDOORPLUS UAPPRO UBNTAIRGW))
- $(eval $(call MultiProfile,WNDR3700,WNDR3700V1 WNDR3700V2 WNDR3800 WNDR3800CH WNDRMAC WNDRMACV2))
- $(eval $(call MultiProfile,WNR612V2,REALWNR612V2 N150R))
- $(eval $(call MultiProfile,WP543,WP543_2M WP543_4M WP543_8M WP543_16M))
-diff --git a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-index 3722519..6bb8884 100644
---- a/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-+++ b/target/linux/ar71xx/patches-3.10/610-MIPS-ath79-openwrt-machines.patch
-@@ -1,6 +1,6 @@
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -16,22 +16,146 @@
-+@@ -16,22 +16,147 @@
-  
-  enum ath79_mach_type {
-  	ATH79_MACH_GENERIC = 0,
-@@ -120,6 +120,7 @@
-  	ATH79_MACH_UBNT_UAP_PRO,	/* Ubiquiti UniFi AP Pro */
-  	ATH79_MACH_UBNT_UNIFI, 		/* Ubiquiti Unifi */
-  	ATH79_MACH_UBNT_UNIFI_OUTDOOR,	/* Ubiquiti UnifiAP Outdoor */
-++	ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, /* Ubiquiti UnifiAP Outdoor+ */
-  	ATH79_MACH_UBNT_XM,		/* Ubiquiti Networks XM board rev 1.0 */
- +	ATH79_MACH_WHR_G301N,		/* Buffalo WHR-G301N */
- +	ATH79_MACH_WHR_HP_G300N,	/* Buffalo WHR-HP-G300N */
-diff --git a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-index 5e3d4d4..3c3c273 100644
---- a/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-+++ b/target/linux/ar71xx/patches-3.10/616-MIPS-ath79-ubnt-xw.patch
-@@ -1,6 +1,65 @@
- --- a/arch/mips/ath79/mach-ubnt-xm.c
- +++ b/arch/mips/ath79/mach-ubnt-xm.c
--@@ -332,3 +332,78 @@ static void __init ubnt_uap_pro_setup(vo
-+@@ -186,6 +186,19 @@ static struct gpio_led ubnt_unifi_outdoo
-+ 	}
-+ };
-+ 
-++static struct gpio_led ubnt_unifi_outdoor_plus_leds_gpio[] __initdata = {
-++	{
-++		.name		= "ubnt:white:front",
-++		.gpio		= 1,
-++		.active_low	= 0,
-++	}, {
-++		.name		= "ubnt:blue:front",
-++		.gpio		= 0,
-++		.active_low	= 0,
-++	}
-++};
-++
-++
-+ static void __init ubnt_unifi_setup(void)
-+ {
-+ 	u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000);
-+@@ -245,6 +258,38 @@ MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI_OUTDO
-+ 	     "Ubiquiti UniFiAP Outdoor",
-+ 	     ubnt_unifi_outdoor_setup);
-+ 
-++
-++static void __init ubnt_unifi_outdoor_plus_setup(void)
-++{
-++	u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000);
-++	u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN);
-++	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
-++
-++	ath79_register_m25p80(NULL);
-++
-++	ath79_register_mdio(0, ~(UBNT_UNIFIOD_PRI_PHYMASK |
-++				 UBNT_UNIFIOD_2ND_PHYMASK));
-++
-++	ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0);
-++	ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0);
-++	ath79_register_eth(0);
-++	ath79_register_eth(1);
-++
-++	ap91_pci_init(ee, NULL);
-++
-++	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_plus_leds_gpio),
-++				 ubnt_unifi_outdoor_plus_leds_gpio);
-++
-++	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
-++					ARRAY_SIZE(ubnt_xm_gpio_keys),
-++					ubnt_xm_gpio_keys);
-++}
-++
-++MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, "UBNT-UOP",
-++	     "Ubiquiti UniFiAP Outdoor+",
-++	     ubnt_unifi_outdoor_plus_setup);
-++
-++
-+ static struct gpio_led ubnt_uap_pro_gpio_leds[] __initdata = {
-+ 	{
-+ 		.name		= "ubnt:white:dome",
-+@@ -332,3 +377,78 @@ static void __init ubnt_uap_pro_setup(vo
-  MIPS_MACHINE(ATH79_MACH_UBNT_UAP_PRO, "UAP-PRO", "Ubiquiti UniFi AP Pro",
-  	     ubnt_uap_pro_setup);
-  
-@@ -81,8 +140,8 @@
- +	     ubnt_loco_m_xw_setup);
- --- a/arch/mips/ath79/machtypes.h
- +++ b/arch/mips/ath79/machtypes.h
--@@ -121,9 +121,11 @@ enum ath79_mach_type {
-- 	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
-+@@ -123,9 +123,11 @@ enum ath79_mach_type {
-+ 	ATH79_MACH_TL_WR941ND_V5,	/* TP-LINK TL-WR941ND v5 */
-  	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
-  	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
- +	ATH79_MACH_UBNT_LOCO_M_XW, 	/* Ubiquiti Loco M XW */

+ 0 - 33655
patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch

@@ -1,33655 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 10 Mar 2015 12:40:53 +0100
-Subject: mac80211: update ath10k to compat-wireless-2015-03-05
-
-Taken from http://openwrt.reigndropsfall.net/
-
-diff --git a/package/kernel/mac80211/patches/917-mac80211-rx-reordering.patch b/package/kernel/mac80211/patches/917-mac80211-rx-reordering.patch
-new file mode 100644
-index 0000000..1d0c559
---- /dev/null
-+++ b/package/kernel/mac80211/patches/917-mac80211-rx-reordering.patch
-@@ -0,0 +1,271 @@
-+commit 08cf42e843f9a7e253502011c81677f61f7e5c42
-+Author: Michal Kazior <michal.kazior@tieto.com>
-+Date:   Wed Jul 16 12:12:15 2014 +0200
-+
-+    mac80211: add support for Rx reordering offloading
-+    
-+    Some drivers may be performing most of Tx/Rx
-+    aggregation on their own (e.g. in firmware)
-+    including AddBa/DelBa negotiations but may
-+    otherwise require Rx reordering assistance.
-+    
-+    The patch exports 2 new functions for establishing
-+    Rx aggregation sessions in assumption device
-+    driver has taken care of the necessary
-+    negotiations.
-+    
-+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-+    [fix endian bug]
-+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-+
-+--- a/include/net/mac80211.h
-++++ b/include/net/mac80211.h
-+@@ -4481,6 +4481,40 @@ void ieee80211_stop_rx_ba_session(struct
-+  */
-+ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
-+ 
-++/**
-++ * ieee80211_start_rx_ba_session_offl - start a Rx BA session
-++ *
-++ * Some device drivers may offload part of the Rx aggregation flow including
-++ * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
-++ * reordering.
-++ *
-++ * Create structures responsible for reordering so device drivers may call here
-++ * when they complete AddBa negotiation.
-++ *
-++ * @vif: &struct ieee80211_vif pointer from the add_interface callback
-++ * @addr: station mac address
-++ * @tid: the rx tid
-++ */
-++void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
-++					const u8 *addr, u16 tid);
-++
-++/**
-++ * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
-++ *
-++ * Some device drivers may offload part of the Rx aggregation flow including
-++ * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
-++ * reordering.
-++ *
-++ * Destroy structures responsible for reordering so device drivers may call here
-++ * when they complete DelBa negotiation.
-++ *
-++ * @vif: &struct ieee80211_vif pointer from the add_interface callback
-++ * @addr: station mac address
-++ * @tid: the rx tid
-++ */
-++void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
-++				       const u8 *addr, u16 tid);
-++
-+ /* Rate control API */
-+ 
-+ /**
-+--- a/net/mac80211/agg-rx.c
-++++ b/net/mac80211/agg-rx.c
-+@@ -224,28 +224,15 @@ static void ieee80211_send_addba_resp(st
-+ 	ieee80211_tx_skb(sdata, skb);
-+ }
-+ 
-+-void ieee80211_process_addba_request(struct ieee80211_local *local,
-+-				     struct sta_info *sta,
-+-				     struct ieee80211_mgmt *mgmt,
-+-				     size_t len)
-++void __ieee80211_start_rx_ba_session(struct sta_info *sta,
-++				     u8 dialog_token, u16 timeout,
-++				     u16 start_seq_num, u16 ba_policy, u16 tid,
-++				     u16 buf_size, bool tx)
-+ {
-++	struct ieee80211_local *local = sta->sdata->local;
-+ 	struct tid_ampdu_rx *tid_agg_rx;
-+-	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
-+-	u8 dialog_token;
-+ 	int ret = -EOPNOTSUPP;
-+-
-+-	/* extract session parameters from addba request frame */
-+-	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
-+-	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
-+-	start_seq_num =
-+-		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
-+-
-+-	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
-+-	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
-+-	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
-+-	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
-+-
-+-	status = WLAN_STATUS_REQUEST_DECLINED;
-++	u16 status = WLAN_STATUS_REQUEST_DECLINED;
-+ 
-+ 	if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
-+ 		ht_dbg(sta->sdata,
-+@@ -264,7 +251,7 @@ void ieee80211_process_addba_request(str
-+ 		status = WLAN_STATUS_INVALID_QOS_PARAM;
-+ 		ht_dbg_ratelimited(sta->sdata,
-+ 				   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
-+-				   mgmt->sa, tid, ba_policy, buf_size);
-++				   sta->sta.addr, tid, ba_policy, buf_size);
-+ 		goto end_no_lock;
-+ 	}
-+ 	/* determine default buffer size */
-+@@ -281,7 +268,7 @@ void ieee80211_process_addba_request(str
-+ 	if (sta->ampdu_mlme.tid_rx[tid]) {
-+ 		ht_dbg_ratelimited(sta->sdata,
-+ 				   "unexpected AddBA Req from %pM on tid %u\n",
-+-				   mgmt->sa, tid);
-++				   sta->sta.addr, tid);
-+ 
-+ 		/* delete existing Rx BA session on the same tid */
-+ 		___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
-+@@ -350,6 +337,74 @@ end:
-+ 	mutex_unlock(&sta->ampdu_mlme.mtx);
-+ 
-+ end_no_lock:
-+-	ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
-+-				  dialog_token, status, 1, buf_size, timeout);
-++	if (tx)
-++		ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
-++					  dialog_token, status, 1, buf_size,
-++					  timeout);
-++}
-++
-++void ieee80211_process_addba_request(struct ieee80211_local *local,
-++				     struct sta_info *sta,
-++				     struct ieee80211_mgmt *mgmt,
-++				     size_t len)
-++{
-++	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
-++	u8 dialog_token;
-++
-++	/* extract session parameters from addba request frame */
-++	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
-++	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
-++	start_seq_num =
-++		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
-++
-++	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
-++	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
-++	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
-++	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
-++
-++	__ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
-++					start_seq_num, ba_policy, tid,
-++					buf_size, true);
-++}
-++
-++void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
-++					const u8 *addr, u16 tid)
-++{
-++	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-++	struct ieee80211_local *local = sdata->local;
-++	struct ieee80211_rx_agg *rx_agg;
-++	struct sk_buff *skb = dev_alloc_skb(0);
-++
-++	if (unlikely(!skb))
-++		return;
-++
-++	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
-++	memcpy(&rx_agg->addr, addr, ETH_ALEN);
-++	rx_agg->tid = tid;
-++
-++	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
-++	skb_queue_tail(&sdata->skb_queue, skb);
-++	ieee80211_queue_work(&local->hw, &sdata->work);
-++}
-++EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);
-++
-++void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
-++				       const u8 *addr, u16 tid)
-++{
-++	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-++	struct ieee80211_local *local = sdata->local;
-++	struct ieee80211_rx_agg *rx_agg;
-++	struct sk_buff *skb = dev_alloc_skb(0);
-++
-++	if (unlikely(!skb))
-++		return;
-++
-++	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
-++	memcpy(&rx_agg->addr, addr, ETH_ALEN);
-++	rx_agg->tid = tid;
-++
-++	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
-++	skb_queue_tail(&sdata->skb_queue, skb);
-++	ieee80211_queue_work(&local->hw, &sdata->work);
-+ }
-++EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
-+--- a/net/mac80211/ieee80211_i.h
-++++ b/net/mac80211/ieee80211_i.h
-+@@ -902,10 +902,17 @@ ieee80211_vif_get_shift(struct ieee80211
-+ 	return shift;
-+ }
-+ 
-++struct ieee80211_rx_agg {
-++	u8 addr[ETH_ALEN];
-++	u16 tid;
-++};
-++
-+ enum sdata_queue_type {
-+ 	IEEE80211_SDATA_QUEUE_TYPE_FRAME	= 0,
-+ 	IEEE80211_SDATA_QUEUE_AGG_START		= 1,
-+ 	IEEE80211_SDATA_QUEUE_AGG_STOP		= 2,
-++	IEEE80211_SDATA_QUEUE_RX_AGG_START	= 3,
-++	IEEE80211_SDATA_QUEUE_RX_AGG_STOP	= 4,
-+ };
-+ 
-+ enum {
-+@@ -1554,6 +1561,10 @@ void ___ieee80211_stop_rx_ba_session(str
-+ 				     u16 initiator, u16 reason, bool stop);
-+ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
-+ 				    u16 initiator, u16 reason, bool stop);
-++void __ieee80211_start_rx_ba_session(struct sta_info *sta,
-++				     u8 dialog_token, u16 timeout,
-++				     u16 start_seq_num, u16 ba_policy, u16 tid,
-++				     u16 buf_size, bool tx);
-+ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
-+ 					 enum ieee80211_agg_stop_reason reason);
-+ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
-+--- a/net/mac80211/iface.c
-++++ b/net/mac80211/iface.c
-+@@ -1154,6 +1154,7 @@ static void ieee80211_iface_work(struct
-+ 	struct sk_buff *skb;
-+ 	struct sta_info *sta;
-+ 	struct ieee80211_ra_tid *ra_tid;
-++	struct ieee80211_rx_agg *rx_agg;
-+ 
-+ 	if (!ieee80211_sdata_running(sdata))
-+ 		return;
-+@@ -1181,6 +1182,34 @@ static void ieee80211_iface_work(struct
-+ 			ra_tid = (void *)&skb->cb;
-+ 			ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra,
-+ 						ra_tid->tid);
-++		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
-++			rx_agg = (void *)&skb->cb;
-++			mutex_lock(&local->sta_mtx);
-++			sta = sta_info_get_bss(sdata, rx_agg->addr);
-++			if (sta) {
-++				u16 last_seq;
-++
-++				last_seq = le16_to_cpu(
-++					sta->last_seq_ctrl[rx_agg->tid]);
-++
-++				__ieee80211_start_rx_ba_session(sta,
-++						0, 0,
-++						ieee80211_sn_inc(last_seq),
-++						1, rx_agg->tid,
-++						IEEE80211_MAX_AMPDU_BUF,
-++						false);
-++			}
-++			mutex_unlock(&local->sta_mtx);
-++		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
-++			rx_agg = (void *)&skb->cb;
-++			mutex_lock(&local->sta_mtx);
-++			sta = sta_info_get_bss(sdata, rx_agg->addr);
-++			if (sta)
-++				__ieee80211_stop_rx_ba_session(sta,
-++							rx_agg->tid,
-++							WLAN_BACK_RECIPIENT, 0,
-++							false);
-++			mutex_unlock(&local->sta_mtx);
-+ 		} else if (ieee80211_is_action(mgmt->frame_control) &&
-+ 			   mgmt->u.action.category == WLAN_CATEGORY_BACK) {
-+ 			int len = skb->len;
-diff --git a/package/kernel/mac80211/patches/918-ath-spectral-debugfs.patch b/package/kernel/mac80211/patches/918-ath-spectral-debugfs.patch
-new file mode 100644
-index 0000000..d0c1bbd
---- /dev/null
-+++ b/package/kernel/mac80211/patches/918-ath-spectral-debugfs.patch
-@@ -0,0 +1,192 @@
-+--- a/drivers/net/wireless/ath/ath9k/spectral.h
-++++ b/drivers/net/wireless/ath/ath9k/spectral.h
-+@@ -17,6 +17,8 @@
-+ #ifndef SPECTRAL_H
-+ #define SPECTRAL_H
-+ 
-++#include "../spectral_common.h"
-++
-+ /* enum spectral_mode:
-+  *
-+  * @SPECTRAL_DISABLED: spectral mode is disabled
-+@@ -54,8 +56,6 @@ struct ath_ht20_mag_info {
-+ 	u8 max_exp;
-+ } __packed;
-+ 
-+-#define SPECTRAL_HT20_NUM_BINS		56
-+-
-+ /* WARNING: don't actually use this struct! MAC may vary the amount of
-+  * data by -1/+2. This struct is for reference only.
-+  */
-+@@ -83,8 +83,6 @@ struct ath_ht20_40_mag_info {
-+ 	u8 max_exp;
-+ } __packed;
-+ 
-+-#define SPECTRAL_HT20_40_NUM_BINS		128
-+-
-+ /* WARNING: don't actually use this struct! MAC may vary the amount of
-+  * data. This struct is for reference only.
-+  */
-+@@ -125,71 +123,6 @@ static inline u8 spectral_bitmap_weight(
-+ 	return bins[0] & 0x3f;
-+ }
-+ 
-+-/* FFT sample format given to userspace via debugfs.
-+- *
-+- * Please keep the type/length at the front position and change
-+- * other fields after adding another sample type
-+- *
-+- * TODO: this might need rework when switching to nl80211-based
-+- * interface.
-+- */
-+-enum ath_fft_sample_type {
-+-	ATH_FFT_SAMPLE_HT20 = 1,
-+-	ATH_FFT_SAMPLE_HT20_40,
-+-};
-+-
-+-struct fft_sample_tlv {
-+-	u8 type;	/* see ath_fft_sample */
-+-	__be16 length;
-+-	/* type dependent data follows */
-+-} __packed;
-+-
-+-struct fft_sample_ht20 {
-+-	struct fft_sample_tlv tlv;
-+-
-+-	u8 max_exp;
-+-
-+-	__be16 freq;
-+-	s8 rssi;
-+-	s8 noise;
-+-
-+-	__be16 max_magnitude;
-+-	u8 max_index;
-+-	u8 bitmap_weight;
-+-
-+-	__be64 tsf;
-+-
-+-	u8 data[SPECTRAL_HT20_NUM_BINS];
-+-} __packed;
-+-
-+-struct fft_sample_ht20_40 {
-+-	struct fft_sample_tlv tlv;
-+-
-+-	u8 channel_type;
-+-	__be16 freq;
-+-
-+-	s8 lower_rssi;
-+-	s8 upper_rssi;
-+-
-+-	__be64 tsf;
-+-
-+-	s8 lower_noise;
-+-	s8 upper_noise;
-+-
-+-	__be16 lower_max_magnitude;
-+-	__be16 upper_max_magnitude;
-+-
-+-	u8 lower_max_index;
-+-	u8 upper_max_index;
-+-
-+-	u8 lower_bitmap_weight;
-+-	u8 upper_bitmap_weight;
-+-
-+-	u8 max_exp;
-+-
-+-	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-+-} __packed;
-+-
-+ void ath9k_spectral_init_debug(struct ath_softc *sc);
-+ void ath9k_spectral_deinit_debug(struct ath_softc *sc);
-+ 
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/spectral_common.h
-+@@ -0,0 +1,88 @@
-++/*
-++ * Copyright (c) 2013 Qualcomm Atheros, Inc.
-++ *
-++ * 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 SPECTRAL_COMMON_H
-++#define SPECTRAL_COMMON_H
-++
-++#define SPECTRAL_HT20_NUM_BINS		56
-++#define SPECTRAL_HT20_40_NUM_BINS		128
-++
-++/* FFT sample format given to userspace via debugfs.
-++ *
-++ * Please keep the type/length at the front position and change
-++ * other fields after adding another sample type
-++ *
-++ * TODO: this might need rework when switching to nl80211-based
-++ * interface.
-++ */
-++enum ath_fft_sample_type {
-++	ATH_FFT_SAMPLE_HT20 = 1,
-++	ATH_FFT_SAMPLE_HT20_40,
-++};
-++
-++struct fft_sample_tlv {
-++	u8 type;	/* see ath_fft_sample */
-++	__be16 length;
-++	/* type dependent data follows */
-++} __packed;
-++
-++struct fft_sample_ht20 {
-++	struct fft_sample_tlv tlv;
-++
-++	u8 max_exp;
-++
-++	__be16 freq;
-++	s8 rssi;
-++	s8 noise;
-++
-++	__be16 max_magnitude;
-++	u8 max_index;
-++	u8 bitmap_weight;
-++
-++	__be64 tsf;
-++
-++	u8 data[SPECTRAL_HT20_NUM_BINS];
-++} __packed;
-++
-++struct fft_sample_ht20_40 {
-++	struct fft_sample_tlv tlv;
-++
-++	u8 channel_type;
-++	__be16 freq;
-++
-++	s8 lower_rssi;
-++	s8 upper_rssi;
-++
-++	__be64 tsf;
-++
-++	s8 lower_noise;
-++	s8 upper_noise;
-++
-++	__be16 lower_max_magnitude;
-++	__be16 upper_max_magnitude;
-++
-++	u8 lower_max_index;
-++	u8 upper_max_index;
-++
-++	u8 lower_bitmap_weight;
-++	u8 upper_bitmap_weight;
-++
-++	u8 max_exp;
-++
-++	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-++} __packed;
-++
-++#endif /* SPECTRAL_COMMON_H */
-diff --git a/package/kernel/mac80211/patches/919-update-ath10k.patch b/package/kernel/mac80211/patches/919-update-ath10k.patch
-new file mode 100644
-index 0000000..45fccb8
---- /dev/null
-+++ b/package/kernel/mac80211/patches/919-update-ath10k.patch
-@@ -0,0 +1,33023 @@
-+--- a/drivers/net/wireless/ath/ath10k/Kconfig
-++++ b/drivers/net/wireless/ath/ath10k/Kconfig
-+@@ -26,13 +26,15 @@ config ATH10K_DEBUG
-+ 
-+ config ATH10K_DEBUGFS
-+ 	bool "Atheros ath10k debugfs support"
-+-	depends on ATH10K
-++	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_TRACING
-++	depends on !KERNEL_3_4
-+ 	bool "Atheros ath10k tracing support"
-+ 	depends on ATH10K
-+ 	depends on EVENT_TRACING
-+--- a/drivers/net/wireless/ath/ath10k/Makefile
-++++ b/drivers/net/wireless/ath/ath10k/Makefile
-+@@ -8,9 +8,15 @@ ath10k_core-y += mac.o \
-+ 		 htt_tx.o \
-+ 		 txrx.o \
-+ 		 wmi.o \
-+-		 bmi.o
-++		 wmi-tlv.o \
-++		 bmi.o \
-++		 hw.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_MAC80211_DEBUGFS) += debugfs_sta.o
-+ 
-+ obj-$(CPTCFG_ATH10K_PCI) += ath10k_pci.o
-+ ath10k_pci-y += pci.o \
-+--- a/drivers/net/wireless/ath/ath10k/bmi.c
-++++ b/drivers/net/wireless/ath/ath10k/bmi.c
-+@@ -22,7 +22,7 @@
-+ 
-+ void ath10k_bmi_start(struct ath10k *ar)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi start\n");
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
-+ 
-+ 	ar->bmi.done_sent = false;
-+ }
-+@@ -33,10 +33,10 @@ int ath10k_bmi_done(struct ath10k *ar)
-+ 	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done);
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi done\n");
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi done\n");
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_dbg(ATH10K_DBG_BMI, "bmi skipped\n");
-++		ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi skipped\n");
-+ 		return 0;
-+ 	}
-+ 
-+@@ -45,7 +45,7 @@ int ath10k_bmi_done(struct ath10k *ar)
-+ 
-+ 	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
-+ 	if (ret) {
-+-		ath10k_warn("unable to write to the device: %d\n", ret);
-++		ath10k_warn(ar, "unable to write to the device: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+@@ -61,10 +61,10 @@ int ath10k_bmi_get_target_info(struct at
-+ 	u32 resplen = sizeof(resp.get_target_info);
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi get target info\n");
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi get target info\n");
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("BMI Get Target Info Command disallowed\n");
-++		ath10k_warn(ar, "BMI Get Target Info Command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -72,12 +72,12 @@ int ath10k_bmi_get_target_info(struct at
-+ 
-+ 	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
-+ 	if (ret) {
-+-		ath10k_warn("unable to get target info from device\n");
-++		ath10k_warn(ar, "unable to get target info from device\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (resplen < sizeof(resp.get_target_info)) {
-+-		ath10k_warn("invalid get_target_info response length (%d)\n",
-++		ath10k_warn(ar, "invalid get_target_info response length (%d)\n",
-+ 			    resplen);
-+ 		return -EIO;
-+ 	}
-+@@ -97,11 +97,11 @@ int ath10k_bmi_read_memory(struct ath10k
-+ 	u32 rxlen;
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi read address 0x%x length %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read address 0x%x length %d\n",
-+ 		   address, length);
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("command disallowed\n");
-++		ath10k_warn(ar, "command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -115,7 +115,7 @@ int ath10k_bmi_read_memory(struct ath10k
-+ 		ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
-+ 						  &resp, &rxlen);
-+ 		if (ret) {
-+-			ath10k_warn("unable to read from the device (%d)\n",
-++			ath10k_warn(ar, "unable to read from the device (%d)\n",
-+ 				    ret);
-+ 			return ret;
-+ 		}
-+@@ -137,11 +137,11 @@ int ath10k_bmi_write_memory(struct ath10
-+ 	u32 txlen;
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi write address 0x%x length %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi write address 0x%x length %d\n",
-+ 		   address, length);
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("command disallowed\n");
-++		ath10k_warn(ar, "command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -159,7 +159,7 @@ int ath10k_bmi_write_memory(struct ath10
-+ 		ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
-+ 						  NULL, NULL);
-+ 		if (ret) {
-+-			ath10k_warn("unable to write to the device (%d)\n",
-++			ath10k_warn(ar, "unable to write to the device (%d)\n",
-+ 				    ret);
-+ 			return ret;
-+ 		}
-+@@ -183,11 +183,11 @@ int ath10k_bmi_execute(struct ath10k *ar
-+ 	u32 resplen = sizeof(resp.execute);
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi execute address 0x%x param 0x%x\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi execute address 0x%x param 0x%x\n",
-+ 		   address, param);
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("command disallowed\n");
-++		ath10k_warn(ar, "command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -197,19 +197,19 @@ int ath10k_bmi_execute(struct ath10k *ar
-+ 
-+ 	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
-+ 	if (ret) {
-+-		ath10k_warn("unable to read from the device\n");
-++		ath10k_warn(ar, "unable to read from the device\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (resplen < sizeof(resp.execute)) {
-+-		ath10k_warn("invalid execute response length (%d)\n",
-++		ath10k_warn(ar, "invalid execute response length (%d)\n",
-+ 			    resplen);
-+ 		return -EIO;
-+ 	}
-+ 
-+ 	*result = __le32_to_cpu(resp.execute.result);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi execute result 0x%x\n", *result);
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi execute result 0x%x\n", *result);
-+ 
-+ 	return 0;
-+ }
-+@@ -221,11 +221,11 @@ int ath10k_bmi_lz_data(struct ath10k *ar
-+ 	u32 txlen;
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
-+ 		   buffer, length);
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("command disallowed\n");
-++		ath10k_warn(ar, "command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -241,7 +241,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar
-+ 		ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
-+ 						  NULL, NULL);
-+ 		if (ret) {
-+-			ath10k_warn("unable to write to the device\n");
-++			ath10k_warn(ar, "unable to write to the device\n");
-+ 			return ret;
-+ 		}
-+ 
-+@@ -258,11 +258,11 @@ int ath10k_bmi_lz_stream_start(struct at
-+ 	u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start);
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI, "bmi lz stream start address 0x%x\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz stream start address 0x%x\n",
-+ 		   address);
-+ 
-+ 	if (ar->bmi.done_sent) {
-+-		ath10k_warn("command disallowed\n");
-++		ath10k_warn(ar, "command disallowed\n");
-+ 		return -EBUSY;
-+ 	}
-+ 
-+@@ -271,7 +271,7 @@ int ath10k_bmi_lz_stream_start(struct at
-+ 
-+ 	ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
-+ 	if (ret) {
-+-		ath10k_warn("unable to Start LZ Stream to the device\n");
-++		ath10k_warn(ar, "unable to Start LZ Stream to the device\n");
-+ 		return ret;
-+ 	}
-+ 
-+@@ -286,7 +286,7 @@ int ath10k_bmi_fast_download(struct ath1
-+ 	u32 trailer_len = length - head_len;
-+ 	int ret;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BMI,
-++	ath10k_dbg(ar, ATH10K_DBG_BMI,
-+ 		   "bmi fast download address 0x%x buffer 0x%p length %d\n",
-+ 		   address, buffer, length);
-+ 
-+--- a/drivers/net/wireless/ath/ath10k/bmi.h
-++++ b/drivers/net/wireless/ath/ath10k/bmi.h
-+@@ -177,7 +177,6 @@ struct bmi_target_info {
-+ 	u32 type;
-+ };
-+ 
-+-
-+ /* in msec */
-+ #define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
-+ 
-+@@ -201,7 +200,8 @@ int ath10k_bmi_write_memory(struct ath10
-+ 									\
-+ 		addr = host_interest_item_address(HI_ITEM(item));	\
-+ 		ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \
-+-		*val = __le32_to_cpu(tmp);				\
-++		if (!ret)						\
-++			*val = __le32_to_cpu(tmp);			\
-+ 		ret;							\
-+ 	 })
-+ 
-+--- a/drivers/net/wireless/ath/ath10k/ce.c
-++++ b/drivers/net/wireless/ath/ath10k/ce.c
-+@@ -260,7 +260,6 @@ static inline void ath10k_ce_engine_int_
-+ 	ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
-+ }
-+ 
-+-
-+ /*
-+  * Guts of ath10k_ce_send, used by both ath10k_ce_send and
-+  * ath10k_ce_sendlist_send.
-+@@ -284,13 +283,9 @@ int ath10k_ce_send_nolock(struct ath10k_
-+ 	int ret = 0;
-+ 
-+ 	if (nbytes > ce_state->src_sz_max)
-+-		ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n",
-++		ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n",
-+ 			    __func__, nbytes, ce_state->src_sz_max);
-+ 
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return ret;
-+-
-+ 	if (unlikely(CE_RING_DELTA(nentries_mask,
-+ 				   write_index, sw_index - 1) <= 0)) {
-+ 		ret = -ENOSR;
-+@@ -325,10 +320,36 @@ int ath10k_ce_send_nolock(struct ath10k_
-+ 
-+ 	src_ring->write_index = write_index;
-+ exit:
-+-	ath10k_pci_sleep(ar);
-+ 	return ret;
-+ }
-+ 
-++void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
-++{
-++	struct ath10k *ar = pipe->ar;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_ce_ring *src_ring = pipe->src_ring;
-++	u32 ctrl_addr = pipe->ctrl_addr;
-++
-++	lockdep_assert_held(&ar_pci->ce_lock);
-++
-++	/*
-++	 * This function must be called only if there is an incomplete
-++	 * scatter-gather transfer (before index register is updated)
-++	 * that needs to be cleaned up.
-++	 */
-++	if (WARN_ON_ONCE(src_ring->write_index == src_ring->sw_index))
-++		return;
-++
-++	if (WARN_ON_ONCE(src_ring->write_index ==
-++			 ath10k_ce_src_ring_write_index_get(ar, ctrl_addr)))
-++		return;
-++
-++	src_ring->write_index--;
-++	src_ring->write_index &= src_ring->nentries_mask;
-++
-++	src_ring->per_transfer_context[src_ring->write_index] = NULL;
-++}
-++
-+ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
-+ 		   void *per_transfer_context,
-+ 		   u32 buffer,
-+@@ -363,49 +384,56 @@ int ath10k_ce_num_free_src_entries(struc
-+ 	return delta;
-+ }
-+ 
-+-int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
-+-			       void *per_recv_context,
-+-			       u32 buffer)
-++int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
-+ {
-+-	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
-+-	u32 ctrl_addr = ce_state->ctrl_addr;
-+-	struct ath10k *ar = ce_state->ar;
-++	struct ath10k *ar = pipe->ar;
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
-+ 	unsigned int nentries_mask = dest_ring->nentries_mask;
-+-	unsigned int write_index;
-+-	unsigned int sw_index;
-+-	int ret;
-++	unsigned int write_index = dest_ring->write_index;
-++	unsigned int sw_index = dest_ring->sw_index;
-+ 
-+-	spin_lock_bh(&ar_pci->ce_lock);
-+-	write_index = dest_ring->write_index;
-+-	sw_index = dest_ring->sw_index;
-++	lockdep_assert_held(&ar_pci->ce_lock);
-+ 
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		goto out;
-++	return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
-++}
-+ 
-+-	if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) {
-+-		struct ce_desc *base = dest_ring->base_addr_owner_space;
-+-		struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index);
-++int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
-++{
-++	struct ath10k *ar = pipe->ar;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
-++	unsigned int nentries_mask = dest_ring->nentries_mask;
-++	unsigned int write_index = dest_ring->write_index;
-++	unsigned int sw_index = dest_ring->sw_index;
-++	struct ce_desc *base = dest_ring->base_addr_owner_space;
-++	struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index);
-++	u32 ctrl_addr = pipe->ctrl_addr;
-+ 
-+-		/* Update destination descriptor */
-+-		desc->addr    = __cpu_to_le32(buffer);
-+-		desc->nbytes = 0;
-++	lockdep_assert_held(&ar_pci->ce_lock);
-+ 
-+-		dest_ring->per_transfer_context[write_index] =
-+-							per_recv_context;
-++	if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
-++		return -EIO;
-+ 
-+-		/* Update Destination Ring Write Index */
-+-		write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
-+-		ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
-+-		dest_ring->write_index = write_index;
-+-		ret = 0;
-+-	} else {
-+-		ret = -EIO;
-+-	}
-+-	ath10k_pci_sleep(ar);
-++	desc->addr = __cpu_to_le32(paddr);
-++	desc->nbytes = 0;
-++
-++	dest_ring->per_transfer_context[write_index] = ctx;
-++	write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
-++	ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
-++	dest_ring->write_index = write_index;
-++
-++	return 0;
-++}
-+ 
-+-out:
-++int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
-++{
-++	struct ath10k *ar = pipe->ar;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	int ret;
-++
-++	spin_lock_bh(&ar_pci->ce_lock);
-++	ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr);
-+ 	spin_unlock_bh(&ar_pci->ce_lock);
-+ 
-+ 	return ret;
-+@@ -415,12 +443,12 @@ out:
-+  * Guts of ath10k_ce_completed_recv_next.
-+  * The caller takes responsibility for any necessary locking.
-+  */
-+-static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-+-						void **per_transfer_contextp,
-+-						u32 *bufferp,
-+-						unsigned int *nbytesp,
-+-						unsigned int *transfer_idp,
-+-						unsigned int *flagsp)
-++int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-++					 void **per_transfer_contextp,
-++					 u32 *bufferp,
-++					 unsigned int *nbytesp,
-++					 unsigned int *transfer_idp,
-++					 unsigned int *flagsp)
-+ {
-+ 	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
-+ 	unsigned int nentries_mask = dest_ring->nentries_mask;
-+@@ -530,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct at
-+ 
-+ 		/* sanity */
-+ 		dest_ring->per_transfer_context[sw_index] = NULL;
-++		desc->nbytes = 0;
-+ 
-+ 		/* Update sw_index */
-+ 		sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
-+@@ -548,11 +577,11 @@ int ath10k_ce_revoke_recv_next(struct at
-+  * Guts of ath10k_ce_completed_send_next.
-+  * The caller takes responsibility for any necessary locking.
-+  */
-+-static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-+-						void **per_transfer_contextp,
-+-						u32 *bufferp,
-+-						unsigned int *nbytesp,
-+-						unsigned int *transfer_idp)
-++int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-++					 void **per_transfer_contextp,
-++					 u32 *bufferp,
-++					 unsigned int *nbytesp,
-++					 unsigned int *transfer_idp)
-+ {
-+ 	struct ath10k_ce_ring *src_ring = ce_state->src_ring;
-+ 	u32 ctrl_addr = ce_state->ctrl_addr;
-+@@ -561,7 +590,6 @@ static int ath10k_ce_completed_send_next
-+ 	unsigned int sw_index = src_ring->sw_index;
-+ 	struct ce_desc *sdesc, *sbase;
-+ 	unsigned int read_index;
-+-	int ret;
-+ 
-+ 	if (src_ring->hw_index == sw_index) {
-+ 		/*
-+@@ -572,20 +600,17 @@ static int ath10k_ce_completed_send_next
-+ 		 * value of the HW index has become stale.
-+ 		 */
-+ 
-+-		ret = ath10k_pci_wake(ar);
-+-		if (ret)
-+-			return ret;
-+-
-+-		src_ring->hw_index =
-+-			ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
-+-		src_ring->hw_index &= nentries_mask;
-++		read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
-++		if (read_index == 0xffffffff)
-++			return -ENODEV;
-+ 
-+-		ath10k_pci_sleep(ar);
-++		read_index &= nentries_mask;
-++		src_ring->hw_index = read_index;
-+ 	}
-+ 
-+ 	read_index = src_ring->hw_index;
-+ 
-+-	if ((read_index == sw_index) || (read_index == 0xffffffff))
-++	if (read_index == sw_index)
-+ 		return -EIO;
-+ 
-+ 	sbase = src_ring->shadow_base;
-+@@ -701,11 +726,6 @@ void ath10k_ce_per_engine_service(struct
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-+ 	u32 ctrl_addr = ce_state->ctrl_addr;
-+-	int ret;
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return;
-+ 
-+ 	spin_lock_bh(&ar_pci->ce_lock);
-+ 
-+@@ -730,7 +750,6 @@ void ath10k_ce_per_engine_service(struct
-+ 	ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
-+ 
-+ 	spin_unlock_bh(&ar_pci->ce_lock);
-+-	ath10k_pci_sleep(ar);
-+ }
-+ 
-+ /*
-+@@ -741,13 +760,9 @@ void ath10k_ce_per_engine_service(struct
-+ 
-+ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
-+ {
-+-	int ce_id, ret;
-++	int ce_id;
-+ 	u32 intr_summary;
-+ 
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return;
-+-
-+ 	intr_summary = CE_INTERRUPT_SUMMARY(ar);
-+ 
-+ 	for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
-+@@ -759,8 +774,6 @@ void ath10k_ce_per_engine_service_any(st
-+ 
-+ 		ath10k_ce_per_engine_service(ar, ce_id);
-+ 	}
-+-
-+-	ath10k_pci_sleep(ar);
-+ }
-+ 
-+ /*
-+@@ -770,16 +783,11 @@ void ath10k_ce_per_engine_service_any(st
-+  *
-+  * Called with ce_lock held.
-+  */
-+-static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
-+-						int disable_copy_compl_intr)
-++static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
-+ {
-+ 	u32 ctrl_addr = ce_state->ctrl_addr;
-+ 	struct ath10k *ar = ce_state->ar;
-+-	int ret;
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return;
-++	bool disable_copy_compl_intr = ce_state->attr_flags & CE_ATTR_DIS_INTR;
-+ 
-+ 	if ((!disable_copy_compl_intr) &&
-+ 	    (ce_state->send_cb || ce_state->recv_cb))
-+@@ -788,54 +796,33 @@ static void ath10k_ce_per_engine_handler
-+ 		ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
-+ 
-+ 	ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
-+-
-+-	ath10k_pci_sleep(ar);
-+ }
-+ 
-+ int ath10k_ce_disable_interrupts(struct ath10k *ar)
-+ {
-+-	int ce_id, ret;
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return ret;
-++	int ce_id;
-+ 
-+ 	for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-+-		u32 ctrl_addr = ath10k_ce_base_address(ce_id);
-++		u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-+ 
-+ 		ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
-+ 		ath10k_ce_error_intr_disable(ar, ctrl_addr);
-+ 		ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
-+ 	}
-+ 
-+-	ath10k_pci_sleep(ar);
-+-
-+ 	return 0;
-+ }
-+ 
-+-void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
-+-				void (*send_cb)(struct ath10k_ce_pipe *),
-+-				int disable_interrupts)
-++void ath10k_ce_enable_interrupts(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar = ce_state->ar;
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	int ce_id;
-+ 
-+-	spin_lock_bh(&ar_pci->ce_lock);
-+-	ce_state->send_cb = send_cb;
-+-	ath10k_ce_per_engine_handler_adjust(ce_state, disable_interrupts);
-+-	spin_unlock_bh(&ar_pci->ce_lock);
-+-}
-+-
-+-void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
-+-				void (*recv_cb)(struct ath10k_ce_pipe *))
-+-{
-+-	struct ath10k *ar = ce_state->ar;
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-
-+-	spin_lock_bh(&ar_pci->ce_lock);
-+-	ce_state->recv_cb = recv_cb;
-+-	ath10k_ce_per_engine_handler_adjust(ce_state, 0);
-+-	spin_unlock_bh(&ar_pci->ce_lock);
-++	/* Skip the last copy engine, CE7 the diagnostic window, as that
-++	 * uses polling and isn't initialized for interrupts.
-++	 */
-++	for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
-++		ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
-+ }
-+ 
-+ static int ath10k_ce_init_src_ring(struct ath10k *ar,
-+@@ -845,12 +832,12 @@ static int ath10k_ce_init_src_ring(struc
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-+ 	struct ath10k_ce_ring *src_ring = ce_state->src_ring;
-+-	u32 nentries, ctrl_addr = ath10k_ce_base_address(ce_id);
-++	u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-+ 
-+ 	nentries = roundup_pow_of_two(attr->src_nentries);
-+ 
-+-	memset(src_ring->per_transfer_context, 0,
-+-	       nentries * sizeof(*src_ring->per_transfer_context));
-++	memset(src_ring->base_addr_owner_space, 0,
-++	       nentries * sizeof(struct ce_desc));
-+ 
-+ 	src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
-+ 	src_ring->sw_index &= src_ring->nentries_mask;
-+@@ -868,7 +855,7 @@ static int ath10k_ce_init_src_ring(struc
-+ 	ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0);
-+ 	ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT,
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 		   "boot init ce src ring id %d entries %d base_addr %p\n",
-+ 		   ce_id, nentries, src_ring->base_addr_owner_space);
-+ 
-+@@ -882,12 +869,12 @@ static int ath10k_ce_init_dest_ring(stru
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-+ 	struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
-+-	u32 nentries, ctrl_addr = ath10k_ce_base_address(ce_id);
-++	u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-+ 
-+ 	nentries = roundup_pow_of_two(attr->dest_nentries);
-+ 
-+-	memset(dest_ring->per_transfer_context, 0,
-+-	       nentries * sizeof(*dest_ring->per_transfer_context));
-++	memset(dest_ring->base_addr_owner_space, 0,
-++	       nentries * sizeof(struct ce_desc));
-+ 
-+ 	dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
-+ 	dest_ring->sw_index &= dest_ring->nentries_mask;
-+@@ -902,7 +889,7 @@ static int ath10k_ce_init_dest_ring(stru
-+ 	ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0);
-+ 	ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT,
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 		   "boot ce dest ring id %d entries %d base_addr %p\n",
-+ 		   ce_id, nentries, dest_ring->base_addr_owner_space);
-+ 
-+@@ -1039,59 +1026,32 @@ ath10k_ce_alloc_dest_ring(struct ath10k
-+ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
-+ 			const struct ce_attr *attr)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-+ 	int ret;
-+ 
-+-	/*
-+-	 * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
-+-	 * additional TX locking checks.
-+-	 *
-+-	 * For the lack of a better place do the check here.
-+-	 */
-+-	BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
-+-		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-+-	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
-+-		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return ret;
-+-
-+-	spin_lock_bh(&ar_pci->ce_lock);
-+-	ce_state->ar = ar;
-+-	ce_state->id = ce_id;
-+-	ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
-+-	ce_state->attr_flags = attr->flags;
-+-	ce_state->src_sz_max = attr->src_sz_max;
-+-	spin_unlock_bh(&ar_pci->ce_lock);
-+-
-+ 	if (attr->src_nentries) {
-+ 		ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
-+ 		if (ret) {
-+-			ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
-++			ath10k_err(ar, "Failed to initialize CE src ring for ID: %d (%d)\n",
-+ 				   ce_id, ret);
-+-			goto out;
-++			return ret;
-+ 		}
-+ 	}
-+ 
-+ 	if (attr->dest_nentries) {
-+ 		ret = ath10k_ce_init_dest_ring(ar, ce_id, attr);
-+ 		if (ret) {
-+-			ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
-++			ath10k_err(ar, "Failed to initialize CE dest ring for ID: %d (%d)\n",
-+ 				   ce_id, ret);
-+-			goto out;
-++			return ret;
-+ 		}
-+ 	}
-+ 
-+-out:
-+-	ath10k_pci_sleep(ar);
-+-	return ret;
-++	return 0;
-+ }
-+ 
-+ static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id)
-+ {
-+-	u32 ctrl_addr = ath10k_ce_base_address(ce_id);
-++	u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-+ 
-+ 	ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, 0);
-+ 	ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0);
-+@@ -1101,7 +1061,7 @@ static void ath10k_ce_deinit_src_ring(st
-+ 
-+ static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id)
-+ {
-+-	u32 ctrl_addr = ath10k_ce_base_address(ce_id);
-++	u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-+ 
-+ 	ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, 0);
-+ 	ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0);
-+@@ -1110,30 +1070,49 @@ static void ath10k_ce_deinit_dest_ring(s
-+ 
-+ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
-+ {
-+-	int ret;
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret)
-+-		return;
-+-
-+ 	ath10k_ce_deinit_src_ring(ar, ce_id);
-+ 	ath10k_ce_deinit_dest_ring(ar, ce_id);
-+-
-+-	ath10k_pci_sleep(ar);
-+ }
-+ 
-+ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
-+-			 const struct ce_attr *attr)
-++			 const struct ce_attr *attr,
-++			 void (*send_cb)(struct ath10k_ce_pipe *),
-++			 void (*recv_cb)(struct ath10k_ce_pipe *))
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-+ 	int ret;
-+ 
-++	/*
-++	 * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
-++	 * additional TX locking checks.
-++	 *
-++	 * For the lack of a better place do the check here.
-++	 */
-++	BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
-++		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-++	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
-++		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-++	BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC >
-++		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-++
-++	ce_state->ar = ar;
-++	ce_state->id = ce_id;
-++	ce_state->ctrl_addr = ath10k_ce_base_address(ar, ce_id);
-++	ce_state->attr_flags = attr->flags;
-++	ce_state->src_sz_max = attr->src_sz_max;
-++
-++	if (attr->src_nentries)
-++		ce_state->send_cb = send_cb;
-++
-++	if (attr->dest_nentries)
-++		ce_state->recv_cb = recv_cb;
-++
-+ 	if (attr->src_nentries) {
-+ 		ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
-+ 		if (IS_ERR(ce_state->src_ring)) {
-+ 			ret = PTR_ERR(ce_state->src_ring);
-+-			ath10k_err("failed to allocate copy engine source ring %d: %d\n",
-++			ath10k_err(ar, "failed to allocate copy engine source ring %d: %d\n",
-+ 				   ce_id, ret);
-+ 			ce_state->src_ring = NULL;
-+ 			return ret;
-+@@ -1145,7 +1124,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *
-+ 								attr);
-+ 		if (IS_ERR(ce_state->dest_ring)) {
-+ 			ret = PTR_ERR(ce_state->dest_ring);
-+-			ath10k_err("failed to allocate copy engine destination ring %d: %d\n",
-++			ath10k_err(ar, "failed to allocate copy engine destination ring %d: %d\n",
-+ 				   ce_id, ret);
-+ 			ce_state->dest_ring = NULL;
-+ 			return ret;
-+--- a/drivers/net/wireless/ath/ath10k/ce.h
-++++ b/drivers/net/wireless/ath/ath10k/ce.h
-+@@ -20,7 +20,6 @@
-+ 
-+ #include "hif.h"
-+ 
-+-
-+ /* Maximum number of Copy Engine's supported */
-+ #define CE_COUNT_MAX 8
-+ #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
-+@@ -37,11 +36,10 @@
-+ 
-+ struct ath10k_ce_pipe;
-+ 
-+-
-+ #define CE_DESC_FLAGS_GATHER         (1 << 0)
-+ #define CE_DESC_FLAGS_BYTE_SWAP      (1 << 1)
-+ #define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
-+-#define CE_DESC_FLAGS_META_DATA_LSB  3
-++#define CE_DESC_FLAGS_META_DATA_LSB  2
-+ 
-+ struct ce_desc {
-+ 	__le32 addr;
-+@@ -160,30 +158,15 @@ int ath10k_ce_send_nolock(struct ath10k_
-+ 			  unsigned int transfer_id,
-+ 			  unsigned int flags);
-+ 
-+-void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
-+-				void (*send_cb)(struct ath10k_ce_pipe *),
-+-				int disable_interrupts);
-++void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe);
-+ 
-+ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
-+ 
-+ /*==================Recv=======================*/
-+ 
-+-/*
-+- * Make a buffer available to receive. The buffer must be at least of a
-+- * minimal size appropriate for this copy engine (src_sz_max attribute).
-+- *   ce                    - which copy engine to use
-+- *   per_transfer_recv_context  - context passed back to caller's recv_cb
-+- *   buffer                     - address of buffer in CE space
-+- * Returns 0 on success; otherwise an error status.
-+- *
-+- * Implemenation note: Pushes a buffer to Dest ring.
-+- */
-+-int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
-+-			       void *per_transfer_recv_context,
-+-			       u32 buffer);
-+-
-+-void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
-+-				void (*recv_cb)(struct ath10k_ce_pipe *));
-++int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
-++int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
-++int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
-+ 
-+ /* recv flags */
-+ /* Data is byte-swapped */
-+@@ -204,10 +187,16 @@ int ath10k_ce_completed_recv_next(struct
-+  * Pops 1 completed send buffer from Source ring.
-+  */
-+ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
-+-			   void **per_transfer_contextp,
-+-			   u32 *bufferp,
-+-			   unsigned int *nbytesp,
-+-			   unsigned int *transfer_idp);
-++				  void **per_transfer_contextp,
-++				  u32 *bufferp,
-++				  unsigned int *nbytesp,
-++				  unsigned int *transfer_idp);
-++
-++int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
-++					 void **per_transfer_contextp,
-++					 u32 *bufferp,
-++					 unsigned int *nbytesp,
-++					 unsigned int *transfer_idp);
-+ 
-+ /*==================CE Engine Initialization=======================*/
-+ 
-+@@ -215,7 +204,9 @@ int ath10k_ce_init_pipe(struct ath10k *a
-+ 			const struct ce_attr *attr);
-+ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
-+ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
-+-			  const struct ce_attr *attr);
-++			 const struct ce_attr *attr,
-++			 void (*send_cb)(struct ath10k_ce_pipe *),
-++			 void (*recv_cb)(struct ath10k_ce_pipe *));
-+ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
-+ 
-+ /*==================CE Engine Shutdown=======================*/
-+@@ -228,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct at
-+ 			       void **per_transfer_contextp,
-+ 			       u32 *bufferp);
-+ 
-++int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
-++					 void **per_transfer_contextp,
-++					 u32 *bufferp,
-++					 unsigned int *nbytesp,
-++					 unsigned int *transfer_idp,
-++					 unsigned int *flagsp);
-++
-+ /*
-+  * Support clean shutdown by allowing the caller to cancel
-+  * pending sends.  Target DMA must be stopped before using
-+@@ -243,6 +241,7 @@ int ath10k_ce_cancel_send_next(struct at
-+ void ath10k_ce_per_engine_service_any(struct ath10k *ar);
-+ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
-+ int ath10k_ce_disable_interrupts(struct ath10k *ar);
-++void ath10k_ce_enable_interrupts(struct ath10k *ar);
-+ 
-+ /* ce_attr.flags values */
-+ /* Use NonSnooping PCIe accesses? */
-+@@ -395,8 +394,7 @@ struct ce_attr {
-+ #define DST_WATERMARK_HIGH_RESET		0
-+ #define DST_WATERMARK_ADDRESS			0x0050
-+ 
-+-
-+-static inline u32 ath10k_ce_base_address(unsigned int ce_id)
-++static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
-+ {
-+ 	return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
-+ }
-+--- a/drivers/net/wireless/ath/ath10k/core.c
-++++ b/drivers/net/wireless/ath/ath10k/core.c
-+@@ -17,6 +17,7 @@
-+ 
-+ #include <linux/module.h>
-+ #include <linux/firmware.h>
-++#include <linux/of.h>
-+ 
-+ #include "core.h"
-+ #include "mac.h"
-+@@ -26,68 +27,88 @@
-+ #include "bmi.h"
-+ #include "debug.h"
-+ #include "htt.h"
-++#include "testmode.h"
-++#include "wmi-ops.h"
-+ 
-+ unsigned int ath10k_debug_mask;
-+ static bool uart_print;
-+-static unsigned int ath10k_p2p;
-++static bool skip_otp;
-++
-+ module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
-+ module_param(uart_print, bool, 0644);
-+-module_param_named(p2p, ath10k_p2p, uint, 0644);
-++module_param(skip_otp, bool, 0644);
-++
-+ MODULE_PARM_DESC(debug_mask, "Debugging mask");
-+ MODULE_PARM_DESC(uart_print, "Uart target debugging");
-+-MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
-++MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
-+ 
-+ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
-+ 	{
-+ 		.id = QCA988X_HW_2_0_VERSION,
-+ 		.name = "qca988x hw2.0",
-+ 		.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
-++		.uart_pin = 7,
-+ 		.fw = {
-+ 			.dir = QCA988X_HW_2_0_FW_DIR,
-+ 			.fw = QCA988X_HW_2_0_FW_FILE,
-+ 			.otp = QCA988X_HW_2_0_OTP_FILE,
-+ 			.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
-++			.board_size = QCA988X_BOARD_DATA_SZ,
-++			.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
-++		},
-++	},
-++	{
-++		.id = QCA6174_HW_2_1_VERSION,
-++		.name = "qca6174 hw2.1",
-++		.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
-++		.uart_pin = 6,
-++		.fw = {
-++			.dir = QCA6174_HW_2_1_FW_DIR,
-++			.fw = QCA6174_HW_2_1_FW_FILE,
-++			.otp = QCA6174_HW_2_1_OTP_FILE,
-++			.board = QCA6174_HW_2_1_BOARD_DATA_FILE,
-++			.board_size = QCA6174_BOARD_DATA_SZ,
-++			.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
-++		},
-++	},
-++	{
-++		.id = QCA6174_HW_3_0_VERSION,
-++		.name = "qca6174 hw3.0",
-++		.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
-++		.uart_pin = 6,
-++		.fw = {
-++			.dir = QCA6174_HW_3_0_FW_DIR,
-++			.fw = QCA6174_HW_3_0_FW_FILE,
-++			.otp = QCA6174_HW_3_0_OTP_FILE,
-++			.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
-++			.board_size = QCA6174_BOARD_DATA_SZ,
-++			.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
-++		},
-++	},
-++	{
-++		.id = QCA6174_HW_3_2_VERSION,
-++		.name = "qca6174 hw3.2",
-++		.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
-++		.uart_pin = 6,
-++		.fw = {
-++			/* uses same binaries as hw3.0 */
-++			.dir = QCA6174_HW_3_0_FW_DIR,
-++			.fw = QCA6174_HW_3_0_FW_FILE,
-++			.otp = QCA6174_HW_3_0_OTP_FILE,
-++			.board = QCA6174_HW_3_0_BOARD_DATA_FILE,
-++			.board_size = QCA6174_BOARD_DATA_SZ,
-++			.board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
-+ 		},
-+ 	},
-+ };
-+ 
-+ static void ath10k_send_suspend_complete(struct ath10k *ar)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot suspend complete\n");
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot suspend complete\n");
-+ 
-+ 	complete(&ar->target_suspend);
-+ }
-+ 
-+-static int ath10k_init_connect_htc(struct ath10k *ar)
-+-{
-+-	int status;
-+-
-+-	status = ath10k_wmi_connect_htc_service(ar);
-+-	if (status)
-+-		goto conn_fail;
-+-
-+-	/* Start HTC */
-+-	status = ath10k_htc_start(&ar->htc);
-+-	if (status)
-+-		goto conn_fail;
-+-
-+-	/* Wait for WMI event to be ready */
-+-	status = ath10k_wmi_wait_for_service_ready(ar);
-+-	if (status <= 0) {
-+-		ath10k_warn("wmi service ready event not received");
-+-		status = -ETIMEDOUT;
-+-		goto timeout;
-+-	}
-+-
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot wmi ready\n");
-+-	return 0;
-+-
-+-timeout:
-+-	ath10k_htc_stop(&ar->htc);
-+-conn_fail:
-+-	return status;
-+-}
-+-
-+ static int ath10k_init_configure_target(struct ath10k *ar)
-+ {
-+ 	u32 param_host;
-+@@ -97,14 +118,14 @@ static int ath10k_init_configure_target(
-+ 	ret = ath10k_bmi_write32(ar, hi_app_host_interest,
-+ 				 HTC_PROTOCOL_VERSION);
-+ 	if (ret) {
-+-		ath10k_err("settings HTC version failed\n");
-++		ath10k_err(ar, "settings HTC version failed\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* set the firmware mode to STA/IBSS/AP */
-+ 	ret = ath10k_bmi_read32(ar, hi_option_flag, &param_host);
-+ 	if (ret) {
-+-		ath10k_err("setting firmware mode (1/2) failed\n");
-++		ath10k_err(ar, "setting firmware mode (1/2) failed\n");
-+ 		return ret;
-+ 	}
-+ 
-+@@ -123,14 +144,14 @@ static int ath10k_init_configure_target(
-+ 
-+ 	ret = ath10k_bmi_write32(ar, hi_option_flag, param_host);
-+ 	if (ret) {
-+-		ath10k_err("setting firmware mode (2/2) failed\n");
-++		ath10k_err(ar, "setting firmware mode (2/2) failed\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* We do all byte-swapping on the host */
-+ 	ret = ath10k_bmi_write32(ar, hi_be, 0);
-+ 	if (ret) {
-+-		ath10k_err("setting host CPU BE mode failed\n");
-++		ath10k_err(ar, "setting host CPU BE mode failed\n");
-+ 		return ret;
-+ 	}
-+ 
-+@@ -138,7 +159,7 @@ static int ath10k_init_configure_target(
-+ 	ret = ath10k_bmi_write32(ar, hi_fw_swap, 0);
-+ 
-+ 	if (ret) {
-+-		ath10k_err("setting FW data/desc swap flags failed\n");
-++		ath10k_err(ar, "setting FW data/desc swap flags failed\n");
-+ 		return ret;
-+ 	}
-+ 
-+@@ -167,79 +188,83 @@ static const struct firmware *ath10k_fet
-+ 	return fw;
-+ }
-+ 
-+-static int ath10k_push_board_ext_data(struct ath10k *ar)
-++static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
-++				      size_t data_len)
-+ {
-+-	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
-+-	u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
-++	u32 board_data_size = ar->hw_params.fw.board_size;
-++	u32 board_ext_data_size = ar->hw_params.fw.board_ext_size;
-+ 	u32 board_ext_data_addr;
-+ 	int ret;
-+ 
-+ 	ret = ath10k_bmi_read32(ar, hi_board_ext_data, &board_ext_data_addr);
-+ 	if (ret) {
-+-		ath10k_err("could not read board ext data addr (%d)\n", ret);
-++		ath10k_err(ar, "could not read board ext data addr (%d)\n",
-++			   ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT,
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 		   "boot push board extended data addr 0x%x\n",
-+ 		   board_ext_data_addr);
-+ 
-+ 	if (board_ext_data_addr == 0)
-+ 		return 0;
-+ 
-+-	if (ar->board_len != (board_data_size + board_ext_data_size)) {
-+-		ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n",
-+-			   ar->board_len, board_data_size, board_ext_data_size);
-++	if (data_len != (board_data_size + board_ext_data_size)) {
-++		ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
-++			   data_len, board_data_size, board_ext_data_size);
-+ 		return -EINVAL;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
-+-				      ar->board_data + board_data_size,
-++				      data + board_data_size,
-+ 				      board_ext_data_size);
-+ 	if (ret) {
-+-		ath10k_err("could not write board ext data (%d)\n", ret);
-++		ath10k_err(ar, "could not write board ext data (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_write32(ar, hi_board_ext_data_config,
-+ 				 (board_ext_data_size << 16) | 1);
-+ 	if (ret) {
-+-		ath10k_err("could not write board ext data bit (%d)\n", ret);
-++		ath10k_err(ar, "could not write board ext data bit (%d)\n",
-++			   ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_download_board_data(struct ath10k *ar)
-++static int ath10k_download_board_data(struct ath10k *ar, const void *data,
-++				      size_t data_len)
-+ {
-+-	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
-++	u32 board_data_size = ar->hw_params.fw.board_size;
-+ 	u32 address;
-+ 	int ret;
-+ 
-+-	ret = ath10k_push_board_ext_data(ar);
-++	ret = ath10k_push_board_ext_data(ar, data, data_len);
-+ 	if (ret) {
-+-		ath10k_err("could not push board ext data (%d)\n", ret);
-++		ath10k_err(ar, "could not push board ext data (%d)\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_read32(ar, hi_board_data, &address);
-+ 	if (ret) {
-+-		ath10k_err("could not read board data addr (%d)\n", ret);
-++		ath10k_err(ar, "could not read board data addr (%d)\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+-	ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
-++	ret = ath10k_bmi_write_memory(ar, address, data,
-+ 				      min_t(u32, board_data_size,
-+-					    ar->board_len));
-++					    data_len));
-+ 	if (ret) {
-+-		ath10k_err("could not write board data (%d)\n", ret);
-++		ath10k_err(ar, "could not write board data (%d)\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
-+ 	if (ret) {
-+-		ath10k_err("could not write board data bit (%d)\n", ret);
-++		ath10k_err(ar, "could not write board data bit (%d)\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+@@ -247,73 +272,182 @@ exit:
-+ 	return ret;
-+ }
-+ 
-++static int ath10k_download_cal_file(struct ath10k *ar)
-++{
-++	int ret;
-++
-++	if (!ar->cal_file)
-++		return -ENOENT;
-++
-++	if (IS_ERR(ar->cal_file))
-++		return PTR_ERR(ar->cal_file);
-++
-++	ret = ath10k_download_board_data(ar, ar->cal_file->data,
-++					 ar->cal_file->size);
-++	if (ret) {
-++		ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
-++
-++	return 0;
-++}
-++
-++static int ath10k_download_cal_dt(struct ath10k *ar)
-++{
-++	struct device_node *node;
-++	int data_len;
-++	void *data;
-++	int ret;
-++
-++	node = ar->dev->of_node;
-++	if (!node)
-++		/* Device Tree is optional, don't print any warnings if
-++		 * there's no node for ath10k.
-++		 */
-++		return -ENOENT;
-++
-++	if (!of_get_property(node, "qcom,ath10k-calibration-data",
-++			     &data_len)) {
-++		/* The calibration data node is optional */
-++		return -ENOENT;
-++	}
-++
-++	if (data_len != QCA988X_CAL_DATA_LEN) {
-++		ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
-++			    data_len);
-++		ret = -EMSGSIZE;
-++		goto out;
-++	}
-++
-++	data = kmalloc(data_len, GFP_KERNEL);
-++	if (!data) {
-++		ret = -ENOMEM;
-++		goto out;
-++	}
-++
-++	ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
-++					data, data_len);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
-++			    ret);
-++		goto out_free;
-++	}
-++
-++	ret = ath10k_download_board_data(ar, data, data_len);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
-++			    ret);
-++		goto out_free;
-++	}
-++
-++	ret = 0;
-++
-++out_free:
-++	kfree(data);
-++
-++out:
-++	return ret;
-++}
-++
-+ static int ath10k_download_and_run_otp(struct ath10k *ar)
-+ {
-+ 	u32 result, address = ar->hw_params.patch_load_addr;
-+ 	int ret;
-+ 
-++	ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
-++	if (ret) {
-++		ath10k_err(ar, "failed to download board data: %d\n", ret);
-++		return ret;
-++	}
-++
-+ 	/* OTP is optional */
-+ 
-+ 	if (!ar->otp_data || !ar->otp_len) {
-+-		ath10k_warn("Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
-++		ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
-+ 			    ar->otp_data, ar->otp_len);
-+ 		return 0;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
-+ 		   address, ar->otp_len);
-+ 
-+ 	ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
-+ 	if (ret) {
-+-		ath10k_err("could not write otp (%d)\n", ret);
-++		ath10k_err(ar, "could not write otp (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_execute(ar, address, 0, &result);
-+ 	if (ret) {
-+-		ath10k_err("could not execute otp (%d)\n", ret);
-++		ath10k_err(ar, "could not execute otp (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-+ 
-+-	if (result != 0) {
-+-		ath10k_err("otp calibration failed: %d", result);
-++	if (!skip_otp && result != 0) {
-++		ath10k_err(ar, "otp calibration failed: %d", result);
-+ 		return -EINVAL;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_download_fw(struct ath10k *ar)
-++static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
-+ {
-+-	u32 address;
-++	u32 address, data_len;
-++	const char *mode_name;
-++	const void *data;
-+ 	int ret;
-+ 
-+ 	address = ar->hw_params.patch_load_addr;
-+ 
-+-	ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
-+-				       ar->firmware_len);
-++	switch (mode) {
-++	case ATH10K_FIRMWARE_MODE_NORMAL:
-++		data = ar->firmware_data;
-++		data_len = ar->firmware_len;
-++		mode_name = "normal";
-++		break;
-++	case ATH10K_FIRMWARE_MODE_UTF:
-++		data = ar->testmode.utf->data;
-++		data_len = ar->testmode.utf->size;
-++		mode_name = "utf";
-++		break;
-++	default:
-++		ath10k_err(ar, "unknown firmware mode: %d\n", mode);
-++		return -EINVAL;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-++		   "boot uploading firmware image %p len %d mode %s\n",
-++		   data, data_len, mode_name);
-++
-++	ret = ath10k_bmi_fast_download(ar, address, data, data_len);
-+ 	if (ret) {
-+-		ath10k_err("could not write fw (%d)\n", ret);
-+-		goto exit;
-++		ath10k_err(ar, "failed to download %s firmware: %d\n",
-++			   mode_name, ret);
-++		return ret;
-+ 	}
-+ 
-+-exit:
-+ 	return ret;
-+ }
-+ 
-+ static void ath10k_core_free_firmware_files(struct ath10k *ar)
-+ {
-+-	if (ar->board && !IS_ERR(ar->board))
-++	if (!IS_ERR(ar->board))
-+ 		release_firmware(ar->board);
-+ 
-+-	if (ar->otp && !IS_ERR(ar->otp))
-++	if (!IS_ERR(ar->otp))
-+ 		release_firmware(ar->otp);
-+ 
-+-	if (ar->firmware && !IS_ERR(ar->firmware))
-++	if (!IS_ERR(ar->firmware))
-+ 		release_firmware(ar->firmware);
-+ 
-++	if (!IS_ERR(ar->cal_file))
-++		release_firmware(ar->cal_file);
-++
-+ 	ar->board = NULL;
-+ 	ar->board_data = NULL;
-+ 	ar->board_len = 0;
-+@@ -325,6 +459,27 @@ static void ath10k_core_free_firmware_fi
-+ 	ar->firmware = NULL;
-+ 	ar->firmware_data = NULL;
-+ 	ar->firmware_len = 0;
-++
-++	ar->cal_file = NULL;
-++}
-++
-++static int ath10k_fetch_cal_file(struct ath10k *ar)
-++{
-++	char filename[100];
-++
-++	/* cal-<bus>-<id>.bin */
-++	scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
-++		  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
-++
-++	ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
-++	if (IS_ERR(ar->cal_file))
-++		/* calibration file is optional, don't print any warnings */
-++		return PTR_ERR(ar->cal_file);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
-++		   ATH10K_FW_DIR, filename);
-++
-++	return 0;
-+ }
-+ 
-+ static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
-+@@ -332,12 +487,12 @@ static int ath10k_core_fetch_firmware_ap
-+ 	int ret = 0;
-+ 
-+ 	if (ar->hw_params.fw.fw == NULL) {
-+-		ath10k_err("firmware file not defined\n");
-++		ath10k_err(ar, "firmware file not defined\n");
-+ 		return -EINVAL;
-+ 	}
-+ 
-+ 	if (ar->hw_params.fw.board == NULL) {
-+-		ath10k_err("board data file not defined");
-++		ath10k_err(ar, "board data file not defined");
-+ 		return -EINVAL;
-+ 	}
-+ 
-+@@ -346,7 +501,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 					 ar->hw_params.fw.board);
-+ 	if (IS_ERR(ar->board)) {
-+ 		ret = PTR_ERR(ar->board);
-+-		ath10k_err("could not fetch board data (%d)\n", ret);
-++		ath10k_err(ar, "could not fetch board data (%d)\n", ret);
-+ 		goto err;
-+ 	}
-+ 
-+@@ -358,7 +513,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 					    ar->hw_params.fw.fw);
-+ 	if (IS_ERR(ar->firmware)) {
-+ 		ret = PTR_ERR(ar->firmware);
-+-		ath10k_err("could not fetch firmware (%d)\n", ret);
-++		ath10k_err(ar, "could not fetch firmware (%d)\n", ret);
-+ 		goto err;
-+ 	}
-+ 
-+@@ -374,7 +529,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 				       ar->hw_params.fw.otp);
-+ 	if (IS_ERR(ar->otp)) {
-+ 		ret = PTR_ERR(ar->otp);
-+-		ath10k_err("could not fetch otp (%d)\n", ret);
-++		ath10k_err(ar, "could not fetch otp (%d)\n", ret);
-+ 		goto err;
-+ 	}
-+ 
-+@@ -394,12 +549,12 @@ static int ath10k_core_fetch_firmware_ap
-+ 	int ie_id, i, index, bit, ret;
-+ 	struct ath10k_fw_ie *hdr;
-+ 	const u8 *data;
-+-	__le32 *timestamp;
-++	__le32 *timestamp, *version;
-+ 
-+ 	/* first fetch the firmware file (firmware-*.bin) */
-+ 	ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
-+ 	if (IS_ERR(ar->firmware)) {
-+-		ath10k_err("could not fetch firmware file '%s/%s': %ld\n",
-++		ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
-+ 			   ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware));
-+ 		return PTR_ERR(ar->firmware);
-+ 	}
-+@@ -411,14 +566,14 @@ static int ath10k_core_fetch_firmware_ap
-+ 	magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
-+ 
-+ 	if (len < magic_len) {
-+-		ath10k_err("firmware file '%s/%s' too small to contain magic: %zu\n",
-++		ath10k_err(ar, "firmware file '%s/%s' too small to contain magic: %zu\n",
-+ 			   ar->hw_params.fw.dir, name, len);
-+ 		ret = -EINVAL;
-+ 		goto err;
-+ 	}
-+ 
-+ 	if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
-+-		ath10k_err("invalid firmware magic\n");
-++		ath10k_err(ar, "invalid firmware magic\n");
-+ 		ret = -EINVAL;
-+ 		goto err;
-+ 	}
-+@@ -440,7 +595,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 		data += sizeof(*hdr);
-+ 
-+ 		if (len < ie_len) {
-+-			ath10k_err("invalid length for FW IE %d (%zu < %zu)\n",
-++			ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
-+ 				   ie_id, len, ie_len);
-+ 			ret = -EINVAL;
-+ 			goto err;
-+@@ -454,7 +609,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 			memcpy(ar->hw->wiphy->fw_version, data, ie_len);
-+ 			ar->hw->wiphy->fw_version[ie_len] = '\0';
-+ 
-+-			ath10k_dbg(ATH10K_DBG_BOOT,
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 				   "found fw version %s\n",
-+ 				    ar->hw->wiphy->fw_version);
-+ 			break;
-+@@ -464,11 +619,11 @@ static int ath10k_core_fetch_firmware_ap
-+ 
-+ 			timestamp = (__le32 *)data;
-+ 
-+-			ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n",
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw timestamp %d\n",
-+ 				   le32_to_cpup(timestamp));
-+ 			break;
-+ 		case ATH10K_FW_IE_FEATURES:
-+-			ath10k_dbg(ATH10K_DBG_BOOT,
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 				   "found firmware features ie (%zd B)\n",
-+ 				   ie_len);
-+ 
-+@@ -480,19 +635,19 @@ static int ath10k_core_fetch_firmware_ap
-+ 					break;
-+ 
-+ 				if (data[index] & (1 << bit)) {
-+-					ath10k_dbg(ATH10K_DBG_BOOT,
-++					ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 						   "Enabling feature bit: %i\n",
-+ 						   i);
-+ 					__set_bit(i, ar->fw_features);
-+ 				}
-+ 			}
-+ 
-+-			ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "",
-++			ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "",
-+ 					ar->fw_features,
-+ 					sizeof(ar->fw_features));
-+ 			break;
-+ 		case ATH10K_FW_IE_FW_IMAGE:
-+-			ath10k_dbg(ATH10K_DBG_BOOT,
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 				   "found fw image ie (%zd B)\n",
-+ 				   ie_len);
-+ 
-+@@ -501,7 +656,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 
-+ 			break;
-+ 		case ATH10K_FW_IE_OTP_IMAGE:
-+-			ath10k_dbg(ATH10K_DBG_BOOT,
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 				   "found otp image ie (%zd B)\n",
-+ 				   ie_len);
-+ 
-+@@ -509,8 +664,19 @@ static int ath10k_core_fetch_firmware_ap
-+ 			ar->otp_len = ie_len;
-+ 
-+ 			break;
-++		case ATH10K_FW_IE_WMI_OP_VERSION:
-++			if (ie_len != sizeof(u32))
-++				break;
-++
-++			version = (__le32 *)data;
-++
-++			ar->wmi.op_version = le32_to_cpup(version);
-++
-++			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
-++				   ar->wmi.op_version);
-++			break;
-+ 		default:
-+-			ath10k_warn("Unknown FW IE: %u\n",
-++			ath10k_warn(ar, "Unknown FW IE: %u\n",
-+ 				    le32_to_cpu(hdr->id));
-+ 			break;
-+ 		}
-+@@ -523,7 +689,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 	}
-+ 
-+ 	if (!ar->firmware_data || !ar->firmware_len) {
-+-		ath10k_warn("No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
-++		ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
-+ 			    ar->hw_params.fw.dir, name);
-+ 		ret = -ENOMEDIUM;
-+ 		goto err;
-+@@ -531,7 +697,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 
-+ 	/* now fetch the board file */
-+ 	if (ar->hw_params.fw.board == NULL) {
-+-		ath10k_err("board data file not defined");
-++		ath10k_err(ar, "board data file not defined");
-+ 		ret = -EINVAL;
-+ 		goto err;
-+ 	}
-+@@ -541,7 +707,7 @@ static int ath10k_core_fetch_firmware_ap
-+ 					 ar->hw_params.fw.board);
-+ 	if (IS_ERR(ar->board)) {
-+ 		ret = PTR_ERR(ar->board);
-+-		ath10k_err("could not fetch board data '%s/%s' (%d)\n",
-++		ath10k_err(ar, "could not fetch board data '%s/%s' (%d)\n",
-+ 			   ar->hw_params.fw.dir, ar->hw_params.fw.board,
-+ 			   ret);
-+ 		goto err;
-+@@ -561,49 +727,79 @@ static int ath10k_core_fetch_firmware_fi
-+ {
-+ 	int ret;
-+ 
-++	/* calibration file is optional, don't check for any errors */
-++	ath10k_fetch_cal_file(ar);
-++
-++	ar->fw_api = 4;
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-++
-++	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE);
-++	if (ret == 0)
-++		goto success;
-++
-++	ar->fw_api = 3;
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-++
-++	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
-++	if (ret == 0)
-++		goto success;
-++
-+ 	ar->fw_api = 2;
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-+ 
-+ 	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
-+ 	if (ret == 0)
-+ 		goto success;
-+ 
-+ 	ar->fw_api = 1;
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-+ 
-+ 	ret = ath10k_core_fetch_firmware_api_1(ar);
-+ 	if (ret)
-+ 		return ret;
-+ 
-+ success:
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_init_download_firmware(struct ath10k *ar)
-++static int ath10k_download_cal_data(struct ath10k *ar)
-+ {
-+ 	int ret;
-+ 
-+-	ret = ath10k_download_board_data(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to download board data: %d\n", ret);
-+-		return ret;
-++	ret = ath10k_download_cal_file(ar);
-++	if (ret == 0) {
-++		ar->cal_mode = ATH10K_CAL_MODE_FILE;
-++		goto done;
-+ 	}
-+ 
-+-	ret = ath10k_download_and_run_otp(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to run otp: %d\n", ret);
-+-		return ret;
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-++		   "boot did not find a calibration file, try DT next: %d\n",
-++		   ret);
-++
-++	ret = ath10k_download_cal_dt(ar);
-++	if (ret == 0) {
-++		ar->cal_mode = ATH10K_CAL_MODE_DT;
-++		goto done;
-+ 	}
-+ 
-+-	ret = ath10k_download_fw(ar);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-++		   "boot did not find DT entry, try OTP next: %d\n",
-++		   ret);
-++
-++	ret = ath10k_download_and_run_otp(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to download firmware: %d\n", ret);
-++		ath10k_err(ar, "failed to run otp: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	return ret;
-++	ar->cal_mode = ATH10K_CAL_MODE_OTP;
-++
-++done:
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
-++		   ath10k_cal_mode_str(ar->cal_mode));
-++	return 0;
-+ }
-+ 
-+ static int ath10k_init_uart(struct ath10k *ar)
-+@@ -616,33 +812,33 @@ static int ath10k_init_uart(struct ath10
-+ 	 */
-+ 	ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);
-+ 	if (ret) {
-+-		ath10k_warn("could not disable UART prints (%d)\n", ret);
-++		ath10k_warn(ar, "could not disable UART prints (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (!uart_print)
-+ 		return 0;
-+ 
-+-	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
-++	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);
-+ 	if (ret) {
-+-		ath10k_warn("could not enable UART prints (%d)\n", ret);
-++		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);
-+ 	if (ret) {
-+-		ath10k_warn("could not enable UART prints (%d)\n", ret);
-++		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* Set the UART baud rate to 19200. */
-+ 	ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200);
-+ 	if (ret) {
-+-		ath10k_warn("could not set the baud rate (%d)\n", ret);
-++		ath10k_warn(ar, "could not set the baud rate (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ath10k_info("UART prints enabled\n");
-++	ath10k_info(ar, "UART prints enabled\n");
-+ 	return 0;
-+ }
-+ 
-+@@ -659,14 +855,14 @@ static int ath10k_init_hw_params(struct
-+ 	}
-+ 
-+ 	if (i == ARRAY_SIZE(ath10k_hw_params_list)) {
-+-		ath10k_err("Unsupported hardware version: 0x%x\n",
-++		ath10k_err(ar, "Unsupported hardware version: 0x%x\n",
-+ 			   ar->target_version);
-+ 		return -EINVAL;
-+ 	}
-+ 
-+ 	ar->hw_params = *hw_params;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
-+ 		   ar->hw_params.name, ar->target_version);
-+ 
-+ 	return 0;
-+@@ -676,101 +872,124 @@ static void ath10k_core_restart(struct w
-+ {
-+ 	struct ath10k *ar = container_of(work, struct ath10k, restart_work);
-+ 
-++	set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-++
-++	/* Place a barrier to make sure the compiler doesn't reorder
-++	 * CRASH_FLUSH and calling other functions.
-++	 */
-++	barrier();
-++
-++	ieee80211_stop_queues(ar->hw);
-++	ath10k_drain_tx(ar);
-++	complete_all(&ar->scan.started);
-++	complete_all(&ar->scan.completed);
-++	complete_all(&ar->scan.on_channel);
-++	complete_all(&ar->offchan_tx_completed);
-++	complete_all(&ar->install_key_done);
-++	complete_all(&ar->vdev_setup_done);
-++	complete_all(&ar->thermal.wmi_sync);
-++	wake_up(&ar->htt.empty_tx_wq);
-++	wake_up(&ar->wmi.tx_credits_wq);
-++	wake_up(&ar->peer_mapping_wq);
-++
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	switch (ar->state) {
-+ 	case ATH10K_STATE_ON:
-+ 		ar->state = ATH10K_STATE_RESTARTING;
-+-		ath10k_halt(ar);
-++		ath10k_hif_stop(ar);
-++		ath10k_scan_finish(ar);
-+ 		ieee80211_restart_hw(ar->hw);
-+ 		break;
-+ 	case ATH10K_STATE_OFF:
-+ 		/* this can happen if driver is being unloaded
-+ 		 * or if the crash happens during FW probing */
-+-		ath10k_warn("cannot restart a device that hasn't been started\n");
-++		ath10k_warn(ar, "cannot restart a device that hasn't been started\n");
-+ 		break;
-+ 	case ATH10K_STATE_RESTARTING:
-++		/* hw restart might be requested from multiple places */
-++		break;
-+ 	case ATH10K_STATE_RESTARTED:
-+ 		ar->state = ATH10K_STATE_WEDGED;
-+ 		/* fall through */
-+ 	case ATH10K_STATE_WEDGED:
-+-		ath10k_warn("device is wedged, will not restart\n");
-++		ath10k_warn(ar, "device is wedged, will not restart\n");
-++		break;
-++	case ATH10K_STATE_UTF:
-++		ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
-+ 		break;
-+ 	}
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+ }
-+ 
-+-struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
-+-				  const struct ath10k_hif_ops *hif_ops)
-++static int ath10k_core_init_firmware_features(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar;
-+-
-+-	ar = ath10k_mac_create();
-+-	if (!ar)
-+-		return NULL;
-+-
-+-	ar->ath_common.priv = ar;
-+-	ar->ath_common.hw = ar->hw;
-+-
-+-	ar->p2p = !!ath10k_p2p;
-+-	ar->dev = dev;
-+-
-+-	ar->hif.priv = hif_priv;
-+-	ar->hif.ops = hif_ops;
-+-
-+-	init_completion(&ar->scan.started);
-+-	init_completion(&ar->scan.completed);
-+-	init_completion(&ar->scan.on_channel);
-+-	init_completion(&ar->target_suspend);
-+-
-+-	init_completion(&ar->install_key_done);
-+-	init_completion(&ar->vdev_setup_done);
-+-
-+-	setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
-+-
-+-	ar->workqueue = create_singlethread_workqueue("ath10k_wq");
-+-	if (!ar->workqueue)
-+-		goto err_wq;
-+-
-+-	mutex_init(&ar->conf_mutex);
-+-	spin_lock_init(&ar->data_lock);
-+-
-+-	INIT_LIST_HEAD(&ar->peers);
-+-	init_waitqueue_head(&ar->peer_mapping_wq);
-+-
-+-	init_completion(&ar->offchan_tx_completed);
-+-	INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
-+-	skb_queue_head_init(&ar->offchan_tx_queue);
-+-
-+-	INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
-+-	skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
-+-
-+-	INIT_WORK(&ar->restart_work, ath10k_core_restart);
-++	if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
-++	    !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-++		ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
-++		return -EINVAL;
-++	}
-+ 
-+-	return ar;
-++	if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
-++		ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
-++			   ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
-++		return -EINVAL;
-++	}
-+ 
-+-err_wq:
-+-	ath10k_mac_destroy(ar);
-+-	return NULL;
-+-}
-+-EXPORT_SYMBOL(ath10k_core_create);
-++	/* Backwards compatibility for firmwares without
-++	 * ATH10K_FW_IE_WMI_OP_VERSION.
-++	 */
-++	if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
-++		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-++			if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
-++				     ar->fw_features))
-++				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
-++			else
-++				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
-++		} else {
-++			ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
-++		}
-++	}
-+ 
-+-void ath10k_core_destroy(struct ath10k *ar)
-+-{
-+-	flush_workqueue(ar->workqueue);
-+-	destroy_workqueue(ar->workqueue);
-++	switch (ar->wmi.op_version) {
-++	case ATH10K_FW_WMI_OP_VERSION_MAIN:
-++		ar->max_num_peers = TARGET_NUM_PEERS;
-++		ar->max_num_stations = TARGET_NUM_STATIONS;
-++		ar->max_num_vdevs = TARGET_NUM_VDEVS;
-++		ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_10_1:
-++	case ATH10K_FW_WMI_OP_VERSION_10_2:
-++	case ATH10K_FW_WMI_OP_VERSION_10_2_4:
-++		ar->max_num_peers = TARGET_10X_NUM_PEERS;
-++		ar->max_num_stations = TARGET_10X_NUM_STATIONS;
-++		ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
-++		ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_TLV:
-++		ar->max_num_peers = TARGET_TLV_NUM_PEERS;
-++		ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
-++		ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
-++		ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_UNSET:
-++	case ATH10K_FW_WMI_OP_VERSION_MAX:
-++		WARN_ON(1);
-++		return -EINVAL;
-++	}
-+ 
-+-	ath10k_mac_destroy(ar);
-++	return 0;
-+ }
-+-EXPORT_SYMBOL(ath10k_core_destroy);
-+ 
-+-int ath10k_core_start(struct ath10k *ar)
-++int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
-+ {
-+ 	int status;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-++	clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-++
-+ 	ath10k_bmi_start(ar);
-+ 
-+ 	if (ath10k_init_configure_target(ar)) {
-+@@ -778,7 +997,11 @@ int ath10k_core_start(struct ath10k *ar)
-+ 		goto err;
-+ 	}
-+ 
-+-	status = ath10k_init_download_firmware(ar);
-++	status = ath10k_download_cal_data(ar);
-++	if (status)
-++		goto err;
-++
-++	status = ath10k_download_fw(ar, mode);
-+ 	if (status)
-+ 		goto err;
-+ 
-+@@ -791,7 +1014,7 @@ int ath10k_core_start(struct ath10k *ar)
-+ 
-+ 	status = ath10k_htc_init(ar);
-+ 	if (status) {
-+-		ath10k_err("could not init HTC (%d)\n", status);
-++		ath10k_err(ar, "could not init HTC (%d)\n", status);
-+ 		goto err;
-+ 	}
-+ 
-+@@ -801,79 +1024,123 @@ int ath10k_core_start(struct ath10k *ar)
-+ 
-+ 	status = ath10k_wmi_attach(ar);
-+ 	if (status) {
-+-		ath10k_err("WMI attach failed: %d\n", status);
-++		ath10k_err(ar, "WMI attach failed: %d\n", status);
-+ 		goto err;
-+ 	}
-+ 
-+-	status = ath10k_hif_start(ar);
-++	status = ath10k_htt_init(ar);
-++	if (status) {
-++		ath10k_err(ar, "failed to init htt: %d\n", status);
-++		goto err_wmi_detach;
-++	}
-++
-++	status = ath10k_htt_tx_alloc(&ar->htt);
-+ 	if (status) {
-+-		ath10k_err("could not start HIF: %d\n", status);
-++		ath10k_err(ar, "failed to alloc htt tx: %d\n", status);
-+ 		goto err_wmi_detach;
-+ 	}
-+ 
-++	status = ath10k_htt_rx_alloc(&ar->htt);
-++	if (status) {
-++		ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
-++		goto err_htt_tx_detach;
-++	}
-++
-++	status = ath10k_hif_start(ar);
-++	if (status) {
-++		ath10k_err(ar, "could not start HIF: %d\n", status);
-++		goto err_htt_rx_detach;
-++	}
-++
-+ 	status = ath10k_htc_wait_target(&ar->htc);
-+ 	if (status) {
-+-		ath10k_err("failed to connect to HTC: %d\n", status);
-++		ath10k_err(ar, "failed to connect to HTC: %d\n", status);
-+ 		goto err_hif_stop;
-+ 	}
-+ 
-+-	status = ath10k_htt_attach(ar);
-++	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
-++		status = ath10k_htt_connect(&ar->htt);
-++		if (status) {
-++			ath10k_err(ar, "failed to connect htt (%d)\n", status);
-++			goto err_hif_stop;
-++		}
-++	}
-++
-++	status = ath10k_wmi_connect(ar);
-+ 	if (status) {
-+-		ath10k_err("could not attach htt (%d)\n", status);
-++		ath10k_err(ar, "could not connect wmi: %d\n", status);
-+ 		goto err_hif_stop;
-+ 	}
-+ 
-+-	status = ath10k_init_connect_htc(ar);
-+-	if (status)
-+-		goto err_htt_detach;
-++	status = ath10k_htc_start(&ar->htc);
-++	if (status) {
-++		ath10k_err(ar, "failed to start htc: %d\n", status);
-++		goto err_hif_stop;
-++	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
-++	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
-++		status = ath10k_wmi_wait_for_service_ready(ar);
-++		if (status <= 0) {
-++			ath10k_warn(ar, "wmi service ready event not received");
-++			status = -ETIMEDOUT;
-++			goto err_hif_stop;
-++		}
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
-+ 		   ar->hw->wiphy->fw_version);
-+ 
-+ 	status = ath10k_wmi_cmd_init(ar);
-+ 	if (status) {
-+-		ath10k_err("could not send WMI init command (%d)\n", status);
-+-		goto err_disconnect_htc;
-++		ath10k_err(ar, "could not send WMI init command (%d)\n",
-++			   status);
-++		goto err_hif_stop;
-+ 	}
-+ 
-+ 	status = ath10k_wmi_wait_for_unified_ready(ar);
-+ 	if (status <= 0) {
-+-		ath10k_err("wmi unified ready event not received\n");
-++		ath10k_err(ar, "wmi unified ready event not received\n");
-+ 		status = -ETIMEDOUT;
-+-		goto err_disconnect_htc;
-++		goto err_hif_stop;
-+ 	}
-+ 
-+-	status = ath10k_htt_attach_target(&ar->htt);
-+-	if (status)
-+-		goto err_disconnect_htc;
-++	/* If firmware indicates Full Rx Reorder support it must be used in a
-++	 * slightly different manner. Let HTT code know.
-++	 */
-++	ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
-++						ar->wmi.svc_map));
-++
-++	status = ath10k_htt_rx_ring_refill(ar);
-++	if (status) {
-++		ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);
-++		goto err_hif_stop;
-++	}
-++
-++	/* we don't care about HTT in UTF mode */
-++	if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
-++		status = ath10k_htt_setup(&ar->htt);
-++		if (status) {
-++			ath10k_err(ar, "failed to setup htt: %d\n", status);
-++			goto err_hif_stop;
-++		}
-++	}
-+ 
-+ 	status = ath10k_debug_start(ar);
-+ 	if (status)
-+-		goto err_disconnect_htc;
-+-
-+-	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
-+-	INIT_LIST_HEAD(&ar->arvifs);
-++		goto err_hif_stop;
-+ 
-+-	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
-+-		ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
-+-			    ar->hw_params.name,
-+-			    ar->target_version,
-+-			    ar->chip_id,
-+-			    ar->hw->wiphy->fw_version,
-+-			    ar->fw_api,
-+-			    ar->htt.target_version_major,
-+-			    ar->htt.target_version_minor);
-++	ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
-+ 
-+-	__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
-++	INIT_LIST_HEAD(&ar->arvifs);
-+ 
-+ 	return 0;
-+ 
-+-err_disconnect_htc:
-+-	ath10k_htc_stop(&ar->htc);
-+-err_htt_detach:
-+-	ath10k_htt_detach(&ar->htt);
-+ err_hif_stop:
-+ 	ath10k_hif_stop(ar);
-++err_htt_rx_detach:
-++	ath10k_htt_rx_free(&ar->htt);
-++err_htt_tx_detach:
-++	ath10k_htt_tx_free(&ar->htt);
-+ err_wmi_detach:
-+ 	ath10k_wmi_detach(ar);
-+ err:
-+@@ -889,14 +1156,14 @@ int ath10k_wait_for_suspend(struct ath10
-+ 
-+ 	ret = ath10k_wmi_pdev_suspend_target(ar, suspend_opt);
-+ 	if (ret) {
-+-		ath10k_warn("could not suspend target (%d)\n", ret);
-++		ath10k_warn(ar, "could not suspend target (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
-+ 
-+ 	if (ret == 0) {
-+-		ath10k_warn("suspend timed out - target pause event never came\n");
-++		ath10k_warn(ar, "suspend timed out - target pause event never came\n");
-+ 		return -ETIMEDOUT;
-+ 	}
-+ 
-+@@ -908,12 +1175,14 @@ void ath10k_core_stop(struct ath10k *ar)
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+ 	/* try to suspend target */
-+-	if (ar->state != ATH10K_STATE_RESTARTING)
-++	if (ar->state != ATH10K_STATE_RESTARTING &&
-++	    ar->state != ATH10K_STATE_UTF)
-+ 		ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
-+ 
-+ 	ath10k_debug_stop(ar);
-+-	ath10k_htc_stop(&ar->htc);
-+-	ath10k_htt_detach(&ar->htt);
-++	ath10k_hif_stop(ar);
-++	ath10k_htt_tx_free(&ar->htt);
-++	ath10k_htt_rx_free(&ar->htt);
-+ 	ath10k_wmi_detach(ar);
-+ }
-+ EXPORT_SYMBOL(ath10k_core_stop);
-+@@ -929,16 +1198,15 @@ static int ath10k_core_probe_fw(struct a
-+ 
-+ 	ret = ath10k_hif_power_up(ar);
-+ 	if (ret) {
-+-		ath10k_err("could not start pci hif (%d)\n", ret);
-++		ath10k_err(ar, "could not start pci hif (%d)\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	memset(&target_info, 0, sizeof(target_info));
-+ 	ret = ath10k_bmi_get_target_info(ar, &target_info);
-+ 	if (ret) {
-+-		ath10k_err("could not get target info (%d)\n", ret);
-+-		ath10k_hif_power_down(ar);
-+-		return ret;
-++		ath10k_err(ar, "could not get target info (%d)\n", ret);
-++		goto err_power_down;
-+ 	}
-+ 
-+ 	ar->target_version = target_info.version;
-+@@ -946,118 +1214,233 @@ static int ath10k_core_probe_fw(struct a
-+ 
-+ 	ret = ath10k_init_hw_params(ar);
-+ 	if (ret) {
-+-		ath10k_err("could not get hw params (%d)\n", ret);
-+-		ath10k_hif_power_down(ar);
-+-		return ret;
-++		ath10k_err(ar, "could not get hw params (%d)\n", ret);
-++		goto err_power_down;
-+ 	}
-+ 
-+ 	ret = ath10k_core_fetch_firmware_files(ar);
-+ 	if (ret) {
-+-		ath10k_err("could not fetch firmware files (%d)\n", ret);
-+-		ath10k_hif_power_down(ar);
-+-		return ret;
-++		ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);
-++		goto err_power_down;
-++	}
-++
-++	ret = ath10k_core_init_firmware_features(ar);
-++	if (ret) {
-++		ath10k_err(ar, "fatal problem with firmware features: %d\n",
-++			   ret);
-++		goto err_free_firmware_files;
-+ 	}
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+-	ret = ath10k_core_start(ar);
-++	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
-+ 	if (ret) {
-+-		ath10k_err("could not init core (%d)\n", ret);
-+-		ath10k_core_free_firmware_files(ar);
-+-		ath10k_hif_power_down(ar);
-+-		mutex_unlock(&ar->conf_mutex);
-+-		return ret;
-++		ath10k_err(ar, "could not init core (%d)\n", ret);
-++		goto err_unlock;
-+ 	}
-+ 
-++	ath10k_print_driver_info(ar);
-+ 	ath10k_core_stop(ar);
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 
-+ 	ath10k_hif_power_down(ar);
-+ 	return 0;
-+-}
-+-
-+-static int ath10k_core_check_chip_id(struct ath10k *ar)
-+-{
-+-	u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV);
-+-
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n",
-+-		   ar->chip_id, hw_revision);
-+ 
-+-	/* Check that we are not using hw1.0 (some of them have same pci id
-+-	 * as hw2.0) before doing anything else as ath10k crashes horribly
-+-	 * due to missing hw1.0 workarounds. */
-+-	switch (hw_revision) {
-+-	case QCA988X_HW_1_0_CHIP_ID_REV:
-+-		ath10k_err("ERROR: qca988x hw1.0 is not supported\n");
-+-		return -EOPNOTSUPP;
-++err_unlock:
-++	mutex_unlock(&ar->conf_mutex);
-+ 
-+-	case QCA988X_HW_2_0_CHIP_ID_REV:
-+-		/* known hardware revision, continue normally */
-+-		return 0;
-++err_free_firmware_files:
-++	ath10k_core_free_firmware_files(ar);
-+ 
-+-	default:
-+-		ath10k_warn("Warning: hardware revision unknown (0x%x), expect problems\n",
-+-			    ar->chip_id);
-+-		return 0;
-+-	}
-++err_power_down:
-++	ath10k_hif_power_down(ar);
-+ 
-+-	return 0;
-++	return ret;
-+ }
-+ 
-+-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
-++static void ath10k_core_register_work(struct work_struct *work)
-+ {
-++	struct ath10k *ar = container_of(work, struct ath10k, register_work);
-+ 	int status;
-+ 
-+-	ar->chip_id = chip_id;
-+-
-+-	status = ath10k_core_check_chip_id(ar);
-+-	if (status) {
-+-		ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
-+-		return status;
-+-	}
-+-
-+ 	status = ath10k_core_probe_fw(ar);
-+ 	if (status) {
-+-		ath10k_err("could not probe fw (%d)\n", status);
-+-		return status;
-++		ath10k_err(ar, "could not probe fw (%d)\n", status);
-++		goto err;
-+ 	}
-+ 
-+ 	status = ath10k_mac_register(ar);
-+ 	if (status) {
-+-		ath10k_err("could not register to mac80211 (%d)\n", status);
-++		ath10k_err(ar, "could not register to mac80211 (%d)\n", status);
-+ 		goto err_release_fw;
-+ 	}
-+ 
-+-	status = ath10k_debug_create(ar);
-++	status = ath10k_debug_register(ar);
-+ 	if (status) {
-+-		ath10k_err("unable to initialize debugfs\n");
-++		ath10k_err(ar, "unable to initialize debugfs\n");
-+ 		goto err_unregister_mac;
-+ 	}
-+ 
-+-	return 0;
-++	status = ath10k_spectral_create(ar);
-++	if (status) {
-++		ath10k_err(ar, "failed to initialize spectral\n");
-++		goto err_debug_destroy;
-++	}
-+ 
-++	status = ath10k_thermal_register(ar);
-++	if (status) {
-++		ath10k_err(ar, "could not register thermal device: %d\n",
-++			   status);
-++		goto err_spectral_destroy;
-++	}
-++
-++	set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
-++	return;
-++
-++err_spectral_destroy:
-++	ath10k_spectral_destroy(ar);
-++err_debug_destroy:
-++	ath10k_debug_destroy(ar);
-+ err_unregister_mac:
-+ 	ath10k_mac_unregister(ar);
-+ err_release_fw:
-+ 	ath10k_core_free_firmware_files(ar);
-+-	return status;
-++err:
-++	/* TODO: It's probably a good idea to release device from the driver
-++	 * but calling device_release_driver() here will cause a deadlock.
-++	 */
-++	return;
-++}
-++
-++int ath10k_core_register(struct ath10k *ar, u32 chip_id)
-++{
-++	ar->chip_id = chip_id;
-++	queue_work(ar->workqueue, &ar->register_work);
-++
-++	return 0;
-+ }
-+ EXPORT_SYMBOL(ath10k_core_register);
-+ 
-+ void ath10k_core_unregister(struct ath10k *ar)
-+ {
-++	cancel_work_sync(&ar->register_work);
-++
-++	if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
-++		return;
-++
-++	ath10k_thermal_unregister(ar);
-++	/* Stop spectral before unregistering from mac80211 to remove the
-++	 * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
-++	 * would be already be free'd recursively, leading to a double free.
-++	 */
-++	ath10k_spectral_destroy(ar);
-++
-+ 	/* We must unregister from mac80211 before we stop HTC and HIF.
-+ 	 * Otherwise we will fail to submit commands to FW and mac80211 will be
-+ 	 * unhappy about callback failures. */
-+ 	ath10k_mac_unregister(ar);
-+ 
-++	ath10k_testmode_destroy(ar);
-++
-+ 	ath10k_core_free_firmware_files(ar);
-+ 
-+-	ath10k_debug_destroy(ar);
-++	ath10k_debug_unregister(ar);
-+ }
-+ EXPORT_SYMBOL(ath10k_core_unregister);
-+ 
-++struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
-++				  enum ath10k_bus bus,
-++				  enum ath10k_hw_rev hw_rev,
-++				  const struct ath10k_hif_ops *hif_ops)
-++{
-++	struct ath10k *ar;
-++	int ret;
-++
-++	ar = ath10k_mac_create(priv_size);
-++	if (!ar)
-++		return NULL;
-++
-++	ar->ath_common.priv = ar;
-++	ar->ath_common.hw = ar->hw;
-++	ar->dev = dev;
-++	ar->hw_rev = hw_rev;
-++	ar->hif.ops = hif_ops;
-++	ar->hif.bus = bus;
-++
-++	switch (hw_rev) {
-++	case ATH10K_HW_QCA988X:
-++		ar->regs = &qca988x_regs;
-++		break;
-++	case ATH10K_HW_QCA6174:
-++		ar->regs = &qca6174_regs;
-++		break;
-++	default:
-++		ath10k_err(ar, "unsupported core hardware revision %d\n",
-++			   hw_rev);
-++		ret = -ENOTSUPP;
-++		goto err_free_mac;
-++	}
-++
-++	init_completion(&ar->scan.started);
-++	init_completion(&ar->scan.completed);
-++	init_completion(&ar->scan.on_channel);
-++	init_completion(&ar->target_suspend);
-++
-++	init_completion(&ar->install_key_done);
-++	init_completion(&ar->vdev_setup_done);
-++	init_completion(&ar->thermal.wmi_sync);
-++
-++	INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);
-++
-++	ar->workqueue = create_singlethread_workqueue("ath10k_wq");
-++	if (!ar->workqueue)
-++		goto err_free_mac;
-++
-++	mutex_init(&ar->conf_mutex);
-++	spin_lock_init(&ar->data_lock);
-++
-++	INIT_LIST_HEAD(&ar->peers);
-++	init_waitqueue_head(&ar->peer_mapping_wq);
-++	init_waitqueue_head(&ar->htt.empty_tx_wq);
-++	init_waitqueue_head(&ar->wmi.tx_credits_wq);
-++
-++	init_completion(&ar->offchan_tx_completed);
-++	INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
-++	skb_queue_head_init(&ar->offchan_tx_queue);
-++
-++	INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
-++	skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
-++
-++	INIT_WORK(&ar->register_work, ath10k_core_register_work);
-++	INIT_WORK(&ar->restart_work, ath10k_core_restart);
-++
-++	ret = ath10k_debug_create(ar);
-++	if (ret)
-++		goto err_free_wq;
-++
-++	return ar;
-++
-++err_free_wq:
-++	destroy_workqueue(ar->workqueue);
-++
-++err_free_mac:
-++	ath10k_mac_destroy(ar);
-++
-++	return NULL;
-++}
-++EXPORT_SYMBOL(ath10k_core_create);
-++
-++void ath10k_core_destroy(struct ath10k *ar)
-++{
-++	flush_workqueue(ar->workqueue);
-++	destroy_workqueue(ar->workqueue);
-++
-++	ath10k_debug_destroy(ar);
-++	ath10k_mac_destroy(ar);
-++}
-++EXPORT_SYMBOL(ath10k_core_destroy);
-++
-+ MODULE_AUTHOR("Qualcomm Atheros");
-+ MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
-+ MODULE_LICENSE("Dual BSD/GPL");
-+--- a/drivers/net/wireless/ath/ath10k/core.h
-++++ b/drivers/net/wireless/ath/ath10k/core.h
-+@@ -22,6 +22,8 @@
-+ #include <linux/if_ether.h>
-+ #include <linux/types.h>
-+ #include <linux/pci.h>
-++#include <linux/uuid.h>
-++#include <linux/time.h>
-+ 
-+ #include "htt.h"
-+ #include "htc.h"
-+@@ -31,6 +33,8 @@
-+ #include "../ath.h"
-+ #include "../regd.h"
-+ #include "../dfs_pattern_detector.h"
-++#include "spectral.h"
-++#include "thermal.h"
-+ 
-+ #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
-+ #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
-+@@ -60,12 +64,28 @@
-+ 
-+ struct ath10k;
-+ 
-++enum ath10k_bus {
-++	ATH10K_BUS_PCI,
-++};
-++
-++static inline const char *ath10k_bus_str(enum ath10k_bus bus)
-++{
-++	switch (bus) {
-++	case ATH10K_BUS_PCI:
-++		return "pci";
-++	}
-++
-++	return "unknown";
-++}
-++
-+ struct ath10k_skb_cb {
-+ 	dma_addr_t paddr;
-++	u8 eid;
-+ 	u8 vdev_id;
-+ 
-+ 	struct {
-+ 		u8 tid;
-++		u16 freq;
-+ 		bool is_offchan;
-+ 		struct ath10k_htt_txbuf *txbuf;
-+ 		u32 txbuf_paddr;
-+@@ -77,6 +97,11 @@ struct ath10k_skb_cb {
-+ 	} bcn;
-+ } __packed;
-+ 
-++struct ath10k_skb_rxcb {
-++	dma_addr_t paddr;
-++	struct hlist_node hlist;
-++};
-++
-+ static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
-+ {
-+ 	BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) >
-+@@ -84,6 +109,15 @@ static inline struct ath10k_skb_cb *ATH1
-+ 	return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
-+ }
-+ 
-++static inline struct ath10k_skb_rxcb *ATH10K_SKB_RXCB(struct sk_buff *skb)
-++{
-++	BUILD_BUG_ON(sizeof(struct ath10k_skb_rxcb) > sizeof(skb->cb));
-++	return (struct ath10k_skb_rxcb *)skb->cb;
-++}
-++
-++#define ATH10K_RXCB_SKB(rxcb) \
-++		container_of((void *)rxcb, struct sk_buff, cb)
-++
-+ static inline u32 host_interest_item_address(u32 item_offset)
-+ {
-+ 	return QCA988X_HOST_INTEREST_ADDRESS + item_offset;
-+@@ -93,8 +127,6 @@ struct ath10k_bmi {
-+ 	bool done_sent;
-+ };
-+ 
-+-#define ATH10K_MAX_MEM_REQS 16
-+-
-+ struct ath10k_mem_chunk {
-+ 	void *vaddr;
-+ 	dma_addr_t paddr;
-+@@ -103,26 +135,52 @@ struct ath10k_mem_chunk {
-+ };
-+ 
-+ struct ath10k_wmi {
-++	enum ath10k_fw_wmi_op_version op_version;
-+ 	enum ath10k_htc_ep_id eid;
-+ 	struct completion service_ready;
-+ 	struct completion unified_ready;
-+ 	wait_queue_head_t tx_credits_wq;
-++	DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
-+ 	struct wmi_cmd_map *cmd;
-+ 	struct wmi_vdev_param_map *vdev_param;
-+ 	struct wmi_pdev_param_map *pdev_param;
-++	const struct wmi_ops *ops;
-+ 
-+ 	u32 num_mem_chunks;
-+-	struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
-++	struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
-+ };
-+ 
-+-struct ath10k_peer_stat {
-++struct ath10k_fw_stats_peer {
-++	struct list_head list;
-++
-+ 	u8 peer_macaddr[ETH_ALEN];
-+ 	u32 peer_rssi;
-+ 	u32 peer_tx_rate;
-+ 	u32 peer_rx_rate; /* 10x only */
-+ };
-+ 
-+-struct ath10k_target_stats {
-++struct ath10k_fw_stats_vdev {
-++	struct list_head list;
-++
-++	u32 vdev_id;
-++	u32 beacon_snr;
-++	u32 data_snr;
-++	u32 num_tx_frames[4];
-++	u32 num_rx_frames;
-++	u32 num_tx_frames_retries[4];
-++	u32 num_tx_frames_failures[4];
-++	u32 num_rts_fail;
-++	u32 num_rts_success;
-++	u32 num_rx_err;
-++	u32 num_rx_discard;
-++	u32 num_tx_not_acked;
-++	u32 tx_rate_history[10];
-++	u32 beacon_rssi_history[10];
-++};
-++
-++struct ath10k_fw_stats_pdev {
-++	struct list_head list;
-++
-+ 	/* PDEV stats */
-+ 	s32 ch_noise_floor;
-+ 	u32 tx_frame_count;
-+@@ -177,15 +235,12 @@ struct ath10k_target_stats {
-+ 	s32 phy_errs;
-+ 	s32 phy_err_drop;
-+ 	s32 mpdu_errs;
-++};
-+ 
-+-	/* VDEV STATS */
-+-
-+-	/* PEER STATS */
-+-	u8 peers;
-+-	struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
-+-
-+-	/* TODO: Beacon filter stats */
-+-
-++struct ath10k_fw_stats {
-++	struct list_head pdevs;
-++	struct list_head vdevs;
-++	struct list_head peers;
-+ };
-+ 
-+ struct ath10k_dfs_stats {
-+@@ -203,6 +258,8 @@ struct ath10k_peer {
-+ 	int vdev_id;
-+ 	u8 addr[ETH_ALEN];
-+ 	DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
-++
-++	/* protected by ar->data_lock */
-+ 	struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
-+ };
-+ 
-+@@ -216,10 +273,21 @@ struct ath10k_sta {
-+ 	u32 smps;
-+ 
-+ 	struct work_struct update_wk;
-++
-++#ifdef CPTCFG_MAC80211_DEBUGFS
-++	/* protected by conf_mutex */
-++	bool aggr_mode;
-++#endif
-+ };
-+ 
-+ #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
-+ 
-++enum ath10k_beacon_state {
-++	ATH10K_BEACON_SCHEDULED = 0,
-++	ATH10K_BEACON_SENDING,
-++	ATH10K_BEACON_SENT,
-++};
-++
-+ struct ath10k_vif {
-+ 	struct list_head list;
-+ 
-+@@ -230,20 +298,22 @@ struct ath10k_vif {
-+ 	u32 dtim_period;
-+ 	struct sk_buff *beacon;
-+ 	/* protected by data_lock */
-+-	bool beacon_sent;
-++	enum ath10k_beacon_state beacon_state;
-++	void *beacon_buf;
-++	dma_addr_t beacon_paddr;
-+ 
-+ 	struct ath10k *ar;
-+ 	struct ieee80211_vif *vif;
-+ 
-+ 	bool is_started;
-+ 	bool is_up;
-++	bool spectral_enabled;
-++	bool ps;
-+ 	u32 aid;
-+ 	u8 bssid[ETH_ALEN];
-+ 
-+-	struct work_struct wep_key_work;
-+ 	struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1];
-+-	u8 def_wep_key_idx;
-+-	u8 def_wep_key_newidx;
-++	s8 def_wep_key_idx;
-+ 
-+ 	u16 tx_seq_no;
-+ 
-+@@ -269,6 +339,8 @@ struct ath10k_vif {
-+ 	u8 force_sgi;
-+ 	bool use_cts_prot;
-+ 	int num_legacy_stations;
-++	int txpower;
-++	struct wmi_wmm_params_all_arg wmm_params;
-+ };
-+ 
-+ struct ath10k_vif_iter {
-+@@ -276,20 +348,38 @@ struct ath10k_vif_iter {
-+ 	struct ath10k_vif *arvif;
-+ };
-+ 
-++/* used for crash-dump storage, protected by data-lock */
-++struct ath10k_fw_crash_data {
-++	bool crashed_since_read;
-++
-++	uuid_le uuid;
-++	struct timespec timestamp;
-++	__le32 registers[REG_DUMP_COUNT_QCA988X];
-++};
-++
-+ struct ath10k_debug {
-+ 	struct dentry *debugfs_phy;
-+ 
-+-	struct ath10k_target_stats target_stats;
-+-	u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
-+-
-+-	struct completion event_stats_compl;
-++	struct ath10k_fw_stats fw_stats;
-++	struct completion fw_stats_complete;
-++	bool fw_stats_done;
-+ 
-+ 	unsigned long htt_stats_mask;
-+ 	struct delayed_work htt_stats_dwork;
-+ 	struct ath10k_dfs_stats dfs_stats;
-+ 	struct ath_dfs_pool_stats dfs_pool_stats;
-+ 
-++	/* protected by conf_mutex */
-+ 	u32 fw_dbglog_mask;
-++	u32 fw_dbglog_level;
-++	u32 pktlog_filter;
-++	u32 reg_addr;
-++	u32 nf_cal_period;
-++
-++	u8 htt_max_amsdu;
-++	u8 htt_max_ampdu;
-++
-++	struct ath10k_fw_crash_data *fw_crash_data;
-+ };
-+ 
-+ enum ath10k_state {
-+@@ -312,13 +402,24 @@ enum ath10k_state {
-+ 	 * prevents completion timeouts and makes the driver more responsive to
-+ 	 * userspace commands. This is also prevents recursive recovery. */
-+ 	ATH10K_STATE_WEDGED,
-++
-++	/* factory tests */
-++	ATH10K_STATE_UTF,
-++};
-++
-++enum ath10k_firmware_mode {
-++	/* the default mode, standard 802.11 functionality */
-++	ATH10K_FIRMWARE_MODE_NORMAL,
-++
-++	/* factory tests etc */
-++	ATH10K_FIRMWARE_MODE_UTF,
-+ };
-+ 
-+ enum ath10k_fw_features {
-+ 	/* wmi_mgmt_rx_hdr contains extra RSSI information */
-+ 	ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
-+ 
-+-	/* firmware from 10X branch */
-++	/* Firmware from 10X branch. Deprecated, don't use in new code. */
-+ 	ATH10K_FW_FEATURE_WMI_10X = 1,
-+ 
-+ 	/* firmware support tx frame management over WMI, otherwise it's HTT */
-+@@ -327,6 +428,18 @@ enum ath10k_fw_features {
-+ 	/* Firmware does not support P2P */
-+ 	ATH10K_FW_FEATURE_NO_P2P = 3,
-+ 
-++	/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature
-++	 * bit is required to be set as well. Deprecated, don't use in new
-++	 * code.
-++	 */
-++	ATH10K_FW_FEATURE_WMI_10_2 = 4,
-++
-++	/* Some firmware revisions lack proper multi-interface client powersave
-++	 * implementation. Enabling PS could result in connection drops,
-++	 * traffic stalls, etc.
-++	 */
-++	ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT = 5,
-++
-+ 	/* keep last */
-+ 	ATH10K_FW_FEATURE_COUNT,
-+ };
-+@@ -334,15 +447,64 @@ enum ath10k_fw_features {
-+ enum ath10k_dev_flags {
-+ 	/* Indicates that ath10k device is during CAC phase of DFS */
-+ 	ATH10K_CAC_RUNNING,
-+-	ATH10K_FLAG_FIRST_BOOT_DONE,
-++	ATH10K_FLAG_CORE_REGISTERED,
-++
-++	/* Device has crashed and needs to restart. This indicates any pending
-++	 * waiters should immediately cancel instead of waiting for a time out.
-++	 */
-++	ATH10K_FLAG_CRASH_FLUSH,
-++};
-++
-++enum ath10k_cal_mode {
-++	ATH10K_CAL_MODE_FILE,
-++	ATH10K_CAL_MODE_OTP,
-++	ATH10K_CAL_MODE_DT,
-++};
-++
-++static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
-++{
-++	switch (mode) {
-++	case ATH10K_CAL_MODE_FILE:
-++		return "file";
-++	case ATH10K_CAL_MODE_OTP:
-++		return "otp";
-++	case ATH10K_CAL_MODE_DT:
-++		return "dt";
-++	}
-++
-++	return "unknown";
-++}
-++
-++enum ath10k_scan_state {
-++	ATH10K_SCAN_IDLE,
-++	ATH10K_SCAN_STARTING,
-++	ATH10K_SCAN_RUNNING,
-++	ATH10K_SCAN_ABORTING,
-+ };
-+ 
-++static inline const char *ath10k_scan_state_str(enum ath10k_scan_state state)
-++{
-++	switch (state) {
-++	case ATH10K_SCAN_IDLE:
-++		return "idle";
-++	case ATH10K_SCAN_STARTING:
-++		return "starting";
-++	case ATH10K_SCAN_RUNNING:
-++		return "running";
-++	case ATH10K_SCAN_ABORTING:
-++		return "aborting";
-++	}
-++
-++	return "unknown";
-++}
-++
-+ struct ath10k {
-+ 	struct ath_common ath_common;
-+ 	struct ieee80211_hw *hw;
-+ 	struct device *dev;
-+ 	u8 mac_addr[ETH_ALEN];
-+ 
-++	enum ath10k_hw_rev hw_rev;
-+ 	u32 chip_id;
-+ 	u32 target_version;
-+ 	u8 fw_version_major;
-+@@ -358,18 +520,16 @@ struct ath10k {
-+ 
-+ 	DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
-+ 
-+-	struct targetdef *targetdef;
-+-	struct hostdef *hostdef;
-+-
-+ 	bool p2p;
-+ 
-+ 	struct {
-+-		void *priv;
-++		enum ath10k_bus bus;
-+ 		const struct ath10k_hif_ops *ops;
-+ 	} hif;
-+ 
-+ 	struct completion target_suspend;
-+ 
-++	const struct ath10k_hw_regs *regs;
-+ 	struct ath10k_bmi bmi;
-+ 	struct ath10k_wmi wmi;
-+ 	struct ath10k_htc htc;
-+@@ -379,12 +539,15 @@ struct ath10k {
-+ 		u32 id;
-+ 		const char *name;
-+ 		u32 patch_load_addr;
-++		int uart_pin;
-+ 
-+ 		struct ath10k_hw_params_fw {
-+ 			const char *dir;
-+ 			const char *fw;
-+ 			const char *otp;
-+ 			const char *board;
-++			size_t board_size;
-++			size_t board_ext_size;
-+ 		} fw;
-+ 	} hw_params;
-+ 
-+@@ -400,16 +563,18 @@ struct ath10k {
-+ 	const void *firmware_data;
-+ 	size_t firmware_len;
-+ 
-++	const struct firmware *cal_file;
-++
-+ 	int fw_api;
-++	enum ath10k_cal_mode cal_mode;
-+ 
-+ 	struct {
-+ 		struct completion started;
-+ 		struct completion completed;
-+ 		struct completion on_channel;
-+-		struct timer_list timeout;
-++		struct delayed_work timeout;
-++		enum ath10k_scan_state state;
-+ 		bool is_roc;
-+-		bool in_progress;
-+-		bool aborting;
-+ 		int vdev_id;
-+ 		int roc_freq;
-+ 	} scan;
-+@@ -427,8 +592,7 @@ struct ath10k {
-+ 	/* current operating channel definition */
-+ 	struct cfg80211_chan_def chandef;
-+ 
-+-	int free_vdev_map;
-+-	bool promisc;
-++	unsigned long long free_vdev_map;
-+ 	bool monitor;
-+ 	int monitor_vdev_id;
-+ 	bool monitor_started;
-+@@ -440,7 +604,12 @@ struct ath10k {
-+ 	bool radar_enabled;
-+ 	int num_started_vdevs;
-+ 
-+-	struct wmi_pdev_set_wmm_params_arg wmm_params;
-++	/* Protected by conf-mutex */
-++	u8 supp_tx_chainmask;
-++	u8 supp_rx_chainmask;
-++	u8 cfg_tx_chainmask;
-++	u8 cfg_rx_chainmask;
-++
-+ 	struct completion install_key_done;
-+ 
-+ 	struct completion vdev_setup_done;
-+@@ -457,8 +626,13 @@ struct ath10k {
-+ 	struct list_head peers;
-+ 	wait_queue_head_t peer_mapping_wq;
-+ 
-+-	/* number of created peers; protected by data_lock */
-++	/* protected by conf_mutex */
-+ 	int num_peers;
-++	int num_stations;
-++
-++	int max_num_peers;
-++	int max_num_stations;
-++	int max_num_vdevs;
-+ 
-+ 	struct work_struct offchan_tx_work;
-+ 	struct sk_buff_head offchan_tx_queue;
-+@@ -470,6 +644,7 @@ struct ath10k {
-+ 
-+ 	enum ath10k_state state;
-+ 
-++	struct work_struct register_work;
-+ 	struct work_struct restart_work;
-+ 
-+ 	/* cycle count is reported twice for each visited channel during scan.
-+@@ -483,13 +658,46 @@ struct ath10k {
-+ #ifdef CPTCFG_ATH10K_DEBUGFS
-+ 	struct ath10k_debug debug;
-+ #endif
-++
-++	struct {
-++		/* relay(fs) channel for spectral scan */
-++		struct rchan *rfs_chan_spec_scan;
-++
-++		/* spectral_mode and spec_config are protected by conf_mutex */
-++		enum ath10k_spectral_mode mode;
-++		struct ath10k_spec_scan config;
-++	} spectral;
-++
-++	struct {
-++		/* protected by conf_mutex */
-++		const struct firmware *utf;
-++		DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
-++		enum ath10k_fw_wmi_op_version orig_wmi_op_version;
-++
-++		/* protected by data_lock */
-++		bool utf_monitor;
-++	} testmode;
-++
-++	struct {
-++		/* protected by data_lock */
-++		u32 fw_crash_counter;
-++		u32 fw_warm_reset_counter;
-++		u32 fw_cold_reset_counter;
-++	} stats;
-++
-++	struct ath10k_thermal thermal;
-++
-++	/* must be last */
-++	u8 drv_priv[0] __aligned(sizeof(void *));
-+ };
-+ 
-+-struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
-++struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
-++				  enum ath10k_bus bus,
-++				  enum ath10k_hw_rev hw_rev,
-+ 				  const struct ath10k_hif_ops *hif_ops);
-+ void ath10k_core_destroy(struct ath10k *ar);
-+ 
-+-int ath10k_core_start(struct ath10k *ar);
-++int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
-+ int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
-+ void ath10k_core_stop(struct ath10k *ar);
-+ int ath10k_core_register(struct ath10k *ar, u32 chip_id);
-+--- a/drivers/net/wireless/ath/ath10k/debug.c
-++++ b/drivers/net/wireless/ath/ath10k/debug.c
-+@@ -17,107 +17,176 @@
-+ 
-+ #include <linux/module.h>
-+ #include <linux/debugfs.h>
-++#include <linux/vmalloc.h>
-++#include <linux/utsname.h>
-+ 
-+ #include "core.h"
-+ #include "debug.h"
-++#include "hif.h"
-++#include "wmi-ops.h"
-+ 
-+ /* ms */
-+ #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
-+ 
-+-static int ath10k_printk(const char *level, const char *fmt, ...)
-+-{
-+-	struct va_format vaf;
-+-	va_list args;
-+-	int rtn;
-++#define ATH10K_FW_CRASH_DUMP_VERSION 1
-+ 
-+-	va_start(args, fmt);
-++/**
-++ * enum ath10k_fw_crash_dump_type - types of data in the dump file
-++ * @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
-++ */
-++enum ath10k_fw_crash_dump_type {
-++	ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
-+ 
-+-	vaf.fmt = fmt;
-+-	vaf.va = &args;
-++	ATH10K_FW_CRASH_DUMP_MAX,
-++};
-+ 
-+-	rtn = printk("%sath10k: %pV", level, &vaf);
-++struct ath10k_tlv_dump_data {
-++	/* see ath10k_fw_crash_dump_type above */
-++	__le32 type;
-+ 
-+-	va_end(args);
-++	/* in bytes */
-++	__le32 tlv_len;
-+ 
-+-	return rtn;
-+-}
-++	/* pad to 32-bit boundaries as needed */
-++	u8 tlv_data[];
-++} __packed;
-++
-++struct ath10k_dump_file_data {
-++	/* dump file information */
-++
-++	/* "ATH10K-FW-DUMP" */
-++	char df_magic[16];
-++
-++	__le32 len;
-++
-++	/* file dump version */
-++	__le32 version;
-++
-++	/* some info we can get from ath10k struct that might help */
-++
-++	u8 uuid[16];
-++
-++	__le32 chip_id;
-++
-++	/* 0 for now, in place for later hardware */
-++	__le32 bus_type;
-++
-++	__le32 target_version;
-++	__le32 fw_version_major;
-++	__le32 fw_version_minor;
-++	__le32 fw_version_release;
-++	__le32 fw_version_build;
-++	__le32 phy_capability;
-++	__le32 hw_min_tx_power;
-++	__le32 hw_max_tx_power;
-++	__le32 ht_cap_info;
-++	__le32 vht_cap_info;
-++	__le32 num_rf_chains;
-++
-++	/* firmware version string */
-++	char fw_ver[ETHTOOL_FWVERS_LEN];
-++
-++	/* Kernel related information */
-++
-++	/* time-of-day stamp */
-++	__le64 tv_sec;
-++
-++	/* time-of-day stamp, nano-seconds */
-++	__le64 tv_nsec;
-++
-++	/* LINUX_VERSION_CODE */
-++	__le32 kernel_ver_code;
-++
-++	/* VERMAGIC_STRING */
-++	char kernel_ver[64];
-+ 
-+-int ath10k_info(const char *fmt, ...)
-++	/* room for growth w/out changing binary format */
-++	u8 unused[128];
-++
-++	/* struct ath10k_tlv_dump_data + more */
-++	u8 data[0];
-++} __packed;
-++
-++void ath10k_info(struct ath10k *ar, const char *fmt, ...)
-+ {
-+ 	struct va_format vaf = {
-+ 		.fmt = fmt,
-+ 	};
-+ 	va_list args;
-+-	int ret;
-+ 
-+ 	va_start(args, fmt);
-+ 	vaf.va = &args;
-+-	ret = ath10k_printk(KERN_INFO, "%pV", &vaf);
-+-	trace_ath10k_log_info(&vaf);
-++	dev_info(ar->dev, "%pV", &vaf);
-++	trace_ath10k_log_info(ar, &vaf);
-+ 	va_end(args);
-+-
-+-	return ret;
-+ }
-+ EXPORT_SYMBOL(ath10k_info);
-+ 
-+-int ath10k_err(const char *fmt, ...)
-++void ath10k_print_driver_info(struct ath10k *ar)
-++{
-++	ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
-++		    ar->hw_params.name,
-++		    ar->target_version,
-++		    ar->chip_id,
-++		    ar->hw->wiphy->fw_version,
-++		    ar->fw_api,
-++		    ar->htt.target_version_major,
-++		    ar->htt.target_version_minor,
-++		    ar->wmi.op_version,
-++		    ath10k_cal_mode_str(ar->cal_mode),
-++		    ar->max_num_stations);
-++	ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
-++		    config_enabled(CPTCFG_ATH10K_DEBUG),
-++		    config_enabled(CPTCFG_ATH10K_DEBUGFS),
-++		    config_enabled(CPTCFG_ATH10K_TRACING),
-++		    config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED),
-++		    config_enabled(CPTCFG_NL80211_TESTMODE));
-++}
-++EXPORT_SYMBOL(ath10k_print_driver_info);
-++
-++void ath10k_err(struct ath10k *ar, const char *fmt, ...)
-+ {
-+ 	struct va_format vaf = {
-+ 		.fmt = fmt,
-+ 	};
-+ 	va_list args;
-+-	int ret;
-+ 
-+ 	va_start(args, fmt);
-+ 	vaf.va = &args;
-+-	ret = ath10k_printk(KERN_ERR, "%pV", &vaf);
-+-	trace_ath10k_log_err(&vaf);
-++	dev_err(ar->dev, "%pV", &vaf);
-++	trace_ath10k_log_err(ar, &vaf);
-+ 	va_end(args);
-+-
-+-	return ret;
-+ }
-+ EXPORT_SYMBOL(ath10k_err);
-+ 
-+-int ath10k_warn(const char *fmt, ...)
-++void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
-+ {
-+ 	struct va_format vaf = {
-+ 		.fmt = fmt,
-+ 	};
-+ 	va_list args;
-+-	int ret = 0;
-+ 
-+ 	va_start(args, fmt);
-+ 	vaf.va = &args;
-+-
-+-	if (net_ratelimit())
-+-		ret = ath10k_printk(KERN_WARNING, "%pV", &vaf);
-+-
-+-	trace_ath10k_log_warn(&vaf);
-++	dev_warn_ratelimited(ar->dev, "%pV", &vaf);
-++	trace_ath10k_log_warn(ar, &vaf);
-+ 
-+ 	va_end(args);
-+-
-+-	return ret;
-+ }
-+ EXPORT_SYMBOL(ath10k_warn);
-+ 
-+ #ifdef CPTCFG_ATH10K_DEBUGFS
-+ 
-+-void ath10k_debug_read_service_map(struct ath10k *ar,
-+-				   void *service_map,
-+-				   size_t map_size)
-+-{
-+-	memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
-+-}
-+-
-+ static ssize_t ath10k_read_wmi_services(struct file *file,
-+ 					char __user *user_buf,
-+ 					size_t count, loff_t *ppos)
-+ {
-+ 	struct ath10k *ar = file->private_data;
-+ 	char *buf;
-+-	unsigned int len = 0, buf_len = 1500;
-+-	const char *status;
-++	unsigned int len = 0, buf_len = 4096;
-++	const char *name;
-+ 	ssize_t ret_cnt;
-++	bool enabled;
-+ 	int i;
-+ 
-+ 	buf = kzalloc(buf_len, GFP_KERNEL);
-+@@ -129,16 +198,25 @@ static ssize_t ath10k_read_wmi_services(
-+ 	if (len > buf_len)
-+ 		len = buf_len;
-+ 
-+-	for (i = 0; i < WMI_SERVICE_LAST; i++) {
-+-		if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i))
-+-			status = "enabled";
-+-		else
-+-			status = "disabled";
-++	spin_lock_bh(&ar->data_lock);
-++	for (i = 0; i < WMI_SERVICE_MAX; i++) {
-++		enabled = test_bit(i, ar->wmi.svc_map);
-++		name = wmi_service_name(i);
-++
-++		if (!name) {
-++			if (enabled)
-++				len += scnprintf(buf + len, buf_len - len,
-++						 "%-40s %s (bit %d)\n",
-++						 "unknown", "enabled", i);
-++
-++			continue;
-++		}
-+ 
-+ 		len += scnprintf(buf + len, buf_len - len,
-+-				 "0x%02x - %20s - %s\n",
-+-				 i, wmi_service_name(i), status);
-++				 "%-40s %s\n",
-++				 name, enabled ? "enabled" : "-");
-+ 	}
-++	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+ 
-+@@ -155,169 +233,221 @@ static const struct file_operations fops
-+ 	.llseek = default_llseek,
-+ };
-+ 
-+-void ath10k_debug_read_target_stats(struct ath10k *ar,
-+-				    struct wmi_stats_event *ev)
-++static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
-+ {
-+-	u8 *tmp = ev->data;
-+-	struct ath10k_target_stats *stats;
-+-	int num_pdev_stats, num_vdev_stats, num_peer_stats;
-+-	struct wmi_pdev_stats_10x *ps;
-+-	int i;
-++	struct ath10k_fw_stats_pdev *i, *tmp;
-+ 
-++	list_for_each_entry_safe(i, tmp, head, list) {
-++		list_del(&i->list);
-++		kfree(i);
-++	}
-++}
-++
-++static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
-++{
-++	struct ath10k_fw_stats_vdev *i, *tmp;
-++
-++	list_for_each_entry_safe(i, tmp, head, list) {
-++		list_del(&i->list);
-++		kfree(i);
-++	}
-++}
-++
-++static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
-++{
-++	struct ath10k_fw_stats_peer *i, *tmp;
-++
-++	list_for_each_entry_safe(i, tmp, head, list) {
-++		list_del(&i->list);
-++		kfree(i);
-++	}
-++}
-++
-++static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
-++{
-+ 	spin_lock_bh(&ar->data_lock);
-++	ar->debug.fw_stats_done = false;
-++	ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
-++	ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
-++	ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
-++	spin_unlock_bh(&ar->data_lock);
-++}
-+ 
-+-	stats = &ar->debug.target_stats;
-++static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
-++{
-++	struct ath10k_fw_stats_peer *i;
-++	size_t num = 0;
-+ 
-+-	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */
-+-	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */
-+-	num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */
-+-
-+-	if (num_pdev_stats) {
-+-		ps = (struct wmi_pdev_stats_10x *)tmp;
-+-
-+-		stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf);
-+-		stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count);
-+-		stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count);
-+-		stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count);
-+-		stats->cycle_count = __le32_to_cpu(ps->cycle_count);
-+-		stats->phy_err_count = __le32_to_cpu(ps->phy_err_count);
-+-		stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr);
-+-
-+-		stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued);
-+-		stats->comp_delivered =
-+-			__le32_to_cpu(ps->wal.tx.comp_delivered);
-+-		stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued);
-+-		stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued);
-+-		stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop);
-+-		stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued);
-+-		stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed);
-+-		stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued);
-+-		stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped);
-+-		stats->underrun = __le32_to_cpu(ps->wal.tx.underrun);
-+-		stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort);
-+-		stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed);
-+-		stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko);
-+-		stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc);
-+-		stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers);
-+-		stats->sw_retry_failure =
-+-			__le32_to_cpu(ps->wal.tx.sw_retry_failure);
-+-		stats->illgl_rate_phy_err =
-+-			__le32_to_cpu(ps->wal.tx.illgl_rate_phy_err);
-+-		stats->pdev_cont_xretry =
-+-			__le32_to_cpu(ps->wal.tx.pdev_cont_xretry);
-+-		stats->pdev_tx_timeout =
-+-			__le32_to_cpu(ps->wal.tx.pdev_tx_timeout);
-+-		stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets);
-+-		stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun);
-+-		stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf);
-+-
-+-		stats->mid_ppdu_route_change =
-+-			__le32_to_cpu(ps->wal.rx.mid_ppdu_route_change);
-+-		stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd);
-+-		stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags);
-+-		stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags);
-+-		stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags);
-+-		stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags);
-+-		stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus);
-+-		stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus);
-+-		stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus);
-+-		stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus);
-+-		stats->oversize_amsdu =
-+-			__le32_to_cpu(ps->wal.rx.oversize_amsdu);
-+-		stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs);
-+-		stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop);
-+-		stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs);
-+-
-+-		if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
-+-			     ar->fw_features)) {
-+-			stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad);
-+-			stats->rts_bad = __le32_to_cpu(ps->rts_bad);
-+-			stats->rts_good = __le32_to_cpu(ps->rts_good);
-+-			stats->fcs_bad = __le32_to_cpu(ps->fcs_bad);
-+-			stats->no_beacons = __le32_to_cpu(ps->no_beacons);
-+-			stats->mib_int_count = __le32_to_cpu(ps->mib_int_count);
-+-			tmp += sizeof(struct wmi_pdev_stats_10x);
-+-		} else {
-+-			tmp += sizeof(struct wmi_pdev_stats_old);
-+-		}
-++	list_for_each_entry(i, head, list)
-++		++num;
-++
-++	return num;
-++}
-++
-++static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
-++{
-++	struct ath10k_fw_stats_vdev *i;
-++	size_t num = 0;
-++
-++	list_for_each_entry(i, head, list)
-++		++num;
-++
-++	return num;
-++}
-++
-++void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct ath10k_fw_stats stats = {};
-++	bool is_start, is_started, is_end;
-++	size_t num_peers;
-++	size_t num_vdevs;
-++	int ret;
-++
-++	INIT_LIST_HEAD(&stats.pdevs);
-++	INIT_LIST_HEAD(&stats.vdevs);
-++	INIT_LIST_HEAD(&stats.peers);
-++
-++	spin_lock_bh(&ar->data_lock);
-++	ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
-++		goto unlock;
-+ 	}
-+ 
-+-	/* 0 or max vdevs */
-+-	/* Currently firmware does not support VDEV stats */
-+-	if (num_vdev_stats) {
-+-		struct wmi_vdev_stats *vdev_stats;
-+-
-+-		for (i = 0; i < num_vdev_stats; i++) {
-+-			vdev_stats = (struct wmi_vdev_stats *)tmp;
-+-			tmp += sizeof(struct wmi_vdev_stats);
-+-		}
-++	/* Stat data may exceed htc-wmi buffer limit. In such case firmware
-++	 * splits the stats data and delivers it in a ping-pong fashion of
-++	 * request cmd-update event.
-++	 *
-++	 * However there is no explicit end-of-data. Instead start-of-data is
-++	 * used as an implicit one. This works as follows:
-++	 *  a) discard stat update events until one with pdev stats is
-++	 *     delivered - this skips session started at end of (b)
-++	 *  b) consume stat update events until another one with pdev stats is
-++	 *     delivered which is treated as end-of-data and is itself discarded
-++	 */
-++
-++	if (ar->debug.fw_stats_done) {
-++		ath10k_warn(ar, "received unsolicited stats update event\n");
-++		goto free;
-+ 	}
-+ 
-+-	if (num_peer_stats) {
-+-		struct wmi_peer_stats_10x *peer_stats;
-+-		struct ath10k_peer_stat *s;
-+-
-+-		stats->peers = num_peer_stats;
-+-
-+-		for (i = 0; i < num_peer_stats; i++) {
-+-			peer_stats = (struct wmi_peer_stats_10x *)tmp;
-+-			s = &stats->peer_stat[i];
-+-
-+-			memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr,
-+-			       ETH_ALEN);
-+-			s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi);
-+-			s->peer_tx_rate =
-+-				__le32_to_cpu(peer_stats->peer_tx_rate);
-+-			if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
-+-				     ar->fw_features)) {
-+-				s->peer_rx_rate =
-+-					__le32_to_cpu(peer_stats->peer_rx_rate);
-+-				tmp += sizeof(struct wmi_peer_stats_10x);
-+-
-+-			} else {
-+-				tmp += sizeof(struct wmi_peer_stats_old);
-+-			}
-++	num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
-++	num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
-++	is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
-++		    !list_empty(&stats.pdevs));
-++	is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
-++		  !list_empty(&stats.pdevs));
-++
-++	if (is_start)
-++		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
-++
-++	if (is_end)
-++		ar->debug.fw_stats_done = true;
-++
-++	is_started = !list_empty(&ar->debug.fw_stats.pdevs);
-++
-++	if (is_started && !is_end) {
-++		if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
-++			/* Although this is unlikely impose a sane limit to
-++			 * prevent firmware from DoS-ing the host.
-++			 */
-++			ath10k_warn(ar, "dropping fw peer stats\n");
-++			goto free;
-+ 		}
-++
-++		if (num_vdevs >= BITS_PER_LONG) {
-++			ath10k_warn(ar, "dropping fw vdev stats\n");
-++			goto free;
-++		}
-++
-++		list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
-++		list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
-+ 	}
-+ 
-++	complete(&ar->debug.fw_stats_complete);
-++
-++free:
-++	/* In some cases lists have been spliced and cleared. Free up
-++	 * resources if that is not the case.
-++	 */
-++	ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
-++	ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
-++	ath10k_debug_fw_stats_peers_free(&stats.peers);
-++
-++unlock:
-+ 	spin_unlock_bh(&ar->data_lock);
-+-	complete(&ar->debug.event_stats_compl);
-+ }
-+ 
-+-static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
-+-				    size_t count, loff_t *ppos)
-++static int ath10k_debug_fw_stats_request(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar = file->private_data;
-+-	struct ath10k_target_stats *fw_stats;
-+-	char *buf = NULL;
-+-	unsigned int len = 0, buf_len = 8000;
-+-	ssize_t ret_cnt = 0;
-+-	long left;
-+-	int i;
-++	unsigned long timeout;
-+ 	int ret;
-+ 
-+-	fw_stats = &ar->debug.target_stats;
-++	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	mutex_lock(&ar->conf_mutex);
-++	timeout = jiffies + msecs_to_jiffies(1*HZ);
-+ 
-+-	if (ar->state != ATH10K_STATE_ON)
-+-		goto exit;
-++	ath10k_debug_fw_stats_reset(ar);
-+ 
-+-	buf = kzalloc(buf_len, GFP_KERNEL);
-+-	if (!buf)
-+-		goto exit;
-++	for (;;) {
-++		if (time_after(jiffies, timeout))
-++			return -ETIMEDOUT;
-+ 
-+-	ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
-+-	if (ret) {
-+-		ath10k_warn("could not request stats (%d)\n", ret);
-+-		goto exit;
-++		reinit_completion(&ar->debug.fw_stats_complete);
-++
-++		ret = ath10k_wmi_request_stats(ar,
-++					       WMI_STAT_PDEV |
-++					       WMI_STAT_VDEV |
-++					       WMI_STAT_PEER);
-++		if (ret) {
-++			ath10k_warn(ar, "could not request stats (%d)\n", ret);
-++			return ret;
-++		}
-++
-++		ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
-++						  1*HZ);
-++		if (ret == 0)
-++			return -ETIMEDOUT;
-++
-++		spin_lock_bh(&ar->data_lock);
-++		if (ar->debug.fw_stats_done) {
-++			spin_unlock_bh(&ar->data_lock);
-++			break;
-++		}
-++		spin_unlock_bh(&ar->data_lock);
-+ 	}
-+ 
-+-	left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
-+-	if (left <= 0)
-+-		goto exit;
-++	return 0;
-++}
-++
-++/* FIXME: How to calculate the buffer size sanely? */
-++#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-++
-++static void ath10k_fw_stats_fill(struct ath10k *ar,
-++				 struct ath10k_fw_stats *fw_stats,
-++				 char *buf)
-++{
-++	unsigned int len = 0;
-++	unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
-++	const struct ath10k_fw_stats_pdev *pdev;
-++	const struct ath10k_fw_stats_vdev *vdev;
-++	const struct ath10k_fw_stats_peer *peer;
-++	size_t num_peers;
-++	size_t num_vdevs;
-++	int i;
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-++
-++	pdev = list_first_entry_or_null(&fw_stats->pdevs,
-++					struct ath10k_fw_stats_pdev, list);
-++	if (!pdev) {
-++		ath10k_warn(ar, "failed to get pdev stats\n");
-++		goto unlock;
-++	}
-++
-++	num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
-++	num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
-++
-+ 	len += scnprintf(buf + len, buf_len - len, "\n");
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
-+ 			 "ath10k PDEV stats");
-+@@ -325,29 +455,29 @@ static ssize_t ath10k_read_fw_stats(stru
-+ 				 "=================");
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Channel noise floor", fw_stats->ch_noise_floor);
-++			 "Channel noise floor", pdev->ch_noise_floor);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "Channel TX power", fw_stats->chan_tx_power);
-++			 "Channel TX power", pdev->chan_tx_power);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "TX frame count", fw_stats->tx_frame_count);
-++			 "TX frame count", pdev->tx_frame_count);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "RX frame count", fw_stats->rx_frame_count);
-++			 "RX frame count", pdev->rx_frame_count);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "RX clear count", fw_stats->rx_clear_count);
-++			 "RX clear count", pdev->rx_clear_count);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "Cycle count", fw_stats->cycle_count);
-++			 "Cycle count", pdev->cycle_count);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "PHY error count", fw_stats->phy_err_count);
-++			 "PHY error count", pdev->phy_err_count);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "RTS bad count", fw_stats->rts_bad);
-++			 "RTS bad count", pdev->rts_bad);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "RTS good count", fw_stats->rts_good);
-++			 "RTS good count", pdev->rts_good);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "FCS bad count", fw_stats->fcs_bad);
-++			 "FCS bad count", pdev->fcs_bad);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "No beacon count", fw_stats->no_beacons);
-++			 "No beacon count", pdev->no_beacons);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
-+-			 "MIB int count", fw_stats->mib_int_count);
-++			 "MIB int count", pdev->mib_int_count);
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "\n");
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
-+@@ -356,51 +486,51 @@ static ssize_t ath10k_read_fw_stats(stru
-+ 				 "=================");
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "HTT cookies queued", fw_stats->comp_queued);
-++			 "HTT cookies queued", pdev->comp_queued);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "HTT cookies disp.", fw_stats->comp_delivered);
-++			 "HTT cookies disp.", pdev->comp_delivered);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MSDU queued", fw_stats->msdu_enqued);
-++			 "MSDU queued", pdev->msdu_enqued);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDU queued", fw_stats->mpdu_enqued);
-++			 "MPDU queued", pdev->mpdu_enqued);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MSDUs dropped", fw_stats->wmm_drop);
-++			 "MSDUs dropped", pdev->wmm_drop);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Local enqued", fw_stats->local_enqued);
-++			 "Local enqued", pdev->local_enqued);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Local freed", fw_stats->local_freed);
-++			 "Local freed", pdev->local_freed);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "HW queued", fw_stats->hw_queued);
-++			 "HW queued", pdev->hw_queued);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PPDUs reaped", fw_stats->hw_reaped);
-++			 "PPDUs reaped", pdev->hw_reaped);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Num underruns", fw_stats->underrun);
-++			 "Num underruns", pdev->underrun);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PPDUs cleaned", fw_stats->tx_abort);
-++			 "PPDUs cleaned", pdev->tx_abort);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDUs requed", fw_stats->mpdus_requed);
-++			 "MPDUs requed", pdev->mpdus_requed);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Excessive retries", fw_stats->tx_ko);
-++			 "Excessive retries", pdev->tx_ko);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "HW rate", fw_stats->data_rc);
-++			 "HW rate", pdev->data_rc);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Sched self tiggers", fw_stats->self_triggers);
-++			 "Sched self tiggers", pdev->self_triggers);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+ 			 "Dropped due to SW retries",
-+-			 fw_stats->sw_retry_failure);
-++			 pdev->sw_retry_failure);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+ 			 "Illegal rate phy errors",
-+-			 fw_stats->illgl_rate_phy_err);
-++			 pdev->illgl_rate_phy_err);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Pdev continous xretry", fw_stats->pdev_cont_xretry);
-++			 "Pdev continous xretry", pdev->pdev_cont_xretry);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "TX timeout", fw_stats->pdev_tx_timeout);
-++			 "TX timeout", pdev->pdev_tx_timeout);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PDEV resets", fw_stats->pdev_resets);
-++			 "PDEV resets", pdev->pdev_resets);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PHY underrun", fw_stats->phy_underrun);
-++			 "PHY underrun", pdev->phy_underrun);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDU is more than txop limit", fw_stats->txop_ovf);
-++			 "MPDU is more than txop limit", pdev->txop_ovf);
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "\n");
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s\n",
-+@@ -410,84 +540,254 @@ static ssize_t ath10k_read_fw_stats(stru
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+ 			 "Mid PPDU route change",
-+-			 fw_stats->mid_ppdu_route_change);
-++			 pdev->mid_ppdu_route_change);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Tot. number of statuses", fw_stats->status_rcvd);
-++			 "Tot. number of statuses", pdev->status_rcvd);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Extra frags on rings 0", fw_stats->r0_frags);
-++			 "Extra frags on rings 0", pdev->r0_frags);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Extra frags on rings 1", fw_stats->r1_frags);
-++			 "Extra frags on rings 1", pdev->r1_frags);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Extra frags on rings 2", fw_stats->r2_frags);
-++			 "Extra frags on rings 2", pdev->r2_frags);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Extra frags on rings 3", fw_stats->r3_frags);
-++			 "Extra frags on rings 3", pdev->r3_frags);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MSDUs delivered to HTT", fw_stats->htt_msdus);
-++			 "MSDUs delivered to HTT", pdev->htt_msdus);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDUs delivered to HTT", fw_stats->htt_mpdus);
-++			 "MPDUs delivered to HTT", pdev->htt_mpdus);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MSDUs delivered to stack", fw_stats->loc_msdus);
-++			 "MSDUs delivered to stack", pdev->loc_msdus);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDUs delivered to stack", fw_stats->loc_mpdus);
-++			 "MPDUs delivered to stack", pdev->loc_mpdus);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "Oversized AMSUs", fw_stats->oversize_amsdu);
-++			 "Oversized AMSUs", pdev->oversize_amsdu);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PHY errors", fw_stats->phy_errs);
-++			 "PHY errors", pdev->phy_errs);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "PHY errors drops", fw_stats->phy_err_drop);
-++			 "PHY errors drops", pdev->phy_err_drop);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
-+-			 "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs);
-++			 "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
-++
-++	len += scnprintf(buf + len, buf_len - len, "\n");
-++	len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
-++			 "ath10k VDEV stats", num_vdevs);
-++	len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
-++				 "=================");
-++
-++	list_for_each_entry(vdev, &fw_stats->vdevs, list) {
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "vdev id", vdev->vdev_id);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "beacon snr", vdev->beacon_snr);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "data snr", vdev->data_snr);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num rx frames", vdev->num_rx_frames);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num rts fail", vdev->num_rts_fail);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num rts success", vdev->num_rts_success);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num rx err", vdev->num_rx_err);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num rx discard", vdev->num_rx_discard);
-++		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-++				 "num tx not acked", vdev->num_tx_not_acked);
-++
-++		for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
-++			len += scnprintf(buf + len, buf_len - len,
-++					"%25s [%02d] %u\n",
-++					 "num tx frames", i,
-++					 vdev->num_tx_frames[i]);
-++
-++		for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
-++			len += scnprintf(buf + len, buf_len - len,
-++					"%25s [%02d] %u\n",
-++					 "num tx frames retries", i,
-++					 vdev->num_tx_frames_retries[i]);
-++
-++		for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
-++			len += scnprintf(buf + len, buf_len - len,
-++					"%25s [%02d] %u\n",
-++					 "num tx frames failures", i,
-++					 vdev->num_tx_frames_failures[i]);
-++
-++		for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
-++			len += scnprintf(buf + len, buf_len - len,
-++					"%25s [%02d] 0x%08x\n",
-++					 "tx rate history", i,
-++					 vdev->tx_rate_history[i]);
-++
-++		for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
-++			len += scnprintf(buf + len, buf_len - len,
-++					"%25s [%02d] %u\n",
-++					 "beacon rssi history", i,
-++					 vdev->beacon_rssi_history[i]);
-++
-++		len += scnprintf(buf + len, buf_len - len, "\n");
-++	}
-+ 
-+ 	len += scnprintf(buf + len, buf_len - len, "\n");
-+-	len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n",
-+-			 "ath10k PEER stats", fw_stats->peers);
-++	len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
-++			 "ath10k PEER stats", num_peers);
-+ 	len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
-+ 				 "=================");
-+ 
-+-	for (i = 0; i < fw_stats->peers; i++) {
-++	list_for_each_entry(peer, &fw_stats->peers, list) {
-+ 		len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
-+-				 "Peer MAC address",
-+-				 fw_stats->peer_stat[i].peer_macaddr);
-++				 "Peer MAC address", peer->peer_macaddr);
-+ 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-+-				 "Peer RSSI", fw_stats->peer_stat[i].peer_rssi);
-++				 "Peer RSSI", peer->peer_rssi);
-+ 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-+-				 "Peer TX rate",
-+-				 fw_stats->peer_stat[i].peer_tx_rate);
-++				 "Peer TX rate", peer->peer_tx_rate);
-+ 		len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
-+-				 "Peer RX rate",
-+-				 fw_stats->peer_stat[i].peer_rx_rate);
-++				 "Peer RX rate", peer->peer_rx_rate);
-+ 		len += scnprintf(buf + len, buf_len - len, "\n");
-+ 	}
-++
-++unlock:
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-+-	if (len > buf_len)
-+-		len = buf_len;
-++	if (len >= buf_len)
-++		buf[len - 1] = 0;
-++	else
-++		buf[len] = 0;
-++}
-+ 
-+-	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
-++{
-++	struct ath10k *ar = inode->i_private;
-++	void *buf = NULL;
-++	int ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_ON) {
-++		ret = -ENETDOWN;
-++		goto err_unlock;
-++	}
-++
-++	buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
-++	if (!buf) {
-++		ret = -ENOMEM;
-++		goto err_unlock;
-++	}
-++
-++	ret = ath10k_debug_fw_stats_request(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
-++		goto err_free;
-++	}
-++
-++	ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
-++	file->private_data = buf;
-+ 
-+-exit:
-+ 	mutex_unlock(&ar->conf_mutex);
-+-	kfree(buf);
-+-	return ret_cnt;
-++	return 0;
-++
-++err_free:
-++	vfree(buf);
-++
-++err_unlock:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
-++{
-++	vfree(file->private_data);
-++
-++	return 0;
-++}
-++
-++static ssize_t ath10k_fw_stats_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_fw_stats = {
-+-	.read = ath10k_read_fw_stats,
-++	.open = ath10k_fw_stats_open,
-++	.release = ath10k_fw_stats_release,
-++	.read = ath10k_fw_stats_read,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
-++						char __user *user_buf,
-++						size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	int ret, len, buf_len;
-++	char *buf;
-++
-++	buf_len = 500;
-++	buf = kmalloc(buf_len, GFP_KERNEL);
-++	if (!buf)
-++		return -ENOMEM;
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	len = 0;
-++	len += scnprintf(buf + len, buf_len - len,
-++			 "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
-++	len += scnprintf(buf + len, buf_len - len,
-++			 "fw_warm_reset_counter\t\t%d\n",
-++			 ar->stats.fw_warm_reset_counter);
-++	len += scnprintf(buf + len, buf_len - len,
-++			 "fw_cold_reset_counter\t\t%d\n",
-++			 ar->stats.fw_cold_reset_counter);
-++
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++
-++	kfree(buf);
-++
-++	return ret;
-++}
-++
-++static const struct file_operations fops_fw_reset_stats = {
-+ 	.open = simple_open,
-++	.read = ath10k_debug_fw_reset_stats_read,
-+ 	.owner = THIS_MODULE,
-+ 	.llseek = default_llseek,
-+ };
-+ 
-++/* This is a clean assert crash in firmware. */
-++static int ath10k_debug_fw_assert(struct ath10k *ar)
-++{
-++	struct wmi_vdev_install_key_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
-++	if (!skb)
-++		return -ENOMEM;
-++
-++	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
-++	memset(cmd, 0, sizeof(*cmd));
-++
-++	/* big enough number so that firmware asserts */
-++	cmd->vdev_id = __cpu_to_le32(0x7ffe);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->vdev_install_key_cmdid);
-++}
-++
-+ static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
-+ 					     char __user *user_buf,
-+ 					     size_t count, loff_t *ppos)
-+ {
-+-	const char buf[] = "To simulate firmware crash write one of the"
-+-			   " keywords to this file:\n `soft` - this will send"
-+-			   " WMI_FORCE_FW_HANG_ASSERT to firmware if FW"
-+-			   " supports that command.\n `hard` - this will send"
-+-			   " to firmware command with illegal parameters"
-+-			   " causing firmware crash.\n";
-++	const char buf[] =
-++		"To simulate firmware crash write one of the keywords to this file:\n"
-++		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
-++		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
-++		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
-++		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
-+ 
-+ 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
-+ }
-+@@ -527,19 +827,30 @@ static ssize_t ath10k_write_simulate_fw_
-+ 	}
-+ 
-+ 	if (!strcmp(buf, "soft")) {
-+-		ath10k_info("simulating soft firmware crash\n");
-++		ath10k_info(ar, "simulating soft firmware crash\n");
-+ 		ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
-+ 	} else if (!strcmp(buf, "hard")) {
-+-		ath10k_info("simulating hard firmware crash\n");
-+-		ret = ath10k_wmi_vdev_set_param(ar, TARGET_NUM_VDEVS + 1,
-+-					ar->wmi.vdev_param->rts_threshold, 0);
-++		ath10k_info(ar, "simulating hard firmware crash\n");
-++		/* 0x7fff is vdev id, and it is always out of range for all
-++		 * firmware variants in order to force a firmware crash.
-++		 */
-++		ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
-++						ar->wmi.vdev_param->rts_threshold,
-++						0);
-++	} else if (!strcmp(buf, "assert")) {
-++		ath10k_info(ar, "simulating firmware assert crash\n");
-++		ret = ath10k_debug_fw_assert(ar);
-++	} else if (!strcmp(buf, "hw-restart")) {
-++		ath10k_info(ar, "user requested hw restart\n");
-++		queue_work(ar->workqueue, &ar->restart_work);
-++		ret = 0;
-+ 	} else {
-+ 		ret = -EINVAL;
-+ 		goto exit;
-+ 	}
-+ 
-+ 	if (ret) {
-+-		ath10k_warn("failed to simulate firmware crash: %d\n", ret);
-++		ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+@@ -565,13 +876,375 @@ static ssize_t ath10k_read_chip_id(struc
-+ 	unsigned int len;
-+ 	char buf[50];
-+ 
-+-	len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
-++	len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
-++
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static const struct file_operations fops_chip_id = {
-++	.read = ath10k_read_chip_id,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++struct ath10k_fw_crash_data *
-++ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
-++{
-++	struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
-++
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	crash_data->crashed_since_read = true;
-++	uuid_le_gen(&crash_data->uuid);
-++	getnstimeofday(&crash_data->timestamp);
-++
-++	return crash_data;
-++}
-++EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
-++
-++static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
-++{
-++	struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
-++	struct ath10k_dump_file_data *dump_data;
-++	struct ath10k_tlv_dump_data *dump_tlv;
-++	int hdr_len = sizeof(*dump_data);
-++	unsigned int len, sofar = 0;
-++	unsigned char *buf;
-++
-++	len = hdr_len;
-++	len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
-++
-++	sofar += hdr_len;
-++
-++	/* This is going to get big when we start dumping FW RAM and such,
-++	 * so go ahead and use vmalloc.
-++	 */
-++	buf = vzalloc(len);
-++	if (!buf)
-++		return NULL;
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	if (!crash_data->crashed_since_read) {
-++		spin_unlock_bh(&ar->data_lock);
-++		vfree(buf);
-++		return NULL;
-++	}
-++
-++	dump_data = (struct ath10k_dump_file_data *)(buf);
-++	strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
-++		sizeof(dump_data->df_magic));
-++	dump_data->len = cpu_to_le32(len);
-++
-++	dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
-++
-++	memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
-++	dump_data->chip_id = cpu_to_le32(ar->chip_id);
-++	dump_data->bus_type = cpu_to_le32(0);
-++	dump_data->target_version = cpu_to_le32(ar->target_version);
-++	dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
-++	dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
-++	dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
-++	dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
-++	dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
-++	dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
-++	dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
-++	dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
-++	dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
-++	dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
-++
-++	strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
-++		sizeof(dump_data->fw_ver));
-++
-++	dump_data->kernel_ver_code = 0;
-++	strlcpy(dump_data->kernel_ver, init_utsname()->release,
-++		sizeof(dump_data->kernel_ver));
-++
-++	dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
-++	dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
-++
-++	/* Gather crash-dump */
-++	dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
-++	dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
-++	dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
-++	memcpy(dump_tlv->tlv_data, &crash_data->registers,
-++	       sizeof(crash_data->registers));
-++	sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
-++
-++	ar->debug.fw_crash_data->crashed_since_read = false;
-++
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	return dump_data;
-++}
-++
-++static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
-++{
-++	struct ath10k *ar = inode->i_private;
-++	struct ath10k_dump_file_data *dump;
-++
-++	dump = ath10k_build_dump_file(ar);
-++	if (!dump)
-++		return -ENODATA;
-++
-++	file->private_data = dump;
-++
-++	return 0;
-++}
-++
-++static ssize_t ath10k_fw_crash_dump_read(struct file *file,
-++					 char __user *user_buf,
-++					 size_t count, loff_t *ppos)
-++{
-++	struct ath10k_dump_file_data *dump_file = file->private_data;
-++
-++	return simple_read_from_buffer(user_buf, count, ppos,
-++				       dump_file,
-++				       le32_to_cpu(dump_file->len));
-++}
-++
-++static int ath10k_fw_crash_dump_release(struct inode *inode,
-++					struct file *file)
-++{
-++	vfree(file->private_data);
-++
-++	return 0;
-++}
-++
-++static const struct file_operations fops_fw_crash_dump = {
-++	.open = ath10k_fw_crash_dump_open,
-++	.read = ath10k_fw_crash_dump_read,
-++	.release = ath10k_fw_crash_dump_release,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_reg_addr_read(struct file *file,
-++				    char __user *user_buf,
-++				    size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u8 buf[32];
-++	unsigned int len = 0;
-++	u32 reg_addr;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	reg_addr = ar->debug.reg_addr;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
-++
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t ath10k_reg_addr_write(struct file *file,
-++				     const char __user *user_buf,
-++				     size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u32 reg_addr;
-++	int ret;
-++
-++	ret = kstrtou32_from_user(user_buf, count, 0, &reg_addr);
-++	if (ret)
-++		return ret;
-++
-++	if (!IS_ALIGNED(reg_addr, 4))
-++		return -EFAULT;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	ar->debug.reg_addr = reg_addr;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return count;
-++}
-++
-++static const struct file_operations fops_reg_addr = {
-++	.read = ath10k_reg_addr_read,
-++	.write = ath10k_reg_addr_write,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_reg_value_read(struct file *file,
-++				     char __user *user_buf,
-++				     size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u8 buf[48];
-++	unsigned int len;
-++	u32 reg_addr, reg_val;
-++	int ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_ON &&
-++	    ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto exit;
-++	}
-++
-++	reg_addr = ar->debug.reg_addr;
-++
-++	reg_val = ath10k_hif_read32(ar, reg_addr);
-++	len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
-++
-++	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++
-++exit:
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static ssize_t ath10k_reg_value_write(struct file *file,
-++				      const char __user *user_buf,
-++				      size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u32 reg_addr, reg_val;
-++	int ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_ON &&
-++	    ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto exit;
-++	}
-++
-++	reg_addr = ar->debug.reg_addr;
-++
-++	ret = kstrtou32_from_user(user_buf, count, 0, &reg_val);
-++	if (ret)
-++		goto exit;
-++
-++	ath10k_hif_write32(ar, reg_addr, reg_val);
-++
-++	ret = count;
-++
-++exit:
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static const struct file_operations fops_reg_value = {
-++	.read = ath10k_reg_value_read,
-++	.write = ath10k_reg_value_write,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_mem_value_read(struct file *file,
-++				     char __user *user_buf,
-++				     size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u8 *buf;
-++	int ret;
-++
-++	if (*ppos < 0)
-++		return -EINVAL;
-++
-++	if (!count)
-++		return 0;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	buf = vmalloc(count);
-++	if (!buf) {
-++		ret = -ENOMEM;
-++		goto exit;
-++	}
-++
-++	if (ar->state != ATH10K_STATE_ON &&
-++	    ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto exit;
-++	}
-++
-++	ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
-++			    (u32)(*ppos), ret);
-++		goto exit;
-++	}
-++
-++	ret = copy_to_user(user_buf, buf, count);
-++	if (ret) {
-++		ret = -EFAULT;
-++		goto exit;
-++	}
-++
-++	count -= ret;
-++	*ppos += count;
-++	ret = count;
-++
-++exit:
-++	vfree(buf);
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static ssize_t ath10k_mem_value_write(struct file *file,
-++				      const char __user *user_buf,
-++				      size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u8 *buf;
-++	int ret;
-++
-++	if (*ppos < 0)
-++		return -EINVAL;
-++
-++	if (!count)
-++		return 0;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	buf = vmalloc(count);
-++	if (!buf) {
-++		ret = -ENOMEM;
-++		goto exit;
-++	}
-++
-++	if (ar->state != ATH10K_STATE_ON &&
-++	    ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto exit;
-++	}
-++
-++	ret = copy_from_user(buf, user_buf, count);
-++	if (ret) {
-++		ret = -EFAULT;
-++		goto exit;
-++	}
-++
-++	ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
-++			    (u32)(*ppos), ret);
-++		goto exit;
-++	}
-++
-++	*ppos += count;
-++	ret = count;
-+ 
-+-	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++exit:
-++	vfree(buf);
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-+ }
-+ 
-+-static const struct file_operations fops_chip_id = {
-+-	.read = ath10k_read_chip_id,
-++static const struct file_operations fops_mem_value = {
-++	.read = ath10k_mem_value_read,
-++	.write = ath10k_mem_value_write,
-+ 	.open = simple_open,
-+ 	.owner = THIS_MODULE,
-+ 	.llseek = default_llseek,
-+@@ -596,7 +1269,7 @@ static int ath10k_debug_htt_stats_req(st
-+ 	ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
-+ 				       cookie);
-+ 	if (ret) {
-+-		ath10k_warn("failed to send htt stats request: %d\n", ret);
-++		ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+@@ -619,8 +1292,8 @@ static void ath10k_debug_htt_stats_dwork
-+ }
-+ 
-+ static ssize_t ath10k_read_htt_stats_mask(struct file *file,
-+-					    char __user *user_buf,
-+-					    size_t count, loff_t *ppos)
-++					  char __user *user_buf,
-++					  size_t count, loff_t *ppos)
-+ {
-+ 	struct ath10k *ar = file->private_data;
-+ 	char buf[32];
-+@@ -632,8 +1305,8 @@ static ssize_t ath10k_read_htt_stats_mas
-+ }
-+ 
-+ static ssize_t ath10k_write_htt_stats_mask(struct file *file,
-+-					     const char __user *user_buf,
-+-					     size_t count, loff_t *ppos)
-++					   const char __user *user_buf,
-++					   size_t count, loff_t *ppos)
-+ {
-+ 	struct ath10k *ar = file->private_data;
-+ 	unsigned long mask;
-+@@ -671,16 +1344,82 @@ static const struct file_operations fops
-+ 	.llseek = default_llseek,
-+ };
-+ 
-++static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
-++					       char __user *user_buf,
-++					       size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	char buf[64];
-++	u8 amsdu = 3, ampdu = 64;
-++	unsigned int len;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->debug.htt_max_amsdu)
-++		amsdu = ar->debug.htt_max_amsdu;
-++
-++	if (ar->debug.htt_max_ampdu)
-++		ampdu = ar->debug.htt_max_ampdu;
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
-++
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
-++						const char __user *user_buf,
-++						size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	int res;
-++	char buf[64];
-++	unsigned int amsdu, ampdu;
-++
-++	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
-++
-++	/* make sure that buf is null terminated */
-++	buf[sizeof(buf) - 1] = 0;
-++
-++	res = sscanf(buf, "%u %u", &amsdu, &ampdu);
-++
-++	if (res != 2)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
-++	if (res)
-++		goto out;
-++
-++	res = count;
-++	ar->debug.htt_max_amsdu = amsdu;
-++	ar->debug.htt_max_ampdu = ampdu;
-++
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return res;
-++}
-++
-++static const struct file_operations fops_htt_max_amsdu_ampdu = {
-++	.read = ath10k_read_htt_max_amsdu_ampdu,
-++	.write = ath10k_write_htt_max_amsdu_ampdu,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-+ static ssize_t ath10k_read_fw_dbglog(struct file *file,
-+-					    char __user *user_buf,
-+-					    size_t count, loff_t *ppos)
-++				     char __user *user_buf,
-++				     size_t count, loff_t *ppos)
-+ {
-+ 	struct ath10k *ar = file->private_data;
-+ 	unsigned int len;
-+-	char buf[32];
-++	char buf[64];
-+ 
-+-	len = scnprintf(buf, sizeof(buf), "0x%08x\n",
-+-			ar->debug.fw_dbglog_mask);
-++	len = scnprintf(buf, sizeof(buf), "0x%08x %u\n",
-++			ar->debug.fw_dbglog_mask, ar->debug.fw_dbglog_level);
-+ 
-+ 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+ }
-+@@ -690,21 +1429,34 @@ static ssize_t ath10k_write_fw_dbglog(st
-+ 				      size_t count, loff_t *ppos)
-+ {
-+ 	struct ath10k *ar = file->private_data;
-+-	unsigned long mask;
-+ 	int ret;
-++	char buf[64];
-++	unsigned int log_level, mask;
-+ 
-+-	ret = kstrtoul_from_user(user_buf, count, 0, &mask);
-+-	if (ret)
-+-		return ret;
-++	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
-++
-++	/* make sure that buf is null terminated */
-++	buf[sizeof(buf) - 1] = 0;
-++
-++	ret = sscanf(buf, "%x %u", &mask, &log_level);
-++
-++	if (!ret)
-++		return -EINVAL;
-++
-++	if (ret == 1)
-++		/* default if user did not specify */
-++		log_level = ATH10K_DBGLOG_LEVEL_WARN;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	ar->debug.fw_dbglog_mask = mask;
-++	ar->debug.fw_dbglog_level = log_level;
-+ 
-+ 	if (ar->state == ATH10K_STATE_ON) {
-+-		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
-++		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
-++					    ar->debug.fw_dbglog_level);
-+ 		if (ret) {
-+-			ath10k_warn("dbglog cfg failed from debugfs: %d\n",
-++			ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
-+ 				    ret);
-+ 			goto exit;
-+ 		}
-+@@ -718,6 +1470,166 @@ exit:
-+ 	return ret;
-+ }
-+ 
-++/* TODO:  Would be nice to always support ethtool stats, would need to
-++ * move the stats storage out of ath10k_debug, or always have ath10k_debug
-++ * struct available..
-++ */
-++
-++/* This generally cooresponds to the debugfs fw_stats file */
-++static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
-++	"tx_pkts_nic",
-++	"tx_bytes_nic",
-++	"rx_pkts_nic",
-++	"rx_bytes_nic",
-++	"d_noise_floor",
-++	"d_cycle_count",
-++	"d_phy_error",
-++	"d_rts_bad",
-++	"d_rts_good",
-++	"d_tx_power", /* in .5 dbM I think */
-++	"d_rx_crc_err", /* fcs_bad */
-++	"d_no_beacon",
-++	"d_tx_mpdus_queued",
-++	"d_tx_msdu_queued",
-++	"d_tx_msdu_dropped",
-++	"d_local_enqued",
-++	"d_local_freed",
-++	"d_tx_ppdu_hw_queued",
-++	"d_tx_ppdu_reaped",
-++	"d_tx_fifo_underrun",
-++	"d_tx_ppdu_abort",
-++	"d_tx_mpdu_requed",
-++	"d_tx_excessive_retries",
-++	"d_tx_hw_rate",
-++	"d_tx_dropped_sw_retries",
-++	"d_tx_illegal_rate",
-++	"d_tx_continuous_xretries",
-++	"d_tx_timeout",
-++	"d_tx_mpdu_txop_limit",
-++	"d_pdev_resets",
-++	"d_rx_mid_ppdu_route_change",
-++	"d_rx_status",
-++	"d_rx_extra_frags_ring0",
-++	"d_rx_extra_frags_ring1",
-++	"d_rx_extra_frags_ring2",
-++	"d_rx_extra_frags_ring3",
-++	"d_rx_msdu_htt",
-++	"d_rx_mpdu_htt",
-++	"d_rx_msdu_stack",
-++	"d_rx_mpdu_stack",
-++	"d_rx_phy_err",
-++	"d_rx_phy_err_drops",
-++	"d_rx_mpdu_errors", /* FCS, MIC, ENC */
-++	"d_fw_crash_count",
-++	"d_fw_warm_reset_count",
-++	"d_fw_cold_reset_count",
-++};
-++
-++#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
-++
-++void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
-++				 struct ieee80211_vif *vif,
-++				 u32 sset, u8 *data)
-++{
-++	if (sset == ETH_SS_STATS)
-++		memcpy(data, *ath10k_gstrings_stats,
-++		       sizeof(ath10k_gstrings_stats));
-++}
-++
-++int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
-++				   struct ieee80211_vif *vif, int sset)
-++{
-++	if (sset == ETH_SS_STATS)
-++		return ATH10K_SSTATS_LEN;
-++
-++	return 0;
-++}
-++
-++void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
-++			       struct ieee80211_vif *vif,
-++			       struct ethtool_stats *stats, u64 *data)
-++{
-++	struct ath10k *ar = hw->priv;
-++	static const struct ath10k_fw_stats_pdev zero_stats = {};
-++	const struct ath10k_fw_stats_pdev *pdev_stats;
-++	int i = 0, ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state == ATH10K_STATE_ON) {
-++		ret = ath10k_debug_fw_stats_request(ar);
-++		if (ret) {
-++			/* just print a warning and try to use older results */
-++			ath10k_warn(ar,
-++				    "failed to get fw stats for ethtool: %d\n",
-++				    ret);
-++		}
-++	}
-++
-++	pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
-++					      struct ath10k_fw_stats_pdev,
-++					      list);
-++	if (!pdev_stats) {
-++		/* no results available so just return zeroes */
-++		pdev_stats = &zero_stats;
-++	}
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
-++	data[i++] = 0; /* tx bytes */
-++	data[i++] = pdev_stats->htt_mpdus;
-++	data[i++] = 0; /* rx bytes */
-++	data[i++] = pdev_stats->ch_noise_floor;
-++	data[i++] = pdev_stats->cycle_count;
-++	data[i++] = pdev_stats->phy_err_count;
-++	data[i++] = pdev_stats->rts_bad;
-++	data[i++] = pdev_stats->rts_good;
-++	data[i++] = pdev_stats->chan_tx_power;
-++	data[i++] = pdev_stats->fcs_bad;
-++	data[i++] = pdev_stats->no_beacons;
-++	data[i++] = pdev_stats->mpdu_enqued;
-++	data[i++] = pdev_stats->msdu_enqued;
-++	data[i++] = pdev_stats->wmm_drop;
-++	data[i++] = pdev_stats->local_enqued;
-++	data[i++] = pdev_stats->local_freed;
-++	data[i++] = pdev_stats->hw_queued;
-++	data[i++] = pdev_stats->hw_reaped;
-++	data[i++] = pdev_stats->underrun;
-++	data[i++] = pdev_stats->tx_abort;
-++	data[i++] = pdev_stats->mpdus_requed;
-++	data[i++] = pdev_stats->tx_ko;
-++	data[i++] = pdev_stats->data_rc;
-++	data[i++] = pdev_stats->sw_retry_failure;
-++	data[i++] = pdev_stats->illgl_rate_phy_err;
-++	data[i++] = pdev_stats->pdev_cont_xretry;
-++	data[i++] = pdev_stats->pdev_tx_timeout;
-++	data[i++] = pdev_stats->txop_ovf;
-++	data[i++] = pdev_stats->pdev_resets;
-++	data[i++] = pdev_stats->mid_ppdu_route_change;
-++	data[i++] = pdev_stats->status_rcvd;
-++	data[i++] = pdev_stats->r0_frags;
-++	data[i++] = pdev_stats->r1_frags;
-++	data[i++] = pdev_stats->r2_frags;
-++	data[i++] = pdev_stats->r3_frags;
-++	data[i++] = pdev_stats->htt_msdus;
-++	data[i++] = pdev_stats->htt_mpdus;
-++	data[i++] = pdev_stats->loc_msdus;
-++	data[i++] = pdev_stats->loc_mpdus;
-++	data[i++] = pdev_stats->phy_errs;
-++	data[i++] = pdev_stats->phy_err_drop;
-++	data[i++] = pdev_stats->mpdu_errs;
-++	data[i++] = ar->stats.fw_crash_counter;
-++	data[i++] = ar->stats.fw_warm_reset_counter;
-++	data[i++] = ar->stats.fw_cold_reset_counter;
-++
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	WARN_ON(i != ATH10K_SSTATS_LEN);
-++}
-++
-+ static const struct file_operations fops_fw_dbglog = {
-+ 	.read = ath10k_read_fw_dbglog,
-+ 	.write = ath10k_write_fw_dbglog,
-+@@ -726,6 +1638,151 @@ static const struct file_operations fops
-+ 	.llseek = default_llseek,
-+ };
-+ 
-++static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
-++{
-++	struct ath10k *ar = inode->i_private;
-++	void *buf;
-++	u32 hi_addr;
-++	__le32 addr;
-++	int ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_ON &&
-++	    ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto err;
-++	}
-++
-++	buf = vmalloc(QCA988X_CAL_DATA_LEN);
-++	if (!buf) {
-++		ret = -ENOMEM;
-++		goto err;
-++	}
-++
-++	hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
-++
-++	ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
-++	if (ret) {
-++		ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
-++		goto err_vfree;
-++	}
-++
-++	ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
-++				   QCA988X_CAL_DATA_LEN);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
-++		goto err_vfree;
-++	}
-++
-++	file->private_data = buf;
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return 0;
-++
-++err_vfree:
-++	vfree(buf);
-++
-++err:
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static ssize_t ath10k_debug_cal_data_read(struct file *file,
-++					  char __user *user_buf,
-++					  size_t count, loff_t *ppos)
-++{
-++	void *buf = file->private_data;
-++
-++	return simple_read_from_buffer(user_buf, count, ppos,
-++				       buf, QCA988X_CAL_DATA_LEN);
-++}
-++
-++static int ath10k_debug_cal_data_release(struct inode *inode,
-++					 struct file *file)
-++{
-++	vfree(file->private_data);
-++
-++	return 0;
-++}
-++
-++static const struct file_operations fops_cal_data = {
-++	.open = ath10k_debug_cal_data_open,
-++	.read = ath10k_debug_cal_data_read,
-++	.release = ath10k_debug_cal_data_release,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_read_nf_cal_period(struct file *file,
-++					 char __user *user_buf,
-++					 size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	unsigned int len;
-++	char buf[32];
-++
-++	len = scnprintf(buf, sizeof(buf), "%d\n",
-++			ar->debug.nf_cal_period);
-++
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t ath10k_write_nf_cal_period(struct file *file,
-++					  const char __user *user_buf,
-++					  size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	unsigned long period;
-++	int ret;
-++
-++	ret = kstrtoul_from_user(user_buf, count, 0, &period);
-++	if (ret)
-++		return ret;
-++
-++	if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
-++		return -EINVAL;
-++
-++	/* there's no way to switch back to the firmware default */
-++	if (period == 0)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	ar->debug.nf_cal_period = period;
-++
-++	if (ar->state != ATH10K_STATE_ON) {
-++		/* firmware is not running, nothing else to do */
-++		ret = count;
-++		goto exit;
-++	}
-++
-++	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
-++					ar->debug.nf_cal_period);
-++	if (ret) {
-++		ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
-++			    ret);
-++		goto exit;
-++	}
-++
-++	ret = count;
-++
-++exit:
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static const struct file_operations fops_nf_cal_period = {
-++	.read = ath10k_read_nf_cal_period,
-++	.write = ath10k_write_nf_cal_period,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-+ int ath10k_debug_start(struct ath10k *ar)
-+ {
-+ 	int ret;
-+@@ -735,17 +1792,44 @@ int ath10k_debug_start(struct ath10k *ar
-+ 	ret = ath10k_debug_htt_stats_req(ar);
-+ 	if (ret)
-+ 		/* continue normally anyway, this isn't serious */
-+-		ath10k_warn("failed to start htt stats workqueue: %d\n", ret);
-++		ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
-++			    ret);
-+ 
-+ 	if (ar->debug.fw_dbglog_mask) {
-+-		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
-++		ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask,
-++					    ATH10K_DBGLOG_LEVEL_WARN);
-+ 		if (ret)
-+ 			/* not serious */
-+-			ath10k_warn("failed to enable dbglog during start: %d",
-++			ath10k_warn(ar, "failed to enable dbglog during start: %d",
-+ 				    ret);
-+ 	}
-+ 
-+-	return 0;
-++	if (ar->debug.pktlog_filter) {
-++		ret = ath10k_wmi_pdev_pktlog_enable(ar,
-++						    ar->debug.pktlog_filter);
-++		if (ret)
-++			/* not serious */
-++			ath10k_warn(ar,
-++				    "failed to enable pktlog filter %x: %d\n",
-++				    ar->debug.pktlog_filter, ret);
-++	} else {
-++		ret = ath10k_wmi_pdev_pktlog_disable(ar);
-++		if (ret)
-++			/* not serious */
-++			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
-++	}
-++
-++	if (ar->debug.nf_cal_period) {
-++		ret = ath10k_wmi_pdev_set_param(ar,
-++						ar->wmi.pdev_param->cal_period,
-++						ar->debug.nf_cal_period);
-++		if (ret)
-++			/* not serious */
-++			ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
-++				    ret);
-++	}
-++
-++	return ret;
-+ }
-+ 
-+ void ath10k_debug_stop(struct ath10k *ar)
-+@@ -757,6 +1841,11 @@ void ath10k_debug_stop(struct ath10k *ar
-+ 	 * warning from del_timer(). */
-+ 	if (ar->debug.htt_stats_mask != 0)
-+ 		cancel_delayed_work(&ar->debug.htt_stats_dwork);
-++
-++	ar->debug.htt_max_amsdu = 0;
-++	ar->debug.htt_max_ampdu = 0;
-++
-++	ath10k_wmi_pdev_pktlog_disable(ar);
-+ }
-+ 
-+ static ssize_t ath10k_write_simulate_radar(struct file *file,
-+@@ -839,37 +1928,149 @@ static const struct file_operations fops
-+ 	.llseek = default_llseek,
-+ };
-+ 
-++static ssize_t ath10k_write_pktlog_filter(struct file *file,
-++					  const char __user *ubuf,
-++					  size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	u32 filter;
-++	int ret;
-++
-++	if (kstrtouint_from_user(ubuf, count, 0, &filter))
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_ON) {
-++		ar->debug.pktlog_filter = filter;
-++		ret = count;
-++		goto out;
-++	}
-++
-++	if (filter && (filter != ar->debug.pktlog_filter)) {
-++		ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
-++				    ar->debug.pktlog_filter, ret);
-++			goto out;
-++		}
-++	} else {
-++		ret = ath10k_wmi_pdev_pktlog_disable(ar);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
-++			goto out;
-++		}
-++	}
-++
-++	ar->debug.pktlog_filter = filter;
-++	ret = count;
-++
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
-++					 size_t count, loff_t *ppos)
-++{
-++	char buf[32];
-++	struct ath10k *ar = file->private_data;
-++	int len = 0;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
-++			ar->debug.pktlog_filter);
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
-++}
-++
-++static const struct file_operations fops_pktlog_filter = {
-++	.read = ath10k_read_pktlog_filter,
-++	.write = ath10k_write_pktlog_filter,
-++	.open = simple_open
-++};
-++
-+ int ath10k_debug_create(struct ath10k *ar)
-+ {
-++	ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
-++	if (!ar->debug.fw_crash_data)
-++		return -ENOMEM;
-++
-++	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
-++	INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
-++	INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
-++
-++	return 0;
-++}
-++
-++void ath10k_debug_destroy(struct ath10k *ar)
-++{
-++	vfree(ar->debug.fw_crash_data);
-++	ar->debug.fw_crash_data = NULL;
-++
-++	ath10k_debug_fw_stats_reset(ar);
-++}
-++
-++int ath10k_debug_register(struct ath10k *ar)
-++{
-+ 	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
-+ 						   ar->hw->wiphy->debugfsdir);
-++	if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
-++		if (IS_ERR(ar->debug.debugfs_phy))
-++			return PTR_ERR(ar->debug.debugfs_phy);
-+ 
-+-	if (!ar->debug.debugfs_phy)
-+ 		return -ENOMEM;
-++	}
-+ 
-+ 	INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
-+ 			  ath10k_debug_htt_stats_dwork);
-+ 
-+-	init_completion(&ar->debug.event_stats_compl);
-++	init_completion(&ar->debug.fw_stats_complete);
-+ 
-+ 	debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
-+ 			    &fops_fw_stats);
-+ 
-++	debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
-++			    ar, &fops_fw_reset_stats);
-++
-+ 	debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
-+ 			    &fops_wmi_services);
-+ 
-+ 	debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
-+ 			    ar, &fops_simulate_fw_crash);
-+ 
-++	debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
-++			    ar, &fops_fw_crash_dump);
-++
-++	debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar, &fops_reg_addr);
-++
-++	debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar, &fops_reg_value);
-++
-++	debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar, &fops_mem_value);
-++
-+ 	debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
-+ 			    ar, &fops_chip_id);
-+ 
-+ 	debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
-+ 			    ar, &fops_htt_stats_mask);
-+ 
-++	debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar,
-++			    &fops_htt_max_amsdu_ampdu);
-++
-+ 	debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
-+ 			    ar, &fops_fw_dbglog);
-+ 
-++	debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
-++			    ar, &fops_cal_data);
-++
-++	debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
-++
-+ 	if (config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED)) {
-+ 		debugfs_create_file("dfs_simulate_radar", S_IWUSR,
-+ 				    ar->debug.debugfs_phy, ar,
-+@@ -884,10 +2085,13 @@ int ath10k_debug_create(struct ath10k *a
-+ 				    &fops_dfs_stats);
-+ 	}
-+ 
-++	debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
-++
-+ 	return 0;
-+ }
-+ 
-+-void ath10k_debug_destroy(struct ath10k *ar)
-++void ath10k_debug_unregister(struct ath10k *ar)
-+ {
-+ 	cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
-+ }
-+@@ -895,7 +2099,8 @@ void ath10k_debug_destroy(struct ath10k
-+ #endif /* CPTCFG_ATH10K_DEBUGFS */
-+ 
-+ #ifdef CPTCFG_ATH10K_DEBUG
-+-void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...)
-++void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
-++		const char *fmt, ...)
-+ {
-+ 	struct va_format vaf;
-+ 	va_list args;
-+@@ -906,27 +2111,43 @@ void ath10k_dbg(enum ath10k_debug_mask m
-+ 	vaf.va = &args;
-+ 
-+ 	if (ath10k_debug_mask & mask)
-+-		ath10k_printk(KERN_DEBUG, "%pV", &vaf);
-++		dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
-+ 
-+-	trace_ath10k_log_dbg(mask, &vaf);
-++	trace_ath10k_log_dbg(ar, mask, &vaf);
-+ 
-+ 	va_end(args);
-+ }
-+ EXPORT_SYMBOL(ath10k_dbg);
-+ 
-+-void ath10k_dbg_dump(enum ath10k_debug_mask mask,
-++void ath10k_dbg_dump(struct ath10k *ar,
-++		     enum ath10k_debug_mask mask,
-+ 		     const char *msg, const char *prefix,
-+ 		     const void *buf, size_t len)
-+ {
-++	char linebuf[256];
-++	unsigned int linebuflen;
-++	const void *ptr;
-++
-+ 	if (ath10k_debug_mask & mask) {
-+ 		if (msg)
-+-			ath10k_dbg(mask, "%s\n", msg);
-++			ath10k_dbg(ar, mask, "%s\n", msg);
-+ 
-+-		print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
-++		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
-++			linebuflen = 0;
-++			linebuflen += scnprintf(linebuf + linebuflen,
-++						sizeof(linebuf) - linebuflen,
-++						"%s%08x: ",
-++						(prefix ? prefix : ""),
-++						(unsigned int)(ptr - buf));
-++			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
-++					   linebuf + linebuflen,
-++					   sizeof(linebuf) - linebuflen, true);
-++			dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
-++		}
-+ 	}
-+ 
-+ 	/* tracing code doesn't like null strings :/ */
-+-	trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "",
-++	trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
-+ 				  buf, len);
-+ }
-+ EXPORT_SYMBOL(ath10k_dbg_dump);
-+--- a/drivers/net/wireless/ath/ath10k/debug.h
-++++ b/drivers/net/wireless/ath/ath10k/debug.h
-+@@ -34,28 +34,55 @@ enum ath10k_debug_mask {
-+ 	ATH10K_DBG_DATA		= 0x00000200,
-+ 	ATH10K_DBG_BMI		= 0x00000400,
-+ 	ATH10K_DBG_REGULATORY	= 0x00000800,
-++	ATH10K_DBG_TESTMODE	= 0x00001000,
-++	ATH10K_DBG_WMI_PRINT	= 0x00002000,
-+ 	ATH10K_DBG_ANY		= 0xffffffff,
-+ };
-+ 
-++enum ath10k_pktlog_filter {
-++	ATH10K_PKTLOG_RX         = 0x000000001,
-++	ATH10K_PKTLOG_TX         = 0x000000002,
-++	ATH10K_PKTLOG_RCFIND     = 0x000000004,
-++	ATH10K_PKTLOG_RCUPDATE   = 0x000000008,
-++	ATH10K_PKTLOG_DBG_PRINT  = 0x000000010,
-++	ATH10K_PKTLOG_ANY        = 0x00000001f,
-++};
-++
-++enum ath10k_dbg_aggr_mode {
-++	ATH10K_DBG_AGGR_MODE_AUTO,
-++	ATH10K_DBG_AGGR_MODE_MANUAL,
-++	ATH10K_DBG_AGGR_MODE_MAX,
-++};
-++
-+ extern unsigned int ath10k_debug_mask;
-+ 
-+-__printf(1, 2) int ath10k_info(const char *fmt, ...);
-+-__printf(1, 2) int ath10k_err(const char *fmt, ...);
-+-__printf(1, 2) int ath10k_warn(const char *fmt, ...);
-++__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
-++__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
-++__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
-++void ath10k_print_driver_info(struct ath10k *ar);
-+ 
-+ #ifdef CPTCFG_ATH10K_DEBUGFS
-+ int ath10k_debug_start(struct ath10k *ar);
-+ void ath10k_debug_stop(struct ath10k *ar);
-+ int ath10k_debug_create(struct ath10k *ar);
-+ void ath10k_debug_destroy(struct ath10k *ar);
-+-void ath10k_debug_read_service_map(struct ath10k *ar,
-+-				   void *service_map,
-+-				   size_t map_size);
-+-void ath10k_debug_read_target_stats(struct ath10k *ar,
-+-				    struct wmi_stats_event *ev);
-++int ath10k_debug_register(struct ath10k *ar);
-++void ath10k_debug_unregister(struct ath10k *ar);
-++void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
-++struct ath10k_fw_crash_data *
-++ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
-+ 
-++void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
-+ #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
-+ 
-++void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
-++				 struct ieee80211_vif *vif,
-++				 u32 sset, u8 *data);
-++int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
-++				   struct ieee80211_vif *vif, int sset);
-++void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
-++			       struct ieee80211_vif *vif,
-++			       struct ethtool_stats *stats, u64 *data);
-+ #else
-+ static inline int ath10k_debug_start(struct ath10k *ar)
-+ {
-+@@ -75,36 +102,62 @@ static inline void ath10k_debug_destroy(
-+ {
-+ }
-+ 
-+-static inline void ath10k_debug_read_service_map(struct ath10k *ar,
-+-						 void *service_map,
-+-						 size_t map_size)
-++static inline int ath10k_debug_register(struct ath10k *ar)
-++{
-++	return 0;
-++}
-++
-++static inline void ath10k_debug_unregister(struct ath10k *ar)
-+ {
-+ }
-+ 
-+-static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
-+-						  struct wmi_stats_event *ev)
-++static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
-++						 struct sk_buff *skb)
-+ {
-+ }
-+ 
-++static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
-++					   int len)
-++{
-++}
-++
-++static inline struct ath10k_fw_crash_data *
-++ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
-++{
-++	return NULL;
-++}
-++
-+ #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
-+ 
-++#define ath10k_debug_get_et_strings NULL
-++#define ath10k_debug_get_et_sset_count NULL
-++#define ath10k_debug_get_et_stats NULL
-++
-+ #endif /* CPTCFG_ATH10K_DEBUGFS */
-++#ifdef CPTCFG_MAC80211_DEBUGFS
-++void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-++			    struct ieee80211_sta *sta, struct dentry *dir);
-++#endif /* CPTCFG_MAC80211_DEBUGFS */
-+ 
-+ #ifdef CPTCFG_ATH10K_DEBUG
-+-__printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
-++__printf(3, 4) void ath10k_dbg(struct ath10k *ar,
-++			       enum ath10k_debug_mask mask,
-+ 			       const char *fmt, ...);
-+-void ath10k_dbg_dump(enum ath10k_debug_mask mask,
-++void ath10k_dbg_dump(struct ath10k *ar,
-++		     enum ath10k_debug_mask mask,
-+ 		     const char *msg, const char *prefix,
-+ 		     const void *buf, size_t len);
-+ #else /* CPTCFG_ATH10K_DEBUG */
-+ 
-+-static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask,
-++static inline int ath10k_dbg(struct ath10k *ar,
-++			     enum ath10k_debug_mask dbg_mask,
-+ 			     const char *fmt, ...)
-+ {
-+ 	return 0;
-+ }
-+ 
-+-static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask,
-++static inline void ath10k_dbg_dump(struct ath10k *ar,
-++				   enum ath10k_debug_mask mask,
-+ 				   const char *msg, const char *prefix,
-+ 				   const void *buf, size_t len)
-+ {
-+--- a/drivers/net/wireless/ath/ath10k/hif.h
-++++ b/drivers/net/wireless/ath/ath10k/hif.h
-+@@ -20,6 +20,7 @@
-+ 
-+ #include <linux/kernel.h>
-+ #include "core.h"
-++#include "debug.h"
-+ 
-+ struct ath10k_hif_sg_item {
-+ 	u16 transfer_id;
-+@@ -31,11 +32,9 @@ struct ath10k_hif_sg_item {
-+ 
-+ struct ath10k_hif_cb {
-+ 	int (*tx_completion)(struct ath10k *ar,
-+-			     struct sk_buff *wbuf,
-+-			     unsigned transfer_id);
-++			     struct sk_buff *wbuf);
-+ 	int (*rx_completion)(struct ath10k *ar,
-+-			     struct sk_buff *wbuf,
-+-			     u8 pipe_id);
-++			     struct sk_buff *wbuf);
-+ };
-+ 
-+ struct ath10k_hif_ops {
-+@@ -43,6 +42,12 @@ struct ath10k_hif_ops {
-+ 	int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
-+ 		     struct ath10k_hif_sg_item *items, int n_items);
-+ 
-++	/* read firmware memory through the diagnose interface */
-++	int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
-++			 size_t buf_len);
-++
-++	int (*diag_write)(struct ath10k *ar, u32 address, const void *data,
-++			  int nbytes);
-+ 	/*
-+ 	 * API to handle HIF-specific BMI message exchanges, this API is
-+ 	 * synchronous and only allowed to be called from a context that
-+@@ -80,6 +85,10 @@ struct ath10k_hif_ops {
-+ 
-+ 	u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
-+ 
-++	u32 (*read32)(struct ath10k *ar, u32 address);
-++
-++	void (*write32)(struct ath10k *ar, u32 address, u32 value);
-++
-+ 	/* Power up the device and enter BMI transfer mode for FW download */
-+ 	int (*power_up)(struct ath10k *ar);
-+ 
-+@@ -91,7 +100,6 @@ struct ath10k_hif_ops {
-+ 	int (*resume)(struct ath10k *ar);
-+ };
-+ 
-+-
-+ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
-+ 				   struct ath10k_hif_sg_item *items,
-+ 				   int n_items)
-+@@ -99,6 +107,21 @@ static inline int ath10k_hif_tx_sg(struc
-+ 	return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
-+ }
-+ 
-++static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
-++				       size_t buf_len)
-++{
-++	return ar->hif.ops->diag_read(ar, address, buf, buf_len);
-++}
-++
-++static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address,
-++					const void *data, int nbytes)
-++{
-++	if (!ar->hif.ops->diag_write)
-++		return -EOPNOTSUPP;
-++
-++	return ar->hif.ops->diag_write(ar, address, data, nbytes);
-++}
-++
-+ static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
-+ 					      void *request, u32 request_len,
-+ 					      void *response, u32 *response_len)
-+@@ -178,4 +201,25 @@ static inline int ath10k_hif_resume(stru
-+ 	return ar->hif.ops->resume(ar);
-+ }
-+ 
-++static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address)
-++{
-++	if (!ar->hif.ops->read32) {
-++		ath10k_warn(ar, "hif read32 not supported\n");
-++		return 0xdeaddead;
-++	}
-++
-++	return ar->hif.ops->read32(ar, address);
-++}
-++
-++static inline void ath10k_hif_write32(struct ath10k *ar,
-++				      u32 address, u32 data)
-++{
-++	if (!ar->hif.ops->write32) {
-++		ath10k_warn(ar, "hif write32 not supported\n");
-++		return;
-++	}
-++
-++	ar->hif.ops->write32(ar, address, data);
-++}
-++
-+ #endif /* _HIF_H_ */
-+--- a/drivers/net/wireless/ath/ath10k/htc.c
-++++ b/drivers/net/wireless/ath/ath10k/htc.c
-+@@ -45,10 +45,8 @@ static struct sk_buff *ath10k_htc_build_
-+ 	struct ath10k_skb_cb *skb_cb;
-+ 
-+ 	skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
-+-	if (!skb) {
-+-		ath10k_warn("Unable to allocate ctrl skb\n");
-++	if (!skb)
-+ 		return NULL;
-+-	}
-+ 
-+ 	skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
-+ 	WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
-+@@ -56,7 +54,7 @@ static struct sk_buff *ath10k_htc_build_
-+ 	skb_cb = ATH10K_SKB_CB(skb);
-+ 	memset(skb_cb, 0, sizeof(*skb_cb));
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
-++	ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
-+ 	return skb;
-+ }
-+ 
-+@@ -72,13 +70,15 @@ static inline void ath10k_htc_restore_tx
-+ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
-+ 					    struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
-++	struct ath10k *ar = ep->htc->ar;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
-+ 		   ep->eid, skb);
-+ 
-+ 	ath10k_htc_restore_tx_skb(ep->htc, skb);
-+ 
-+ 	if (!ep->ep_ops.ep_tx_complete) {
-+-		ath10k_warn("no tx handler for eid %d\n", ep->eid);
-++		ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid);
-+ 		dev_kfree_skb_any(skb);
-+ 		return;
-+ 	}
-+@@ -89,12 +89,14 @@ static void ath10k_htc_notify_tx_complet
-+ /* assumes tx_lock is held */
-+ static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep)
-+ {
-++	struct ath10k *ar = ep->htc->ar;
-++
-+ 	if (!ep->tx_credit_flow_enabled)
-+ 		return false;
-+ 	if (ep->tx_credits >= ep->tx_credits_per_max_message)
-+ 		return false;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
-+ 		   ep->eid);
-+ 	return true;
-+ }
-+@@ -123,6 +125,7 @@ int ath10k_htc_send(struct ath10k_htc *h
-+ 		    enum ath10k_htc_ep_id eid,
-+ 		    struct sk_buff *skb)
-+ {
-++	struct ath10k *ar = htc->ar;
-+ 	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
-+ 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
-+ 	struct ath10k_hif_sg_item sg_item;
-+@@ -134,18 +137,10 @@ int ath10k_htc_send(struct ath10k_htc *h
-+ 		return -ECOMM;
-+ 
-+ 	if (eid >= ATH10K_HTC_EP_COUNT) {
-+-		ath10k_warn("Invalid endpoint id: %d\n", eid);
-++		ath10k_warn(ar, "Invalid endpoint id: %d\n", eid);
-+ 		return -ENOENT;
-+ 	}
-+ 
-+-	/* FIXME: This looks ugly, can we fix it? */
-+-	spin_lock_bh(&htc->tx_lock);
-+-	if (htc->stopped) {
-+-		spin_unlock_bh(&htc->tx_lock);
-+-		return -ESHUTDOWN;
-+-	}
-+-	spin_unlock_bh(&htc->tx_lock);
-+-
-+ 	skb_push(skb, sizeof(struct ath10k_htc_hdr));
-+ 
-+ 	if (ep->tx_credit_flow_enabled) {
-+@@ -157,7 +152,7 @@ int ath10k_htc_send(struct ath10k_htc *h
-+ 			goto err_pull;
-+ 		}
-+ 		ep->tx_credits -= credits;
-+-		ath10k_dbg(ATH10K_DBG_HTC,
-++		ath10k_dbg(ar, ATH10K_DBG_HTC,
-+ 			   "htc ep %d consumed %d credits (total %d)\n",
-+ 			   eid, credits, ep->tx_credits);
-+ 		spin_unlock_bh(&htc->tx_lock);
-+@@ -165,6 +160,7 @@ int ath10k_htc_send(struct ath10k_htc *h
-+ 
-+ 	ath10k_htc_prepare_tx_skb(ep, skb);
-+ 
-++	skb_cb->eid = eid;
-+ 	skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
-+ 	ret = dma_mapping_error(dev, skb_cb->paddr);
-+ 	if (ret)
-+@@ -188,7 +184,7 @@ err_credits:
-+ 	if (ep->tx_credit_flow_enabled) {
-+ 		spin_lock_bh(&htc->tx_lock);
-+ 		ep->tx_credits += credits;
-+-		ath10k_dbg(ATH10K_DBG_HTC,
-++		ath10k_dbg(ar, ATH10K_DBG_HTC,
-+ 			   "htc ep %d reverted %d credits back (total %d)\n",
-+ 			   eid, credits, ep->tx_credits);
-+ 		spin_unlock_bh(&htc->tx_lock);
-+@@ -202,15 +198,18 @@ err_pull:
-+ }
-+ 
-+ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
-+-					    struct sk_buff *skb,
-+-					    unsigned int eid)
-++					    struct sk_buff *skb)
-+ {
-+ 	struct ath10k_htc *htc = &ar->htc;
-+-	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
-++	struct ath10k_skb_cb *skb_cb;
-++	struct ath10k_htc_ep *ep;
-+ 
-+ 	if (WARN_ON_ONCE(!skb))
-+ 		return 0;
-+ 
-++	skb_cb = ATH10K_SKB_CB(skb);
-++	ep = &htc->endpoint[skb_cb->eid];
-++
-+ 	ath10k_htc_notify_tx_completion(ep, skb);
-+ 	/* the skb now belongs to the completion handler */
-+ 
-+@@ -227,11 +226,12 @@ ath10k_htc_process_credit_report(struct
-+ 				 int len,
-+ 				 enum ath10k_htc_ep_id eid)
-+ {
-++	struct ath10k *ar = htc->ar;
-+ 	struct ath10k_htc_ep *ep;
-+ 	int i, n_reports;
-+ 
-+ 	if (len % sizeof(*report))
-+-		ath10k_warn("Uneven credit report len %d", len);
-++		ath10k_warn(ar, "Uneven credit report len %d", len);
-+ 
-+ 	n_reports = len / sizeof(*report);
-+ 
-+@@ -243,7 +243,7 @@ ath10k_htc_process_credit_report(struct
-+ 		ep = &htc->endpoint[report->eid];
-+ 		ep->tx_credits += report->credits;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
-++		ath10k_dbg(ar, ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
-+ 			   report->eid, report->credits, ep->tx_credits);
-+ 
-+ 		if (ep->ep_ops.ep_tx_credits) {
-+@@ -260,6 +260,7 @@ static int ath10k_htc_process_trailer(st
-+ 				      int length,
-+ 				      enum ath10k_htc_ep_id src_eid)
-+ {
-++	struct ath10k *ar = htc->ar;
-+ 	int status = 0;
-+ 	struct ath10k_htc_record *record;
-+ 	u8 *orig_buffer;
-+@@ -279,7 +280,7 @@ static int ath10k_htc_process_trailer(st
-+ 
-+ 		if (record->hdr.len > length) {
-+ 			/* no room left in buffer for record */
-+-			ath10k_warn("Invalid record length: %d\n",
-++			ath10k_warn(ar, "Invalid record length: %d\n",
-+ 				    record->hdr.len);
-+ 			status = -EINVAL;
-+ 			break;
-+@@ -289,7 +290,7 @@ static int ath10k_htc_process_trailer(st
-+ 		case ATH10K_HTC_RECORD_CREDITS:
-+ 			len = sizeof(struct ath10k_htc_credit_report);
-+ 			if (record->hdr.len < len) {
-+-				ath10k_warn("Credit report too long\n");
-++				ath10k_warn(ar, "Credit report too long\n");
-+ 				status = -EINVAL;
-+ 				break;
-+ 			}
-+@@ -299,7 +300,7 @@ static int ath10k_htc_process_trailer(st
-+ 							 src_eid);
-+ 			break;
-+ 		default:
-+-			ath10k_warn("Unhandled record: id:%d length:%d\n",
-++			ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
-+ 				    record->hdr.id, record->hdr.len);
-+ 			break;
-+ 		}
-+@@ -313,15 +314,14 @@ static int ath10k_htc_process_trailer(st
-+ 	}
-+ 
-+ 	if (status)
-+-		ath10k_dbg_dump(ATH10K_DBG_HTC, "htc rx bad trailer", "",
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "",
-+ 				orig_buffer, orig_length);
-+ 
-+ 	return status;
-+ }
-+ 
-+ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
-+-					    struct sk_buff *skb,
-+-					    u8 pipe_id)
-++					    struct sk_buff *skb)
-+ {
-+ 	int status = 0;
-+ 	struct ath10k_htc *htc = &ar->htc;
-+@@ -339,8 +339,8 @@ static int ath10k_htc_rx_completion_hand
-+ 	eid = hdr->eid;
-+ 
-+ 	if (eid >= ATH10K_HTC_EP_COUNT) {
-+-		ath10k_warn("HTC Rx: invalid eid %d\n", eid);
-+-		ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad header", "",
-++		ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid);
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "",
-+ 				hdr, sizeof(*hdr));
-+ 		status = -EINVAL;
-+ 		goto out;
-+@@ -360,19 +360,19 @@ static int ath10k_htc_rx_completion_hand
-+ 	payload_len = __le16_to_cpu(hdr->len);
-+ 
-+ 	if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
-+-		ath10k_warn("HTC rx frame too long, len: %zu\n",
-++		ath10k_warn(ar, "HTC rx frame too long, len: %zu\n",
-+ 			    payload_len + sizeof(*hdr));
-+-		ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", "",
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "",
-+ 				hdr, sizeof(*hdr));
-+ 		status = -EINVAL;
-+ 		goto out;
-+ 	}
-+ 
-+ 	if (skb->len < payload_len) {
-+-		ath10k_dbg(ATH10K_DBG_HTC,
-++		ath10k_dbg(ar, ATH10K_DBG_HTC,
-+ 			   "HTC Rx: insufficient length, got %d, expected %d\n",
-+ 			   skb->len, payload_len);
-+-		ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len",
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len",
-+ 				"", hdr, sizeof(*hdr));
-+ 		status = -EINVAL;
-+ 		goto out;
-+@@ -388,7 +388,7 @@ static int ath10k_htc_rx_completion_hand
-+ 
-+ 		if ((trailer_len < min_len) ||
-+ 		    (trailer_len > payload_len)) {
-+-			ath10k_warn("Invalid trailer length: %d\n",
-++			ath10k_warn(ar, "Invalid trailer length: %d\n",
-+ 				    trailer_len);
-+ 			status = -EPROTO;
-+ 			goto out;
-+@@ -421,7 +421,7 @@ static int ath10k_htc_rx_completion_hand
-+ 				 * this is a fatal error, target should not be
-+ 				 * sending unsolicited messages on the ep 0
-+ 				 */
-+-				ath10k_warn("HTC rx ctrl still processing\n");
-++				ath10k_warn(ar, "HTC rx ctrl still processing\n");
-+ 				status = -EINVAL;
-+ 				complete(&htc->ctl_resp);
-+ 				goto out;
-+@@ -442,7 +442,7 @@ static int ath10k_htc_rx_completion_hand
-+ 		goto out;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
-+ 		   eid, skb);
-+ 	ep->ep_ops.ep_rx_complete(ar, skb);
-+ 
-+@@ -459,7 +459,7 @@ static void ath10k_htc_control_rx_comple
-+ {
-+ 	/* This is unexpected. FW is not supposed to send regular rx on this
-+ 	 * endpoint. */
-+-	ath10k_warn("unexpected htc rx\n");
-++	ath10k_warn(ar, "unexpected htc rx\n");
-+ 	kfree_skb(skb);
-+ }
-+ 
-+@@ -546,7 +546,8 @@ static u8 ath10k_htc_get_credit_allocati
-+ 
-+ int ath10k_htc_wait_target(struct ath10k_htc *htc)
-+ {
-+-	int status = 0;
-++	struct ath10k *ar = htc->ar;
-++	int i, status = 0;
-+ 	struct ath10k_htc_svc_conn_req conn_req;
-+ 	struct ath10k_htc_svc_conn_resp conn_resp;
-+ 	struct ath10k_htc_msg *msg;
-+@@ -556,16 +557,32 @@ int ath10k_htc_wait_target(struct ath10k
-+ 
-+ 	status = wait_for_completion_timeout(&htc->ctl_resp,
-+ 					     ATH10K_HTC_WAIT_TIMEOUT_HZ);
-+-	if (status <= 0) {
-++	if (status == 0) {
-++		/* Workaround: In some cases the PCI HIF doesn't
-++		 * receive interrupt for the control response message
-++		 * even if the buffer was completed. It is suspected
-++		 * iomap writes unmasking PCI CE irqs aren't propagated
-++		 * properly in KVM PCI-passthrough sometimes.
-++		 */
-++		ath10k_warn(ar, "failed to receive control response completion, polling..\n");
-++
-++		for (i = 0; i < CE_COUNT; i++)
-++			ath10k_hif_send_complete_check(htc->ar, i, 1);
-++
-++		status = wait_for_completion_timeout(&htc->ctl_resp,
-++						     ATH10K_HTC_WAIT_TIMEOUT_HZ);
-++
-+ 		if (status == 0)
-+ 			status = -ETIMEDOUT;
-++	}
-+ 
-+-		ath10k_err("ctl_resp never came in (%d)\n", status);
-++	if (status < 0) {
-++		ath10k_err(ar, "ctl_resp never came in (%d)\n", status);
-+ 		return status;
-+ 	}
-+ 
-+ 	if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
-+-		ath10k_err("Invalid HTC ready msg len:%d\n",
-++		ath10k_err(ar, "Invalid HTC ready msg len:%d\n",
-+ 			   htc->control_resp_len);
-+ 		return -ECOMM;
-+ 	}
-+@@ -576,21 +593,21 @@ int ath10k_htc_wait_target(struct ath10k
-+ 	credit_size  = __le16_to_cpu(msg->ready.credit_size);
-+ 
-+ 	if (message_id != ATH10K_HTC_MSG_READY_ID) {
-+-		ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
-++		ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
-+ 		return -ECOMM;
-+ 	}
-+ 
-+ 	htc->total_transmit_credits = credit_count;
-+ 	htc->target_credit_size = credit_size;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC,
-++	ath10k_dbg(ar, ATH10K_DBG_HTC,
-+ 		   "Target ready! transmit resources: %d size:%d\n",
-+ 		   htc->total_transmit_credits,
-+ 		   htc->target_credit_size);
-+ 
-+ 	if ((htc->total_transmit_credits == 0) ||
-+ 	    (htc->target_credit_size == 0)) {
-+-		ath10k_err("Invalid credit size received\n");
-++		ath10k_err(ar, "Invalid credit size received\n");
-+ 		return -ECOMM;
-+ 	}
-+ 
-+@@ -607,7 +624,8 @@ int ath10k_htc_wait_target(struct ath10k
-+ 	/* connect fake service */
-+ 	status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
-+ 	if (status) {
-+-		ath10k_err("could not connect to htc service (%d)\n", status);
-++		ath10k_err(ar, "could not connect to htc service (%d)\n",
-++			   status);
-+ 		return status;
-+ 	}
-+ 
-+@@ -618,6 +636,7 @@ int ath10k_htc_connect_service(struct at
-+ 			       struct ath10k_htc_svc_conn_req *conn_req,
-+ 			       struct ath10k_htc_svc_conn_resp *conn_resp)
-+ {
-++	struct ath10k *ar = htc->ar;
-+ 	struct ath10k_htc_msg *msg;
-+ 	struct ath10k_htc_conn_svc *req_msg;
-+ 	struct ath10k_htc_conn_svc_response resp_msg_dummy;
-+@@ -643,13 +662,13 @@ int ath10k_htc_connect_service(struct at
-+ 	tx_alloc = ath10k_htc_get_credit_allocation(htc,
-+ 						    conn_req->service_id);
-+ 	if (!tx_alloc)
-+-		ath10k_dbg(ATH10K_DBG_BOOT,
-++		ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 			   "boot htc service %s does not allocate target credits\n",
-+ 			   htc_service_name(conn_req->service_id));
-+ 
-+ 	skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
-+ 	if (!skb) {
-+-		ath10k_err("Failed to allocate HTC packet\n");
-++		ath10k_err(ar, "Failed to allocate HTC packet\n");
-+ 		return -ENOMEM;
-+ 	}
-+ 
-+@@ -684,11 +703,9 @@ int ath10k_htc_connect_service(struct at
-+ 	/* wait for response */
-+ 	status = wait_for_completion_timeout(&htc->ctl_resp,
-+ 					     ATH10K_HTC_CONN_SVC_TIMEOUT_HZ);
-+-	if (status <= 0) {
-+-		if (status == 0)
-+-			status = -ETIMEDOUT;
-+-		ath10k_err("Service connect timeout: %d\n", status);
-+-		return status;
-++	if (status == 0) {
-++		ath10k_err(ar, "Service connect timeout: %d\n", status);
-++		return -ETIMEDOUT;
-+ 	}
-+ 
-+ 	/* we controlled the buffer creation, it's aligned */
-+@@ -700,11 +717,11 @@ int ath10k_htc_connect_service(struct at
-+ 	if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) ||
-+ 	    (htc->control_resp_len < sizeof(msg->hdr) +
-+ 	     sizeof(msg->connect_service_response))) {
-+-		ath10k_err("Invalid resp message ID 0x%x", message_id);
-++		ath10k_err(ar, "Invalid resp message ID 0x%x", message_id);
-+ 		return -EPROTO;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC,
-++	ath10k_dbg(ar, ATH10K_DBG_HTC,
-+ 		   "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n",
-+ 		   htc_service_name(service_id),
-+ 		   resp_msg->status, resp_msg->eid);
-+@@ -713,7 +730,7 @@ int ath10k_htc_connect_service(struct at
-+ 
-+ 	/* check response status */
-+ 	if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) {
-+-		ath10k_err("HTC Service %s connect request failed: 0x%x)\n",
-++		ath10k_err(ar, "HTC Service %s connect request failed: 0x%x)\n",
-+ 			   htc_service_name(service_id),
-+ 			   resp_msg->status);
-+ 		return -EPROTO;
-+@@ -764,18 +781,18 @@ setup:
-+ 	if (status)
-+ 		return status;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT,
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 		   "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
-+ 		   htc_service_name(ep->service_id), ep->ul_pipe_id,
-+ 		   ep->dl_pipe_id, ep->eid);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT,
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 		   "boot htc ep %d ul polled %d dl polled %d\n",
-+ 		   ep->eid, ep->ul_is_polled, ep->dl_is_polled);
-+ 
-+ 	if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
-+ 		ep->tx_credit_flow_enabled = false;
-+-		ath10k_dbg(ATH10K_DBG_BOOT,
-++		ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ 			   "boot htc service '%s' eid %d TX flow control disabled\n",
-+ 			   htc_service_name(ep->service_id), assigned_eid);
-+ 	}
-+@@ -783,27 +800,26 @@ setup:
-+ 	return status;
-+ }
-+ 
-+-struct sk_buff *ath10k_htc_alloc_skb(int size)
-++struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
-+ {
-+ 	struct sk_buff *skb;
-+ 
-+ 	skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
-+-	if (!skb) {
-+-		ath10k_warn("could not allocate HTC tx skb\n");
-++	if (!skb)
-+ 		return NULL;
-+-	}
-+ 
-+ 	skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
-+ 
-+ 	/* FW/HTC requires 4-byte aligned streams */
-+ 	if (!IS_ALIGNED((unsigned long)skb->data, 4))
-+-		ath10k_warn("Unaligned HTC tx skb\n");
-++		ath10k_warn(ar, "Unaligned HTC tx skb\n");
-+ 
-+ 	return skb;
-+ }
-+ 
-+ int ath10k_htc_start(struct ath10k_htc *htc)
-+ {
-++	struct ath10k *ar = htc->ar;
-+ 	struct sk_buff *skb;
-+ 	int status = 0;
-+ 	struct ath10k_htc_msg *msg;
-+@@ -819,7 +835,7 @@ int ath10k_htc_start(struct ath10k_htc *
-+ 	msg->hdr.message_id =
-+ 		__cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
-++	ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
-+ 
-+ 	status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
-+ 	if (status) {
-+@@ -830,19 +846,6 @@ int ath10k_htc_start(struct ath10k_htc *
-+ 	return 0;
-+ }
-+ 
-+-/*
-+- * stop HTC communications, i.e. stop interrupt reception, and flush all
-+- * queued buffers
-+- */
-+-void ath10k_htc_stop(struct ath10k_htc *htc)
-+-{
-+-	spin_lock_bh(&htc->tx_lock);
-+-	htc->stopped = true;
-+-	spin_unlock_bh(&htc->tx_lock);
-+-
-+-	ath10k_hif_stop(htc->ar);
-+-}
-+-
-+ /* registered target arrival callback from the HIF layer */
-+ int ath10k_htc_init(struct ath10k *ar)
-+ {
-+@@ -852,7 +855,6 @@ int ath10k_htc_init(struct ath10k *ar)
-+ 
-+ 	spin_lock_init(&htc->tx_lock);
-+ 
-+-	htc->stopped = false;
-+ 	ath10k_htc_reset_endpoint_states(htc);
-+ 
-+ 	/* setup HIF layer callbacks */
-+--- a/drivers/net/wireless/ath/ath10k/htc.h
-++++ b/drivers/net/wireless/ath/ath10k/htc.h
-+@@ -214,7 +214,6 @@ struct ath10k_htc_frame {
-+ 	struct ath10k_htc_record trailer[0];
-+ } __packed __aligned(4);
-+ 
-+-
-+ /*******************/
-+ /* Host-side stuff */
-+ /*******************/
-+@@ -332,7 +331,7 @@ struct ath10k_htc {
-+ 	struct ath10k *ar;
-+ 	struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
-+ 
-+-	/* protects endpoint and stopped fields */
-++	/* protects endpoints */
-+ 	spinlock_t tx_lock;
-+ 
-+ 	struct ath10k_htc_ops htc_ops;
-+@@ -345,8 +344,6 @@ struct ath10k_htc {
-+ 	int total_transmit_credits;
-+ 	struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
-+ 	int target_credit_size;
-+-
-+-	bool stopped;
-+ };
-+ 
-+ int ath10k_htc_init(struct ath10k *ar);
-+@@ -357,7 +354,6 @@ int ath10k_htc_connect_service(struct at
-+ 			       struct ath10k_htc_svc_conn_resp *conn_resp);
-+ int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
-+ 		    struct sk_buff *packet);
-+-void ath10k_htc_stop(struct ath10k_htc *htc);
-+-struct sk_buff *ath10k_htc_alloc_skb(int size);
-++struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
-+ 
-+ #endif
-+--- a/drivers/net/wireless/ath/ath10k/htt.c
-++++ b/drivers/net/wireless/ath/ath10k/htt.c
-+@@ -22,7 +22,7 @@
-+ #include "core.h"
-+ #include "debug.h"
-+ 
-+-static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
-++int ath10k_htt_connect(struct ath10k_htt *htt)
-+ {
-+ 	struct ath10k_htc_svc_conn_req conn_req;
-+ 	struct ath10k_htc_svc_conn_resp conn_resp;
-+@@ -48,37 +48,11 @@ static int ath10k_htt_htc_attach(struct
-+ 	return 0;
-+ }
-+ 
-+-int ath10k_htt_attach(struct ath10k *ar)
-++int ath10k_htt_init(struct ath10k *ar)
-+ {
-+ 	struct ath10k_htt *htt = &ar->htt;
-+-	int ret;
-+ 
-+ 	htt->ar = ar;
-+-	htt->max_throughput_mbps = 800;
-+-
-+-	/*
-+-	 * Connect to HTC service.
-+-	 * This has to be done before calling ath10k_htt_rx_attach,
-+-	 * since ath10k_htt_rx_attach involves sending a rx ring configure
-+-	 * message to the target.
-+-	 */
-+-	ret = ath10k_htt_htc_attach(htt);
-+-	if (ret) {
-+-		ath10k_err("could not attach htt htc (%d)\n", ret);
-+-		goto err_htc_attach;
-+-	}
-+-
-+-	ret = ath10k_htt_tx_attach(htt);
-+-	if (ret) {
-+-		ath10k_err("could not attach htt tx (%d)\n", ret);
-+-		goto err_htc_attach;
-+-	}
-+-
-+-	ret = ath10k_htt_rx_attach(htt);
-+-	if (ret) {
-+-		ath10k_err("could not attach htt rx (%d)\n", ret);
-+-		goto err_rx_attach;
-+-	}
-+ 
-+ 	/*
-+ 	 * Prefetch enough data to satisfy target
-+@@ -93,23 +67,20 @@ int ath10k_htt_attach(struct ath10k *ar)
-+ 		2; /* ip4 dscp or ip6 priority */
-+ 
-+ 	return 0;
-+-
-+-err_rx_attach:
-+-	ath10k_htt_tx_detach(htt);
-+-err_htc_attach:
-+-	return ret;
-+ }
-+ 
-+ #define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
-+ 
-+ static int ath10k_htt_verify_version(struct ath10k_htt *htt)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "htt target version %d.%d\n",
-++	struct ath10k *ar = htt->ar;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt target version %d.%d\n",
-+ 		   htt->target_version_major, htt->target_version_minor);
-+ 
-+ 	if (htt->target_version_major != 2 &&
-+ 	    htt->target_version_major != 3) {
-+-		ath10k_err("unsupported htt major version %d. supported versions are 2 and 3\n",
-++		ath10k_err(ar, "unsupported htt major version %d. supported versions are 2 and 3\n",
-+ 			   htt->target_version_major);
-+ 		return -ENOTSUPP;
-+ 	}
-+@@ -117,8 +88,9 @@ static int ath10k_htt_verify_version(str
-+ 	return 0;
-+ }
-+ 
-+-int ath10k_htt_attach_target(struct ath10k_htt *htt)
-++int ath10k_htt_setup(struct ath10k_htt *htt)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	int status;
-+ 
-+ 	init_completion(&htt->target_version_received);
-+@@ -128,9 +100,9 @@ int ath10k_htt_attach_target(struct ath1
-+ 		return status;
-+ 
-+ 	status = wait_for_completion_timeout(&htt->target_version_received,
-+-						HTT_TARGET_VERSION_TIMEOUT_HZ);
-+-	if (status <= 0) {
-+-		ath10k_warn("htt version request timed out\n");
-++					     HTT_TARGET_VERSION_TIMEOUT_HZ);
-++	if (status == 0) {
-++		ath10k_warn(ar, "htt version request timed out\n");
-+ 		return -ETIMEDOUT;
-+ 	}
-+ 
-+@@ -140,9 +112,3 @@ int ath10k_htt_attach_target(struct ath1
-+ 
-+ 	return ath10k_htt_send_rx_ring_cfg_ll(htt);
-+ }
-+-
-+-void ath10k_htt_detach(struct ath10k_htt *htt)
-+-{
-+-	ath10k_htt_rx_detach(htt);
-+-	ath10k_htt_tx_detach(htt);
-+-}
-+--- a/drivers/net/wireless/ath/ath10k/htt.h
-++++ b/drivers/net/wireless/ath/ath10k/htt.h
-+@@ -21,6 +21,7 @@
-+ #include <linux/bug.h>
-+ #include <linux/interrupt.h>
-+ #include <linux/dmapool.h>
-++#include <linux/hashtable.h>
-+ #include <net/mac80211.h>
-+ 
-+ #include "htc.h"
-+@@ -126,6 +127,7 @@ enum htt_data_tx_ext_tid {
-+  *                  (HL hosts manage queues on the host )
-+  *       more_in_batch: only for HL hosts. indicates if more packets are
-+  *                      pending. this allows target to wait and aggregate
-++ *       freq: 0 means home channel of given vdev. intended for offchannel
-+  */
-+ struct htt_data_tx_desc {
-+ 	u8 flags0; /* %HTT_DATA_TX_DESC_FLAGS0_ */
-+@@ -133,7 +135,8 @@ struct htt_data_tx_desc {
-+ 	__le16 len;
-+ 	__le16 id;
-+ 	__le32 frags_paddr;
-+-	__le32 peerid;
-++	__le16 peerid;
-++	__le16 freq;
-+ 	u8 prefetch[0]; /* start of frame, for FW classification engine */
-+ } __packed;
-+ 
-+@@ -156,6 +159,9 @@ enum htt_rx_ring_flags {
-+ 	HTT_RX_RING_FLAGS_PHY_DATA_RX  = 1 << 15
-+ };
-+ 
-++#define HTT_RX_RING_SIZE_MIN 128
-++#define HTT_RX_RING_SIZE_MAX 2048
-++
-+ struct htt_rx_ring_setup_ring {
-+ 	__le32 fw_idx_shadow_reg_paddr;
-+ 	__le32 rx_ring_base_paddr;
-+@@ -240,16 +246,10 @@ struct htt_oob_sync_req {
-+ 	__le16 rsvd0;
-+ } __packed;
-+ 
-+-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
-+-#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB  0
-+-
-+ struct htt_aggr_conf {
-+ 	u8 max_num_ampdu_subframes;
-+-	union {
-+-		/* dont use bitfields; undefined behaviour */
-+-		u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
-+-		u8 max_num_amsdu_subframes:5;
-+-	} __packed;
-++	/* amsdu_subframes is limited by 0x1F mask */
-++	u8 max_num_amsdu_subframes;
-+ } __packed;
-+ 
-+ #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
-+@@ -271,7 +271,6 @@ enum htt_mgmt_tx_status {
-+ 
-+ /*=== target -> host messages ===============================================*/
-+ 
-+-
-+ enum htt_t2h_msg_type {
-+ 	HTT_T2H_MSG_TYPE_VERSION_CONF		= 0x0,
-+ 	HTT_T2H_MSG_TYPE_RX_IND			= 0x1,
-+@@ -288,7 +287,19 @@ enum htt_t2h_msg_type {
-+ 	HTT_T2H_MSG_TYPE_RC_UPDATE_IND		= 0xc,
-+ 	HTT_T2H_MSG_TYPE_TX_INSPECT_IND		= 0xd,
-+ 	HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION	= 0xe,
-++	HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND	= 0xf,
-++	HTT_T2H_MSG_TYPE_RX_PN_IND		= 0x10,
-++	HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND = 0x11,
-++	HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND	= 0x12,
-++	/* 0x13 reservd */
-++	HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE	= 0x14,
-++
-++	/* FIXME: Do not depend on this event id. Numbering of this event id is
-++	 * broken across different firmware revisions and HTT version fails to
-++	 * indicate this.
-++	 */
-+ 	HTT_T2H_MSG_TYPE_TEST,
-++
-+ 	/* keep this last */
-+ 	HTT_T2H_NUM_MSGS
-+ };
-+@@ -657,6 +668,53 @@ struct htt_rx_fragment_indication {
-+ #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_MASK   0x00000FC0
-+ #define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_LSB    6
-+ 
-++struct htt_rx_pn_ind {
-++	__le16 peer_id;
-++	u8 tid;
-++	u8 seqno_start;
-++	u8 seqno_end;
-++	u8 pn_ie_count;
-++	u8 reserved;
-++	u8 pn_ies[0];
-++} __packed;
-++
-++struct htt_rx_offload_msdu {
-++	__le16 msdu_len;
-++	__le16 peer_id;
-++	u8 vdev_id;
-++	u8 tid;
-++	u8 fw_desc;
-++	u8 payload[0];
-++} __packed;
-++
-++struct htt_rx_offload_ind {
-++	u8 reserved;
-++	__le16 msdu_count;
-++} __packed;
-++
-++struct htt_rx_in_ord_msdu_desc {
-++	__le32 msdu_paddr;
-++	__le16 msdu_len;
-++	u8 fw_desc;
-++	u8 reserved;
-++} __packed;
-++
-++struct htt_rx_in_ord_ind {
-++	u8 info;
-++	__le16 peer_id;
-++	u8 vdev_id;
-++	u8 reserved;
-++	__le16 msdu_count;
-++	struct htt_rx_in_ord_msdu_desc msdu_descs[0];
-++} __packed;
-++
-++#define HTT_RX_IN_ORD_IND_INFO_TID_MASK		0x0000001f
-++#define HTT_RX_IN_ORD_IND_INFO_TID_LSB		0
-++#define HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK	0x00000020
-++#define HTT_RX_IN_ORD_IND_INFO_OFFLOAD_LSB	5
-++#define HTT_RX_IN_ORD_IND_INFO_FRAG_MASK	0x00000040
-++#define HTT_RX_IN_ORD_IND_INFO_FRAG_LSB		6
-++
-+ /*
-+  * target -> host test message definition
-+  *
-+@@ -732,7 +790,7 @@ static inline u8 *htt_rx_test_get_chars(
-+  */
-+ struct htt_pktlog_msg {
-+ 	u8 pad[3];
-+-	__le32 payload[1 /* or more */];
-++	u8 payload[0];
-+ } __packed;
-+ 
-+ struct htt_dbg_stats_rx_reorder_stats {
-+@@ -1038,6 +1096,7 @@ static inline struct htt_stats_conf_item
-+ {
-+ 	return (void *)item + sizeof(*item) + roundup(item->length, 4);
-+ }
-++
-+ /*
-+  * host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank
-+  *
-+@@ -1151,10 +1210,12 @@ struct htt_resp {
-+ 		struct htt_rx_test rx_test;
-+ 		struct htt_pktlog_msg pktlog_msg;
-+ 		struct htt_stats_conf stats_conf;
-++		struct htt_rx_pn_ind rx_pn_ind;
-++		struct htt_rx_offload_ind rx_offload_ind;
-++		struct htt_rx_in_ord_ind rx_in_ord_ind;
-+ 	};
-+ } __packed;
-+ 
-+-
-+ /*** host side structures follow ***/
-+ 
-+ struct htt_tx_done {
-+@@ -1184,7 +1245,6 @@ struct ath10k_htt {
-+ 	struct ath10k *ar;
-+ 	enum ath10k_htc_ep_id eid;
-+ 
-+-	int max_throughput_mbps;
-+ 	u8 target_version_major;
-+ 	u8 target_version_minor;
-+ 	struct completion target_version_received;
-+@@ -1200,6 +1260,20 @@ struct ath10k_htt {
-+ 		 * filled.
-+ 		 */
-+ 		struct sk_buff **netbufs_ring;
-++
-++		/* This is used only with firmware supporting IN_ORD_IND.
-++		 *
-++		 * With Full Rx Reorder the HTT Rx Ring is more of a temporary
-++		 * buffer ring from which buffer addresses are copied by the
-++		 * firmware to MAC Rx ring. Firmware then delivers IN_ORD_IND
-++		 * pointing to specific (re-ordered) buffers.
-++		 *
-++		 * FIXME: With kernel generic hashing functions there's a lot
-++		 * of hash collisions for sk_buffs.
-++		 */
-++		bool in_ord_rx;
-++		DECLARE_HASHTABLE(skb_table, 4);
-++
-+ 		/*
-+ 		 * Ring of buffer addresses -
-+ 		 * This ring holds the "physical" device address of the
-+@@ -1254,12 +1328,11 @@ struct ath10k_htt {
-+ 
-+ 	unsigned int prefetch_len;
-+ 
-+-	/* Protects access to %pending_tx, %used_msdu_ids */
-++	/* Protects access to pending_tx, num_pending_tx */
-+ 	spinlock_t tx_lock;
-+ 	int max_num_pending_tx;
-+ 	int num_pending_tx;
-+-	struct sk_buff **pending_tx;
-+-	unsigned long *used_msdu_ids; /* bitmap */
-++	struct idr pending_tx;
-+ 	wait_queue_head_t empty_tx_wq;
-+ 	struct dma_pool *tx_pool;
-+ 
-+@@ -1273,6 +1346,7 @@ struct ath10k_htt {
-+ 	struct tasklet_struct txrx_compl_task;
-+ 	struct sk_buff_head tx_compl_q;
-+ 	struct sk_buff_head rx_compl_q;
-++	struct sk_buff_head rx_in_ord_compl_q;
-+ 
-+ 	/* rx_status template */
-+ 	struct ieee80211_rx_status rx_status;
-+@@ -1328,22 +1402,28 @@ struct htt_rx_desc {
-+ #define HTT_LOG2_MAX_CACHE_LINE_SIZE 7	/* 2^7 = 128 */
-+ #define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
-+ 
-+-int ath10k_htt_attach(struct ath10k *ar);
-+-int ath10k_htt_attach_target(struct ath10k_htt *htt);
-+-void ath10k_htt_detach(struct ath10k_htt *htt);
-+-
-+-int ath10k_htt_tx_attach(struct ath10k_htt *htt);
-+-void ath10k_htt_tx_detach(struct ath10k_htt *htt);
-+-int ath10k_htt_rx_attach(struct ath10k_htt *htt);
-+-void ath10k_htt_rx_detach(struct ath10k_htt *htt);
-++int ath10k_htt_connect(struct ath10k_htt *htt);
-++int ath10k_htt_init(struct ath10k *ar);
-++int ath10k_htt_setup(struct ath10k_htt *htt);
-++
-++int ath10k_htt_tx_alloc(struct ath10k_htt *htt);
-++void ath10k_htt_tx_free(struct ath10k_htt *htt);
-++
-++int ath10k_htt_rx_alloc(struct ath10k_htt *htt);
-++int ath10k_htt_rx_ring_refill(struct ath10k *ar);
-++void ath10k_htt_rx_free(struct ath10k_htt *htt);
-++
-+ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
-+ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
-+ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
-+ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
-+ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
-++int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
-++				u8 max_subfrms_ampdu,
-++				u8 max_subfrms_amsdu);
-+ 
-+ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
-+-int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
-++int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
-+ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
-+ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
-+ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *);
-+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
-++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
-+@@ -21,118 +21,84 @@
-+ #include "txrx.h"
-+ #include "debug.h"
-+ #include "trace.h"
-++#include "mac.h"
-+ 
-+ #include <linux/log2.h>
-+ 
-+-/* slightly larger than one large A-MPDU */
-+-#define HTT_RX_RING_SIZE_MIN 128
-+-
-+-/* roughly 20 ms @ 1 Gbps of 1500B MSDUs */
-+-#define HTT_RX_RING_SIZE_MAX 2048
-+-
-+-#define HTT_RX_AVG_FRM_BYTES 1000
-+-
-+-/* ms, very conservative */
-+-#define HTT_RX_HOST_LATENCY_MAX_MS 20
-+-
-+-/* ms, conservative */
-+-#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10
-++#define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX
-++#define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
-+ 
-+ /* when under memory pressure rx ring refill may fail and needs a retry */
-+ #define HTT_RX_RING_REFILL_RETRY_MS 50
-+ 
-+-
-+ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
-+ static void ath10k_htt_txrx_compl_task(unsigned long ptr);
-+ 
-+-static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt)
-+-{
-+-	int size;
-+-
-+-	/*
-+-	 * It is expected that the host CPU will typically be able to
-+-	 * service the rx indication from one A-MPDU before the rx
-+-	 * indication from the subsequent A-MPDU happens, roughly 1-2 ms
-+-	 * later. However, the rx ring should be sized very conservatively,
-+-	 * to accomodate the worst reasonable delay before the host CPU
-+-	 * services a rx indication interrupt.
-+-	 *
-+-	 * The rx ring need not be kept full of empty buffers. In theory,
-+-	 * the htt host SW can dynamically track the low-water mark in the
-+-	 * rx ring, and dynamically adjust the level to which the rx ring
-+-	 * is filled with empty buffers, to dynamically meet the desired
-+-	 * low-water mark.
-+-	 *
-+-	 * In contrast, it's difficult to resize the rx ring itself, once
-+-	 * it's in use. Thus, the ring itself should be sized very
-+-	 * conservatively, while the degree to which the ring is filled
-+-	 * with empty buffers should be sized moderately conservatively.
-+-	 */
-+-
-+-	/* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
-+-	size =
-+-	    htt->max_throughput_mbps +
-+-	    1000  /
-+-	    (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_MAX_MS;
-+-
-+-	if (size < HTT_RX_RING_SIZE_MIN)
-+-		size = HTT_RX_RING_SIZE_MIN;
-+-
-+-	if (size > HTT_RX_RING_SIZE_MAX)
-+-		size = HTT_RX_RING_SIZE_MAX;
-+-
-+-	size = roundup_pow_of_two(size);
-+-
-+-	return size;
-+-}
-+-
-+-static int ath10k_htt_rx_ring_fill_level(struct ath10k_htt *htt)
-++static struct sk_buff *
-++ath10k_htt_rx_find_skb_paddr(struct ath10k *ar, u32 paddr)
-+ {
-+-	int size;
-++	struct ath10k_skb_rxcb *rxcb;
-+ 
-+-	/* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
-+-	size =
-+-	    htt->max_throughput_mbps *
-+-	    1000  /
-+-	    (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS;
-+-
-+-	/*
-+-	 * Make sure the fill level is at least 1 less than the ring size.
-+-	 * Leaving 1 element empty allows the SW to easily distinguish
-+-	 * between a full ring vs. an empty ring.
-+-	 */
-+-	if (size >= htt->rx_ring.size)
-+-		size = htt->rx_ring.size - 1;
-++	hash_for_each_possible(ar->htt.rx_ring.skb_table, rxcb, hlist, paddr)
-++		if (rxcb->paddr == paddr)
-++			return ATH10K_RXCB_SKB(rxcb);
-+ 
-+-	return size;
-++	WARN_ON_ONCE(1);
-++	return NULL;
-+ }
-+ 
-+ static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt)
-+ {
-+ 	struct sk_buff *skb;
-+-	struct ath10k_skb_cb *cb;
-++	struct ath10k_skb_rxcb *rxcb;
-++	struct hlist_node *n;
-+ 	int i;
-+ 
-+-	for (i = 0; i < htt->rx_ring.fill_cnt; i++) {
-+-		skb = htt->rx_ring.netbufs_ring[i];
-+-		cb = ATH10K_SKB_CB(skb);
-+-		dma_unmap_single(htt->ar->dev, cb->paddr,
-+-				 skb->len + skb_tailroom(skb),
-+-				 DMA_FROM_DEVICE);
-+-		dev_kfree_skb_any(skb);
-++	if (htt->rx_ring.in_ord_rx) {
-++		hash_for_each_safe(htt->rx_ring.skb_table, i, n, rxcb, hlist) {
-++			skb = ATH10K_RXCB_SKB(rxcb);
-++			dma_unmap_single(htt->ar->dev, rxcb->paddr,
-++					 skb->len + skb_tailroom(skb),
-++					 DMA_FROM_DEVICE);
-++			hash_del(&rxcb->hlist);
-++			dev_kfree_skb_any(skb);
-++		}
-++	} else {
-++		for (i = 0; i < htt->rx_ring.size; i++) {
-++			skb = htt->rx_ring.netbufs_ring[i];
-++			if (!skb)
-++				continue;
-++
-++			rxcb = ATH10K_SKB_RXCB(skb);
-++			dma_unmap_single(htt->ar->dev, rxcb->paddr,
-++					 skb->len + skb_tailroom(skb),
-++					 DMA_FROM_DEVICE);
-++			dev_kfree_skb_any(skb);
-++		}
-+ 	}
-+ 
-+ 	htt->rx_ring.fill_cnt = 0;
-++	hash_init(htt->rx_ring.skb_table);
-++	memset(htt->rx_ring.netbufs_ring, 0,
-++	       htt->rx_ring.size * sizeof(htt->rx_ring.netbufs_ring[0]));
-+ }
-+ 
-+ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
-+ {
-+ 	struct htt_rx_desc *rx_desc;
-++	struct ath10k_skb_rxcb *rxcb;
-+ 	struct sk_buff *skb;
-+ 	dma_addr_t paddr;
-+ 	int ret = 0, idx;
-+ 
-+-	idx = __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr));
-++	/* The Full Rx Reorder firmware has no way of telling the host
-++	 * implicitly when it copied HTT Rx Ring buffers to MAC Rx Ring.
-++	 * To keep things simple make sure ring is always half empty. This
-++	 * guarantees there'll be no replenishment overruns possible.
-++	 */
-++	BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2);
-++
-++	idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
-+ 	while (num > 0) {
-+ 		skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
-+ 		if (!skb) {
-+@@ -159,18 +125,30 @@ static int __ath10k_htt_rx_ring_fill_n(s
-+ 			goto fail;
-+ 		}
-+ 
-+-		ATH10K_SKB_CB(skb)->paddr = paddr;
-++		rxcb = ATH10K_SKB_RXCB(skb);
-++		rxcb->paddr = paddr;
-+ 		htt->rx_ring.netbufs_ring[idx] = skb;
-+ 		htt->rx_ring.paddrs_ring[idx] = __cpu_to_le32(paddr);
-+ 		htt->rx_ring.fill_cnt++;
-+ 
-++		if (htt->rx_ring.in_ord_rx) {
-++			hash_add(htt->rx_ring.skb_table,
-++				 &ATH10K_SKB_RXCB(skb)->hlist,
-++				 (u32)paddr);
-++		}
-++
-+ 		num--;
-+ 		idx++;
-+ 		idx &= htt->rx_ring.size_mask;
-+ 	}
-+ 
-+ fail:
-+-	*(htt->rx_ring.alloc_idx.vaddr) = __cpu_to_le32(idx);
-++	/*
-++	 * Make sure the rx buffer is updated before available buffer
-++	 * index to avoid any potential rx ring corruption.
-++	 */
-++	mb();
-++	*htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx);
-+ 	return ret;
-+ }
-+ 
-+@@ -198,7 +176,7 @@ static void ath10k_htt_rx_msdu_buff_repl
-+ 	 * automatically balances load wrt to CPU power.
-+ 	 *
-+ 	 * This probably comes at a cost of lower maximum throughput but
-+-	 * improves the avarage and stability. */
-++	 * improves the average and stability. */
-+ 	spin_lock_bh(&htt->rx_ring.lock);
-+ 	num_deficit = htt->rx_ring.fill_level - htt->rx_ring.fill_cnt;
-+ 	num_to_fill = min(ATH10K_HTT_MAX_NUM_REFILL, num_deficit);
-+@@ -222,32 +200,37 @@ static void ath10k_htt_rx_msdu_buff_repl
-+ static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
-+ {
-+ 	struct ath10k_htt *htt = (struct ath10k_htt *)arg;
-++
-+ 	ath10k_htt_rx_msdu_buff_replenish(htt);
-+ }
-+ 
-+-void ath10k_htt_rx_detach(struct ath10k_htt *htt)
-++int ath10k_htt_rx_ring_refill(struct ath10k *ar)
-+ {
-+-	int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld;
-++	struct ath10k_htt *htt = &ar->htt;
-++	int ret;
-++
-++	spin_lock_bh(&htt->rx_ring.lock);
-++	ret = ath10k_htt_rx_ring_fill_n(htt, (htt->rx_ring.fill_level -
-++					      htt->rx_ring.fill_cnt));
-++	spin_unlock_bh(&htt->rx_ring.lock);
-++
-++	if (ret)
-++		ath10k_htt_rx_ring_free(htt);
-++
-++	return ret;
-++}
-+ 
-++void ath10k_htt_rx_free(struct ath10k_htt *htt)
-++{
-+ 	del_timer_sync(&htt->rx_ring.refill_retry_timer);
-+ 	tasklet_kill(&htt->rx_replenish_task);
-+ 	tasklet_kill(&htt->txrx_compl_task);
-+ 
-+ 	skb_queue_purge(&htt->tx_compl_q);
-+ 	skb_queue_purge(&htt->rx_compl_q);
-++	skb_queue_purge(&htt->rx_in_ord_compl_q);
-+ 
-+-	while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) {
-+-		struct sk_buff *skb =
-+-				htt->rx_ring.netbufs_ring[sw_rd_idx];
-+-		struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
-+-
-+-		dma_unmap_single(htt->ar->dev, cb->paddr,
-+-				 skb->len + skb_tailroom(skb),
-+-				 DMA_FROM_DEVICE);
-+-		dev_kfree_skb_any(htt->rx_ring.netbufs_ring[sw_rd_idx]);
-+-		sw_rd_idx++;
-+-		sw_rd_idx &= htt->rx_ring.size_mask;
-+-	}
-++	ath10k_htt_rx_ring_free(htt);
-+ 
-+ 	dma_free_coherent(htt->ar->dev,
-+ 			  (htt->rx_ring.size *
-+@@ -265,66 +248,59 @@ void ath10k_htt_rx_detach(struct ath10k_
-+ 
-+ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	int idx;
-+ 	struct sk_buff *msdu;
-+ 
-+ 	lockdep_assert_held(&htt->rx_ring.lock);
-+ 
-+ 	if (htt->rx_ring.fill_cnt == 0) {
-+-		ath10k_warn("tried to pop sk_buff from an empty rx ring\n");
-++		ath10k_warn(ar, "tried to pop sk_buff from an empty rx ring\n");
-+ 		return NULL;
-+ 	}
-+ 
-+ 	idx = htt->rx_ring.sw_rd_idx.msdu_payld;
-+ 	msdu = htt->rx_ring.netbufs_ring[idx];
-++	htt->rx_ring.netbufs_ring[idx] = NULL;
-++	htt->rx_ring.paddrs_ring[idx] = 0;
-+ 
-+ 	idx++;
-+ 	idx &= htt->rx_ring.size_mask;
-+ 	htt->rx_ring.sw_rd_idx.msdu_payld = idx;
-+ 	htt->rx_ring.fill_cnt--;
-+ 
-+-	return msdu;
-+-}
-+-
-+-static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
-+-{
-+-	struct sk_buff *next;
-++	dma_unmap_single(htt->ar->dev,
-++			 ATH10K_SKB_RXCB(msdu)->paddr,
-++			 msdu->len + skb_tailroom(msdu),
-++			 DMA_FROM_DEVICE);
-++	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
-++			msdu->data, msdu->len + skb_tailroom(msdu));
-+ 
-+-	while (skb) {
-+-		next = skb->next;
-+-		dev_kfree_skb_any(skb);
-+-		skb = next;
-+-	}
-++	return msdu;
-+ }
-+ 
-+ /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
-+ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
-+ 				   u8 **fw_desc, int *fw_desc_len,
-+-				   struct sk_buff **head_msdu,
-+-				   struct sk_buff **tail_msdu)
-++				   struct sk_buff_head *amsdu)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	int msdu_len, msdu_chaining = 0;
-+ 	struct sk_buff *msdu;
-+ 	struct htt_rx_desc *rx_desc;
-+ 
-+ 	lockdep_assert_held(&htt->rx_ring.lock);
-+ 
-+-	if (htt->rx_confused) {
-+-		ath10k_warn("htt is confused. refusing rx\n");
-+-		return -1;
-+-	}
-+-
-+-	msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt);
-+-	while (msdu) {
-++	for (;;) {
-+ 		int last_msdu, msdu_len_invalid, msdu_chained;
-+ 
-+-		dma_unmap_single(htt->ar->dev,
-+-				 ATH10K_SKB_CB(msdu)->paddr,
-+-				 msdu->len + skb_tailroom(msdu),
-+-				 DMA_FROM_DEVICE);
-++		msdu = ath10k_htt_rx_netbuf_pop(htt);
-++		if (!msdu) {
-++			__skb_queue_purge(amsdu);
-++			return -ENOENT;
-++		}
-+ 
-+-		ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
-+-				msdu->data, msdu->len + skb_tailroom(msdu));
-++		__skb_queue_tail(amsdu, msdu);
-+ 
-+ 		rx_desc = (struct htt_rx_desc *)msdu->data;
-+ 
-+@@ -343,12 +319,8 @@ static int ath10k_htt_rx_amsdu_pop(struc
-+ 		 */
-+ 		if (!(__le32_to_cpu(rx_desc->attention.flags)
-+ 				& RX_ATTENTION_FLAGS_MSDU_DONE)) {
-+-			ath10k_htt_rx_free_msdu_chain(*head_msdu);
-+-			*head_msdu = NULL;
-+-			msdu = NULL;
-+-			ath10k_err("htt rx stopped. cannot recover\n");
-+-			htt->rx_confused = true;
-+-			break;
-++			__skb_queue_purge(amsdu);
-++			return -EIO;
-+ 		}
-+ 
-+ 		/*
-+@@ -399,7 +371,6 @@ static int ath10k_htt_rx_amsdu_pop(struc
-+ 		msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0),
-+ 			      RX_MSDU_START_INFO0_MSDU_LENGTH);
-+ 		msdu_chained = rx_desc->frag_info.ring2_more_count;
-+-		msdu_chaining = msdu_chained;
-+ 
-+ 		if (msdu_len_invalid)
-+ 			msdu_len = 0;
-+@@ -408,42 +379,32 @@ static int ath10k_htt_rx_amsdu_pop(struc
-+ 		skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
-+ 		msdu_len -= msdu->len;
-+ 
-+-		/* FIXME: Do chained buffers include htt_rx_desc or not? */
-++		/* Note: Chained buffers do not contain rx descriptor */
-+ 		while (msdu_chained--) {
-+-			struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
-+-
-+-			dma_unmap_single(htt->ar->dev,
-+-					 ATH10K_SKB_CB(next)->paddr,
-+-					 next->len + skb_tailroom(next),
-+-					 DMA_FROM_DEVICE);
-+-
-+-			ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL,
-+-					"htt rx chained: ", next->data,
-+-					next->len + skb_tailroom(next));
-+-
-+-			skb_trim(next, 0);
-+-			skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE));
-+-			msdu_len -= next->len;
-++			msdu = ath10k_htt_rx_netbuf_pop(htt);
-++			if (!msdu) {
-++				__skb_queue_purge(amsdu);
-++				return -ENOENT;
-++			}
-+ 
-+-			msdu->next = next;
-+-			msdu = next;
-++			__skb_queue_tail(amsdu, msdu);
-++			skb_trim(msdu, 0);
-++			skb_put(msdu, min(msdu_len, HTT_RX_BUF_SIZE));
-++			msdu_len -= msdu->len;
-++			msdu_chaining = 1;
-+ 		}
-+ 
-+ 		last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
-+ 				RX_MSDU_END_INFO0_LAST_MSDU;
-+ 
-+-		if (last_msdu) {
-+-			msdu->next = NULL;
-++		trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
-++					 sizeof(*rx_desc) - sizeof(u32));
-++
-++		if (last_msdu)
-+ 			break;
-+-		} else {
-+-			struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
-+-			msdu->next = next;
-+-			msdu = next;
-+-		}
-+ 	}
-+-	*tail_msdu = msdu;
-+ 
-+-	if (*head_msdu == NULL)
-++	if (skb_queue_empty(amsdu))
-+ 		msdu_chaining = -1;
-+ 
-+ 	/*
-+@@ -465,43 +426,117 @@ static int ath10k_htt_rx_amsdu_pop(struc
-+ static void ath10k_htt_rx_replenish_task(unsigned long ptr)
-+ {
-+ 	struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
-++
-+ 	ath10k_htt_rx_msdu_buff_replenish(htt);
-+ }
-+ 
-+-int ath10k_htt_rx_attach(struct ath10k_htt *htt)
-++static struct sk_buff *ath10k_htt_rx_pop_paddr(struct ath10k_htt *htt,
-++					       u32 paddr)
-++{
-++	struct ath10k *ar = htt->ar;
-++	struct ath10k_skb_rxcb *rxcb;
-++	struct sk_buff *msdu;
-++
-++	lockdep_assert_held(&htt->rx_ring.lock);
-++
-++	msdu = ath10k_htt_rx_find_skb_paddr(ar, paddr);
-++	if (!msdu)
-++		return NULL;
-++
-++	rxcb = ATH10K_SKB_RXCB(msdu);
-++	hash_del(&rxcb->hlist);
-++	htt->rx_ring.fill_cnt--;
-++
-++	dma_unmap_single(htt->ar->dev, rxcb->paddr,
-++			 msdu->len + skb_tailroom(msdu),
-++			 DMA_FROM_DEVICE);
-++	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
-++			msdu->data, msdu->len + skb_tailroom(msdu));
-++
-++	return msdu;
-++}
-++
-++static int ath10k_htt_rx_pop_paddr_list(struct ath10k_htt *htt,
-++					struct htt_rx_in_ord_ind *ev,
-++					struct sk_buff_head *list)
-+ {
-++	struct ath10k *ar = htt->ar;
-++	struct htt_rx_in_ord_msdu_desc *msdu_desc = ev->msdu_descs;
-++	struct htt_rx_desc *rxd;
-++	struct sk_buff *msdu;
-++	int msdu_count;
-++	bool is_offload;
-++	u32 paddr;
-++
-++	lockdep_assert_held(&htt->rx_ring.lock);
-++
-++	msdu_count = __le16_to_cpu(ev->msdu_count);
-++	is_offload = !!(ev->info & HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK);
-++
-++	while (msdu_count--) {
-++		paddr = __le32_to_cpu(msdu_desc->msdu_paddr);
-++
-++		msdu = ath10k_htt_rx_pop_paddr(htt, paddr);
-++		if (!msdu) {
-++			__skb_queue_purge(list);
-++			return -ENOENT;
-++		}
-++
-++		__skb_queue_tail(list, msdu);
-++
-++		if (!is_offload) {
-++			rxd = (void *)msdu->data;
-++
-++			trace_ath10k_htt_rx_desc(ar, rxd, sizeof(*rxd));
-++
-++			skb_put(msdu, sizeof(*rxd));
-++			skb_pull(msdu, sizeof(*rxd));
-++			skb_put(msdu, __le16_to_cpu(msdu_desc->msdu_len));
-++
-++			if (!(__le32_to_cpu(rxd->attention.flags) &
-++			      RX_ATTENTION_FLAGS_MSDU_DONE)) {
-++				ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n");
-++				return -EIO;
-++			}
-++		}
-++
-++		msdu_desc++;
-++	}
-++
-++	return 0;
-++}
-++
-++int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
-++{
-++	struct ath10k *ar = htt->ar;
-+ 	dma_addr_t paddr;
-+ 	void *vaddr;
-++	size_t size;
-+ 	struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
-+ 
-+-	htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
-+-	if (!is_power_of_2(htt->rx_ring.size)) {
-+-		ath10k_warn("htt rx ring size is not power of 2\n");
-+-		return -EINVAL;
-+-	}
-++	htt->rx_confused = false;
-+ 
-++	/* XXX: The fill level could be changed during runtime in response to
-++	 * the host processing latency. Is this really worth it?
-++	 */
-++	htt->rx_ring.size = HTT_RX_RING_SIZE;
-+ 	htt->rx_ring.size_mask = htt->rx_ring.size - 1;
-++	htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
-+ 
-+-	/*
-+-	 * Set the initial value for the level to which the rx ring
-+-	 * should be filled, based on the max throughput and the
-+-	 * worst likely latency for the host to fill the rx ring
-+-	 * with new buffers. In theory, this fill level can be
-+-	 * dynamically adjusted from the initial value set here, to
-+-	 * reflect the actual host latency rather than a
-+-	 * conservative assumption about the host latency.
-+-	 */
-+-	htt->rx_ring.fill_level = ath10k_htt_rx_ring_fill_level(htt);
-++	if (!is_power_of_2(htt->rx_ring.size)) {
-++		ath10k_warn(ar, "htt rx ring size is not power of 2\n");
-++		return -EINVAL;
-++	}
-+ 
-+ 	htt->rx_ring.netbufs_ring =
-+-		kmalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
-++		kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
-+ 			GFP_KERNEL);
-+ 	if (!htt->rx_ring.netbufs_ring)
-+ 		goto err_netbuf;
-+ 
-+-	vaddr = dma_alloc_coherent(htt->ar->dev,
-+-		   (htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring)),
-+-		   &paddr, GFP_DMA);
-++	size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
-++
-++	vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
-+ 	if (!vaddr)
-+ 		goto err_dma_ring;
-+ 
-+@@ -516,7 +551,7 @@ int ath10k_htt_rx_attach(struct ath10k_h
-+ 
-+ 	htt->rx_ring.alloc_idx.vaddr = vaddr;
-+ 	htt->rx_ring.alloc_idx.paddr = paddr;
-+-	htt->rx_ring.sw_rd_idx.msdu_payld = 0;
-++	htt->rx_ring.sw_rd_idx.msdu_payld = htt->rx_ring.size_mask;
-+ 	*htt->rx_ring.alloc_idx.vaddr = 0;
-+ 
-+ 	/* Initialize the Rx refill retry timer */
-+@@ -525,28 +560,23 @@ int ath10k_htt_rx_attach(struct ath10k_h
-+ 	spin_lock_init(&htt->rx_ring.lock);
-+ 
-+ 	htt->rx_ring.fill_cnt = 0;
-+-	if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level))
-+-		goto err_fill_ring;
-++	htt->rx_ring.sw_rd_idx.msdu_payld = 0;
-++	hash_init(htt->rx_ring.skb_table);
-+ 
-+ 	tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task,
-+ 		     (unsigned long)htt);
-+ 
-+ 	skb_queue_head_init(&htt->tx_compl_q);
-+ 	skb_queue_head_init(&htt->rx_compl_q);
-++	skb_queue_head_init(&htt->rx_in_ord_compl_q);
-+ 
-+ 	tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
-+ 		     (unsigned long)htt);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
-+ 		   htt->rx_ring.size, htt->rx_ring.fill_level);
-+ 	return 0;
-+ 
-+-err_fill_ring:
-+-	ath10k_htt_rx_ring_free(htt);
-+-	dma_free_coherent(htt->ar->dev,
-+-			  sizeof(*htt->rx_ring.alloc_idx.vaddr),
-+-			  htt->rx_ring.alloc_idx.vaddr,
-+-			  htt->rx_ring.alloc_idx.paddr);
-+ err_dma_idx:
-+ 	dma_free_coherent(htt->ar->dev,
-+ 			  (htt->rx_ring.size *
-+@@ -559,73 +589,54 @@ err_netbuf:
-+ 	return -ENOMEM;
-+ }
-+ 
-+-static int ath10k_htt_rx_crypto_param_len(enum htt_rx_mpdu_encrypt_type type)
-++static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
-++					  enum htt_rx_mpdu_encrypt_type type)
-+ {
-+ 	switch (type) {
-++	case HTT_RX_MPDU_ENCRYPT_NONE:
-++		return 0;
-+ 	case HTT_RX_MPDU_ENCRYPT_WEP40:
-+ 	case HTT_RX_MPDU_ENCRYPT_WEP104:
-+-		return 4;
-++		return IEEE80211_WEP_IV_LEN;
-+ 	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
-+-	case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */
-+ 	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-+-	case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */
-++		return IEEE80211_TKIP_IV_LEN;
-+ 	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-+-		return 8;
-+-	case HTT_RX_MPDU_ENCRYPT_NONE:
-+-		return 0;
-++		return IEEE80211_CCMP_HDR_LEN;
-++	case HTT_RX_MPDU_ENCRYPT_WEP128:
-++	case HTT_RX_MPDU_ENCRYPT_WAPI:
-++		break;
-+ 	}
-+ 
-+-	ath10k_warn("unknown encryption type %d\n", type);
-++	ath10k_warn(ar, "unsupported encryption type %d\n", type);
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_htt_rx_crypto_tail_len(enum htt_rx_mpdu_encrypt_type type)
-++#define MICHAEL_MIC_LEN 8
-++
-++static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
-++					 enum htt_rx_mpdu_encrypt_type type)
-+ {
-+ 	switch (type) {
-+ 	case HTT_RX_MPDU_ENCRYPT_NONE:
-++		return 0;
-+ 	case HTT_RX_MPDU_ENCRYPT_WEP40:
-+ 	case HTT_RX_MPDU_ENCRYPT_WEP104:
-+-	case HTT_RX_MPDU_ENCRYPT_WEP128:
-+-	case HTT_RX_MPDU_ENCRYPT_WAPI:
-+-		return 0;
-++		return IEEE80211_WEP_ICV_LEN;
-+ 	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
-+ 	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
-+-		return 4;
-++		return IEEE80211_TKIP_ICV_LEN;
-+ 	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
-+-		return 8;
-++		return IEEE80211_CCMP_MIC_LEN;
-++	case HTT_RX_MPDU_ENCRYPT_WEP128:
-++	case HTT_RX_MPDU_ENCRYPT_WAPI:
-++		break;
-+ 	}
-+ 
-+-	ath10k_warn("unknown encryption type %d\n", type);
-++	ath10k_warn(ar, "unsupported encryption type %d\n", type);
-+ 	return 0;
-+ }
-+ 
-+-/* Applies for first msdu in chain, before altering it. */
-+-static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
-+-{
-+-	struct htt_rx_desc *rxd;
-+-	enum rx_msdu_decap_format fmt;
-+-
-+-	rxd = (void *)skb->data - sizeof(*rxd);
-+-	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-+-			RX_MSDU_START_INFO1_DECAP_FORMAT);
-+-
-+-	if (fmt == RX_MSDU_DECAP_RAW)
-+-		return (void *)skb->data;
-+-	else
-+-		return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
-+-}
-+-
-+-/* This function only applies for first msdu in an msdu chain */
-+-static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
-+-{
-+-	if (ieee80211_is_data_qos(hdr->frame_control)) {
-+-		u8 *qc = ieee80211_get_qos_ctl(hdr);
-+-		if (qc[0] & 0x80)
-+-			return true;
-+-	}
-+-	return false;
-+-}
-+-
-+ struct rfc1042_hdr {
-+ 	u8 llc_dsap;
-+ 	u8 llc_ssap;
-+@@ -660,23 +671,34 @@ static const u8 rx_legacy_rate_idx[] = {
-+ };
-+ 
-+ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
-+-				  enum ieee80211_band band,
-+-				  u8 info0, u32 info1, u32 info2,
-+-				  struct ieee80211_rx_status *status)
-++				  struct ieee80211_rx_status *status,
-++				  struct htt_rx_desc *rxd)
-+ {
-++	enum ieee80211_band band;
-+ 	u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
-+ 	u8 preamble = 0;
-++	u32 info1, info2, info3;
-+ 
-+-	/* Check if valid fields */
-+-	if (!(info0 & HTT_RX_INDICATION_INFO0_START_VALID))
-++	/* Band value can't be set as undefined but freq can be 0 - use that to
-++	 * determine whether band is provided.
-++	 *
-++	 * FIXME: Perhaps this can go away if CCK rate reporting is a little
-++	 * reworked?
-++	 */
-++	if (!status->freq)
-+ 		return;
-+ 
-+-	preamble = MS(info1, HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE);
-++	band = status->band;
-++	info1 = __le32_to_cpu(rxd->ppdu_start.info1);
-++	info2 = __le32_to_cpu(rxd->ppdu_start.info2);
-++	info3 = __le32_to_cpu(rxd->ppdu_start.info3);
-++
-++	preamble = MS(info1, RX_PPDU_START_INFO1_PREAMBLE_TYPE);
-+ 
-+ 	switch (preamble) {
-+ 	case HTT_RX_LEGACY:
-+-		cck = info0 & HTT_RX_INDICATION_INFO0_LEGACY_RATE_CCK;
-+-		rate = MS(info0, HTT_RX_INDICATION_INFO0_LEGACY_RATE);
-++		cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
-++		rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
-+ 		rate_idx = 0;
-+ 
-+ 		if (rate < 0x08 || rate > 0x0F)
-+@@ -703,11 +725,11 @@ static void ath10k_htt_rx_h_rates(struct
-+ 		break;
-+ 	case HTT_RX_HT:
-+ 	case HTT_RX_HT_WITH_TXBF:
-+-		/* HT-SIG - Table 20-11 in info1 and info2 */
-+-		mcs = info1 & 0x1F;
-++		/* HT-SIG - Table 20-11 in info2 and info3 */
-++		mcs = info2 & 0x1F;
-+ 		nss = mcs >> 3;
-+-		bw = (info1 >> 7) & 1;
-+-		sgi = (info2 >> 7) & 1;
-++		bw = (info2 >> 7) & 1;
-++		sgi = (info3 >> 7) & 1;
-+ 
-+ 		status->rate_idx = mcs;
-+ 		status->flag |= RX_FLAG_HT;
-+@@ -718,12 +740,12 @@ static void ath10k_htt_rx_h_rates(struct
-+ 		break;
-+ 	case HTT_RX_VHT:
-+ 	case HTT_RX_VHT_WITH_TXBF:
-+-		/* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
-++		/* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
-+ 		   TODO check this */
-+-		mcs = (info2 >> 4) & 0x0F;
-+-		nss = ((info1 >> 10) & 0x07) + 1;
-+-		bw = info1 & 3;
-+-		sgi = info2 & 1;
-++		mcs = (info3 >> 4) & 0x0F;
-++		nss = ((info2 >> 10) & 0x07) + 1;
-++		bw = info2 & 3;
-++		sgi = info3 & 1;
-+ 
-+ 		status->rate_idx = mcs;
-+ 		status->vht_nss = nss;
-+@@ -751,28 +773,6 @@ static void ath10k_htt_rx_h_rates(struct
-+ 	}
-+ }
-+ 
-+-static void ath10k_htt_rx_h_protected(struct ath10k_htt *htt,
-+-				      struct ieee80211_rx_status *rx_status,
-+-				      struct sk_buff *skb,
-+-				      enum htt_rx_mpdu_encrypt_type enctype)
-+-{
-+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+-
-+-
-+-	if (enctype == HTT_RX_MPDU_ENCRYPT_NONE) {
-+-		rx_status->flag &= ~(RX_FLAG_DECRYPTED |
-+-				     RX_FLAG_IV_STRIPPED |
-+-				     RX_FLAG_MMIC_STRIPPED);
-+-		return;
-+-	}
-+-
-+-	rx_status->flag |= RX_FLAG_DECRYPTED |
-+-			   RX_FLAG_IV_STRIPPED |
-+-			   RX_FLAG_MMIC_STRIPPED;
-+-	hdr->frame_control = __cpu_to_le16(__le16_to_cpu(hdr->frame_control) &
-+-					   ~IEEE80211_FCTL_PROTECTED);
-+-}
-+-
-+ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
-+ 				    struct ieee80211_rx_status *status)
-+ {
-+@@ -793,19 +793,121 @@ static bool ath10k_htt_rx_h_channel(stru
-+ 	return true;
-+ }
-+ 
-++static void ath10k_htt_rx_h_signal(struct ath10k *ar,
-++				   struct ieee80211_rx_status *status,
-++				   struct htt_rx_desc *rxd)
-++{
-++	/* FIXME: Get real NF */
-++	status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
-++			 rxd->ppdu_start.rssi_comb;
-++	status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
-++}
-++
-++static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
-++				    struct ieee80211_rx_status *status,
-++				    struct htt_rx_desc *rxd)
-++{
-++	/* FIXME: TSF is known only at the end of PPDU, in the last MPDU. This
-++	 * means all prior MSDUs in a PPDU are reported to mac80211 without the
-++	 * TSF. Is it worth holding frames until end of PPDU is known?
-++	 *
-++	 * FIXME: Can we get/compute 64bit TSF?
-++	 */
-++	status->mactime = __le32_to_cpu(rxd->ppdu_end.common.tsf_timestamp);
-++	status->flag |= RX_FLAG_MACTIME_END;
-++}
-++
-++static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
-++				 struct sk_buff_head *amsdu,
-++				 struct ieee80211_rx_status *status)
-++{
-++	struct sk_buff *first;
-++	struct htt_rx_desc *rxd;
-++	bool is_first_ppdu;
-++	bool is_last_ppdu;
-++
-++	if (skb_queue_empty(amsdu))
-++		return;
-++
-++	first = skb_peek(amsdu);
-++	rxd = (void *)first->data - sizeof(*rxd);
-++
-++	is_first_ppdu = !!(rxd->attention.flags &
-++			   __cpu_to_le32(RX_ATTENTION_FLAGS_FIRST_MPDU));
-++	is_last_ppdu = !!(rxd->attention.flags &
-++			  __cpu_to_le32(RX_ATTENTION_FLAGS_LAST_MPDU));
-++
-++	if (is_first_ppdu) {
-++		/* New PPDU starts so clear out the old per-PPDU status. */
-++		status->freq = 0;
-++		status->rate_idx = 0;
-++		status->vht_nss = 0;
-++		status->vht_flag &= ~RX_VHT_FLAG_80MHZ;
-++		status->flag &= ~(RX_FLAG_HT |
-++				  RX_FLAG_VHT |
-++				  RX_FLAG_SHORT_GI |
-++				  RX_FLAG_40MHZ |
-++				  RX_FLAG_MACTIME_END);
-++		status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-++
-++		ath10k_htt_rx_h_signal(ar, status, rxd);
-++		ath10k_htt_rx_h_channel(ar, status);
-++		ath10k_htt_rx_h_rates(ar, status, rxd);
-++	}
-++
-++	if (is_last_ppdu)
-++		ath10k_htt_rx_h_mactime(ar, status, rxd);
-++}
-++
-++static const char * const tid_to_ac[] = {
-++	"BE",
-++	"BK",
-++	"BK",
-++	"BE",
-++	"VI",
-++	"VI",
-++	"VO",
-++	"VO",
-++};
-++
-++static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size)
-++{
-++	u8 *qc;
-++	int tid;
-++
-++	if (!ieee80211_is_data_qos(hdr->frame_control))
-++		return "";
-++
-++	qc = ieee80211_get_qos_ctl(hdr);
-++	tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
-++	if (tid < 8)
-++		snprintf(out, size, "tid %d (%s)", tid, tid_to_ac[tid]);
-++	else
-++		snprintf(out, size, "tid %d", tid);
-++
-++	return out;
-++}
-++
-+ static void ath10k_process_rx(struct ath10k *ar,
-+ 			      struct ieee80211_rx_status *rx_status,
-+ 			      struct sk_buff *skb)
-+ {
-+ 	struct ieee80211_rx_status *status;
-++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-++	char tid[32];
-+ 
-+ 	status = IEEE80211_SKB_RXCB(skb);
-+ 	*status = *rx_status;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_DATA,
-+-		   "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n",
-++	ath10k_dbg(ar, ATH10K_DBG_DATA,
-++		   "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
-+ 		   skb,
-+ 		   skb->len,
-++		   ieee80211_get_SA(hdr),
-++		   ath10k_get_tid(hdr, tid, sizeof(tid)),
-++		   is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
-++							"mcast" : "ucast",
-++		   (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
-+ 		   status->flag == 0 ? "legacy" : "",
-+ 		   status->flag & RX_FLAG_HT ? "ht" : "",
-+ 		   status->flag & RX_FLAG_VHT ? "vht" : "",
-+@@ -817,9 +919,12 @@ static void ath10k_process_rx(struct ath
-+ 		   status->freq,
-+ 		   status->band, status->flag,
-+ 		   !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
-+-		   !!(status->flag & RX_FLAG_MMIC_ERROR));
-+-	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
-++		   !!(status->flag & RX_FLAG_MMIC_ERROR),
-++		   !!(status->flag & RX_FLAG_AMSDU_MORE));
-++	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
-+ 			skb->data, skb->len);
-++	trace_ath10k_rx_hdr(ar, skb->data, skb->len);
-++	trace_ath10k_rx_payload(ar, skb->data, skb->len);
-+ 
-+ 	ieee80211_rx(ar->hw, skb);
-+ }
-+@@ -830,179 +935,263 @@ static int ath10k_htt_rx_nwifi_hdrlen(st
-+ 	return round_up(ieee80211_hdrlen(hdr->frame_control), 4);
-+ }
-+ 
-+-static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
-+-				struct ieee80211_rx_status *rx_status,
-+-				struct sk_buff *skb_in)
-++static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
-++					struct sk_buff *msdu,
-++					struct ieee80211_rx_status *status,
-++					enum htt_rx_mpdu_encrypt_type enctype,
-++					bool is_decrypted)
-+ {
-++	struct ieee80211_hdr *hdr;
-+ 	struct htt_rx_desc *rxd;
-+-	struct sk_buff *skb = skb_in;
-+-	struct sk_buff *first;
-+-	enum rx_msdu_decap_format fmt;
-+-	enum htt_rx_mpdu_encrypt_type enctype;
-++	size_t hdr_len;
-++	size_t crypto_len;
-++	bool is_first;
-++	bool is_last;
-++
-++	rxd = (void *)msdu->data - sizeof(*rxd);
-++	is_first = !!(rxd->msdu_end.info0 &
-++		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-++	is_last = !!(rxd->msdu_end.info0 &
-++		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
-++
-++	/* Delivered decapped frame:
-++	 * [802.11 header]
-++	 * [crypto param] <-- can be trimmed if !fcs_err &&
-++	 *                    !decrypt_err && !peer_idx_invalid
-++	 * [amsdu header] <-- only if A-MSDU
-++	 * [rfc1042/llc]
-++	 * [payload]
-++	 * [FCS] <-- at end, needs to be trimmed
-++	 */
-++
-++	/* This probably shouldn't happen but warn just in case */
-++	if (unlikely(WARN_ON_ONCE(!is_first)))
-++		return;
-++
-++	/* This probably shouldn't happen but warn just in case */
-++	if (unlikely(WARN_ON_ONCE(!(is_first && is_last))))
-++		return;
-++
-++	skb_trim(msdu, msdu->len - FCS_LEN);
-++
-++	/* In most cases this will be true for sniffed frames. It makes sense
-++	 * to deliver them as-is without stripping the crypto param. This would
-++	 * also make sense for software based decryption (which is not
-++	 * implemented in ath10k).
-++	 *
-++	 * If there's no error then the frame is decrypted. At least that is
-++	 * the case for frames that come in via fragmented rx indication.
-++	 */
-++	if (!is_decrypted)
-++		return;
-++
-++	/* The payload is decrypted so strip crypto params. Start from tail
-++	 * since hdr is used to compute some stuff.
-++	 */
-++
-++	hdr = (void *)msdu->data;
-++
-++	/* Tail */
-++	skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype));
-++
-++	/* MMIC */
-++	if (!ieee80211_has_morefrags(hdr->frame_control) &&
-++	    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
-++		skb_trim(msdu, msdu->len - 8);
-++
-++	/* Head */
-++	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-++	crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
-++
-++	memmove((void *)msdu->data + crypto_len,
-++		(void *)msdu->data, hdr_len);
-++	skb_pull(msdu, crypto_len);
-++}
-++
-++static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
-++					  struct sk_buff *msdu,
-++					  struct ieee80211_rx_status *status,
-++					  const u8 first_hdr[64])
-++{
-+ 	struct ieee80211_hdr *hdr;
-+-	u8 hdr_buf[64], addr[ETH_ALEN], *qos;
-+-	unsigned int hdr_len;
-++	size_t hdr_len;
-++	u8 da[ETH_ALEN];
-++	u8 sa[ETH_ALEN];
-++
-++	/* Delivered decapped frame:
-++	 * [nwifi 802.11 header] <-- replaced with 802.11 hdr
-++	 * [rfc1042/llc]
-++	 *
-++	 * Note: The nwifi header doesn't have QoS Control and is
-++	 * (always?) a 3addr frame.
-++	 *
-++	 * Note2: There's no A-MSDU subframe header. Even if it's part
-++	 * of an A-MSDU.
-++	 */
-+ 
-+-	rxd = (void *)skb->data - sizeof(*rxd);
-+-	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-+-			RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-++	/* pull decapped header and copy SA & DA */
-++	hdr = (struct ieee80211_hdr *)msdu->data;
-++	hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-++	ether_addr_copy(da, ieee80211_get_DA(hdr));
-++	ether_addr_copy(sa, ieee80211_get_SA(hdr));
-++	skb_pull(msdu, hdr_len);
-+ 
-+-	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
-++	/* push original 802.11 header */
-++	hdr = (struct ieee80211_hdr *)first_hdr;
-+ 	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-+-	memcpy(hdr_buf, hdr, hdr_len);
-+-	hdr = (struct ieee80211_hdr *)hdr_buf;
-++	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-+ 
-+-	first = skb;
-+-	while (skb) {
-+-		void *decap_hdr;
-+-		int len;
-+-
-+-		rxd = (void *)skb->data - sizeof(*rxd);
-+-		fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-+-			 RX_MSDU_START_INFO1_DECAP_FORMAT);
-+-		decap_hdr = (void *)rxd->rx_hdr_status;
-+-
-+-		skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
-+-
-+-		/* First frame in an A-MSDU chain has more decapped data. */
-+-		if (skb == first) {
-+-			len = round_up(ieee80211_hdrlen(hdr->frame_control), 4);
-+-			len += round_up(ath10k_htt_rx_crypto_param_len(enctype),
-+-					4);
-+-			decap_hdr += len;
-+-		}
-++	/* original 802.11 header has a different DA and in
-++	 * case of 4addr it may also have different SA
-++	 */
-++	hdr = (struct ieee80211_hdr *)msdu->data;
-++	ether_addr_copy(ieee80211_get_DA(hdr), da);
-++	ether_addr_copy(ieee80211_get_SA(hdr), sa);
-++}
-+ 
-+-		switch (fmt) {
-+-		case RX_MSDU_DECAP_RAW:
-+-			/* remove trailing FCS */
-+-			skb_trim(skb, skb->len - FCS_LEN);
-+-			break;
-+-		case RX_MSDU_DECAP_NATIVE_WIFI:
-+-			/* pull decapped header and copy DA */
-+-			hdr = (struct ieee80211_hdr *)skb->data;
-+-			hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-+-			memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
-+-			skb_pull(skb, hdr_len);
-+-
-+-			/* push original 802.11 header */
-+-			hdr = (struct ieee80211_hdr *)hdr_buf;
-+-			hdr_len = ieee80211_hdrlen(hdr->frame_control);
-+-			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-+-
-+-			/* original A-MSDU header has the bit set but we're
-+-			 * not including A-MSDU subframe header */
-+-			hdr = (struct ieee80211_hdr *)skb->data;
-+-			qos = ieee80211_get_qos_ctl(hdr);
-+-			qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
-++static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
-++					  struct sk_buff *msdu,
-++					  enum htt_rx_mpdu_encrypt_type enctype)
-++{
-++	struct ieee80211_hdr *hdr;
-++	struct htt_rx_desc *rxd;
-++	size_t hdr_len, crypto_len;
-++	void *rfc1042;
-++	bool is_first, is_last, is_amsdu;
-+ 
-+-			/* original 802.11 header has a different DA */
-+-			memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
-+-			break;
-+-		case RX_MSDU_DECAP_ETHERNET2_DIX:
-+-			/* strip ethernet header and insert decapped 802.11
-+-			 * header, amsdu subframe header and rfc1042 header */
-+-
-+-			len = 0;
-+-			len += sizeof(struct rfc1042_hdr);
-+-			len += sizeof(struct amsdu_subframe_hdr);
-+-
-+-			skb_pull(skb, sizeof(struct ethhdr));
-+-			memcpy(skb_push(skb, len), decap_hdr, len);
-+-			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-+-			break;
-+-		case RX_MSDU_DECAP_8023_SNAP_LLC:
-+-			/* insert decapped 802.11 header making a singly
-+-			 * A-MSDU */
-+-			memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-+-			break;
-+-		}
-++	rxd = (void *)msdu->data - sizeof(*rxd);
-++	hdr = (void *)rxd->rx_hdr_status;
-+ 
-+-		skb_in = skb;
-+-		ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype);
-+-		skb = skb->next;
-+-		skb_in->next = NULL;
-++	is_first = !!(rxd->msdu_end.info0 &
-++		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
-++	is_last = !!(rxd->msdu_end.info0 &
-++		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
-++	is_amsdu = !(is_first && is_last);
-+ 
-+-		if (skb)
-+-			rx_status->flag |= RX_FLAG_AMSDU_MORE;
-+-		else
-+-			rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
-++	rfc1042 = hdr;
-++
-++	if (is_first) {
-++		hdr_len = ieee80211_hdrlen(hdr->frame_control);
-++		crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
-+ 
-+-		ath10k_process_rx(htt->ar, rx_status, skb_in);
-++		rfc1042 += round_up(hdr_len, 4) +
-++			   round_up(crypto_len, 4);
-+ 	}
-+ 
-+-	/* FIXME: It might be nice to re-assemble the A-MSDU when there's a
-+-	 * monitor interface active for sniffing purposes. */
-++	if (is_amsdu)
-++		rfc1042 += sizeof(struct amsdu_subframe_hdr);
-++
-++	return rfc1042;
-+ }
-+ 
-+-static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
-+-			       struct ieee80211_rx_status *rx_status,
-+-			       struct sk_buff *skb)
-++static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
-++					struct sk_buff *msdu,
-++					struct ieee80211_rx_status *status,
-++					const u8 first_hdr[64],
-++					enum htt_rx_mpdu_encrypt_type enctype)
-+ {
-+-	struct htt_rx_desc *rxd;
-+ 	struct ieee80211_hdr *hdr;
-+-	enum rx_msdu_decap_format fmt;
-+-	enum htt_rx_mpdu_encrypt_type enctype;
-+-	int hdr_len;
-++	struct ethhdr *eth;
-++	size_t hdr_len;
-+ 	void *rfc1042;
-++	u8 da[ETH_ALEN];
-++	u8 sa[ETH_ALEN];
-+ 
-+-	/* This shouldn't happen. If it does than it may be a FW bug. */
-+-	if (skb->next) {
-+-		ath10k_warn("htt rx received chained non A-MSDU frame\n");
-+-		ath10k_htt_rx_free_msdu_chain(skb->next);
-+-		skb->next = NULL;
-+-	}
-++	/* Delivered decapped frame:
-++	 * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
-++	 * [payload]
-++	 */
-+ 
-+-	rxd = (void *)skb->data - sizeof(*rxd);
-+-	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-+-			RX_MSDU_START_INFO1_DECAP_FORMAT);
-+-	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-+-			RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-+-	hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
-++	rfc1042 = ath10k_htt_rx_h_find_rfc1042(ar, msdu, enctype);
-++	if (WARN_ON_ONCE(!rfc1042))
-++		return;
-++
-++	/* pull decapped header and copy SA & DA */
-++	eth = (struct ethhdr *)msdu->data;
-++	ether_addr_copy(da, eth->h_dest);
-++	ether_addr_copy(sa, eth->h_source);
-++	skb_pull(msdu, sizeof(struct ethhdr));
-++
-++	/* push rfc1042/llc/snap */
-++	memcpy(skb_push(msdu, sizeof(struct rfc1042_hdr)), rfc1042,
-++	       sizeof(struct rfc1042_hdr));
-++
-++	/* push original 802.11 header */
-++	hdr = (struct ieee80211_hdr *)first_hdr;
-+ 	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-++	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-++
-++	/* original 802.11 header has a different DA and in
-++	 * case of 4addr it may also have different SA
-++	 */
-++	hdr = (struct ieee80211_hdr *)msdu->data;
-++	ether_addr_copy(ieee80211_get_DA(hdr), da);
-++	ether_addr_copy(ieee80211_get_SA(hdr), sa);
-++}
-++
-++static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
-++					 struct sk_buff *msdu,
-++					 struct ieee80211_rx_status *status,
-++					 const u8 first_hdr[64])
-++{
-++	struct ieee80211_hdr *hdr;
-++	size_t hdr_len;
-++
-++	/* Delivered decapped frame:
-++	 * [amsdu header] <-- replaced with 802.11 hdr
-++	 * [rfc1042/llc]
-++	 * [payload]
-++	 */
-++
-++	skb_pull(msdu, sizeof(struct amsdu_subframe_hdr));
-++
-++	hdr = (struct ieee80211_hdr *)first_hdr;
-++	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-++	memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-++}
-++
-++static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
-++				    struct sk_buff *msdu,
-++				    struct ieee80211_rx_status *status,
-++				    u8 first_hdr[64],
-++				    enum htt_rx_mpdu_encrypt_type enctype,
-++				    bool is_decrypted)
-++{
-++	struct htt_rx_desc *rxd;
-++	enum rx_msdu_decap_format decap;
-++	struct ieee80211_hdr *hdr;
-++
-++	/* First msdu's decapped header:
-++	 * [802.11 header] <-- padded to 4 bytes long
-++	 * [crypto param] <-- padded to 4 bytes long
-++	 * [amsdu header] <-- only if A-MSDU
-++	 * [rfc1042/llc]
-++	 *
-++	 * Other (2nd, 3rd, ..) msdu's decapped header:
-++	 * [amsdu header] <-- only if A-MSDU
-++	 * [rfc1042/llc]
-++	 */
-+ 
-+-	skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
-++	rxd = (void *)msdu->data - sizeof(*rxd);
-++	hdr = (void *)rxd->rx_hdr_status;
-++	decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
-++		   RX_MSDU_START_INFO1_DECAP_FORMAT);
-+ 
-+-	switch (fmt) {
-++	switch (decap) {
-+ 	case RX_MSDU_DECAP_RAW:
-+-		/* remove trailing FCS */
-+-		skb_trim(skb, skb->len - FCS_LEN);
-++		ath10k_htt_rx_h_undecap_raw(ar, msdu, status, enctype,
-++					    is_decrypted);
-+ 		break;
-+ 	case RX_MSDU_DECAP_NATIVE_WIFI:
-+-		/* Pull decapped header */
-+-		hdr = (struct ieee80211_hdr *)skb->data;
-+-		hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
-+-		skb_pull(skb, hdr_len);
-+-
-+-		/* Push original header */
-+-		hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
-+-		hdr_len = ieee80211_hdrlen(hdr->frame_control);
-+-		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-++		ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr);
-+ 		break;
-+ 	case RX_MSDU_DECAP_ETHERNET2_DIX:
-+-		/* strip ethernet header and insert decapped 802.11 header and
-+-		 * rfc1042 header */
-+-
-+-		rfc1042 = hdr;
-+-		rfc1042 += roundup(hdr_len, 4);
-+-		rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(enctype), 4);
-+-
-+-		skb_pull(skb, sizeof(struct ethhdr));
-+-		memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)),
-+-		       rfc1042, sizeof(struct rfc1042_hdr));
-+-		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-++		ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype);
-+ 		break;
-+ 	case RX_MSDU_DECAP_8023_SNAP_LLC:
-+-		/* remove A-MSDU subframe header and insert
-+-		 * decapped 802.11 header. rfc1042 header is already there */
-+-
-+-		skb_pull(skb, sizeof(struct amsdu_subframe_hdr));
-+-		memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
-++		ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr);
-+ 		break;
-+ 	}
-+-
-+-	ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype);
-+-
-+-	ath10k_process_rx(htt->ar, rx_status, skb);
-+ }
-+ 
-+ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
-+@@ -1036,10 +1225,128 @@ static int ath10k_htt_rx_get_csum_state(
-+ 	return CHECKSUM_UNNECESSARY;
-+ }
-+ 
-+-static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
-++static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
-++{
-++	msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
-++}
-++
-++static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
-++				 struct sk_buff_head *amsdu,
-++				 struct ieee80211_rx_status *status)
-++{
-++	struct sk_buff *first;
-++	struct sk_buff *last;
-++	struct sk_buff *msdu;
-++	struct htt_rx_desc *rxd;
-++	struct ieee80211_hdr *hdr;
-++	enum htt_rx_mpdu_encrypt_type enctype;
-++	u8 first_hdr[64];
-++	u8 *qos;
-++	size_t hdr_len;
-++	bool has_fcs_err;
-++	bool has_crypto_err;
-++	bool has_tkip_err;
-++	bool has_peer_idx_invalid;
-++	bool is_decrypted;
-++	u32 attention;
-++
-++	if (skb_queue_empty(amsdu))
-++		return;
-++
-++	first = skb_peek(amsdu);
-++	rxd = (void *)first->data - sizeof(*rxd);
-++
-++	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-++		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-++
-++	/* First MSDU's Rx descriptor in an A-MSDU contains full 802.11
-++	 * decapped header. It'll be used for undecapping of each MSDU.
-++	 */
-++	hdr = (void *)rxd->rx_hdr_status;
-++	hdr_len = ieee80211_hdrlen(hdr->frame_control);
-++	memcpy(first_hdr, hdr, hdr_len);
-++
-++	/* Each A-MSDU subframe will use the original header as the base and be
-++	 * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
-++	 */
-++	hdr = (void *)first_hdr;
-++	qos = ieee80211_get_qos_ctl(hdr);
-++	qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
-++
-++	/* Some attention flags are valid only in the last MSDU. */
-++	last = skb_peek_tail(amsdu);
-++	rxd = (void *)last->data - sizeof(*rxd);
-++	attention = __le32_to_cpu(rxd->attention.flags);
-++
-++	has_fcs_err = !!(attention & RX_ATTENTION_FLAGS_FCS_ERR);
-++	has_crypto_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
-++	has_tkip_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-++	has_peer_idx_invalid = !!(attention & RX_ATTENTION_FLAGS_PEER_IDX_INVALID);
-++
-++	/* Note: If hardware captures an encrypted frame that it can't decrypt,
-++	 * e.g. due to fcs error, missing peer or invalid key data it will
-++	 * report the frame as raw.
-++	 */
-++	is_decrypted = (enctype != HTT_RX_MPDU_ENCRYPT_NONE &&
-++			!has_fcs_err &&
-++			!has_crypto_err &&
-++			!has_peer_idx_invalid);
-++
-++	/* Clear per-MPDU flags while leaving per-PPDU flags intact. */
-++	status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
-++			  RX_FLAG_MMIC_ERROR |
-++			  RX_FLAG_DECRYPTED |
-++			  RX_FLAG_IV_STRIPPED |
-++			  RX_FLAG_MMIC_STRIPPED);
-++
-++	if (has_fcs_err)
-++		status->flag |= RX_FLAG_FAILED_FCS_CRC;
-++
-++	if (has_tkip_err)
-++		status->flag |= RX_FLAG_MMIC_ERROR;
-++
-++	if (is_decrypted)
-++		status->flag |= RX_FLAG_DECRYPTED |
-++				RX_FLAG_IV_STRIPPED |
-++				RX_FLAG_MMIC_STRIPPED;
-++
-++	skb_queue_walk(amsdu, msdu) {
-++		ath10k_htt_rx_h_csum_offload(msdu);
-++		ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
-++					is_decrypted);
-++
-++		/* Undecapping involves copying the original 802.11 header back
-++		 * to sk_buff. If frame is protected and hardware has decrypted
-++		 * it then remove the protected bit.
-++		 */
-++		if (!is_decrypted)
-++			continue;
-++
-++		hdr = (void *)msdu->data;
-++		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-++	}
-++}
-++
-++static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
-++				    struct sk_buff_head *amsdu,
-++				    struct ieee80211_rx_status *status)
-++{
-++	struct sk_buff *msdu;
-++
-++	while ((msdu = __skb_dequeue(amsdu))) {
-++		/* Setup per-MSDU flags */
-++		if (skb_queue_empty(amsdu))
-++			status->flag &= ~RX_FLAG_AMSDU_MORE;
-++		else
-++			status->flag |= RX_FLAG_AMSDU_MORE;
-++
-++		ath10k_process_rx(ar, status, msdu);
-++	}
-++}
-++
-++static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
-+ {
-+-	struct sk_buff *next = msdu_head->next;
-+-	struct sk_buff *to_free = next;
-++	struct sk_buff *skb, *first;
-+ 	int space;
-+ 	int total_len = 0;
-+ 
-+@@ -1050,110 +1357,142 @@ static int ath10k_unchain_msdu(struct sk
-+ 	 * skb?
-+ 	 */
-+ 
-+-	msdu_head->next = NULL;
-++	first = __skb_dequeue(amsdu);
-+ 
-+ 	/* Allocate total length all at once. */
-+-	while (next) {
-+-		total_len += next->len;
-+-		next = next->next;
-+-	}
-++	skb_queue_walk(amsdu, skb)
-++		total_len += skb->len;
-+ 
-+-	space = total_len - skb_tailroom(msdu_head);
-++	space = total_len - skb_tailroom(first);
-+ 	if ((space > 0) &&
-+-	    (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) {
-++	    (pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
-+ 		/* TODO:  bump some rx-oom error stat */
-+ 		/* put it back together so we can free the
-+ 		 * whole list at once.
-+ 		 */
-+-		msdu_head->next = to_free;
-++		__skb_queue_head(amsdu, first);
-+ 		return -1;
-+ 	}
-+ 
-+ 	/* Walk list again, copying contents into
-+ 	 * msdu_head
-+ 	 */
-+-	next = to_free;
-+-	while (next) {
-+-		skb_copy_from_linear_data(next, skb_put(msdu_head, next->len),
-+-					  next->len);
-+-		next = next->next;
-++	while ((skb = __skb_dequeue(amsdu))) {
-++		skb_copy_from_linear_data(skb, skb_put(first, skb->len),
-++					  skb->len);
-++		dev_kfree_skb_any(skb);
-+ 	}
-+ 
-+-	/* If here, we have consolidated skb.  Free the
-+-	 * fragments and pass the main skb on up the
-+-	 * stack.
-+-	 */
-+-	ath10k_htt_rx_free_msdu_chain(to_free);
-++	__skb_queue_head(amsdu, first);
-+ 	return 0;
-+ }
-+ 
-+-static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
-+-					struct sk_buff *head,
-+-					enum htt_rx_mpdu_status status,
-+-					bool channel_set,
-+-					u32 attention)
-+-{
-+-	if (head->len == 0) {
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-+-			   "htt rx dropping due to zero-len\n");
-+-		return false;
-+-	}
-++static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
-++				    struct sk_buff_head *amsdu,
-++				    bool chained)
-++{
-++	struct sk_buff *first;
-++	struct htt_rx_desc *rxd;
-++	enum rx_msdu_decap_format decap;
-+ 
-+-	if (attention & RX_ATTENTION_FLAGS_DECRYPT_ERR) {
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-+-			   "htt rx dropping due to decrypt-err\n");
-+-		return false;
-+-	}
-++	first = skb_peek(amsdu);
-++	rxd = (void *)first->data - sizeof(*rxd);
-++	decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
-++		   RX_MSDU_START_INFO1_DECAP_FORMAT);
-+ 
-+-	if (!channel_set) {
-+-		ath10k_warn("no channel configured; ignoring frame!\n");
-+-		return false;
-++	if (!chained)
-++		return;
-++
-++	/* FIXME: Current unchaining logic can only handle simple case of raw
-++	 * msdu chaining. If decapping is other than raw the chaining may be
-++	 * more complex and this isn't handled by the current code. Don't even
-++	 * try re-constructing such frames - it'll be pretty much garbage.
-++	 */
-++	if (decap != RX_MSDU_DECAP_RAW ||
-++	    skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
-++		__skb_queue_purge(amsdu);
-++		return;
-+ 	}
-+ 
-+-	/* Skip mgmt frames while we handle this in WMI */
-+-	if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
-+-	    attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
-+-		ath10k_dbg(ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
-++	ath10k_unchain_msdu(amsdu);
-++}
-++
-++static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
-++					struct sk_buff_head *amsdu,
-++					struct ieee80211_rx_status *rx_status)
-++{
-++	struct sk_buff *msdu;
-++	struct htt_rx_desc *rxd;
-++	bool is_mgmt;
-++	bool has_fcs_err;
-++
-++	msdu = skb_peek(amsdu);
-++	rxd = (void *)msdu->data - sizeof(*rxd);
-++
-++	/* FIXME: It might be a good idea to do some fuzzy-testing to drop
-++	 * invalid/dangerous frames.
-++	 */
-++
-++	if (!rx_status->freq) {
-++		ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
-+ 		return false;
-+ 	}
-+ 
-+-	if (status != HTT_RX_IND_MPDU_STATUS_OK &&
-+-	    status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
-+-	    status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
-+-	    !htt->ar->monitor_started) {
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-+-			   "htt rx ignoring frame w/ status %d\n",
-+-			   status);
-++	is_mgmt = !!(rxd->attention.flags &
-++		     __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
-++	has_fcs_err = !!(rxd->attention.flags &
-++			 __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR));
-++
-++	/* Management frames are handled via WMI events. The pros of such
-++	 * approach is that channel is explicitly provided in WMI events
-++	 * whereas HTT doesn't provide channel information for Rxed frames.
-++	 *
-++	 * However some firmware revisions don't report corrupted frames via
-++	 * WMI so don't drop them.
-++	 */
-++	if (is_mgmt && !has_fcs_err) {
-++		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
-+ 		return false;
-+ 	}
-+ 
-+-	if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-+-			   "htt rx CAC running\n");
-++	if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
-++		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
-+ 		return false;
-+ 	}
-+ 
-+ 	return true;
-+ }
-+ 
-++static void ath10k_htt_rx_h_filter(struct ath10k *ar,
-++				   struct sk_buff_head *amsdu,
-++				   struct ieee80211_rx_status *rx_status)
-++{
-++	if (skb_queue_empty(amsdu))
-++		return;
-++
-++	if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status))
-++		return;
-++
-++	__skb_queue_purge(amsdu);
-++}
-++
-+ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
-+ 				  struct htt_rx_indication *rx)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	struct ieee80211_rx_status *rx_status = &htt->rx_status;
-+ 	struct htt_rx_indication_mpdu_range *mpdu_ranges;
-+-	struct htt_rx_desc *rxd;
-+-	enum htt_rx_mpdu_status status;
-+-	struct ieee80211_hdr *hdr;
-++	struct sk_buff_head amsdu;
-+ 	int num_mpdu_ranges;
-+-	u32 attention;
-+ 	int fw_desc_len;
-+ 	u8 *fw_desc;
-+-	bool channel_set;
-+-	int i, j;
-+-	int ret;
-++	int i, ret, mpdu_count = 0;
-+ 
-+ 	lockdep_assert_held(&htt->rx_ring.lock);
-+ 
-++	if (htt->rx_confused)
-++		return;
-++
-+ 	fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes);
-+ 	fw_desc = (u8 *)&rx->fw_desc;
-+ 
-+@@ -1161,201 +1500,82 @@ static void ath10k_htt_rx_handler(struct
-+ 			     HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
-+ 	mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);
-+ 
-+-	/* Fill this once, while this is per-ppdu */
-+-	if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_START_VALID) {
-+-		memset(rx_status, 0, sizeof(*rx_status));
-+-		rx_status->signal  = ATH10K_DEFAULT_NOISE_FLOOR +
-+-				     rx->ppdu.combined_rssi;
-+-	}
-+-
-+-	if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_END_VALID) {
-+-		/* TSF available only in 32-bit */
-+-		rx_status->mactime = __le32_to_cpu(rx->ppdu.tsf) & 0xffffffff;
-+-		rx_status->flag |= RX_FLAG_MACTIME_END;
-+-	}
-+-
-+-	channel_set = ath10k_htt_rx_h_channel(htt->ar, rx_status);
-+-
-+-	if (channel_set) {
-+-		ath10k_htt_rx_h_rates(htt->ar, rx_status->band,
-+-				      rx->ppdu.info0,
-+-				      __le32_to_cpu(rx->ppdu.info1),
-+-				      __le32_to_cpu(rx->ppdu.info2),
-+-				      rx_status);
-+-	}
-+-
-+-	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
-++	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
-+ 			rx, sizeof(*rx) +
-+ 			(sizeof(struct htt_rx_indication_mpdu_range) *
-+ 				num_mpdu_ranges));
-+ 
-+-	for (i = 0; i < num_mpdu_ranges; i++) {
-+-		status = mpdu_ranges[i].mpdu_range_status;
-+-
-+-		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
-+-			struct sk_buff *msdu_head, *msdu_tail;
-++	for (i = 0; i < num_mpdu_ranges; i++)
-++		mpdu_count += mpdu_ranges[i].mpdu_count;
-+ 
-+-			msdu_head = NULL;
-+-			msdu_tail = NULL;
-+-			ret = ath10k_htt_rx_amsdu_pop(htt,
-+-						      &fw_desc,
-+-						      &fw_desc_len,
-+-						      &msdu_head,
-+-						      &msdu_tail);
-+-
-+-			if (ret < 0) {
-+-				ath10k_warn("failed to pop amsdu from htt rx ring %d\n",
-+-					    ret);
-+-				ath10k_htt_rx_free_msdu_chain(msdu_head);
-+-				continue;
-+-			}
-+-
-+-			rxd = container_of((void *)msdu_head->data,
-+-					   struct htt_rx_desc,
-+-					   msdu_payload);
-+-			attention = __le32_to_cpu(rxd->attention.flags);
-+-
-+-			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
-+-							 status,
-+-							 channel_set,
-+-							 attention)) {
-+-				ath10k_htt_rx_free_msdu_chain(msdu_head);
-+-				continue;
-+-			}
-+-
-+-			if (ret > 0 &&
-+-			    ath10k_unchain_msdu(msdu_head) < 0) {
-+-				ath10k_htt_rx_free_msdu_chain(msdu_head);
-+-				continue;
-+-			}
-+-
-+-			if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
-+-				rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-+-			else
-+-				rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
-+-
-+-			if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
-+-				rx_status->flag |= RX_FLAG_MMIC_ERROR;
-+-			else
-+-				rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
-+-
-+-			hdr = ath10k_htt_rx_skb_get_hdr(msdu_head);
-+-
-+-			if (ath10k_htt_rx_hdr_is_amsdu(hdr))
-+-				ath10k_htt_rx_amsdu(htt, rx_status, msdu_head);
-+-			else
-+-				ath10k_htt_rx_msdu(htt, rx_status, msdu_head);
-++	while (mpdu_count--) {
-++		__skb_queue_head_init(&amsdu);
-++		ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
-++					      &fw_desc_len, &amsdu);
-++		if (ret < 0) {
-++			ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
-++			__skb_queue_purge(&amsdu);
-++			/* FIXME: It's probably a good idea to reboot the
-++			 * device instead of leaving it inoperable.
-++			 */
-++			htt->rx_confused = true;
-++			break;
-+ 		}
-++
-++		ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
-++		ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
-++		ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-++		ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-++		ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
-+ 	}
-+ 
-+ 	tasklet_schedule(&htt->rx_replenish_task);
-+ }
-+ 
-+ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
-+-				struct htt_rx_fragment_indication *frag)
-++				       struct htt_rx_fragment_indication *frag)
-+ {
-+-	struct sk_buff *msdu_head, *msdu_tail;
-+-	enum htt_rx_mpdu_encrypt_type enctype;
-+-	struct htt_rx_desc *rxd;
-+-	enum rx_msdu_decap_format fmt;
-++	struct ath10k *ar = htt->ar;
-+ 	struct ieee80211_rx_status *rx_status = &htt->rx_status;
-+-	struct ieee80211_hdr *hdr;
-++	struct sk_buff_head amsdu;
-+ 	int ret;
-+-	bool tkip_mic_err;
-+-	bool decrypt_err;
-+ 	u8 *fw_desc;
-+-	int fw_desc_len, hdrlen, paramlen;
-+-	int trim;
-++	int fw_desc_len;
-+ 
-+ 	fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
-+ 	fw_desc = (u8 *)frag->fw_msdu_rx_desc;
-+ 
-+-	msdu_head = NULL;
-+-	msdu_tail = NULL;
-++	__skb_queue_head_init(&amsdu);
-+ 
-+ 	spin_lock_bh(&htt->rx_ring.lock);
-+ 	ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-+-				      &msdu_head, &msdu_tail);
-++				      &amsdu);
-+ 	spin_unlock_bh(&htt->rx_ring.lock);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
-++	tasklet_schedule(&htt->rx_replenish_task);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
-+ 
-+ 	if (ret) {
-+-		ath10k_warn("failed to pop amsdu from httr rx ring for fragmented rx %d\n",
-++		ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
-+ 			    ret);
-+-		ath10k_htt_rx_free_msdu_chain(msdu_head);
-++		__skb_queue_purge(&amsdu);
-+ 		return;
-+ 	}
-+ 
-+-	/* FIXME: implement signal strength */
-+-
-+-	hdr = (struct ieee80211_hdr *)msdu_head->data;
-+-	rxd = (void *)msdu_head->data - sizeof(*rxd);
-+-	tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) &
-+-				RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
-+-	decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) &
-+-				RX_ATTENTION_FLAGS_DECRYPT_ERR);
-+-	fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
-+-			RX_MSDU_START_INFO1_DECAP_FORMAT);
-+-
-+-	if (fmt != RX_MSDU_DECAP_RAW) {
-+-		ath10k_warn("we dont support non-raw fragmented rx yet\n");
-+-		dev_kfree_skb_any(msdu_head);
-+-		goto end;
-+-	}
-+-
-+-	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
-+-		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-+-	ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype);
-+-	msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
-+-
-+-	if (tkip_mic_err)
-+-		ath10k_warn("tkip mic error\n");
-+-
-+-	if (decrypt_err) {
-+-		ath10k_warn("decryption err in fragmented rx\n");
-+-		dev_kfree_skb_any(msdu_head);
-+-		goto end;
-+-	}
-+-
-+-	if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) {
-+-		hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+-		paramlen = ath10k_htt_rx_crypto_param_len(enctype);
-+-
-+-		/* It is more efficient to move the header than the payload */
-+-		memmove((void *)msdu_head->data + paramlen,
-+-			(void *)msdu_head->data,
-+-			hdrlen);
-+-		skb_pull(msdu_head, paramlen);
-+-		hdr = (struct ieee80211_hdr *)msdu_head->data;
-+-	}
-+-
-+-	/* remove trailing FCS */
-+-	trim  = 4;
-+-
-+-	/* remove crypto trailer */
-+-	trim += ath10k_htt_rx_crypto_tail_len(enctype);
-+-
-+-	/* last fragment of TKIP frags has MIC */
-+-	if (!ieee80211_has_morefrags(hdr->frame_control) &&
-+-	    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
-+-		trim += 8;
-+-
-+-	if (trim > msdu_head->len) {
-+-		ath10k_warn("htt rx fragment: trailer longer than the frame itself? drop\n");
-+-		dev_kfree_skb_any(msdu_head);
-+-		goto end;
-++	if (skb_queue_len(&amsdu) != 1) {
-++		ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
-++		__skb_queue_purge(&amsdu);
-++		return;
-+ 	}
-+ 
-+-	skb_trim(msdu_head, msdu_head->len - trim);
-+-
-+-	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
-+-			msdu_head->data, msdu_head->len);
-+-	ath10k_process_rx(htt->ar, rx_status, msdu_head);
-++	ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
-++	ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-++	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-++	ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
-+ 
-+-end:
-+ 	if (fw_desc_len > 0) {
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-++		ath10k_dbg(ar, ATH10K_DBG_HTT,
-+ 			   "expecting more fragmented rx in one indication %d\n",
-+ 			   fw_desc_len);
-+ 	}
-+@@ -1385,12 +1605,12 @@ static void ath10k_htt_rx_frm_tx_compl(s
-+ 		tx_done.discard = true;
-+ 		break;
-+ 	default:
-+-		ath10k_warn("unhandled tx completion status %d\n", status);
-++		ath10k_warn(ar, "unhandled tx completion status %d\n", status);
-+ 		tx_done.discard = true;
-+ 		break;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n",
-+ 		   resp->data_tx_completion.num_msdus);
-+ 
-+ 	for (i = 0; i < resp->data_tx_completion.num_msdus; i++) {
-+@@ -1400,6 +1620,274 @@ static void ath10k_htt_rx_frm_tx_compl(s
-+ 	}
-+ }
-+ 
-++static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
-++{
-++	struct htt_rx_addba *ev = &resp->rx_addba;
-++	struct ath10k_peer *peer;
-++	struct ath10k_vif *arvif;
-++	u16 info0, tid, peer_id;
-++
-++	info0 = __le16_to_cpu(ev->info0);
-++	tid = MS(info0, HTT_RX_BA_INFO0_TID);
-++	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt rx addba tid %hu peer_id %hu size %hhu\n",
-++		   tid, peer_id, ev->window_size);
-++
-++	spin_lock_bh(&ar->data_lock);
-++	peer = ath10k_peer_find_by_id(ar, peer_id);
-++	if (!peer) {
-++		ath10k_warn(ar, "received addba event for invalid peer_id: %hu\n",
-++			    peer_id);
-++		spin_unlock_bh(&ar->data_lock);
-++		return;
-++	}
-++
-++	arvif = ath10k_get_arvif(ar, peer->vdev_id);
-++	if (!arvif) {
-++		ath10k_warn(ar, "received addba event for invalid vdev_id: %u\n",
-++			    peer->vdev_id);
-++		spin_unlock_bh(&ar->data_lock);
-++		return;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
-++		   peer->addr, tid, ev->window_size);
-++
-++	ieee80211_start_rx_ba_session_offl(arvif->vif, peer->addr, tid);
-++	spin_unlock_bh(&ar->data_lock);
-++}
-++
-++static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
-++{
-++	struct htt_rx_delba *ev = &resp->rx_delba;
-++	struct ath10k_peer *peer;
-++	struct ath10k_vif *arvif;
-++	u16 info0, tid, peer_id;
-++
-++	info0 = __le16_to_cpu(ev->info0);
-++	tid = MS(info0, HTT_RX_BA_INFO0_TID);
-++	peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt rx delba tid %hu peer_id %hu\n",
-++		   tid, peer_id);
-++
-++	spin_lock_bh(&ar->data_lock);
-++	peer = ath10k_peer_find_by_id(ar, peer_id);
-++	if (!peer) {
-++		ath10k_warn(ar, "received addba event for invalid peer_id: %hu\n",
-++			    peer_id);
-++		spin_unlock_bh(&ar->data_lock);
-++		return;
-++	}
-++
-++	arvif = ath10k_get_arvif(ar, peer->vdev_id);
-++	if (!arvif) {
-++		ath10k_warn(ar, "received addba event for invalid vdev_id: %u\n",
-++			    peer->vdev_id);
-++		spin_unlock_bh(&ar->data_lock);
-++		return;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt rx stop rx ba session sta %pM tid %hu\n",
-++		   peer->addr, tid);
-++
-++	ieee80211_stop_rx_ba_session_offl(arvif->vif, peer->addr, tid);
-++	spin_unlock_bh(&ar->data_lock);
-++}
-++
-++static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
-++				       struct sk_buff_head *amsdu)
-++{
-++	struct sk_buff *msdu;
-++	struct htt_rx_desc *rxd;
-++
-++	if (skb_queue_empty(list))
-++		return -ENOBUFS;
-++
-++	if (WARN_ON(!skb_queue_empty(amsdu)))
-++		return -EINVAL;
-++
-++	while ((msdu = __skb_dequeue(list))) {
-++		__skb_queue_tail(amsdu, msdu);
-++
-++		rxd = (void *)msdu->data - sizeof(*rxd);
-++		if (rxd->msdu_end.info0 &
-++		    __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))
-++			break;
-++	}
-++
-++	msdu = skb_peek_tail(amsdu);
-++	rxd = (void *)msdu->data - sizeof(*rxd);
-++	if (!(rxd->msdu_end.info0 &
-++	      __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) {
-++		skb_queue_splice_init(amsdu, list);
-++		return -EAGAIN;
-++	}
-++
-++	return 0;
-++}
-++
-++static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status,
-++					    struct sk_buff *skb)
-++{
-++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-++
-++	if (!ieee80211_has_protected(hdr->frame_control))
-++		return;
-++
-++	/* Offloaded frames are already decrypted but firmware insists they are
-++	 * protected in the 802.11 header. Strip the flag.  Otherwise mac80211
-++	 * will drop the frame.
-++	 */
-++
-++	hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-++	status->flag |= RX_FLAG_DECRYPTED |
-++			RX_FLAG_IV_STRIPPED |
-++			RX_FLAG_MMIC_STRIPPED;
-++}
-++
-++static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
-++				       struct sk_buff_head *list)
-++{
-++	struct ath10k_htt *htt = &ar->htt;
-++	struct ieee80211_rx_status *status = &htt->rx_status;
-++	struct htt_rx_offload_msdu *rx;
-++	struct sk_buff *msdu;
-++	size_t offset;
-++
-++	while ((msdu = __skb_dequeue(list))) {
-++		/* Offloaded frames don't have Rx descriptor. Instead they have
-++		 * a short meta information header.
-++		 */
-++
-++		rx = (void *)msdu->data;
-++
-++		skb_put(msdu, sizeof(*rx));
-++		skb_pull(msdu, sizeof(*rx));
-++
-++		if (skb_tailroom(msdu) < __le16_to_cpu(rx->msdu_len)) {
-++			ath10k_warn(ar, "dropping frame: offloaded rx msdu is too long!\n");
-++			dev_kfree_skb_any(msdu);
-++			continue;
-++		}
-++
-++		skb_put(msdu, __le16_to_cpu(rx->msdu_len));
-++
-++		/* Offloaded rx header length isn't multiple of 2 nor 4 so the
-++		 * actual payload is unaligned. Align the frame.  Otherwise
-++		 * mac80211 complains.  This shouldn't reduce performance much
-++		 * because these offloaded frames are rare.
-++		 */
-++		offset = 4 - ((unsigned long)msdu->data & 3);
-++		skb_put(msdu, offset);
-++		memmove(msdu->data + offset, msdu->data, msdu->len);
-++		skb_pull(msdu, offset);
-++
-++		/* FIXME: The frame is NWifi. Re-construct QoS Control
-++		 * if possible later.
-++		 */
-++
-++		memset(status, 0, sizeof(*status));
-++		status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-++
-++		ath10k_htt_rx_h_rx_offload_prot(status, msdu);
-++		ath10k_htt_rx_h_channel(ar, status);
-++		ath10k_process_rx(ar, status, msdu);
-++	}
-++}
-++
-++static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct ath10k_htt *htt = &ar->htt;
-++	struct htt_resp *resp = (void *)skb->data;
-++	struct ieee80211_rx_status *status = &htt->rx_status;
-++	struct sk_buff_head list;
-++	struct sk_buff_head amsdu;
-++	u16 peer_id;
-++	u16 msdu_count;
-++	u8 vdev_id;
-++	u8 tid;
-++	bool offload;
-++	bool frag;
-++	int ret;
-++
-++	lockdep_assert_held(&htt->rx_ring.lock);
-++
-++	if (htt->rx_confused)
-++		return;
-++
-++	skb_pull(skb, sizeof(resp->hdr));
-++	skb_pull(skb, sizeof(resp->rx_in_ord_ind));
-++
-++	peer_id = __le16_to_cpu(resp->rx_in_ord_ind.peer_id);
-++	msdu_count = __le16_to_cpu(resp->rx_in_ord_ind.msdu_count);
-++	vdev_id = resp->rx_in_ord_ind.vdev_id;
-++	tid = SM(resp->rx_in_ord_ind.info, HTT_RX_IN_ORD_IND_INFO_TID);
-++	offload = !!(resp->rx_in_ord_ind.info &
-++			HTT_RX_IN_ORD_IND_INFO_OFFLOAD_MASK);
-++	frag = !!(resp->rx_in_ord_ind.info & HTT_RX_IN_ORD_IND_INFO_FRAG_MASK);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt rx in ord vdev %i peer %i tid %i offload %i frag %i msdu count %i\n",
-++		   vdev_id, peer_id, tid, offload, frag, msdu_count);
-++
-++	if (skb->len < msdu_count * sizeof(*resp->rx_in_ord_ind.msdu_descs)) {
-++		ath10k_warn(ar, "dropping invalid in order rx indication\n");
-++		return;
-++	}
-++
-++	/* The event can deliver more than 1 A-MSDU. Each A-MSDU is later
-++	 * extracted and processed.
-++	 */
-++	__skb_queue_head_init(&list);
-++	ret = ath10k_htt_rx_pop_paddr_list(htt, &resp->rx_in_ord_ind, &list);
-++	if (ret < 0) {
-++		ath10k_warn(ar, "failed to pop paddr list: %d\n", ret);
-++		htt->rx_confused = true;
-++		return;
-++	}
-++
-++	/* Offloaded frames are very different and need to be handled
-++	 * separately.
-++	 */
-++	if (offload)
-++		ath10k_htt_rx_h_rx_offload(ar, &list);
-++
-++	while (!skb_queue_empty(&list)) {
-++		__skb_queue_head_init(&amsdu);
-++		ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu);
-++		switch (ret) {
-++		case 0:
-++			/* Note: The in-order indication may report interleaved
-++			 * frames from different PPDUs meaning reported rx rate
-++			 * to mac80211 isn't accurate/reliable. It's still
-++			 * better to report something than nothing though. This
-++			 * should still give an idea about rx rate to the user.
-++			 */
-++			ath10k_htt_rx_h_ppdu(ar, &amsdu, status);
-++			ath10k_htt_rx_h_filter(ar, &amsdu, status);
-++			ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
-++			ath10k_htt_rx_h_deliver(ar, &amsdu, status);
-++			break;
-++		case -EAGAIN:
-++			/* fall through */
-++		default:
-++			/* Should not happen. */
-++			ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
-++			htt->rx_confused = true;
-++			__skb_queue_purge(&list);
-++			return;
-++		}
-++	}
-++
-++	tasklet_schedule(&htt->rx_replenish_task);
-++}
-++
-+ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+ 	struct ath10k_htt *htt = &ar->htt;
-+@@ -1407,9 +1895,9 @@ void ath10k_htt_t2h_msg_handler(struct a
-+ 
-+ 	/* confirm alignment */
-+ 	if (!IS_ALIGNED((unsigned long)skb->data, 4))
-+-		ath10k_warn("unaligned htt message, expect trouble\n");
-++		ath10k_warn(ar, "unaligned htt message, expect trouble\n");
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n",
-+ 		   resp->hdr.msg_type);
-+ 	switch (resp->hdr.msg_type) {
-+ 	case HTT_T2H_MSG_TYPE_VERSION_CONF: {
-+@@ -1473,7 +1961,7 @@ void ath10k_htt_t2h_msg_handler(struct a
-+ 		struct ath10k *ar = htt->ar;
-+ 		struct htt_security_indication *ev = &resp->security_indication;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_HTT,
-++		ath10k_dbg(ar, ATH10K_DBG_HTT,
-+ 			   "sec ind peer_id %d unicast %d type %d\n",
-+ 			  __le16_to_cpu(ev->peer_id),
-+ 			  !!(ev->flags & HTT_SECURITY_IS_UNICAST),
-+@@ -1482,7 +1970,7 @@ void ath10k_htt_t2h_msg_handler(struct a
-+ 		break;
-+ 	}
-+ 	case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
-+-		ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
-+ 				skb->data, skb->len);
-+ 		ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind);
-+ 		break;
-+@@ -1491,16 +1979,55 @@ void ath10k_htt_t2h_msg_handler(struct a
-+ 		/* FIX THIS */
-+ 		break;
-+ 	case HTT_T2H_MSG_TYPE_STATS_CONF:
-+-		trace_ath10k_htt_stats(skb->data, skb->len);
-++		trace_ath10k_htt_stats(ar, skb->data, skb->len);
-+ 		break;
-+ 	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
-++		/* Firmware can return tx frames if it's unable to fully
-++		 * process them and suspects host may be able to fix it. ath10k
-++		 * sends all tx frames as already inspected so this shouldn't
-++		 * happen unless fw has a bug.
-++		 */
-++		ath10k_warn(ar, "received an unexpected htt tx inspect event\n");
-++		break;
-+ 	case HTT_T2H_MSG_TYPE_RX_ADDBA:
-++		ath10k_htt_rx_addba(ar, resp);
-++		break;
-+ 	case HTT_T2H_MSG_TYPE_RX_DELBA:
-+-	case HTT_T2H_MSG_TYPE_RX_FLUSH:
-++		ath10k_htt_rx_delba(ar, resp);
-++		break;
-++	case HTT_T2H_MSG_TYPE_PKTLOG: {
-++		struct ath10k_pktlog_hdr *hdr =
-++			(struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
-++
-++		trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
-++					sizeof(*hdr) +
-++					__le16_to_cpu(hdr->size));
-++		break;
-++	}
-++	case HTT_T2H_MSG_TYPE_RX_FLUSH: {
-++		/* Ignore this event because mac80211 takes care of Rx
-++		 * aggregation reordering.
-++		 */
-++		break;
-++	}
-++	case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
-++		spin_lock_bh(&htt->rx_ring.lock);
-++		__skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
-++		spin_unlock_bh(&htt->rx_ring.lock);
-++		tasklet_schedule(&htt->txrx_compl_task);
-++		return;
-++	}
-++	case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
-++		/* FIXME: This WMI-TLV event is overlapping with 10.2
-++		 * CHAN_CHANGE - both being 0xF. Neither is being used in
-++		 * practice so no immediate action is necessary. Nevertheless
-++		 * HTT may need an abstraction layer like WMI has one day.
-++		 */
-++		break;
-+ 	default:
-+-		ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n",
-+-			   resp->hdr.msg_type);
-+-		ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
-++		ath10k_warn(ar, "htt event (%d) not handled\n",
-++			    resp->hdr.msg_type);
-++		ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
-+ 				skb->data, skb->len);
-+ 		break;
-+ 	};
-+@@ -1512,6 +2039,7 @@ void ath10k_htt_t2h_msg_handler(struct a
-+ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
-+ {
-+ 	struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
-++	struct ath10k *ar = htt->ar;
-+ 	struct htt_resp *resp;
-+ 	struct sk_buff *skb;
-+ 
-+@@ -1528,5 +2056,10 @@ static void ath10k_htt_txrx_compl_task(u
-+ 		ath10k_htt_rx_handler(htt, &resp->rx_ind);
-+ 		dev_kfree_skb_any(skb);
-+ 	}
-++
-++	while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) {
-++		ath10k_htt_rx_in_ord_ind(ar, skb);
-++		dev_kfree_skb_any(skb);
-++	}
-+ 	spin_unlock_bh(&htt->rx_ring.lock);
-+ }
-+--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
-++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
-+@@ -56,98 +56,74 @@ exit:
-+ 	return ret;
-+ }
-+ 
-+-int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt)
-++int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
-+ {
-+-	int msdu_id;
-++	struct ath10k *ar = htt->ar;
-++	int ret;
-+ 
-+ 	lockdep_assert_held(&htt->tx_lock);
-+ 
-+-	msdu_id = find_first_zero_bit(htt->used_msdu_ids,
-+-				      htt->max_num_pending_tx);
-+-	if (msdu_id == htt->max_num_pending_tx)
-+-		return -ENOBUFS;
-+-
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", msdu_id);
-+-	__set_bit(msdu_id, htt->used_msdu_ids);
-+-	return msdu_id;
-++	ret = idr_alloc(&htt->pending_tx, skb, 0, 0x10000, GFP_ATOMIC);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", ret);
-++
-++	return ret;
-+ }
-+ 
-+ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
-+ {
-++	struct ath10k *ar = htt->ar;
-++
-+ 	lockdep_assert_held(&htt->tx_lock);
-+ 
-+-	if (!test_bit(msdu_id, htt->used_msdu_ids))
-+-		ath10k_warn("trying to free unallocated msdu_id %d\n", msdu_id);
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id);
-+-	__clear_bit(msdu_id, htt->used_msdu_ids);
-++	idr_remove(&htt->pending_tx, msdu_id);
-+ }
-+ 
-+-int ath10k_htt_tx_attach(struct ath10k_htt *htt)
-++int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
-+ {
-+-	spin_lock_init(&htt->tx_lock);
-+-	init_waitqueue_head(&htt->empty_tx_wq);
-+-
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
-+-		htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
-+-	else
-+-		htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
-++	struct ath10k *ar = htt->ar;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
-+ 		   htt->max_num_pending_tx);
-+ 
-+-	htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) *
-+-				  htt->max_num_pending_tx, GFP_KERNEL);
-+-	if (!htt->pending_tx)
-+-		return -ENOMEM;
-+-
-+-	htt->used_msdu_ids = kzalloc(sizeof(unsigned long) *
-+-				     BITS_TO_LONGS(htt->max_num_pending_tx),
-+-				     GFP_KERNEL);
-+-	if (!htt->used_msdu_ids) {
-+-		kfree(htt->pending_tx);
-+-		return -ENOMEM;
-+-	}
-++	spin_lock_init(&htt->tx_lock);
-++	idr_init(&htt->pending_tx);
-+ 
-+ 	htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev,
-+ 				       sizeof(struct ath10k_htt_txbuf), 4, 0);
-+ 	if (!htt->tx_pool) {
-+-		kfree(htt->used_msdu_ids);
-+-		kfree(htt->pending_tx);
-++		idr_destroy(&htt->pending_tx);
-+ 		return -ENOMEM;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
-++static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
-+ {
-++	struct ath10k *ar = ctx;
-++	struct ath10k_htt *htt = &ar->htt;
-+ 	struct htt_tx_done tx_done = {0};
-+-	int msdu_id;
-+-
-+-	spin_lock_bh(&htt->tx_lock);
-+-	for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) {
-+-		if (!test_bit(msdu_id, htt->used_msdu_ids))
-+-			continue;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n",
-+-			   msdu_id);
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id);
-+ 
-+-		tx_done.discard = 1;
-+-		tx_done.msdu_id = msdu_id;
-++	tx_done.discard = 1;
-++	tx_done.msdu_id = msdu_id;
-+ 
-+-		ath10k_txrx_tx_unref(htt, &tx_done);
-+-	}
-++	spin_lock_bh(&htt->tx_lock);
-++	ath10k_txrx_tx_unref(htt, &tx_done);
-+ 	spin_unlock_bh(&htt->tx_lock);
-++
-++	return 0;
-+ }
-+ 
-+-void ath10k_htt_tx_detach(struct ath10k_htt *htt)
-++void ath10k_htt_tx_free(struct ath10k_htt *htt)
-+ {
-+-	ath10k_htt_tx_cleanup_pending(htt);
-+-	kfree(htt->pending_tx);
-+-	kfree(htt->used_msdu_ids);
-++	idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
-++	idr_destroy(&htt->pending_tx);
-+ 	dma_pool_destroy(htt->tx_pool);
-+-	return;
-+ }
-+ 
-+ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
-+@@ -157,6 +133,7 @@ void ath10k_htt_htc_tx_complete(struct a
-+ 
-+ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	struct sk_buff *skb;
-+ 	struct htt_cmd *cmd;
-+ 	int len = 0;
-+@@ -165,7 +142,7 @@ int ath10k_htt_h2t_ver_req_msg(struct at
-+ 	len += sizeof(cmd->hdr);
-+ 	len += sizeof(cmd->ver_req);
-+ 
-+-	skb = ath10k_htc_alloc_skb(len);
-++	skb = ath10k_htc_alloc_skb(ar, len);
-+ 	if (!skb)
-+ 		return -ENOMEM;
-+ 
-+@@ -184,6 +161,7 @@ int ath10k_htt_h2t_ver_req_msg(struct at
-+ 
-+ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	struct htt_stats_req *req;
-+ 	struct sk_buff *skb;
-+ 	struct htt_cmd *cmd;
-+@@ -192,7 +170,7 @@ int ath10k_htt_h2t_stats_req(struct ath1
-+ 	len += sizeof(cmd->hdr);
-+ 	len += sizeof(cmd->stats_req);
-+ 
-+-	skb = ath10k_htc_alloc_skb(len);
-++	skb = ath10k_htc_alloc_skb(ar, len);
-+ 	if (!skb)
-+ 		return -ENOMEM;
-+ 
-+@@ -214,7 +192,8 @@ int ath10k_htt_h2t_stats_req(struct ath1
-+ 
-+ 	ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
-+ 	if (ret) {
-+-		ath10k_warn("failed to send htt type stats request: %d", ret);
-++		ath10k_warn(ar, "failed to send htt type stats request: %d",
-++			    ret);
-+ 		dev_kfree_skb_any(skb);
-+ 		return ret;
-+ 	}
-+@@ -224,6 +203,7 @@ int ath10k_htt_h2t_stats_req(struct ath1
-+ 
-+ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
-+ {
-++	struct ath10k *ar = htt->ar;
-+ 	struct sk_buff *skb;
-+ 	struct htt_cmd *cmd;
-+ 	struct htt_rx_ring_setup_ring *ring;
-+@@ -242,7 +222,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struc
-+ 
-+ 	len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup.hdr)
-+ 	    + (sizeof(*ring) * num_rx_ring);
-+-	skb = ath10k_htc_alloc_skb(len);
-++	skb = ath10k_htc_alloc_skb(ar, len);
-+ 	if (!skb)
-+ 		return -ENOMEM;
-+ 
-+@@ -307,9 +287,57 @@ int ath10k_htt_send_rx_ring_cfg_ll(struc
-+ 	return 0;
-+ }
-+ 
-++int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
-++				u8 max_subfrms_ampdu,
-++				u8 max_subfrms_amsdu)
-++{
-++	struct ath10k *ar = htt->ar;
-++	struct htt_aggr_conf *aggr_conf;
-++	struct sk_buff *skb;
-++	struct htt_cmd *cmd;
-++	int len;
-++	int ret;
-++
-++	/* Firmware defaults are: amsdu = 3 and ampdu = 64 */
-++
-++	if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
-++		return -EINVAL;
-++
-++	if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
-++		return -EINVAL;
-++
-++	len = sizeof(cmd->hdr);
-++	len += sizeof(cmd->aggr_conf);
-++
-++	skb = ath10k_htc_alloc_skb(ar, len);
-++	if (!skb)
-++		return -ENOMEM;
-++
-++	skb_put(skb, len);
-++	cmd = (struct htt_cmd *)skb->data;
-++	cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
-++
-++	aggr_conf = &cmd->aggr_conf;
-++	aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
-++	aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
-++		   aggr_conf->max_num_amsdu_subframes,
-++		   aggr_conf->max_num_ampdu_subframes);
-++
-++	ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
-++	if (ret) {
-++		dev_kfree_skb_any(skb);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-+ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
-+ {
-+-	struct device *dev = htt->ar->dev;
-++	struct ath10k *ar = htt->ar;
-++	struct device *dev = ar->dev;
-+ 	struct sk_buff *txdesc = NULL;
-+ 	struct htt_cmd *cmd;
-+ 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
-+@@ -318,7 +346,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt
-+ 	int msdu_id = -1;
-+ 	int res;
-+ 
-+-
-+ 	res = ath10k_htt_tx_inc_pending(htt);
-+ 	if (res)
-+ 		goto err;
-+@@ -327,16 +354,15 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt
-+ 	len += sizeof(cmd->mgmt_tx);
-+ 
-+ 	spin_lock_bh(&htt->tx_lock);
-+-	res = ath10k_htt_tx_alloc_msdu_id(htt);
-++	res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
-+ 	if (res < 0) {
-+ 		spin_unlock_bh(&htt->tx_lock);
-+ 		goto err_tx_dec;
-+ 	}
-+ 	msdu_id = res;
-+-	htt->pending_tx[msdu_id] = msdu;
-+ 	spin_unlock_bh(&htt->tx_lock);
-+ 
-+-	txdesc = ath10k_htc_alloc_skb(len);
-++	txdesc = ath10k_htc_alloc_skb(ar, len);
-+ 	if (!txdesc) {
-+ 		res = -ENOMEM;
-+ 		goto err_free_msdu_id;
-+@@ -372,7 +398,6 @@ err_free_txdesc:
-+ 	dev_kfree_skb_any(txdesc);
-+ err_free_msdu_id:
-+ 	spin_lock_bh(&htt->tx_lock);
-+-	htt->pending_tx[msdu_id] = NULL;
-+ 	ath10k_htt_tx_free_msdu_id(htt, msdu_id);
-+ 	spin_unlock_bh(&htt->tx_lock);
-+ err_tx_dec:
-+@@ -383,7 +408,8 @@ err:
-+ 
-+ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
-+ {
-+-	struct device *dev = htt->ar->dev;
-++	struct ath10k *ar = htt->ar;
-++	struct device *dev = ar->dev;
-+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
-+ 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
-+ 	struct ath10k_hif_sg_item sg_items[2];
-+@@ -403,13 +429,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt
-+ 		goto err;
-+ 
-+ 	spin_lock_bh(&htt->tx_lock);
-+-	res = ath10k_htt_tx_alloc_msdu_id(htt);
-++	res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
-+ 	if (res < 0) {
-+ 		spin_unlock_bh(&htt->tx_lock);
-+ 		goto err_tx_dec;
-+ 	}
-+ 	msdu_id = res;
-+-	htt->pending_tx[msdu_id] = msdu;
-+ 	spin_unlock_bh(&htt->tx_lock);
-+ 
-+ 	prefetch_len = min(htt->prefetch_len, msdu->len);
-+@@ -423,10 +448,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt
-+ 
-+ 	skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC,
-+ 					   &paddr);
-+-	if (!skb_cb->htt.txbuf)
-++	if (!skb_cb->htt.txbuf) {
-++		res = -ENOMEM;
-+ 		goto err_free_msdu_id;
-++	}
-+ 	skb_cb->htt.txbuf_paddr = paddr;
-+ 
-++	if ((ieee80211_is_action(hdr->frame_control) ||
-++	     ieee80211_is_deauth(hdr->frame_control) ||
-++	     ieee80211_is_disassoc(hdr->frame_control)) &&
-++	     ieee80211_has_protected(hdr->frame_control))
-++		skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
-++
-+ 	skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
-+ 				       DMA_TO_DEVICE);
-+ 	res = dma_mapping_error(dev, skb_cb->paddr);
-+@@ -482,8 +515,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt
-+ 
-+ 	flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
-+ 	flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
-+-	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
-+-	flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
-++	if (msdu->ip_summed == CHECKSUM_PARTIAL) {
-++		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
-++		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
-++	}
-++
-++	/* Prevent firmware from sending up tx inspection requests. There's
-++	 * nothing ath10k can do with frames requested for inspection so force
-++	 * it to simply rely a regular tx completion with discard status.
-++	 */
-++	flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
-+ 
-+ 	skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
-+ 	skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
-+@@ -491,14 +532,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt
-+ 	skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
-+ 	skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
-+ 	skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
-+-	skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID);
-++	skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
-++	skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT,
-+-		   "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n",
-++	trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
-++	ath10k_dbg(ar, ATH10K_DBG_HTT,
-++		   "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
-+ 		   flags0, flags1, msdu->len, msdu_id, frags_paddr,
-+-		   (u32)skb_cb->paddr, vdev_id, tid);
-+-	ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
-++		   (u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
-++	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
-+ 			msdu->data, msdu->len);
-++	trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
-++	trace_ath10k_tx_payload(ar, msdu->data, msdu->len);
-+ 
-+ 	sg_items[0].transfer_id = 0;
-+ 	sg_items[0].transfer_context = NULL;
-+@@ -531,7 +576,6 @@ err_free_txbuf:
-+ 		      skb_cb->htt.txbuf_paddr);
-+ err_free_msdu_id:
-+ 	spin_lock_bh(&htt->tx_lock);
-+-	htt->pending_tx[msdu_id] = NULL;
-+ 	ath10k_htt_tx_free_msdu_id(htt, msdu_id);
-+ 	spin_unlock_bh(&htt->tx_lock);
-+ err_tx_dec:
-+--- a/drivers/net/wireless/ath/ath10k/hw.h
-++++ b/drivers/net/wireless/ath/ath10k/hw.h
-+@@ -20,24 +20,73 @@
-+ 
-+ #include "targaddrs.h"
-+ 
-++#define ATH10K_FW_DIR			"ath10k"
-++
-+ /* QCA988X 1.0 definitions (unsupported) */
-+ #define QCA988X_HW_1_0_CHIP_ID_REV	0x0
-+ 
-+ /* QCA988X 2.0 definitions */
-+ #define QCA988X_HW_2_0_VERSION		0x4100016c
-+ #define QCA988X_HW_2_0_CHIP_ID_REV	0x2
-+-#define QCA988X_HW_2_0_FW_DIR		"ath10k/QCA988X/hw2.0"
-++#define QCA988X_HW_2_0_FW_DIR		ATH10K_FW_DIR "/QCA988X/hw2.0"
-+ #define QCA988X_HW_2_0_FW_FILE		"firmware.bin"
-+-#define QCA988X_HW_2_0_FW_2_FILE	"firmware-2.bin"
-+ #define QCA988X_HW_2_0_OTP_FILE		"otp.bin"
-+ #define QCA988X_HW_2_0_BOARD_DATA_FILE	"board.bin"
-+ #define QCA988X_HW_2_0_PATCH_LOAD_ADDR	0x1234
-+ 
-++/* QCA6174 target BMI version signatures */
-++#define QCA6174_HW_1_0_VERSION		0x05000000
-++#define QCA6174_HW_1_1_VERSION		0x05000001
-++#define QCA6174_HW_1_3_VERSION		0x05000003
-++#define QCA6174_HW_2_1_VERSION		0x05010000
-++#define QCA6174_HW_3_0_VERSION		0x05020000
-++#define QCA6174_HW_3_2_VERSION		0x05030000
-++
-++enum qca6174_pci_rev {
-++	QCA6174_PCI_REV_1_1 = 0x11,
-++	QCA6174_PCI_REV_1_3 = 0x13,
-++	QCA6174_PCI_REV_2_0 = 0x20,
-++	QCA6174_PCI_REV_3_0 = 0x30,
-++};
-++
-++enum qca6174_chip_id_rev {
-++	QCA6174_HW_1_0_CHIP_ID_REV = 0,
-++	QCA6174_HW_1_1_CHIP_ID_REV = 1,
-++	QCA6174_HW_1_3_CHIP_ID_REV = 2,
-++	QCA6174_HW_2_1_CHIP_ID_REV = 4,
-++	QCA6174_HW_2_2_CHIP_ID_REV = 5,
-++	QCA6174_HW_3_0_CHIP_ID_REV = 8,
-++	QCA6174_HW_3_1_CHIP_ID_REV = 9,
-++	QCA6174_HW_3_2_CHIP_ID_REV = 10,
-++};
-++
-++#define QCA6174_HW_2_1_FW_DIR		"ath10k/QCA6174/hw2.1"
-++#define QCA6174_HW_2_1_FW_FILE		"firmware.bin"
-++#define QCA6174_HW_2_1_OTP_FILE		"otp.bin"
-++#define QCA6174_HW_2_1_BOARD_DATA_FILE	"board.bin"
-++#define QCA6174_HW_2_1_PATCH_LOAD_ADDR	0x1234
-++
-++#define QCA6174_HW_3_0_FW_DIR		"ath10k/QCA6174/hw3.0"
-++#define QCA6174_HW_3_0_FW_FILE		"firmware.bin"
-++#define QCA6174_HW_3_0_OTP_FILE		"otp.bin"
-++#define QCA6174_HW_3_0_BOARD_DATA_FILE	"board.bin"
-++#define QCA6174_HW_3_0_PATCH_LOAD_ADDR	0x1234
-++
-+ #define ATH10K_FW_API2_FILE		"firmware-2.bin"
-++#define ATH10K_FW_API3_FILE		"firmware-3.bin"
-++
-++/* added support for ATH10K_FW_IE_WMI_OP_VERSION */
-++#define ATH10K_FW_API4_FILE		"firmware-4.bin"
-++
-++#define ATH10K_FW_UTF_FILE		"utf.bin"
-+ 
-+ /* includes also the null byte */
-+ #define ATH10K_FIRMWARE_MAGIC               "QCA-ATH10K"
-+ 
-++#define REG_DUMP_COUNT_QCA988X 60
-++
-++#define QCA988X_CAL_DATA_LEN		2116
-++
-+ struct ath10k_fw_ie {
-+ 	__le32 id;
-+ 	__le32 len;
-+@@ -50,8 +99,57 @@ enum ath10k_fw_ie_type {
-+ 	ATH10K_FW_IE_FEATURES = 2,
-+ 	ATH10K_FW_IE_FW_IMAGE = 3,
-+ 	ATH10K_FW_IE_OTP_IMAGE = 4,
-++
-++	/* WMI "operations" interface version, 32 bit value. Supported from
-++	 * FW API 4 and above.
-++	 */
-++	ATH10K_FW_IE_WMI_OP_VERSION = 5,
-++};
-++
-++enum ath10k_fw_wmi_op_version {
-++	ATH10K_FW_WMI_OP_VERSION_UNSET = 0,
-++
-++	ATH10K_FW_WMI_OP_VERSION_MAIN = 1,
-++	ATH10K_FW_WMI_OP_VERSION_10_1 = 2,
-++	ATH10K_FW_WMI_OP_VERSION_10_2 = 3,
-++	ATH10K_FW_WMI_OP_VERSION_TLV = 4,
-++	ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
-++
-++	/* keep last */
-++	ATH10K_FW_WMI_OP_VERSION_MAX,
-++};
-++
-++enum ath10k_hw_rev {
-++	ATH10K_HW_QCA988X,
-++	ATH10K_HW_QCA6174,
-++};
-++
-++struct ath10k_hw_regs {
-++	u32 rtc_state_cold_reset_mask;
-++	u32 rtc_soc_base_address;
-++	u32 rtc_wmac_base_address;
-++	u32 soc_core_base_address;
-++	u32 ce_wrapper_base_address;
-++	u32 ce0_base_address;
-++	u32 ce1_base_address;
-++	u32 ce2_base_address;
-++	u32 ce3_base_address;
-++	u32 ce4_base_address;
-++	u32 ce5_base_address;
-++	u32 ce6_base_address;
-++	u32 ce7_base_address;
-++	u32 soc_reset_control_si0_rst_mask;
-++	u32 soc_reset_control_ce_rst_mask;
-++	u32 soc_chip_id_address;
-++	u32 scratch_3_address;
-+ };
-+ 
-++extern const struct ath10k_hw_regs qca988x_regs;
-++extern const struct ath10k_hw_regs qca6174_regs;
-++
-++#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
-++#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
-++
-+ /* Known pecularities:
-+  *  - current FW doesn't support raw rx mode (last tested v599)
-+  *  - current FW dumps upon raw tx mode (last tested v599)
-+@@ -73,6 +171,15 @@ enum ath10k_mcast2ucast_mode {
-+ 	ATH10K_MCAST2UCAST_ENABLED = 1,
-+ };
-+ 
-++struct ath10k_pktlog_hdr {
-++	__le16 flags;
-++	__le16 missed_cnt;
-++	__le16 log_type;
-++	__le16 size;
-++	__le32 timestamp;
-++	u8 payload[0];
-++} __packed;
-++
-+ /* Target specific defines for MAIN firmware */
-+ #define TARGET_NUM_VDEVS			8
-+ #define TARGET_NUM_PEER_AST			2
-+@@ -80,11 +187,13 @@ enum ath10k_mcast2ucast_mode {
-+ #define TARGET_DMA_BURST_SIZE			0
-+ #define TARGET_MAC_AGGR_DELIM			0
-+ #define TARGET_AST_SKID_LIMIT			16
-+-#define TARGET_NUM_PEERS			16
-++#define TARGET_NUM_STATIONS			16
-++#define TARGET_NUM_PEERS			((TARGET_NUM_STATIONS) + \
-++						 (TARGET_NUM_VDEVS))
-+ #define TARGET_NUM_OFFLOAD_PEERS		0
-+ #define TARGET_NUM_OFFLOAD_REORDER_BUFS         0
-+ #define TARGET_NUM_PEER_KEYS			2
-+-#define TARGET_NUM_TIDS		(2 * ((TARGET_NUM_PEERS) + (TARGET_NUM_VDEVS)))
-++#define TARGET_NUM_TIDS				((TARGET_NUM_PEERS) * 2)
-+ #define TARGET_TX_CHAIN_MASK			(BIT(0) | BIT(1) | BIT(2))
-+ #define TARGET_RX_CHAIN_MASK			(BIT(0) | BIT(1) | BIT(2))
-+ #define TARGET_RX_TIMEOUT_LO_PRI		100
-+@@ -115,12 +224,15 @@ enum ath10k_mcast2ucast_mode {
-+ #define TARGET_10X_DMA_BURST_SIZE		0
-+ #define TARGET_10X_MAC_AGGR_DELIM		0
-+ #define TARGET_10X_AST_SKID_LIMIT		16
-+-#define TARGET_10X_NUM_PEERS			(128 + (TARGET_10X_NUM_VDEVS))
-+-#define TARGET_10X_NUM_PEERS_MAX		128
-++#define TARGET_10X_NUM_STATIONS			128
-++#define TARGET_10X_NUM_PEERS			((TARGET_10X_NUM_STATIONS) + \
-++						 (TARGET_10X_NUM_VDEVS))
-+ #define TARGET_10X_NUM_OFFLOAD_PEERS		0
-+ #define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS	0
-+ #define TARGET_10X_NUM_PEER_KEYS		2
-+-#define TARGET_10X_NUM_TIDS			256
-++#define TARGET_10X_NUM_TIDS_MAX			256
-++#define TARGET_10X_NUM_TIDS			min((TARGET_10X_NUM_TIDS_MAX), \
-++						    (TARGET_10X_NUM_PEERS) * 2)
-+ #define TARGET_10X_TX_CHAIN_MASK		(BIT(0) | BIT(1) | BIT(2))
-+ #define TARGET_10X_RX_CHAIN_MASK		(BIT(0) | BIT(1) | BIT(2))
-+ #define TARGET_10X_RX_TIMEOUT_LO_PRI		100
-+@@ -140,6 +252,18 @@ enum ath10k_mcast2ucast_mode {
-+ #define TARGET_10X_NUM_MSDU_DESC		(1024 + 400)
-+ #define TARGET_10X_MAX_FRAG_ENTRIES		0
-+ 
-++/* 10.2 parameters */
-++#define TARGET_10_2_DMA_BURST_SIZE		1
-++
-++/* Target specific defines for WMI-TLV firmware */
-++#define TARGET_TLV_NUM_VDEVS			3
-++#define TARGET_TLV_NUM_STATIONS			32
-++#define TARGET_TLV_NUM_PEERS			((TARGET_TLV_NUM_STATIONS) + \
-++						 (TARGET_TLV_NUM_VDEVS) + \
-++						 2)
-++#define TARGET_TLV_NUM_TIDS			((TARGET_TLV_NUM_PEERS) * 2)
-++#define TARGET_TLV_NUM_MSDU_DESC		(1024 + 32)
-++
-+ /* Number of Copy Engines supported */
-+ #define CE_COUNT 8
-+ 
-+@@ -170,7 +294,7 @@ enum ath10k_mcast2ucast_mode {
-+ /* as of IP3.7.1 */
-+ #define RTC_STATE_V_ON				3
-+ 
-+-#define RTC_STATE_COLD_RESET_MASK		0x00000400
-++#define RTC_STATE_COLD_RESET_MASK		ar->regs->rtc_state_cold_reset_mask
-+ #define RTC_STATE_V_LSB				0
-+ #define RTC_STATE_V_MASK			0x00000007
-+ #define RTC_STATE_ADDRESS			0x0000
-+@@ -179,12 +303,12 @@ enum ath10k_mcast2ucast_mode {
-+ #define PCIE_SOC_WAKE_RESET			0x00000000
-+ #define SOC_GLOBAL_RESET_ADDRESS		0x0008
-+ 
-+-#define RTC_SOC_BASE_ADDRESS			0x00004000
-+-#define RTC_WMAC_BASE_ADDRESS			0x00005000
-++#define RTC_SOC_BASE_ADDRESS			ar->regs->rtc_soc_base_address
-++#define RTC_WMAC_BASE_ADDRESS			ar->regs->rtc_wmac_base_address
-+ #define MAC_COEX_BASE_ADDRESS			0x00006000
-+ #define BT_COEX_BASE_ADDRESS			0x00007000
-+ #define SOC_PCIE_BASE_ADDRESS			0x00008000
-+-#define SOC_CORE_BASE_ADDRESS			0x00009000
-++#define SOC_CORE_BASE_ADDRESS			ar->regs->soc_core_base_address
-+ #define WLAN_UART_BASE_ADDRESS			0x0000c000
-+ #define WLAN_SI_BASE_ADDRESS			0x00010000
-+ #define WLAN_GPIO_BASE_ADDRESS			0x00014000
-+@@ -193,23 +317,23 @@ enum ath10k_mcast2ucast_mode {
-+ #define EFUSE_BASE_ADDRESS			0x00030000
-+ #define FPGA_REG_BASE_ADDRESS			0x00039000
-+ #define WLAN_UART2_BASE_ADDRESS			0x00054c00
-+-#define CE_WRAPPER_BASE_ADDRESS			0x00057000
-+-#define CE0_BASE_ADDRESS			0x00057400
-+-#define CE1_BASE_ADDRESS			0x00057800
-+-#define CE2_BASE_ADDRESS			0x00057c00
-+-#define CE3_BASE_ADDRESS			0x00058000
-+-#define CE4_BASE_ADDRESS			0x00058400
-+-#define CE5_BASE_ADDRESS			0x00058800
-+-#define CE6_BASE_ADDRESS			0x00058c00
-+-#define CE7_BASE_ADDRESS			0x00059000
-++#define CE_WRAPPER_BASE_ADDRESS			ar->regs->ce_wrapper_base_address
-++#define CE0_BASE_ADDRESS			ar->regs->ce0_base_address
-++#define CE1_BASE_ADDRESS			ar->regs->ce1_base_address
-++#define CE2_BASE_ADDRESS			ar->regs->ce2_base_address
-++#define CE3_BASE_ADDRESS			ar->regs->ce3_base_address
-++#define CE4_BASE_ADDRESS			ar->regs->ce4_base_address
-++#define CE5_BASE_ADDRESS			ar->regs->ce5_base_address
-++#define CE6_BASE_ADDRESS			ar->regs->ce6_base_address
-++#define CE7_BASE_ADDRESS			ar->regs->ce7_base_address
-+ #define DBI_BASE_ADDRESS			0x00060000
-+ #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS	0x0006c000
-+ #define PCIE_LOCAL_BASE_ADDRESS			0x00080000
-+ 
-+ #define SOC_RESET_CONTROL_ADDRESS		0x00000000
-+ #define SOC_RESET_CONTROL_OFFSET		0x00000000
-+-#define SOC_RESET_CONTROL_SI0_RST_MASK		0x00000001
-+-#define SOC_RESET_CONTROL_CE_RST_MASK		0x00040000
-++#define SOC_RESET_CONTROL_SI0_RST_MASK		ar->regs->soc_reset_control_si0_rst_mask
-++#define SOC_RESET_CONTROL_CE_RST_MASK		ar->regs->soc_reset_control_ce_rst_mask
-+ #define SOC_RESET_CONTROL_CPU_WARM_RST_MASK	0x00000040
-+ #define SOC_CPU_CLOCK_OFFSET			0x00000020
-+ #define SOC_CPU_CLOCK_STANDARD_LSB		0
-+@@ -223,7 +347,7 @@ enum ath10k_mcast2ucast_mode {
-+ #define SOC_LF_TIMER_CONTROL0_ADDRESS		0x00000050
-+ #define SOC_LF_TIMER_CONTROL0_ENABLE_MASK	0x00000004
-+ 
-+-#define SOC_CHIP_ID_ADDRESS			0x000000ec
-++#define SOC_CHIP_ID_ADDRESS			ar->regs->soc_chip_id_address
-+ #define SOC_CHIP_ID_REV_LSB			8
-+ #define SOC_CHIP_ID_REV_MASK			0x00000f00
-+ 
-+@@ -274,11 +398,12 @@ enum ath10k_mcast2ucast_mode {
-+ #define SI_RX_DATA1_OFFSET			0x00000014
-+ 
-+ #define CORE_CTRL_CPU_INTR_MASK			0x00002000
-++#define CORE_CTRL_PCIE_REG_31_MASK		0x00000800
-+ #define CORE_CTRL_ADDRESS			0x0000
-+ #define PCIE_INTR_ENABLE_ADDRESS		0x0008
-+ #define PCIE_INTR_CAUSE_ADDRESS			0x000c
-+ #define PCIE_INTR_CLR_ADDRESS			0x0014
-+-#define SCRATCH_3_ADDRESS			0x0030
-++#define SCRATCH_3_ADDRESS			ar->regs->scratch_3_address
-+ #define CPU_INTR_ADDRESS			0x0010
-+ 
-+ /* Firmware indications to the Host via SCRATCH_3 register. */
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -26,6 +26,9 @@
-+ #include "wmi.h"
-+ #include "htt.h"
-+ #include "txrx.h"
-++#include "testmode.h"
-++#include "wmi.h"
-++#include "wmi-ops.h"
-+ 
-+ /**********/
-+ /* Crypto */
-+@@ -34,8 +37,9 @@
-+ static int ath10k_send_key(struct ath10k_vif *arvif,
-+ 			   struct ieee80211_key_conf *key,
-+ 			   enum set_key_cmd cmd,
-+-			   const u8 *macaddr)
-++			   const u8 *macaddr, bool def_idx)
-+ {
-++	struct ath10k *ar = arvif->ar;
-+ 	struct wmi_vdev_install_key_arg arg = {
-+ 		.vdev_id = arvif->vdev_id,
-+ 		.key_idx = key->keyidx,
-+@@ -54,7 +58,7 @@ static int ath10k_send_key(struct ath10k
-+ 	switch (key->cipher) {
-+ 	case WLAN_CIPHER_SUITE_CCMP:
-+ 		arg.key_cipher = WMI_CIPHER_AES_CCM;
-+-		key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
-++		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
-+ 		break;
-+ 	case WLAN_CIPHER_SUITE_TKIP:
-+ 		arg.key_cipher = WMI_CIPHER_TKIP;
-+@@ -68,9 +72,12 @@ static int ath10k_send_key(struct ath10k
-+ 		 * Otherwise pairwise key must be set */
-+ 		if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN))
-+ 			arg.key_flags = WMI_KEY_PAIRWISE;
-++
-++		if (def_idx)
-++			arg.key_flags |= WMI_KEY_TX_USAGE;
-+ 		break;
-+ 	default:
-+-		ath10k_warn("cipher %d is not supported\n", key->cipher);
-++		ath10k_warn(ar, "cipher %d is not supported\n", key->cipher);
-+ 		return -EOPNOTSUPP;
-+ 	}
-+ 
-+@@ -85,7 +92,7 @@ static int ath10k_send_key(struct ath10k
-+ static int ath10k_install_key(struct ath10k_vif *arvif,
-+ 			      struct ieee80211_key_conf *key,
-+ 			      enum set_key_cmd cmd,
-+-			      const u8 *macaddr)
-++			      const u8 *macaddr, bool def_idx)
-+ {
-+ 	struct ath10k *ar = arvif->ar;
-+ 	int ret;
-+@@ -94,7 +101,7 @@ static int ath10k_install_key(struct ath
-+ 
-+ 	reinit_completion(&ar->install_key_done);
-+ 
-+-	ret = ath10k_send_key(arvif, key, cmd, macaddr);
-++	ret = ath10k_send_key(arvif, key, cmd, macaddr, def_idx);
-+ 	if (ret)
-+ 		return ret;
-+ 
-+@@ -112,6 +119,7 @@ static int ath10k_install_peer_wep_keys(
-+ 	struct ath10k_peer *peer;
-+ 	int ret;
-+ 	int i;
-++	bool def_idx;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+@@ -125,13 +133,20 @@ static int ath10k_install_peer_wep_keys(
-+ 	for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) {
-+ 		if (arvif->wep_keys[i] == NULL)
-+ 			continue;
-++		/* set TX_USAGE flag for default key id */
-++		if (arvif->def_wep_key_idx == i)
-++			def_idx = true;
-++		else
-++			def_idx = false;
-+ 
-+ 		ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
-+-					 addr);
-++					 addr, def_idx);
-+ 		if (ret)
-+ 			return ret;
-+ 
-++		spin_lock_bh(&ar->data_lock);
-+ 		peer->keys[i] = arvif->wep_keys[i];
-++		spin_unlock_bh(&ar->data_lock);
-+ 	}
-+ 
-+ 	return 0;
-+@@ -159,21 +174,49 @@ static int ath10k_clear_peer_keys(struct
-+ 		if (peer->keys[i] == NULL)
-+ 			continue;
-+ 
-++		/* key flags are not required to delete the key */
-+ 		ret = ath10k_install_key(arvif, peer->keys[i],
-+-					 DISABLE_KEY, addr);
-++					 DISABLE_KEY, addr, false);
-+ 		if (ret && first_errno == 0)
-+ 			first_errno = ret;
-+ 
-+ 		if (ret)
-+-			ath10k_warn("failed to remove peer wep key %d: %d\n",
-++			ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
-+ 				    i, ret);
-+ 
-++		spin_lock_bh(&ar->data_lock);
-+ 		peer->keys[i] = NULL;
-++		spin_unlock_bh(&ar->data_lock);
-+ 	}
-+ 
-+ 	return first_errno;
-+ }
-+ 
-++bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
-++				    u8 keyidx)
-++{
-++	struct ath10k_peer *peer;
-++	int i;
-++
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	/* We don't know which vdev this peer belongs to,
-++	 * since WMI doesn't give us that information.
-++	 *
-++	 * FIXME: multi-bss needs to be handled.
-++	 */
-++	peer = ath10k_peer_find(ar, 0, addr);
-++	if (!peer)
-++		return false;
-++
-++	for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
-++		if (peer->keys[i] && peer->keys[i]->keyidx == keyidx)
-++			return true;
-++	}
-++
-++	return false;
-++}
-++
-+ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
-+ 				 struct ieee80211_key_conf *key)
-+ {
-+@@ -194,7 +237,7 @@ static int ath10k_clear_vdev_key(struct
-+ 		list_for_each_entry(peer, &ar->peers, list) {
-+ 			for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
-+ 				if (peer->keys[i] == key) {
-+-					memcpy(addr, peer->addr, ETH_ALEN);
-++					ether_addr_copy(addr, peer->addr);
-+ 					peer->keys[i] = NULL;
-+ 					break;
-+ 				}
-+@@ -207,20 +250,19 @@ static int ath10k_clear_vdev_key(struct
-+ 
-+ 		if (i == ARRAY_SIZE(peer->keys))
-+ 			break;
-+-
-+-		ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr);
-++		/* key flags are not required to delete the key */
-++		ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, false);
-+ 		if (ret && first_errno == 0)
-+ 			first_errno = ret;
-+ 
-+ 		if (ret)
-+-			ath10k_warn("failed to remove key for %pM: %d\n",
-++			ath10k_warn(ar, "failed to remove key for %pM: %d\n",
-+ 				    addr, ret);
-+ 	}
-+ 
-+ 	return first_errno;
-+ }
-+ 
-+-
-+ /*********************/
-+ /* General utilities */
-+ /*********************/
-+@@ -234,7 +276,10 @@ chan_to_phymode(const struct cfg80211_ch
-+ 	case IEEE80211_BAND_2GHZ:
-+ 		switch (chandef->width) {
-+ 		case NL80211_CHAN_WIDTH_20_NOHT:
-+-			phymode = MODE_11G;
-++			if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM)
-++				phymode = MODE_11B;
-++			else
-++				phymode = MODE_11G;
-+ 			break;
-+ 		case NL80211_CHAN_WIDTH_20:
-+ 			phymode = MODE_11NG_HT20;
-+@@ -322,22 +367,24 @@ static int ath10k_peer_create(struct ath
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-++	if (ar->num_peers >= ar->max_num_peers)
-++		return -ENOBUFS;
-++
-+ 	ret = ath10k_wmi_peer_create(ar, vdev_id, addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to create wmi peer %pM on vdev %i: %i\n",
-++		ath10k_warn(ar, "failed to create wmi peer %pM on vdev %i: %i\n",
-+ 			    addr, vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_wait_for_peer_created(ar, vdev_id, addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to wait for created wmi peer %pM on vdev %i: %i\n",
-++		ath10k_warn(ar, "failed to wait for created wmi peer %pM on vdev %i: %i\n",
-+ 			    addr, vdev_id, ret);
-+ 		return ret;
-+ 	}
-+-	spin_lock_bh(&ar->data_lock);
-++
-+ 	ar->num_peers++;
-+-	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	return 0;
-+ }
-+@@ -352,7 +399,7 @@ static int ath10k_mac_set_kickout(struct
-+ 	ret = ath10k_wmi_pdev_set_param(ar, param,
-+ 					ATH10K_KICKOUT_THRESHOLD);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set kickout threshold on vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to set kickout threshold on vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -361,7 +408,7 @@ static int ath10k_mac_set_kickout(struct
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
-+ 					ATH10K_KEEPALIVE_MIN_IDLE);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set keepalive minimum idle time on vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to set keepalive minimum idle time on vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -370,7 +417,7 @@ static int ath10k_mac_set_kickout(struct
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
-+ 					ATH10K_KEEPALIVE_MAX_IDLE);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set keepalive maximum idle time on vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to set keepalive maximum idle time on vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -379,7 +426,7 @@ static int ath10k_mac_set_kickout(struct
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param,
-+ 					ATH10K_KEEPALIVE_MAX_UNRESPONSIVE);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to set keepalive maximum unresponsive time on vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -387,15 +434,11 @@ static int ath10k_mac_set_kickout(struct
-+ 	return 0;
-+ }
-+ 
-+-static int  ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
-++static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
-+ {
-+ 	struct ath10k *ar = arvif->ar;
-+ 	u32 vdev_param;
-+ 
-+-	if (value != 0xFFFFFFFF)
-+-		value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold,
-+-			      ATH10K_RTS_MAX);
-+-
-+ 	vdev_param = ar->wmi.vdev_param->rts_threshold;
-+ 	return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
-+ }
-+@@ -428,9 +471,7 @@ static int ath10k_peer_delete(struct ath
-+ 	if (ret)
-+ 		return ret;
-+ 
-+-	spin_lock_bh(&ar->data_lock);
-+ 	ar->num_peers--;
-+-	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	return 0;
-+ }
-+@@ -446,7 +487,7 @@ static void ath10k_peer_cleanup(struct a
-+ 		if (peer->vdev_id != vdev_id)
-+ 			continue;
-+ 
-+-		ath10k_warn("removing stale peer %pM from vdev_id %d\n",
-++		ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n",
-+ 			    peer->addr, vdev_id);
-+ 
-+ 		list_del(&peer->list);
-+@@ -467,20 +508,63 @@ static void ath10k_peer_cleanup_all(stru
-+ 		list_del(&peer->list);
-+ 		kfree(peer);
-+ 	}
-+-	ar->num_peers = 0;
-+ 	spin_unlock_bh(&ar->data_lock);
-++
-++	ar->num_peers = 0;
-++	ar->num_stations = 0;
-+ }
-+ 
-+ /************************/
-+ /* Interface management */
-+ /************************/
-+ 
-++void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	if (!arvif->beacon)
-++		return;
-++
-++	if (!arvif->beacon_buf)
-++		dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr,
-++				 arvif->beacon->len, DMA_TO_DEVICE);
-++
-++	if (WARN_ON(arvif->beacon_state != ATH10K_BEACON_SCHEDULED &&
-++		    arvif->beacon_state != ATH10K_BEACON_SENT))
-++		return;
-++
-++	dev_kfree_skb_any(arvif->beacon);
-++
-++	arvif->beacon = NULL;
-++	arvif->beacon_state = ATH10K_BEACON_SCHEDULED;
-++}
-++
-++static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	ath10k_mac_vif_beacon_free(arvif);
-++
-++	if (arvif->beacon_buf) {
-++		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-++				  arvif->beacon_buf, arvif->beacon_paddr);
-++		arvif->beacon_buf = NULL;
-++	}
-++}
-++
-+ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
-+ {
-+ 	int ret;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-++	if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
-++		return -ESHUTDOWN;
-++
-+ 	ret = wait_for_completion_timeout(&ar->vdev_setup_done,
-+ 					  ATH10K_VDEV_SETUP_TIMEOUT_HZ);
-+ 	if (ret == 0)
-+@@ -489,19 +573,6 @@ static inline int ath10k_vdev_setup_sync
-+ 	return 0;
-+ }
-+ 
-+-static bool ath10k_monitor_is_enabled(struct ath10k *ar)
-+-{
-+-	lockdep_assert_held(&ar->conf_mutex);
-+-
-+-	ath10k_dbg(ATH10K_DBG_MAC,
-+-		   "mac monitor refs: promisc %d monitor %d cac %d\n",
-+-		   ar->promisc, ar->monitor,
-+-		   test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
-+-
-+-	return ar->promisc || ar->monitor ||
-+-	       test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-+-}
-+-
-+ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
-+ {
-+ 	struct cfg80211_chan_def *chandef = &ar->chandef;
-+@@ -526,37 +597,39 @@ static int ath10k_monitor_vdev_start(str
-+ 	arg.channel.max_reg_power = channel->max_reg_power * 2;
-+ 	arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
-+ 
-++	reinit_completion(&ar->vdev_setup_done);
-++
-+ 	ret = ath10k_wmi_vdev_start(ar, &arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request monitor vdev %i start: %d\n",
-++		ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n",
-+ 			    vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_vdev_setup_sync(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to synchronize setup for monitor vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to synchronize setup for monitor vdev %i start: %d\n",
-+ 			    vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to put up monitor vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to put up monitor vdev %i: %d\n",
-+ 			    vdev_id, ret);
-+ 		goto vdev_stop;
-+ 	}
-+ 
-+ 	ar->monitor_vdev_id = vdev_id;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %i started\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %i started\n",
-+ 		   ar->monitor_vdev_id);
-+ 	return 0;
-+ 
-+ vdev_stop:
-+ 	ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
-+ 	if (ret)
-+-		ath10k_warn("failed to stop monitor vdev %i after start failure: %d\n",
-++		ath10k_warn(ar, "failed to stop monitor vdev %i after start failure: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+ 
-+ 	return ret;
-+@@ -570,20 +643,22 @@ static int ath10k_monitor_vdev_stop(stru
-+ 
-+ 	ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id);
-+ 	if (ret)
-+-		ath10k_warn("failed to put down monitor vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+ 
-++	reinit_completion(&ar->vdev_setup_done);
-++
-+ 	ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
-+ 	if (ret)
-+-		ath10k_warn("failed to to request monitor vdev %i stop: %d\n",
-++		ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+ 
-+ 	ret = ath10k_vdev_setup_sync(ar);
-+ 	if (ret)
-+-		ath10k_warn("failed to synchronise monitor vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to synchronize monitor vdev %i stop: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %i stopped\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %i stopped\n",
-+ 		   ar->monitor_vdev_id);
-+ 	return ret;
-+ }
-+@@ -594,35 +669,29 @@ static int ath10k_monitor_vdev_create(st
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	bit = ffs(ar->free_vdev_map);
-+-	if (bit == 0) {
-+-		ath10k_warn("failed to find free vdev id for monitor vdev\n");
-++	if (ar->free_vdev_map == 0) {
-++		ath10k_warn(ar, "failed to find free vdev id for monitor vdev\n");
-+ 		return -ENOMEM;
-+ 	}
-+ 
-+-	ar->monitor_vdev_id = bit - 1;
-+-	ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
-++	bit = __ffs64(ar->free_vdev_map);
-++
-++	ar->monitor_vdev_id = bit;
-+ 
-+ 	ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
-+ 				     WMI_VDEV_TYPE_MONITOR,
-+ 				     0, ar->mac_addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request monitor vdev %i creation: %d\n",
-++		ath10k_warn(ar, "failed to request monitor vdev %i creation: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+-		goto vdev_fail;
-++		return ret;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
-++	ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
-+ 		   ar->monitor_vdev_id);
-+ 
-+ 	return 0;
-+-
-+-vdev_fail:
-+-	/*
-+-	 * Restore the ID to the global map.
-+-	 */
-+-	ar->free_vdev_map |= 1 << (ar->monitor_vdev_id);
-+-	return ret;
-+ }
-+ 
-+ static int ath10k_monitor_vdev_delete(struct ath10k *ar)
-+@@ -633,14 +702,14 @@ static int ath10k_monitor_vdev_delete(st
-+ 
-+ 	ret = ath10k_wmi_vdev_delete(ar, ar->monitor_vdev_id);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request wmi monitor vdev %i removal: %d\n",
-++		ath10k_warn(ar, "failed to request wmi monitor vdev %i removal: %d\n",
-+ 			    ar->monitor_vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ar->free_vdev_map |= 1 << (ar->monitor_vdev_id);
-++	ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
-+ 		   ar->monitor_vdev_id);
-+ 	return ret;
-+ }
-+@@ -651,63 +720,70 @@ static int ath10k_monitor_start(struct a
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	if (!ath10k_monitor_is_enabled(ar)) {
-+-		ath10k_warn("trying to start monitor with no references\n");
-+-		return 0;
-+-	}
-+-
-+-	if (ar->monitor_started) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac monitor already started\n");
-+-		return 0;
-+-	}
-+-
-+ 	ret = ath10k_monitor_vdev_create(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to create monitor vdev: %d\n", ret);
-++		ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
-+ 	if (ret) {
-+-		ath10k_warn("failed to start monitor vdev: %d\n", ret);
-++		ath10k_warn(ar, "failed to start monitor vdev: %d\n", ret);
-+ 		ath10k_monitor_vdev_delete(ar);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ar->monitor_started = true;
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor started\n");
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor started\n");
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_monitor_stop(struct ath10k *ar)
-++static int ath10k_monitor_stop(struct ath10k *ar)
-+ {
-+ 	int ret;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	if (ath10k_monitor_is_enabled(ar)) {
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-+-			   "mac monitor will be stopped later\n");
-+-		return;
-++	ret = ath10k_monitor_vdev_stop(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret);
-++		return ret;
-+ 	}
-+ 
-+-	if (!ar->monitor_started) {
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-+-			   "mac monitor probably failed to start earlier\n");
-+-		return;
-++	ret = ath10k_monitor_vdev_delete(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret);
-++		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_monitor_vdev_stop(ar);
-+-	if (ret)
-+-		ath10k_warn("failed to stop monitor vdev: %d\n", ret);
-++	ar->monitor_started = false;
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n");
-+ 
-+-	ret = ath10k_monitor_vdev_delete(ar);
-+-	if (ret)
-+-		ath10k_warn("failed to delete monitor vdev: %d\n", ret);
-++	return 0;
-++}
-+ 
-+-	ar->monitor_started = false;
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac monitor stopped\n");
-++static int ath10k_monitor_recalc(struct ath10k *ar)
-++{
-++	bool should_start;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	should_start = ar->monitor ||
-++		       ar->filter_flags & FIF_PROMISC_IN_BSS ||
-++		       test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC,
-++		   "mac monitor recalc started? %d should? %d\n",
-++		   ar->monitor_started, should_start);
-++
-++	if (should_start == ar->monitor_started)
-++		return 0;
-++
-++	if (should_start)
-++		return ath10k_monitor_start(ar);
-++
-++	return ath10k_monitor_stop(ar);
-+ }
-+ 
-+ static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
-+@@ -738,14 +814,14 @@ static int ath10k_start_cac(struct ath10
-+ 
-+ 	set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-+ 
-+-	ret = ath10k_monitor_start(ar);
-++	ret = ath10k_monitor_recalc(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to start monitor (cac): %d\n", ret);
-++		ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret);
-+ 		clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-+ 		return ret;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac cac start monitor vdev %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac cac start monitor vdev %d\n",
-+ 		   ar->monitor_vdev_id);
-+ 
-+ 	return 0;
-+@@ -762,7 +838,7 @@ static int ath10k_stop_cac(struct ath10k
-+ 	clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-+ 	ath10k_monitor_stop(ar);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac cac finished\n");
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac cac finished\n");
-+ 
-+ 	return 0;
-+ }
-+@@ -788,12 +864,12 @@ static void ath10k_recalc_radar_detectio
-+ 		 * radiation is not allowed, make this channel DFS_UNAVAILABLE
-+ 		 * by indicating that radar was detected.
-+ 		 */
-+-		ath10k_warn("failed to start CAC: %d\n", ret);
-++		ath10k_warn(ar, "failed to start CAC: %d\n", ret);
-+ 		ieee80211_radar_detected(ar->hw);
-+ 	}
-+ }
-+ 
-+-static int ath10k_vdev_start(struct ath10k_vif *arvif)
-++static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, bool restart)
-+ {
-+ 	struct ath10k *ar = arvif->ar;
-+ 	struct cfg80211_chan_def *chandef = &ar->chandef;
-+@@ -830,22 +906,27 @@ static int ath10k_vdev_start(struct ath1
-+ 		arg.ssid_len = arvif->vif->bss_conf.ssid_len;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC,
-++	ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 		   "mac vdev %d start center_freq %d phymode %s\n",
-+ 		   arg.vdev_id, arg.channel.freq,
-+ 		   ath10k_wmi_phymode_str(arg.channel.mode));
-+ 
-+-	ret = ath10k_wmi_vdev_start(ar, &arg);
-++	if (restart)
-++		ret = ath10k_wmi_vdev_restart(ar, &arg);
-++	else
-++		ret = ath10k_wmi_vdev_start(ar, &arg);
-++
-+ 	if (ret) {
-+-		ath10k_warn("failed to start WMI vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to start WMI vdev %i: %d\n",
-+ 			    arg.vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_vdev_setup_sync(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to synchronise setup for vdev %i: %d\n",
-+-			    arg.vdev_id, ret);
-++		ath10k_warn(ar,
-++			    "failed to synchronize setup for vdev %i restart %d: %d\n",
-++			    arg.vdev_id, restart, ret);
-+ 		return ret;
-+ 	}
-+ 
-+@@ -855,6 +936,16 @@ static int ath10k_vdev_start(struct ath1
-+ 	return ret;
-+ }
-+ 
-++static int ath10k_vdev_start(struct ath10k_vif *arvif)
-++{
-++	return ath10k_vdev_start_restart(arvif, false);
-++}
-++
-++static int ath10k_vdev_restart(struct ath10k_vif *arvif)
-++{
-++	return ath10k_vdev_start_restart(arvif, true);
-++}
-++
-+ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
-+ {
-+ 	struct ath10k *ar = arvif->ar;
-+@@ -866,14 +957,14 @@ static int ath10k_vdev_stop(struct ath10
-+ 
-+ 	ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id);
-+ 	if (ret) {
-+-		ath10k_warn("failed to stop WMI vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to stop WMI vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_vdev_setup_sync(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to syncronise setup for vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to synchronize setup for vdev %i stop: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -888,9 +979,147 @@ static int ath10k_vdev_stop(struct ath10
-+ 	return ret;
-+ }
-+ 
-++static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif,
-++				       struct sk_buff *bcn)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	struct ieee80211_mgmt *mgmt;
-++	const u8 *p2p_ie;
-++	int ret;
-++
-++	if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
-++		return 0;
-++
-++	if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
-++		return 0;
-++
-++	mgmt = (void *)bcn->data;
-++	p2p_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
-++					 mgmt->u.beacon.variable,
-++					 bcn->len - (mgmt->u.beacon.variable -
-++						     bcn->data));
-++	if (!p2p_ie)
-++		return -ENOENT;
-++
-++	ret = ath10k_wmi_p2p_go_bcn_ie(ar, arvif->vdev_id, p2p_ie);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit p2p go bcn ie for vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
-++				       u8 oui_type, size_t ie_offset)
-++{
-++	size_t len;
-++	const u8 *next;
-++	const u8 *end;
-++	u8 *ie;
-++
-++	if (WARN_ON(skb->len < ie_offset))
-++		return -EINVAL;
-++
-++	ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
-++					   skb->data + ie_offset,
-++					   skb->len - ie_offset);
-++	if (!ie)
-++		return -ENOENT;
-++
-++	len = ie[1] + 2;
-++	end = skb->data + skb->len;
-++	next = ie + len;
-++
-++	if (WARN_ON(next > end))
-++		return -EINVAL;
-++
-++	memmove(ie, next, end - next);
-++	skb_trim(skb, skb->len - len);
-++
-++	return 0;
-++}
-++
-++static int ath10k_mac_setup_bcn_tmpl(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	struct ieee80211_hw *hw = ar->hw;
-++	struct ieee80211_vif *vif = arvif->vif;
-++	struct ieee80211_mutable_offsets offs = {};
-++	struct sk_buff *bcn;
-++	int ret;
-++
-++	if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map))
-++		return 0;
-++
-++	bcn = ieee80211_beacon_get_template(hw, vif, &offs);
-++	if (!bcn) {
-++		ath10k_warn(ar, "failed to get beacon template from mac80211\n");
-++		return -EPERM;
-++	}
-++
-++	ret = ath10k_mac_setup_bcn_p2p_ie(arvif, bcn);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to setup p2p go bcn ie: %d\n", ret);
-++		kfree_skb(bcn);
-++		return ret;
-++	}
-++
-++	/* P2P IE is inserted by firmware automatically (as configured above)
-++	 * so remove it from the base beacon template to avoid duplicate P2P
-++	 * IEs in beacon frames.
-++	 */
-++	ath10k_mac_remove_vendor_ie(bcn, WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
-++				    offsetof(struct ieee80211_mgmt,
-++					     u.beacon.variable));
-++
-++	ret = ath10k_wmi_bcn_tmpl(ar, arvif->vdev_id, offs.tim_offset, bcn, 0,
-++				  0, NULL, 0);
-++	kfree_skb(bcn);
-++
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit beacon template command: %d\n",
-++			    ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_mac_setup_prb_tmpl(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	struct ieee80211_hw *hw = ar->hw;
-++	struct ieee80211_vif *vif = arvif->vif;
-++	struct sk_buff *prb;
-++	int ret;
-++
-++	if (!test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map))
-++		return 0;
-++
-++	prb = ieee80211_proberesp_get(hw, vif);
-++	if (!prb) {
-++		ath10k_warn(ar, "failed to get probe resp template from mac80211\n");
-++		return -EPERM;
-++	}
-++
-++	ret = ath10k_wmi_prb_tmpl(ar, arvif->vdev_id, prb);
-++	kfree_skb(prb);
-++
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit probe resp template command: %d\n",
-++			    ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-+ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
-+-				struct ieee80211_bss_conf *info)
-++				     struct ieee80211_bss_conf *info)
-+ {
-++	struct ath10k *ar = arvif->ar;
-+ 	int ret = 0;
-+ 
-+ 	lockdep_assert_held(&arvif->ar->conf_mutex);
-+@@ -902,15 +1131,7 @@ static void ath10k_control_beaconing(str
-+ 		arvif->is_up = false;
-+ 
-+ 		spin_lock_bh(&arvif->ar->data_lock);
-+-		if (arvif->beacon) {
-+-			dma_unmap_single(arvif->ar->dev,
-+-					 ATH10K_SKB_CB(arvif->beacon)->paddr,
-+-					 arvif->beacon->len, DMA_TO_DEVICE);
-+-			dev_kfree_skb_any(arvif->beacon);
-+-
-+-			arvif->beacon = NULL;
-+-			arvif->beacon_sent = false;
-+-		}
-++		ath10k_mac_vif_beacon_free(arvif);
-+ 		spin_unlock_bh(&arvif->ar->data_lock);
-+ 
-+ 		return;
-+@@ -923,12 +1144,12 @@ static void ath10k_control_beaconing(str
-+ 		return;
-+ 
-+ 	arvif->aid = 0;
-+-	memcpy(arvif->bssid, info->bssid, ETH_ALEN);
-++	ether_addr_copy(arvif->bssid, info->bssid);
-+ 
-+ 	ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
-+ 				 arvif->bssid);
-+ 	if (ret) {
-+-		ath10k_warn("failed to bring up vdev %d: %i\n",
-++		ath10k_warn(ar, "failed to bring up vdev %d: %i\n",
-+ 			    arvif->vdev_id, ret);
-+ 		ath10k_vdev_stop(arvif);
-+ 		return;
-+@@ -937,13 +1158,14 @@ static void ath10k_control_beaconing(str
-+ 	arvif->is_started = true;
-+ 	arvif->is_up = true;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d up\n", arvif->vdev_id);
-+ }
-+ 
-+ static void ath10k_control_ibss(struct ath10k_vif *arvif,
-+ 				struct ieee80211_bss_conf *info,
-+ 				const u8 self_peer[ETH_ALEN])
-+ {
-++	struct ath10k *ar = arvif->ar;
-+ 	u32 vdev_param;
-+ 	int ret = 0;
-+ 
-+@@ -952,20 +1174,12 @@ static void ath10k_control_ibss(struct a
-+ 	if (!info->ibss_joined) {
-+ 		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, self_peer);
-+ 		if (ret)
-+-			ath10k_warn("failed to delete IBSS self peer %pM for vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to delete IBSS self peer %pM for vdev %d: %d\n",
-+ 				    self_peer, arvif->vdev_id, ret);
-+ 
-+ 		if (is_zero_ether_addr(arvif->bssid))
-+ 			return;
-+ 
-+-		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
-+-					 arvif->bssid);
-+-		if (ret) {
-+-			ath10k_warn("failed to delete IBSS BSSID peer %pM for vdev %d: %d\n",
-+-				    arvif->bssid, arvif->vdev_id, ret);
-+-			return;
-+-		}
-+-
-+ 		memset(arvif->bssid, 0, ETH_ALEN);
-+ 
-+ 		return;
-+@@ -973,7 +1187,7 @@ static void ath10k_control_ibss(struct a
-+ 
-+ 	ret = ath10k_peer_create(arvif->ar, arvif->vdev_id, self_peer);
-+ 	if (ret) {
-+-		ath10k_warn("failed to create IBSS self peer %pM for vdev %d: %d\n",
-++		ath10k_warn(ar, "failed to create IBSS self peer %pM for vdev %d: %d\n",
-+ 			    self_peer, arvif->vdev_id, ret);
-+ 		return;
-+ 	}
-+@@ -982,103 +1196,211 @@ static void ath10k_control_ibss(struct a
-+ 	ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, vdev_param,
-+ 					ATH10K_DEFAULT_ATIM);
-+ 	if (ret)
-+-		ath10k_warn("failed to set IBSS ATIM for vdev %d: %d\n",
-++		ath10k_warn(ar, "failed to set IBSS ATIM for vdev %d: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ }
-+ 
-+-/*
-+- * Review this when mac80211 gains per-interface powersave support.
-+- */
-+-static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
-++static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
-+ {
-+ 	struct ath10k *ar = arvif->ar;
-+-	struct ieee80211_conf *conf = &ar->hw->conf;
-+-	enum wmi_sta_powersave_param param;
-+-	enum wmi_sta_ps_mode psmode;
-++	u32 param;
-++	u32 value;
-+ 	int ret;
-+ 
-+ 	lockdep_assert_held(&arvif->ar->conf_mutex);
-+ 
-+-	if (arvif->vif->type != NL80211_IFTYPE_STATION)
-+-		return 0;
-+-
-+-	if (conf->flags & IEEE80211_CONF_PS) {
-+-		psmode = WMI_STA_PS_MODE_ENABLED;
-+-		param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
-++	if (arvif->u.sta.uapsd)
-++		value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
-++	else
-++		value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
-+ 
-+-		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
-+-						  conf->dynamic_ps_timeout);
-+-		if (ret) {
-+-			ath10k_warn("failed to set inactivity time for vdev %d: %i\n",
-+-				    arvif->vdev_id, ret);
-+-			return ret;
-+-		}
-+-	} else {
-+-		psmode = WMI_STA_PS_MODE_DISABLED;
-++	param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
-++	ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
-++			    value, arvif->vdev_id, ret);
-++		return ret;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d psmode %s\n",
-+-		   arvif->vdev_id, psmode ? "enable" : "disable");
-++	return 0;
-++}
-+ 
-+-	ret = ath10k_wmi_set_psmode(ar, arvif->vdev_id, psmode);
-++static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	u32 param;
-++	u32 value;
-++	int ret;
-++
-++	lockdep_assert_held(&arvif->ar->conf_mutex);
-++
-++	if (arvif->u.sta.uapsd)
-++		value = WMI_STA_PS_PSPOLL_COUNT_UAPSD;
-++	else
-++		value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
-++
-++	param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
-++	ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-++					  param, value);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set PS Mode %d for vdev %d: %d\n",
-+-			    psmode, arvif->vdev_id, ret);
-++		ath10k_warn(ar, "failed to submit ps poll count %u on vdev %i: %d\n",
-++			    value, arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-/**********************/
-+-/* Station management */
-+-/**********************/
-+-
-+-static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
-+-				      struct ath10k_vif *arvif,
-+-				      struct ieee80211_sta *sta,
-+-				      struct ieee80211_bss_conf *bss_conf,
-+-				      struct wmi_peer_assoc_complete_arg *arg)
-++static int ath10k_mac_ps_vif_count(struct ath10k *ar)
-+ {
-++	struct ath10k_vif *arvif;
-++	int num = 0;
-++
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	memcpy(arg->addr, sta->addr, ETH_ALEN);
-+-	arg->vdev_id = arvif->vdev_id;
-+-	arg->peer_aid = sta->aid;
-+-	arg->peer_flags |= WMI_PEER_AUTH;
-++	list_for_each_entry(arvif, &ar->arvifs, list)
-++		if (arvif->ps)
-++			num++;
-+ 
-+-	if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
-+-		/*
-+-		 * Seems FW have problems with Power Save in STA
-+-		 * mode when we setup this parameter to high (eg. 5).
-+-		 * Often we see that FW don't send NULL (with clean P flags)
-+-		 * frame even there is info about buffered frames in beacons.
-+-		 * Sometimes we have to wait more than 10 seconds before FW
-+-		 * will wakeup. Often sending one ping from AP to our device
-+-		 * just fail (more than 50%).
-+-		 *
-+-		 * Seems setting this FW parameter to 1 couse FW
-+-		 * will check every beacon and will wakup immediately
-+-		 * after detection buffered data.
-+-		 */
-+-		arg->peer_listen_intval = 1;
-+-	else
-+-		arg->peer_listen_intval = ar->hw->conf.listen_interval;
-++	return num;
-++}
-+ 
-+-	arg->peer_num_spatial_streams = 1;
-++static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	struct ieee80211_vif *vif = arvif->vif;
-++	struct ieee80211_conf *conf = &ar->hw->conf;
-++	enum wmi_sta_powersave_param param;
-++	enum wmi_sta_ps_mode psmode;
-++	int ret;
-++	int ps_timeout;
-++	bool enable_ps;
-+ 
-+-	/*
-+-	 * The assoc capabilities are available only in managed mode.
-++	lockdep_assert_held(&arvif->ar->conf_mutex);
-++
-++	if (arvif->vif->type != NL80211_IFTYPE_STATION)
-++		return 0;
-++
-++	enable_ps = arvif->ps;
-++
-++	if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 &&
-++	    !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
-++		      ar->fw_features)) {
-++		ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
-++			    arvif->vdev_id);
-++		enable_ps = false;
-++	}
-++
-++	if (enable_ps) {
-++		psmode = WMI_STA_PS_MODE_ENABLED;
-++		param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
-++
-++		ps_timeout = conf->dynamic_ps_timeout;
-++		if (ps_timeout == 0) {
-++			/* Firmware doesn't like 0 */
-++			ps_timeout = ieee80211_tu_to_usec(
-++				vif->bss_conf.beacon_int) / 1000;
-++		}
-++
-++		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
-++						  ps_timeout);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
-++				    arvif->vdev_id, ret);
-++			return ret;
-++		}
-++	} else {
-++		psmode = WMI_STA_PS_MODE_DISABLED;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d psmode %s\n",
-++		   arvif->vdev_id, psmode ? "enable" : "disable");
-++
-++	ret = ath10k_wmi_set_psmode(ar, arvif->vdev_id, psmode);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set PS Mode %d for vdev %d: %d\n",
-++			    psmode, arvif->vdev_id, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_mac_vif_disable_keepalive(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++	struct wmi_sta_keepalive_arg arg = {};
-++	int ret;
-++
-++	lockdep_assert_held(&arvif->ar->conf_mutex);
-++
-++	if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
-++		return 0;
-++
-++	if (!test_bit(WMI_SERVICE_STA_KEEP_ALIVE, ar->wmi.svc_map))
-++		return 0;
-++
-++	/* Some firmware revisions have a bug and ignore the `enabled` field.
-++	 * Instead use the interval to disable the keepalive.
-++	 */
-++	arg.vdev_id = arvif->vdev_id;
-++	arg.enabled = 1;
-++	arg.method = WMI_STA_KEEPALIVE_METHOD_NULL_FRAME;
-++	arg.interval = WMI_STA_KEEPALIVE_INTERVAL_DISABLE;
-++
-++	ret = ath10k_wmi_sta_keepalive(ar, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit keepalive on vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++/**********************/
-++/* Station management */
-++/**********************/
-++
-++static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar,
-++					     struct ieee80211_vif *vif)
-++{
-++	/* Some firmware revisions have unstable STA powersave when listen
-++	 * interval is set too high (e.g. 5). The symptoms are firmware doesn't
-++	 * generate NullFunc frames properly even if buffered frames have been
-++	 * indicated in Beacon TIM. Firmware would seldom wake up to pull
-++	 * buffered frames. Often pinging the device from AP would simply fail.
-++	 *
-++	 * As a workaround set it to 1.
-+ 	 */
-+-	if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf)
-+-		arg->peer_caps = bss_conf->assoc_capability;
-++	if (vif->type == NL80211_IFTYPE_STATION)
-++		return 1;
-++
-++	return ar->hw->conf.listen_interval;
-++}
-++
-++static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
-++				      struct ieee80211_vif *vif,
-++				      struct ieee80211_sta *sta,
-++				      struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	ether_addr_copy(arg->addr, sta->addr);
-++	arg->vdev_id = arvif->vdev_id;
-++	arg->peer_aid = sta->aid;
-++	arg->peer_flags |= WMI_PEER_AUTH;
-++	arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
-++	arg->peer_num_spatial_streams = 1;
-++	arg->peer_caps = vif->bss_conf.assoc_capability;
-+ }
-+ 
-+ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
-+-				       struct ath10k_vif *arvif,
-++				       struct ieee80211_vif *vif,
-+ 				       struct wmi_peer_assoc_complete_arg *arg)
-+ {
-+-	struct ieee80211_vif *vif = arvif->vif;
-+ 	struct ieee80211_bss_conf *info = &vif->bss_conf;
-+ 	struct cfg80211_bss *bss;
-+ 	const u8 *rsnie = NULL;
-+@@ -1097,21 +1419,21 @@ static void ath10k_peer_assoc_h_crypto(s
-+ 		ies = rcu_dereference(bss->ies);
-+ 
-+ 		wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
-+-				WLAN_OUI_TYPE_MICROSOFT_WPA,
-+-				ies->data,
-+-				ies->len);
-++						WLAN_OUI_TYPE_MICROSOFT_WPA,
-++						ies->data,
-++						ies->len);
-+ 		rcu_read_unlock();
-+ 		cfg80211_put_bss(ar->hw->wiphy, bss);
-+ 	}
-+ 
-+ 	/* FIXME: base on RSN IE/WPA IE is a correct idea? */
-+ 	if (rsnie || wpaie) {
-+-		ath10k_dbg(ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__);
-++		ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__);
-+ 		arg->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
-+ 	}
-+ 
-+ 	if (wpaie) {
-+-		ath10k_dbg(ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__);
-++		ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__);
-+ 		arg->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
-+ 	}
-+ }
-+@@ -1149,6 +1471,7 @@ static void ath10k_peer_assoc_h_ht(struc
-+ {
-+ 	const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-+ 	int i, n;
-++	u32 stbc;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+@@ -1185,7 +1508,6 @@ static void ath10k_peer_assoc_h_ht(struc
-+ 	}
-+ 
-+ 	if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
-+-		u32 stbc;
-+ 		stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
-+ 		stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
-+ 		stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
-+@@ -1220,7 +1542,7 @@ static void ath10k_peer_assoc_h_ht(struc
-+ 		arg->peer_num_spatial_streams = sta->rx_nss;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
-+ 		   arg->addr,
-+ 		   arg->peer_ht_rates.num_rates,
-+ 		   arg->peer_num_spatial_streams);
-+@@ -1237,7 +1559,7 @@ static int ath10k_peer_assoc_qos_ap(stru
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+ 	if (sta->wme && sta->uapsd_queues) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac uapsd_queues 0x%x max_sp %d\n",
-+ 			   sta->uapsd_queues, sta->max_sp);
-+ 
-+ 		if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
-+@@ -1253,7 +1575,6 @@ static int ath10k_peer_assoc_qos_ap(stru
-+ 			uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
-+ 				 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
-+ 
-+-
-+ 		if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
-+ 			max_sp = sta->max_sp;
-+ 
-+@@ -1262,7 +1583,7 @@ static int ath10k_peer_assoc_qos_ap(stru
-+ 						 WMI_AP_PS_PEER_PARAM_UAPSD,
-+ 						 uapsd);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set ap ps peer param uapsd for vdev %i: %d\n",
-++			ath10k_warn(ar, "failed to set ap ps peer param uapsd for vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			return ret;
-+ 		}
-+@@ -1272,7 +1593,7 @@ static int ath10k_peer_assoc_qos_ap(stru
-+ 						 WMI_AP_PS_PEER_PARAM_MAX_SP,
-+ 						 max_sp);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set ap ps peer param max sp for vdev %i: %d\n",
-++			ath10k_warn(ar, "failed to set ap ps peer param max sp for vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			return ret;
-+ 		}
-+@@ -1282,9 +1603,10 @@ static int ath10k_peer_assoc_qos_ap(stru
-+ 		   sta->listen_interval - mac80211 patch required.
-+ 		   Currently use 10 seconds */
-+ 		ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr,
-+-					WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10);
-++						 WMI_AP_PS_PEER_PARAM_AGEOUT_TIME,
-++						 10);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set ap ps peer param ageout time for vdev %i: %d\n",
-++			ath10k_warn(ar, "failed to set ap ps peer param ageout time for vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			return ret;
-+ 		}
-+@@ -1304,8 +1626,11 @@ static void ath10k_peer_assoc_h_vht(stru
-+ 		return;
-+ 
-+ 	arg->peer_flags |= WMI_PEER_VHT;
-+-	arg->peer_vht_caps = vht_cap->cap;
-+ 
-++	if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
-++		arg->peer_flags |= WMI_PEER_VHT_2G;
-++
-++	arg->peer_vht_caps = vht_cap->cap;
-+ 
-+ 	ampdu_factor = (vht_cap->cap &
-+ 			IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
-+@@ -1331,16 +1656,17 @@ static void ath10k_peer_assoc_h_vht(stru
-+ 	arg->peer_vht_rates.tx_mcs_set =
-+ 		__le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
-++	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);
-+ }
-+ 
-+ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
-+-				    struct ath10k_vif *arvif,
-++				    struct ieee80211_vif *vif,
-+ 				    struct ieee80211_sta *sta,
-+-				    struct ieee80211_bss_conf *bss_conf,
-+ 				    struct wmi_peer_assoc_complete_arg *arg)
-+ {
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++
-+ 	switch (arvif->vdev_type) {
-+ 	case WMI_VDEV_TYPE_AP:
-+ 		if (sta->wme)
-+@@ -1352,16 +1678,29 @@ static void ath10k_peer_assoc_h_qos(stru
-+ 		}
-+ 		break;
-+ 	case WMI_VDEV_TYPE_STA:
-+-		if (bss_conf->qos)
-++		if (vif->bss_conf.qos)
-++			arg->peer_flags |= WMI_PEER_QOS;
-++		break;
-++	case WMI_VDEV_TYPE_IBSS:
-++		if (sta->wme)
-+ 			arg->peer_flags |= WMI_PEER_QOS;
-+ 		break;
-+ 	default:
-+ 		break;
-+ 	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
-++		   sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
-++}
-++
-++static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
-++{
-++	/* First 4 rates in ath10k_rates are CCK (11b) rates. */
-++	return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
-+ }
-+ 
-+ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
-+-					struct ath10k_vif *arvif,
-++					struct ieee80211_vif *vif,
-+ 					struct ieee80211_sta *sta,
-+ 					struct wmi_peer_assoc_complete_arg *arg)
-+ {
-+@@ -1369,13 +1708,20 @@ static void ath10k_peer_assoc_h_phymode(
-+ 
-+ 	switch (ar->hw->conf.chandef.chan->band) {
-+ 	case IEEE80211_BAND_2GHZ:
-+-		if (sta->ht_cap.ht_supported) {
-++		if (sta->vht_cap.vht_supported) {
-++			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
-++				phymode = MODE_11AC_VHT40;
-++			else
-++				phymode = MODE_11AC_VHT20;
-++		} else if (sta->ht_cap.ht_supported) {
-+ 			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
-+ 				phymode = MODE_11NG_HT40;
-+ 			else
-+ 				phymode = MODE_11NG_HT20;
-+-		} else {
-++		} else if (ath10k_mac_sta_has_11g_rates(sta)) {
-+ 			phymode = MODE_11G;
-++		} else {
-++			phymode = MODE_11B;
-+ 		}
-+ 
-+ 		break;
-+@@ -1404,7 +1750,7 @@ static void ath10k_peer_assoc_h_phymode(
-+ 		break;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac peer %pM phymode %s\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM phymode %s\n",
-+ 		   sta->addr, ath10k_wmi_phymode_str(phymode));
-+ 
-+ 	arg->peer_phymode = phymode;
-+@@ -1412,22 +1758,21 @@ static void ath10k_peer_assoc_h_phymode(
-+ }
-+ 
-+ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
-+-				     struct ath10k_vif *arvif,
-++				     struct ieee80211_vif *vif,
-+ 				     struct ieee80211_sta *sta,
-+-				     struct ieee80211_bss_conf *bss_conf,
-+ 				     struct wmi_peer_assoc_complete_arg *arg)
-+ {
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+ 	memset(arg, 0, sizeof(*arg));
-+ 
-+-	ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg);
-+-	ath10k_peer_assoc_h_crypto(ar, arvif, arg);
-++	ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
-++	ath10k_peer_assoc_h_crypto(ar, vif, arg);
-+ 	ath10k_peer_assoc_h_rates(ar, sta, arg);
-+ 	ath10k_peer_assoc_h_ht(ar, sta, arg);
-+ 	ath10k_peer_assoc_h_vht(ar, sta, arg);
-+-	ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg);
-+-	ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg);
-++	ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
-++	ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
-+ 
-+ 	return 0;
-+ }
-+@@ -1459,6 +1804,68 @@ static int ath10k_setup_peer_smps(struct
-+ 					 ath10k_smps_map[smps]);
-+ }
-+ 
-++static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
-++				      struct ieee80211_vif *vif,
-++				      struct ieee80211_sta_vht_cap vht_cap)
-++{
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++	int ret;
-++	u32 param;
-++	u32 value;
-++
-++	if (!(ar->vht_cap_info &
-++	      (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-++	       IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
-++	       IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
-++	       IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
-++		return 0;
-++
-++	param = ar->wmi.vdev_param->txbf;
-++	value = 0;
-++
-++	if (WARN_ON(param == WMI_VDEV_PARAM_UNSUPPORTED))
-++		return 0;
-++
-++	/* The following logic is correct. If a remote STA advertises support
-++	 * for being a beamformer then we should enable us being a beamformee.
-++	 */
-++
-++	if (ar->vht_cap_info &
-++	    (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-++	     IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
-++		if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
-++			value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
-++
-++		if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
-++			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFEE;
-++	}
-++
-++	if (ar->vht_cap_info &
-++	    (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
-++	     IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
-++		if (vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
-++			value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
-++
-++		if (vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
-++			value |= WMI_VDEV_PARAM_TXBF_MU_TX_BFER;
-++	}
-++
-++	if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFEE)
-++		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
-++
-++	if (value & WMI_VDEV_PARAM_TXBF_MU_TX_BFER)
-++		value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
-++
-++	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, param, value);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to submit vdev param txbf 0x%x: %d\n",
-++			    value, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-+ /* can be called only in mac80211 callbacks due to `key_count` usage */
-+ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
-+ 			     struct ieee80211_vif *vif,
-+@@ -1467,17 +1874,21 @@ static void ath10k_bss_assoc(struct ieee
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	struct ieee80211_sta_ht_cap ht_cap;
-++	struct ieee80211_sta_vht_cap vht_cap;
-+ 	struct wmi_peer_assoc_complete_arg peer_arg;
-+ 	struct ieee80211_sta *ap_sta;
-+ 	int ret;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
-++		   arvif->vdev_id, arvif->bssid, arvif->aid);
-++
-+ 	rcu_read_lock();
-+ 
-+ 	ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
-+ 	if (!ap_sta) {
-+-		ath10k_warn("failed to find station entry for bss %pM vdev %i\n",
-++		ath10k_warn(ar, "failed to find station entry for bss %pM vdev %i\n",
-+ 			    bss_conf->bssid, arvif->vdev_id);
-+ 		rcu_read_unlock();
-+ 		return;
-+@@ -1486,11 +1897,11 @@ static void ath10k_bss_assoc(struct ieee
-+ 	/* ap_sta must be accessed only within rcu section which must be left
-+ 	 * before calling ath10k_setup_peer_smps() which might sleep. */
-+ 	ht_cap = ap_sta->ht_cap;
-++	vht_cap = ap_sta->vht_cap;
-+ 
-+-	ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
-+-					bss_conf, &peer_arg);
-++	ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to prepare peer assoc for %pM vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n",
-+ 			    bss_conf->bssid, arvif->vdev_id, ret);
-+ 		rcu_read_unlock();
-+ 		return;
-+@@ -1500,88 +1911,100 @@ static void ath10k_bss_assoc(struct ieee
-+ 
-+ 	ret = ath10k_wmi_peer_assoc(ar, &peer_arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to run peer assoc for %pM vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to run peer assoc for %pM vdev %i: %d\n",
-+ 			    bss_conf->bssid, arvif->vdev_id, ret);
-+ 		return;
-+ 	}
-+ 
-+ 	ret = ath10k_setup_peer_smps(ar, arvif, bss_conf->bssid, &ht_cap);
-+ 	if (ret) {
-+-		ath10k_warn("failed to setup peer SMPS for vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to setup peer SMPS for vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC,
-++	ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to recalc txbf for vdev %i on bss %pM: %d\n",
-++			    arvif->vdev_id, bss_conf->bssid, ret);
-++		return;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 		   "mac vdev %d up (associated) bssid %pM aid %d\n",
-+ 		   arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
-+ 
-++	WARN_ON(arvif->is_up);
-++
-+ 	arvif->aid = bss_conf->aid;
-+-	memcpy(arvif->bssid, bss_conf->bssid, ETH_ALEN);
-++	ether_addr_copy(arvif->bssid, bss_conf->bssid);
-+ 
-+ 	ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set vdev %d up: %d\n",
-++		ath10k_warn(ar, "failed to set vdev %d up: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return;
-+ 	}
-+ 
-+ 	arvif->is_up = true;
-++
-++	/* Workaround: Some firmware revisions (tested with qca6174
-++	 * WLAN.RM.2.0-00073) have buggy powersave state machine and must be
-++	 * poked with peer param command.
-++	 */
-++	ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
-++					WMI_PEER_DUMMY_VAR, 1);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
-++			    arvif->bssid, arvif->vdev_id, ret);
-++		return;
-++	}
-+ }
-+ 
-+-/*
-+- * FIXME: flush TIDs
-+- */
-+ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
-+ 				struct ieee80211_vif *vif)
-+ {
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++	struct ieee80211_sta_vht_cap vht_cap = {};
-+ 	int ret;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	/*
-+-	 * For some reason, calling VDEV-DOWN before VDEV-STOP
-+-	 * makes the FW to send frames via HTT after disassociation.
-+-	 * No idea why this happens, even though VDEV-DOWN is supposed
-+-	 * to be analogous to link down, so just stop the VDEV.
-+-	 */
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n",
-+-		   arvif->vdev_id);
-+-
-+-	/* FIXME: check return value */
-+-	ret = ath10k_vdev_stop(arvif);
-+-
-+-	/*
-+-	 * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and
-+-	 * report beacons from previously associated network through HTT.
-+-	 * This in turn would spam mac80211 WARN_ON if we bring down all
-+-	 * interfaces as it expects there is no rx when no interface is
-+-	 * running.
-+-	 */
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id);
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
-++		   arvif->vdev_id, arvif->bssid);
-+ 
-+-	/* FIXME: why don't we print error if wmi call fails? */
-+ 	ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-++	if (ret)
-++		ath10k_warn(ar, "faield to down vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-+ 
-+-	arvif->def_wep_key_idx = 0;
-++	arvif->def_wep_key_idx = -1;
-++
-++	ret = ath10k_mac_vif_recalc_txbf(ar, vif, vht_cap);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to recalc txbf for vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++		return;
-++	}
-+ 
-+-	arvif->is_started = false;
-+ 	arvif->is_up = false;
-+ }
-+ 
-+-static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
-+-				struct ieee80211_sta *sta, bool reassoc)
-++static int ath10k_station_assoc(struct ath10k *ar,
-++				struct ieee80211_vif *vif,
-++				struct ieee80211_sta *sta,
-++				bool reassoc)
-+ {
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	struct wmi_peer_assoc_complete_arg peer_arg;
-+ 	int ret = 0;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg);
-++	ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to prepare WMI peer assoc for %pM vdev %i: %i\n",
-++		ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n",
-+ 			    sta->addr, arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -1589,48 +2012,59 @@ static int ath10k_station_assoc(struct a
-+ 	peer_arg.peer_reassoc = reassoc;
-+ 	ret = ath10k_wmi_peer_assoc(ar, &peer_arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to run peer assoc for STA %pM vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to run peer assoc for STA %pM vdev %i: %d\n",
-+ 			    sta->addr, arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap);
-+-	if (ret) {
-+-		ath10k_warn("failed to setup peer SMPS for vdev %d: %d\n",
-+-			    arvif->vdev_id, ret);
-+-		return ret;
-+-	}
-+-
-+-	if (!sta->wme) {
-+-		arvif->num_legacy_stations++;
-+-		ret  = ath10k_recalc_rtscts_prot(arvif);
-++	/* Re-assoc is run only to update supported rates for given station. It
-++	 * doesn't make much sense to reconfigure the peer completely.
-++	 */
-++	if (!reassoc) {
-++		ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
-++					     &sta->ht_cap);
-+ 		if (ret) {
-+-			ath10k_warn("failed to recalculate rts/cts prot for vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			return ret;
-+ 		}
-+-	}
-+ 
-+-	ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
-+-	if (ret) {
-+-		ath10k_warn("failed to install peer wep keys for vdev %i: %d\n",
-+-			    arvif->vdev_id, ret);
-+-		return ret;
-+-	}
-++		ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
-++				    sta->addr, arvif->vdev_id, ret);
-++			return ret;
-++		}
-+ 
-+-	ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
-+-	if (ret) {
-+-		ath10k_warn("failed to set qos params for STA %pM for vdev %i: %d\n",
-+-			    sta->addr, arvif->vdev_id, ret);
-+-		return ret;
-++		if (!sta->wme) {
-++			arvif->num_legacy_stations++;
-++			ret  = ath10k_recalc_rtscts_prot(arvif);
-++			if (ret) {
-++				ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
-++					    arvif->vdev_id, ret);
-++				return ret;
-++			}
-++		}
-++
-++		/* Plumb cached keys only for static WEP */
-++		if (arvif->def_wep_key_idx != -1) {
-++			ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
-++			if (ret) {
-++				ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
-++					    arvif->vdev_id, ret);
-++				return ret;
-++			}
-++		}
-+ 	}
-+ 
-+ 	return ret;
-+ }
-+ 
-+-static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
-++static int ath10k_station_disassoc(struct ath10k *ar,
-++				   struct ieee80211_vif *vif,
-+ 				   struct ieee80211_sta *sta)
-+ {
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	int ret = 0;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+@@ -1639,7 +2073,7 @@ static int ath10k_station_disassoc(struc
-+ 		arvif->num_legacy_stations--;
-+ 		ret = ath10k_recalc_rtscts_prot(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to recalculate rts/cts prot for vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			return ret;
-+ 		}
-+@@ -1647,7 +2081,7 @@ static int ath10k_station_disassoc(struc
-+ 
-+ 	ret = ath10k_clear_peer_keys(arvif, sta->addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to clear all peer wep keys for vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to clear all peer wep keys for vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		return ret;
-+ 	}
-+@@ -1722,6 +2156,7 @@ static int ath10k_update_channel_list(st
-+ 			ch->passive = passive;
-+ 
-+ 			ch->freq = channel->center_freq;
-++			ch->band_center_freq1 = channel->center_freq;
-+ 			ch->min_power = 0;
-+ 			ch->max_power = channel->max_power * 2;
-+ 			ch->max_reg_power = channel->max_reg_power * 2;
-+@@ -1739,7 +2174,7 @@ static int ath10k_update_channel_list(st
-+ 			if (WARN_ON_ONCE(ch->mode == MODE_UNKNOWN))
-+ 				continue;
-+ 
-+-			ath10k_dbg(ATH10K_DBG_WMI,
-++			ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 				   "mac channel [%zd/%d] freq %d maxpower %d regpower %d antenna %d mode %d\n",
-+ 				    ch - arg.channels, arg.n_channels,
-+ 				   ch->freq, ch->max_power, ch->max_reg_power,
-+@@ -1782,7 +2217,7 @@ static void ath10k_regd_update(struct at
-+ 
-+ 	ret = ath10k_update_channel_list(ar);
-+ 	if (ret)
-+-		ath10k_warn("failed to update channel list: %d\n", ret);
-++		ath10k_warn(ar, "failed to update channel list: %d\n", ret);
-+ 
-+ 	regpair = ar->ath_common.regulatory.regpair;
-+ 
-+@@ -1803,7 +2238,7 @@ static void ath10k_regd_update(struct at
-+ 					    regpair->reg_5ghz_ctl,
-+ 					    wmi_dfs_reg);
-+ 	if (ret)
-+-		ath10k_warn("failed to set pdev regdomain: %d\n", ret);
-++		ath10k_warn(ar, "failed to set pdev regdomain: %d\n", ret);
-+ }
-+ 
-+ static void ath10k_reg_notifier(struct wiphy *wiphy,
-+@@ -1816,12 +2251,12 @@ static void ath10k_reg_notifier(struct w
-+ 	ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
-+ 
-+ 	if (config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
-+-		ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
-++		ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
-+ 			   request->dfs_region);
-+ 		result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector,
-+ 							  request->dfs_region);
-+ 		if (!result)
-+-			ath10k_warn("DFS region 0x%X not supported, will trigger radar for every pulse\n",
-++			ath10k_warn(ar, "DFS region 0x%X not supported, will trigger radar for every pulse\n",
-+ 				    request->dfs_region);
-+ 	}
-+ 
-+@@ -1849,28 +2284,25 @@ static u8 ath10k_tx_h_get_tid(struct iee
-+ 	return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-+ }
-+ 
-+-static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar,
-+-				  struct ieee80211_tx_info *info)
-++static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
-+ {
-+-	if (info->control.vif)
-+-		return ath10k_vif_to_arvif(info->control.vif)->vdev_id;
-++	if (vif)
-++		return ath10k_vif_to_arvif(vif)->vdev_id;
-+ 
-+ 	if (ar->monitor_started)
-+ 		return ar->monitor_vdev_id;
-+ 
-+-	ath10k_warn("failed to resolve vdev id\n");
-++	ath10k_warn(ar, "failed to resolve vdev id\n");
-+ 	return 0;
-+ }
-+ 
-+-/*
-+- * Frames sent to the FW have to be in "Native Wifi" format.
-+- * Strip the QoS field from the 802.11 header.
-++/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
-++ * Control in the header.
-+  */
-+-static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw,
-+-				       struct ieee80211_tx_control *control,
-+-				       struct sk_buff *skb)
-++static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
-+ {
-+ 	struct ieee80211_hdr *hdr = (void *)skb->data;
-++	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
-+ 	u8 *qos_ctl;
-+ 
-+ 	if (!ieee80211_is_data_qos(hdr->frame_control))
-+@@ -1880,68 +2312,24 @@ static void ath10k_tx_h_qos_workaround(s
-+ 	memmove(skb->data + IEEE80211_QOS_CTL_LEN,
-+ 		skb->data, (void *)qos_ctl - (void *)skb->data);
-+ 	skb_pull(skb, IEEE80211_QOS_CTL_LEN);
-+-}
-+-
-+-static void ath10k_tx_wep_key_work(struct work_struct *work)
-+-{
-+-	struct ath10k_vif *arvif = container_of(work, struct ath10k_vif,
-+-						wep_key_work);
-+-	int ret, keyidx = arvif->def_wep_key_newidx;
-+-
-+-	if (arvif->def_wep_key_idx == keyidx)
-+-		return;
-+-
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n",
-+-		   arvif->vdev_id, keyidx);
-+ 
-+-	ret = ath10k_wmi_vdev_set_param(arvif->ar,
-+-					arvif->vdev_id,
-+-					arvif->ar->wmi.vdev_param->def_keyid,
-+-					keyidx);
-+-	if (ret) {
-+-		ath10k_warn("failed to update wep key index for vdev %d: %d\n",
-+-			    arvif->vdev_id,
-+-			    ret);
-+-		return;
-++	/* Fw/Hw generates a corrupted QoS Control Field for QoS NullFunc
-++	 * frames. Powersave is handled by the fw/hw so QoS NyllFunc frames are
-++	 * used only for CQM purposes (e.g. hostapd station keepalive ping) so
-++	 * it is safe to downgrade to NullFunc.
-++	 */
-++	hdr = (void *)skb->data;
-++	if (ieee80211_is_qos_nullfunc(hdr->frame_control)) {
-++		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
-++		cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
-+ 	}
-+-
-+-	arvif->def_wep_key_idx = keyidx;
-+ }
-+ 
-+-static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
-+-{
-+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+-	struct ieee80211_vif *vif = info->control.vif;
-+-	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+-	struct ath10k *ar = arvif->ar;
-+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+-	struct ieee80211_key_conf *key = info->control.hw_key;
-+-
-+-	if (!ieee80211_has_protected(hdr->frame_control))
-+-		return;
-+-
-+-	if (!key)
-+-		return;
-+-
-+-	if (key->cipher != WLAN_CIPHER_SUITE_WEP40 &&
-+-	    key->cipher != WLAN_CIPHER_SUITE_WEP104)
-+-		return;
-+-
-+-	if (key->keyidx == arvif->def_wep_key_idx)
-+-		return;
-+-
-+-	/* FIXME: Most likely a few frames will be TXed with an old key. Simply
-+-	 * queueing frames until key index is updated is not an option because
-+-	 * sk_buff may need more processing to be done, e.g. offchannel */
-+-	arvif->def_wep_key_newidx = key->keyidx;
-+-	ieee80211_queue_work(ar->hw, &arvif->wep_key_work);
-+-}
-+-
-+-static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb)
-++static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
-++				       struct ieee80211_vif *vif,
-++				       struct sk_buff *skb)
-+ {
-+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+-	struct ieee80211_vif *vif = info->control.vif;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 
-+ 	/* This is case only for P2P_GO */
-+@@ -1961,6 +2349,18 @@ static void ath10k_tx_h_add_p2p_noa_ie(s
-+ 	}
-+ }
-+ 
-++static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
-++{
-++	/* FIXME: Not really sure since when the behaviour changed. At some
-++	 * point new firmware stopped requiring creation of peer entries for
-++	 * offchannel tx (and actually creating them causes issues with wmi-htc
-++	 * tx credit replenishment and reliability). Assuming it's at least 3.4
-++	 * because that's when the `freq` was introduced to TX_FRM HTT command.
-++	 */
-++	return !(ar->htt.target_version_major >= 3 &&
-++		 ar->htt.target_version_minor >= 4);
-++}
-++
-+ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+@@ -1977,7 +2377,7 @@ static void ath10k_tx_htt(struct ath10k
-+ 			     ar->fw_features)) {
-+ 			if (skb_queue_len(&ar->wmi_mgmt_tx_queue) >=
-+ 			    ATH10K_MAX_NUM_MGMT_PENDING) {
-+-				ath10k_warn("reached WMI management tranmist queue limit\n");
-++				ath10k_warn(ar, "reached WMI management transmit queue limit\n");
-+ 				ret = -EBUSY;
-+ 				goto exit;
-+ 			}
-+@@ -2001,7 +2401,8 @@ static void ath10k_tx_htt(struct ath10k
-+ 
-+ exit:
-+ 	if (ret) {
-+-		ath10k_warn("failed to transmit packet, dropping: %d\n", ret);
-++		ath10k_warn(ar, "failed to transmit packet, dropping: %d\n",
-++			    ret);
-+ 		ieee80211_free_txskb(ar->hw, skb);
-+ 	}
-+ }
-+@@ -2043,7 +2444,7 @@ void ath10k_offchan_tx_work(struct work_
-+ 
-+ 		mutex_lock(&ar->conf_mutex);
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac offchannel skb %p\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %p\n",
-+ 			   skb);
-+ 
-+ 		hdr = (struct ieee80211_hdr *)skb->data;
-+@@ -2056,13 +2457,13 @@ void ath10k_offchan_tx_work(struct work_
-+ 
-+ 		if (peer)
-+ 			/* FIXME: should this use ath10k_warn()? */
-+-			ath10k_dbg(ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n",
-++			ath10k_dbg(ar, ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n",
-+ 				   peer_addr, vdev_id);
-+ 
-+ 		if (!peer) {
-+ 			ret = ath10k_peer_create(ar, vdev_id, peer_addr);
-+ 			if (ret)
-+-				ath10k_warn("failed to create peer %pM on vdev %d: %d\n",
-++				ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n",
-+ 					    peer_addr, vdev_id, ret);
-+ 		}
-+ 
-+@@ -2075,14 +2476,14 @@ void ath10k_offchan_tx_work(struct work_
-+ 
-+ 		ret = wait_for_completion_timeout(&ar->offchan_tx_completed,
-+ 						  3 * HZ);
-+-		if (ret <= 0)
-+-			ath10k_warn("timed out waiting for offchannel skb %p\n",
-++		if (ret == 0)
-++			ath10k_warn(ar, "timed out waiting for offchannel skb %p\n",
-+ 				    skb);
-+ 
-+ 		if (!peer) {
-+ 			ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
-+ 			if (ret)
-+-				ath10k_warn("failed to delete peer %pM on vdev %d: %d\n",
-++				ath10k_warn(ar, "failed to delete peer %pM on vdev %d: %d\n",
-+ 					    peer_addr, vdev_id, ret);
-+ 		}
-+ 
-+@@ -2116,7 +2517,7 @@ void ath10k_mgmt_over_wmi_tx_work(struct
-+ 
-+ 		ret = ath10k_wmi_mgmt_tx(ar, skb);
-+ 		if (ret) {
-+-			ath10k_warn("failed to transmit management frame via WMI: %d\n",
-++			ath10k_warn(ar, "failed to transmit management frame via WMI: %d\n",
-+ 				    ret);
-+ 			ieee80211_free_txskb(ar->hw, skb);
-+ 		}
-+@@ -2127,34 +2528,41 @@ void ath10k_mgmt_over_wmi_tx_work(struct
-+ /* Scanning */
-+ /************/
-+ 
-+-/*
-+- * This gets called if we dont get a heart-beat during scan.
-+- * This may indicate the FW has hung and we need to abort the
-+- * scan manually to prevent cancel_hw_scan() from deadlocking
-+- */
-+-void ath10k_reset_scan(unsigned long ptr)
-++void __ath10k_scan_finish(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar = (struct ath10k *)ptr;
-+-
-+-	spin_lock_bh(&ar->data_lock);
-+-	if (!ar->scan.in_progress) {
-+-		spin_unlock_bh(&ar->data_lock);
-+-		return;
-+-	}
-++	lockdep_assert_held(&ar->data_lock);
-+ 
-+-	ath10k_warn("scan timed out, firmware problem?\n");
-+-
-+-	if (ar->scan.is_roc)
-+-		ieee80211_remain_on_channel_expired(ar->hw);
-+-	else
-+-		ieee80211_scan_completed(ar->hw, 1 /* aborted */);
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++		break;
-++	case ATH10K_SCAN_RUNNING:
-++		if (ar->scan.is_roc)
-++			ieee80211_remain_on_channel_expired(ar->hw);
-++		/* fall through */
-++	case ATH10K_SCAN_ABORTING:
-++		if (!ar->scan.is_roc)
-++			ieee80211_scan_completed(ar->hw,
-++						 (ar->scan.state ==
-++						  ATH10K_SCAN_ABORTING));
-++		/* fall through */
-++	case ATH10K_SCAN_STARTING:
-++		ar->scan.state = ATH10K_SCAN_IDLE;
-++		ar->scan_channel = NULL;
-++		ath10k_offchan_tx_purge(ar);
-++		cancel_delayed_work(&ar->scan.timeout);
-++		complete_all(&ar->scan.completed);
-++		break;
-++	}
-++}
-+ 
-+-	ar->scan.in_progress = false;
-+-	complete_all(&ar->scan.completed);
-++void ath10k_scan_finish(struct ath10k *ar)
-++{
-++	spin_lock_bh(&ar->data_lock);
-++	__ath10k_scan_finish(ar);
-+ 	spin_unlock_bh(&ar->data_lock);
-+ }
-+ 
-+-static int ath10k_abort_scan(struct ath10k *ar)
-++static int ath10k_scan_stop(struct ath10k *ar)
-+ {
-+ 	struct wmi_stop_scan_arg arg = {
-+ 		.req_id = 1, /* FIXME */
-+@@ -2165,47 +2573,79 @@ static int ath10k_abort_scan(struct ath1
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	del_timer_sync(&ar->scan.timeout);
-++	ret = ath10k_wmi_stop_scan(ar, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to stop wmi scan: %d\n", ret);
-++		goto out;
-++	}
-+ 
-+-	spin_lock_bh(&ar->data_lock);
-+-	if (!ar->scan.in_progress) {
-+-		spin_unlock_bh(&ar->data_lock);
-+-		return 0;
-++	ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
-++	if (ret == 0) {
-++		ath10k_warn(ar, "failed to receive scan abortion completion: timed out\n");
-++		ret = -ETIMEDOUT;
-++	} else if (ret > 0) {
-++		ret = 0;
-+ 	}
-+ 
-+-	ar->scan.aborting = true;
-++out:
-++	/* Scan state should be updated upon scan completion but in case
-++	 * firmware fails to deliver the event (for whatever reason) it is
-++	 * desired to clean up scan state anyway. Firmware may have just
-++	 * dropped the scan completion event delivery due to transport pipe
-++	 * being overflown with data and/or it can recover on its own before
-++	 * next scan request is submitted.
-++	 */
-++	spin_lock_bh(&ar->data_lock);
-++	if (ar->scan.state != ATH10K_SCAN_IDLE)
-++		__ath10k_scan_finish(ar);
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-+-	ret = ath10k_wmi_stop_scan(ar, &arg);
-+-	if (ret) {
-+-		ath10k_warn("failed to stop wmi scan: %d\n", ret);
-+-		spin_lock_bh(&ar->data_lock);
-+-		ar->scan.in_progress = false;
-+-		ath10k_offchan_tx_purge(ar);
-+-		spin_unlock_bh(&ar->data_lock);
-+-		return -EIO;
-+-	}
-++	return ret;
-++}
-+ 
-+-	ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ);
-+-	if (ret == 0)
-+-		ath10k_warn("timed out while waiting for scan to stop\n");
-++static void ath10k_scan_abort(struct ath10k *ar)
-++{
-++	int ret;
-+ 
-+-	/* scan completion may be done right after we timeout here, so let's
-+-	 * check the in_progress and tell mac80211 scan is completed. if we
-+-	 * don't do that and FW fails to send us scan completion indication
-+-	 * then userspace won't be able to scan anymore */
-+-	ret = 0;
-++	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+-	if (ar->scan.in_progress) {
-+-		ath10k_warn("failed to stop scan, it's still in progress\n");
-+-		ar->scan.in_progress = false;
-+-		ath10k_offchan_tx_purge(ar);
-+-		ret = -ETIMEDOUT;
-++
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++		/* This can happen if timeout worker kicked in and called
-++		 * abortion while scan completion was being processed.
-++		 */
-++		break;
-++	case ATH10K_SCAN_STARTING:
-++	case ATH10K_SCAN_ABORTING:
-++		ath10k_warn(ar, "refusing scan abortion due to invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-++		break;
-++	case ATH10K_SCAN_RUNNING:
-++		ar->scan.state = ATH10K_SCAN_ABORTING;
-++		spin_unlock_bh(&ar->data_lock);
-++
-++		ret = ath10k_scan_stop(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to abort scan: %d\n", ret);
-++
-++		spin_lock_bh(&ar->data_lock);
-++		break;
-+ 	}
-++
-+ 	spin_unlock_bh(&ar->data_lock);
-++}
-+ 
-+-	return ret;
-++void ath10k_scan_timeout_work(struct work_struct *work)
-++{
-++	struct ath10k *ar = container_of(work, struct ath10k,
-++					 scan.timeout.work);
-++
-++	mutex_lock(&ar->conf_mutex);
-++	ath10k_scan_abort(ar);
-++	mutex_unlock(&ar->conf_mutex);
-+ }
-+ 
-+ static int ath10k_start_scan(struct ath10k *ar,
-+@@ -2221,17 +2661,27 @@ static int ath10k_start_scan(struct ath1
-+ 
-+ 	ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ);
-+ 	if (ret == 0) {
-+-		ath10k_abort_scan(ar);
-+-		return ret;
-++		ret = ath10k_scan_stop(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to stop scan: %d\n", ret);
-++
-++		return -ETIMEDOUT;
-++	}
-++
-++	/* If we failed to start the scan, return error code at
-++	 * this point.  This is probably due to some issue in the
-++	 * firmware, but no need to wedge the driver due to that...
-++	 */
-++	spin_lock_bh(&ar->data_lock);
-++	if (ar->scan.state == ATH10K_SCAN_IDLE) {
-++		spin_unlock_bh(&ar->data_lock);
-++		return -EINVAL;
-+ 	}
-++	spin_unlock_bh(&ar->data_lock);
-+ 
-+-	/* the scan can complete earlier, before we even
-+-	 * start the timer. in that case the timer handler
-+-	 * checks ar->scan.in_progress and bails out if its
-+-	 * false. Add a 200ms margin to account event/command
-+-	 * processing. */
-+-	mod_timer(&ar->scan.timeout, jiffies +
-+-		  msecs_to_jiffies(arg->max_scan_time+200));
-++	/* 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));
-+ 	return 0;
-+ }
-+ 
-+@@ -2243,90 +2693,163 @@ static void ath10k_tx(struct ieee80211_h
-+ 		      struct ieee80211_tx_control *control,
-+ 		      struct sk_buff *skb)
-+ {
-++	struct ath10k *ar = hw->priv;
-+ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-++	struct ieee80211_vif *vif = info->control.vif;
-+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+-	struct ath10k *ar = hw->priv;
-+-	u8 tid, vdev_id;
-+ 
-+ 	/* We should disable CCK RATE due to P2P */
-+ 	if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
-+-		ath10k_dbg(ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
-+ 
-+-	/* we must calculate tid before we apply qos workaround
-+-	 * as we'd lose the qos control field */
-+-	tid = ath10k_tx_h_get_tid(hdr);
-+-	vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
-++	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
-++	ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
-++	ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
-+ 
-+ 	/* it makes no sense to process injected frames like that */
-+-	if (info->control.vif &&
-+-	    info->control.vif->type != NL80211_IFTYPE_MONITOR) {
-+-		ath10k_tx_h_qos_workaround(hw, control, skb);
-+-		ath10k_tx_h_update_wep_key(skb);
-+-		ath10k_tx_h_add_p2p_noa_ie(ar, skb);
-+-		ath10k_tx_h_seq_no(skb);
-++	if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
-++		ath10k_tx_h_nwifi(hw, skb);
-++		ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
-++		ath10k_tx_h_seq_no(vif, skb);
-+ 	}
-+ 
-+-	ATH10K_SKB_CB(skb)->vdev_id = vdev_id;
-+-	ATH10K_SKB_CB(skb)->htt.is_offchan = false;
-+-	ATH10K_SKB_CB(skb)->htt.tid = tid;
-+-
-+ 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
-+ 		spin_lock_bh(&ar->data_lock);
-+-		ATH10K_SKB_CB(skb)->htt.is_offchan = true;
-++		ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
-+ 		ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
-+ 		spin_unlock_bh(&ar->data_lock);
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb);
-++		if (ath10k_mac_need_offchan_tx_work(ar)) {
-++			ATH10K_SKB_CB(skb)->htt.freq = 0;
-++			ATH10K_SKB_CB(skb)->htt.is_offchan = true;
-+ 
-+-		skb_queue_tail(&ar->offchan_tx_queue, skb);
-+-		ieee80211_queue_work(hw, &ar->offchan_tx_work);
-+-		return;
-++			ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
-++				   skb);
-++
-++			skb_queue_tail(&ar->offchan_tx_queue, skb);
-++			ieee80211_queue_work(hw, &ar->offchan_tx_work);
-++			return;
-++		}
-+ 	}
-+ 
-+ 	ath10k_tx_htt(ar, skb);
-+ }
-+ 
-+-/*
-+- * Initialize various parameters with default vaules.
-+- */
-++/* Must not be called with conf_mutex held as workers can use that also. */
-++void ath10k_drain_tx(struct ath10k *ar)
-++{
-++	/* make sure rcu-protected mac80211 tx path itself is drained */
-++	synchronize_net();
-++
-++	ath10k_offchan_tx_purge(ar);
-++	ath10k_mgmt_over_wmi_tx_purge(ar);
-++
-++	cancel_work_sync(&ar->offchan_tx_work);
-++	cancel_work_sync(&ar->wmi_mgmt_tx_work);
-++}
-++
-+ void ath10k_halt(struct ath10k *ar)
-+ {
-+ 	struct ath10k_vif *arvif;
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	if (ath10k_monitor_is_enabled(ar)) {
-+-		clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-+-		ar->promisc = false;
-+-		ar->monitor = false;
-++	clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-++	ar->filter_flags = 0;
-++	ar->monitor = false;
-++
-++	if (ar->monitor_started)
-+ 		ath10k_monitor_stop(ar);
-+-	}
-+ 
-+-	del_timer_sync(&ar->scan.timeout);
-+-	ath10k_offchan_tx_purge(ar);
-+-	ath10k_mgmt_over_wmi_tx_purge(ar);
-++	ar->monitor_started = false;
-++
-++	ath10k_scan_finish(ar);
-+ 	ath10k_peer_cleanup_all(ar);
-+ 	ath10k_core_stop(ar);
-+ 	ath10k_hif_power_down(ar);
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+-	if (ar->scan.in_progress) {
-+-		del_timer(&ar->scan.timeout);
-+-		ar->scan.in_progress = false;
-+-		ieee80211_scan_completed(ar->hw, true);
-++	list_for_each_entry(arvif, &ar->arvifs, list)
-++		ath10k_mac_vif_beacon_cleanup(arvif);
-++	spin_unlock_bh(&ar->data_lock);
-++}
-++
-++static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
-++{
-++	struct ath10k *ar = hw->priv;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->cfg_tx_chainmask) {
-++		*tx_ant = ar->cfg_tx_chainmask;
-++		*rx_ant = ar->cfg_rx_chainmask;
-++	} else {
-++		*tx_ant = ar->supp_tx_chainmask;
-++		*rx_ant = ar->supp_rx_chainmask;
-+ 	}
-+ 
-+-	list_for_each_entry(arvif, &ar->arvifs, list) {
-+-		if (!arvif->beacon)
-+-			continue;
-++	mutex_unlock(&ar->conf_mutex);
-+ 
-+-		dma_unmap_single(arvif->ar->dev,
-+-				 ATH10K_SKB_CB(arvif->beacon)->paddr,
-+-				 arvif->beacon->len, DMA_TO_DEVICE);
-+-		dev_kfree_skb_any(arvif->beacon);
-+-		arvif->beacon = NULL;
-++	return 0;
-++}
-++
-++static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg)
-++{
-++	/* It is not clear that allowing gaps in chainmask
-++	 * is helpful.  Probably it will not do what user
-++	 * is hoping for, so warn in that case.
-++	 */
-++	if (cm == 15 || cm == 7 || cm == 3 || cm == 1 || cm == 0)
-++		return;
-++
-++	ath10k_warn(ar, "mac %s antenna chainmask may be invalid: 0x%x.  Suggested values: 15, 7, 3, 1 or 0.\n",
-++		    dbg, cm);
-++}
-++
-++static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
-++{
-++	int ret;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	ath10k_check_chain_mask(ar, tx_ant, "tx");
-++	ath10k_check_chain_mask(ar, rx_ant, "rx");
-++
-++	ar->cfg_tx_chainmask = tx_ant;
-++	ar->cfg_rx_chainmask = rx_ant;
-++
-++	if ((ar->state != ATH10K_STATE_ON) &&
-++	    (ar->state != ATH10K_STATE_RESTARTED))
-++		return 0;
-++
-++	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_chain_mask,
-++					tx_ant);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set tx-chainmask: %d, req 0x%x\n",
-++			    ret, tx_ant);
-++		return ret;
-+ 	}
-+-	spin_unlock_bh(&ar->data_lock);
-++
-++	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rx_chain_mask,
-++					rx_ant);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set rx-chainmask: %d, req 0x%x\n",
-++			    ret, rx_ant);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
-++{
-++	struct ath10k *ar = hw->priv;
-++	int ret;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	ret = __ath10k_set_antenna(ar, tx_ant, rx_ant);
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-+ }
-+ 
-+ static int ath10k_start(struct ieee80211_hw *hw)
-+@@ -2334,41 +2857,61 @@ static int ath10k_start(struct ieee80211
-+ 	struct ath10k *ar = hw->priv;
-+ 	int ret = 0;
-+ 
-++	/*
-++	 * This makes sense only when restarting hw. It is harmless to call
-++	 * uncoditionally. This is necessary to make sure no HTT/WMI tx
-++	 * commands will be submitted while restarting.
-++	 */
-++	ath10k_drain_tx(ar);
-++
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+-	if (ar->state != ATH10K_STATE_OFF &&
-+-	    ar->state != ATH10K_STATE_RESTARTING) {
-++	switch (ar->state) {
-++	case ATH10K_STATE_OFF:
-++		ar->state = ATH10K_STATE_ON;
-++		break;
-++	case ATH10K_STATE_RESTARTING:
-++		ath10k_halt(ar);
-++		ar->state = ATH10K_STATE_RESTARTED;
-++		break;
-++	case ATH10K_STATE_ON:
-++	case ATH10K_STATE_RESTARTED:
-++	case ATH10K_STATE_WEDGED:
-++		WARN_ON(1);
-+ 		ret = -EINVAL;
-+-		goto exit;
-++		goto err;
-++	case ATH10K_STATE_UTF:
-++		ret = -EBUSY;
-++		goto err;
-+ 	}
-+ 
-+ 	ret = ath10k_hif_power_up(ar);
-+ 	if (ret) {
-+-		ath10k_err("Could not init hif: %d\n", ret);
-+-		ar->state = ATH10K_STATE_OFF;
-+-		goto exit;
-++		ath10k_err(ar, "Could not init hif: %d\n", ret);
-++		goto err_off;
-+ 	}
-+ 
-+-	ret = ath10k_core_start(ar);
-++	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
-+ 	if (ret) {
-+-		ath10k_err("Could not init core: %d\n", ret);
-+-		ath10k_hif_power_down(ar);
-+-		ar->state = ATH10K_STATE_OFF;
-+-		goto exit;
-++		ath10k_err(ar, "Could not init core: %d\n", ret);
-++		goto err_power_down;
-+ 	}
-+ 
-+-	if (ar->state == ATH10K_STATE_OFF)
-+-		ar->state = ATH10K_STATE_ON;
-+-	else if (ar->state == ATH10K_STATE_RESTARTING)
-+-		ar->state = ATH10K_STATE_RESTARTED;
-+-
-+ 	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1);
-+-	if (ret)
-+-		ath10k_warn("failed to enable PMF QOS: %d\n", ret);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to enable PMF QOS: %d\n", ret);
-++		goto err_core_stop;
-++	}
-+ 
-+ 	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1);
-+-	if (ret)
-+-		ath10k_warn("failed to enable dynamic BW: %d\n", ret);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to enable dynamic BW: %d\n", ret);
-++		goto err_core_stop;
-++	}
-++
-++	if (ar->cfg_tx_chainmask)
-++		__ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
-++				     ar->cfg_rx_chainmask);
-+ 
-+ 	/*
-+ 	 * By default FW set ARP frames ac to voice (6). In that case ARP
-+@@ -2382,16 +2925,29 @@ static int ath10k_start(struct ieee80211
-+ 	ret = ath10k_wmi_pdev_set_param(ar,
-+ 					ar->wmi.pdev_param->arp_ac_override, 0);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set arp ac override parameter: %d\n",
-++		ath10k_warn(ar, "failed to set arp ac override parameter: %d\n",
-+ 			    ret);
-+-		goto exit;
-++		goto err_core_stop;
-+ 	}
-+ 
-+ 	ar->num_started_vdevs = 0;
-+ 	ath10k_regd_update(ar);
-+-	ret = 0;
-+ 
-+-exit:
-++	ath10k_spectral_start(ar);
-++
-++	mutex_unlock(&ar->conf_mutex);
-++	return 0;
-++
-++err_core_stop:
-++	ath10k_core_stop(ar);
-++
-++err_power_down:
-++	ath10k_hif_power_down(ar);
-++
-++err_off:
-++	ar->state = ATH10K_STATE_OFF;
-++
-++err:
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 	return ret;
-+ }
-+@@ -2400,19 +2956,16 @@ static void ath10k_stop(struct ieee80211
-+ {
-+ 	struct ath10k *ar = hw->priv;
-+ 
-++	ath10k_drain_tx(ar);
-++
-+ 	mutex_lock(&ar->conf_mutex);
-+-	if (ar->state == ATH10K_STATE_ON ||
-+-	    ar->state == ATH10K_STATE_RESTARTED ||
-+-	    ar->state == ATH10K_STATE_WEDGED)
-++	if (ar->state != ATH10K_STATE_OFF) {
-+ 		ath10k_halt(ar);
-+-
-+-	ar->state = ATH10K_STATE_OFF;
-++		ar->state = ATH10K_STATE_OFF;
-++	}
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 
-+-	ath10k_mgmt_over_wmi_tx_purge(ar);
-+-
-+-	cancel_work_sync(&ar->offchan_tx_work);
-+-	cancel_work_sync(&ar->wmi_mgmt_tx_work);
-++	cancel_delayed_work_sync(&ar->scan.timeout);
-+ 	cancel_work_sync(&ar->restart_work);
-+ }
-+ 
-+@@ -2426,7 +2979,7 @@ static int ath10k_config_ps(struct ath10
-+ 	list_for_each_entry(arvif, &ar->arvifs, list) {
-+ 		ret = ath10k_mac_vif_setup_ps(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to setup powersave: %d\n", ret);
-++			ath10k_warn(ar, "failed to setup powersave: %d\n", ret);
-+ 			break;
-+ 		}
-+ 	}
-+@@ -2464,7 +3017,7 @@ static void ath10k_config_chan(struct at
-+ 
-+ 	lockdep_assert_held(&ar->conf_mutex);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC,
-++	ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 		   "mac config channel to %dMHz (cf1 %dMHz cf2 %dMHz width %s)\n",
-+ 		   ar->chandef.chan->center_freq,
-+ 		   ar->chandef.center_freq1,
-+@@ -2474,24 +3027,27 @@ static void ath10k_config_chan(struct at
-+ 	/* First stop monitor interface. Some FW versions crash if there's a
-+ 	 * lone monitor interface. */
-+ 	if (ar->monitor_started)
-+-		ath10k_monitor_vdev_stop(ar);
-++		ath10k_monitor_stop(ar);
-+ 
-+ 	list_for_each_entry(arvif, &ar->arvifs, list) {
-+ 		if (!arvif->is_started)
-+ 			continue;
-+ 
-++		if (!arvif->is_up)
-++			continue;
-++
-+ 		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-+ 			continue;
-+ 
-+-		ret = ath10k_vdev_stop(arvif);
-++		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-+ 		if (ret) {
-+-			ath10k_warn("failed to stop vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to down vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			continue;
-+ 		}
-+ 	}
-+ 
-+-	/* all vdevs are now stopped - now attempt to restart them */
-++	/* all vdevs are downed now - attempt to restart and re-up them */
-+ 
-+ 	list_for_each_entry(arvif, &ar->arvifs, list) {
-+ 		if (!arvif->is_started)
-+@@ -2500,9 +3056,9 @@ static void ath10k_config_chan(struct at
-+ 		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-+ 			continue;
-+ 
-+-		ret = ath10k_vdev_start(arvif);
-++		ret = ath10k_vdev_restart(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to start vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to restart vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			continue;
-+ 		}
-+@@ -2513,14 +3069,70 @@ static void ath10k_config_chan(struct at
-+ 		ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
-+ 					 arvif->bssid);
-+ 		if (ret) {
-+-			ath10k_warn("failed to bring vdev up %d: %d\n",
-++			ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			continue;
-+ 		}
-+ 	}
-+ 
-+-	if (ath10k_monitor_is_enabled(ar))
-+-		ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
-++	ath10k_monitor_recalc(ar);
-++}
-++
-++static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
-++{
-++	int ret;
-++	u32 param;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower);
-++
-++	param = ar->wmi.pdev_param->txpower_limit2g;
-++	ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
-++			    txpower, ret);
-++		return ret;
-++	}
-++
-++	param = ar->wmi.pdev_param->txpower_limit5g;
-++	ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
-++			    txpower, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_mac_txpower_recalc(struct ath10k *ar)
-++{
-++	struct ath10k_vif *arvif;
-++	int ret, txpower = -1;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	list_for_each_entry(arvif, &ar->arvifs, list) {
-++		WARN_ON(arvif->txpower < 0);
-++
-++		if (txpower == -1)
-++			txpower = arvif->txpower;
-++		else
-++			txpower = min(txpower, arvif->txpower);
-++	}
-++
-++	if (WARN_ON(txpower == -1))
-++		return -EINVAL;
-++
-++	ret = ath10k_mac_txpower_setup(ar, txpower);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to setup tx power %d: %d\n",
-++			    txpower, ret);
-++		return ret;
-++	}
-++
-++	return 0;
-+ }
-+ 
-+ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
-+@@ -2528,12 +3140,11 @@ static int ath10k_config(struct ieee8021
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ieee80211_conf *conf = &hw->conf;
-+ 	int ret = 0;
-+-	u32 param;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "mac config channel %dMHz flags 0x%x radar %d\n",
-+ 			   conf->chandef.chan->center_freq,
-+ 			   conf->chandef.chan->flags,
-+@@ -2552,48 +3163,31 @@ static int ath10k_config(struct ieee8021
-+ 		}
-+ 	}
-+ 
-+-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac config power %d\n",
-+-			   hw->conf.power_level);
-+-
-+-		param = ar->wmi.pdev_param->txpower_limit2g;
-+-		ret = ath10k_wmi_pdev_set_param(ar, param,
-+-						hw->conf.power_level * 2);
-+-		if (ret)
-+-			ath10k_warn("failed to set 2g txpower %d: %d\n",
-+-				    hw->conf.power_level, ret);
-+-
-+-		param = ar->wmi.pdev_param->txpower_limit5g;
-+-		ret = ath10k_wmi_pdev_set_param(ar, param,
-+-						hw->conf.power_level * 2);
-+-		if (ret)
-+-			ath10k_warn("failed to set 5g txpower %d: %d\n",
-+-				    hw->conf.power_level, ret);
-+-	}
-+-
-+ 	if (changed & IEEE80211_CONF_CHANGE_PS)
-+ 		ath10k_config_ps(ar);
-+ 
-+ 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-+-		if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) {
-+-			ar->monitor = true;
-+-			ret = ath10k_monitor_start(ar);
-+-			if (ret) {
-+-				ath10k_warn("failed to start monitor (config): %d\n",
-+-					    ret);
-+-				ar->monitor = false;
-+-			}
-+-		} else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
-+-			   ar->monitor) {
-+-			ar->monitor = false;
-+-			ath10k_monitor_stop(ar);
-+-		}
-++		ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
-++		ret = ath10k_monitor_recalc(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
-+ 	}
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 	return ret;
-+ }
-+ 
-++static u32 get_nss_from_chainmask(u16 chain_mask)
-++{
-++	if ((chain_mask & 0x15) == 0x15)
-++		return 4;
-++	else if ((chain_mask & 0x7) == 0x7)
-++		return 3;
-++	else if ((chain_mask & 0x3) == 0x3)
-++		return 2;
-++	return 1;
-++}
-++
-+ /*
-+  * TODO:
-+  * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
-+@@ -2619,22 +3213,26 @@ static int ath10k_add_interface(struct i
-+ 	arvif->ar = ar;
-+ 	arvif->vif = vif;
-+ 
-+-	INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work);
-+ 	INIT_LIST_HEAD(&arvif->list);
-+ 
-+-	bit = ffs(ar->free_vdev_map);
-+-	if (bit == 0) {
-++	if (ar->free_vdev_map == 0) {
-++		ath10k_warn(ar, "Free vdev map is empty, no more interfaces allowed.\n");
-+ 		ret = -EBUSY;
-+ 		goto err;
-+ 	}
-++	bit = __ffs64(ar->free_vdev_map);
-+ 
-+-	arvif->vdev_id = bit - 1;
-+-	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n",
-++		   bit, ar->free_vdev_map);
-+ 
-+-	if (ar->p2p)
-+-		arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
-++	arvif->vdev_id = bit;
-++	arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
-+ 
-+ 	switch (vif->type) {
-++	case NL80211_IFTYPE_P2P_DEVICE:
-++		arvif->vdev_type = WMI_VDEV_TYPE_STA;
-++		arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
-++		break;
-+ 	case NL80211_IFTYPE_UNSPECIFIED:
-+ 	case NL80211_IFTYPE_STATION:
-+ 		arvif->vdev_type = WMI_VDEV_TYPE_STA;
-+@@ -2658,50 +3256,98 @@ static int ath10k_add_interface(struct i
-+ 		break;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n",
-+-		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype);
-++	/* Some firmware revisions don't wait for beacon tx completion before
-++	 * sending another SWBA event. This could lead to hardware using old
-++	 * (freed) beacon data in some cases, e.g. tx credit starvation
-++	 * combined with missed TBTT. This is very very rare.
-++	 *
-++	 * On non-IOMMU-enabled hosts this could be a possible security issue
-++	 * because hw could beacon some random data on the air.  On
-++	 * IOMMU-enabled hosts DMAR faults would occur in most cases and target
-++	 * device would crash.
-++	 *
-++	 * Since there are no beacon tx completions (implicit nor explicit)
-++	 * propagated to host the only workaround for this is to allocate a
-++	 * DMA-coherent buffer for a lifetime of a vif and use it for all
-++	 * beacon tx commands. Worst case for this approach is some beacons may
-++	 * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
-++	 */
-++	if (vif->type == NL80211_IFTYPE_ADHOC ||
-++	    vif->type == NL80211_IFTYPE_AP) {
-++		arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
-++							IEEE80211_MAX_FRAME_LEN,
-++							&arvif->beacon_paddr,
-++							GFP_ATOMIC);
-++		if (!arvif->beacon_buf) {
-++			ret = -ENOMEM;
-++			ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
-++				    ret);
-++			goto err;
-++		}
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
-++		   arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
-++		   arvif->beacon_buf ? "single-buf" : "per-skb");
-+ 
-+ 	ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type,
-+ 				     arvif->vdev_subtype, vif->addr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to create WMI vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to create WMI vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		goto err;
-+ 	}
-+ 
-+-	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
-++	ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
-+ 	list_add(&arvif->list, &ar->arvifs);
-+ 
-+-	vdev_param = ar->wmi.vdev_param->def_keyid;
-+-	ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param,
-+-					arvif->def_wep_key_idx);
-++	/* It makes no sense to have firmware do keepalives. mac80211 already
-++	 * takes care of this with idle connection polling.
-++	 */
-++	ret = ath10k_mac_vif_disable_keepalive(arvif);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set vdev %i default key id: %d\n",
-++		ath10k_warn(ar, "failed to disable keepalive on vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		goto err_vdev_delete;
-+ 	}
-+ 
-++	arvif->def_wep_key_idx = -1;
-++
-+ 	vdev_param = ar->wmi.vdev_param->tx_encap_type;
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 					ATH10K_HW_TXRX_NATIVE_WIFI);
-+ 	/* 10.X firmware does not support this VDEV parameter. Do not warn */
-+ 	if (ret && ret != -EOPNOTSUPP) {
-+-		ath10k_warn("failed to set vdev %i TX encapsulation: %d\n",
-++		ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		goto err_vdev_delete;
-+ 	}
-+ 
-++	if (ar->cfg_tx_chainmask) {
-++		u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-++
-++		vdev_param = ar->wmi.vdev_param->nss;
-++		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-++						nss);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
-++				    arvif->vdev_id, ar->cfg_tx_chainmask, nss,
-++				    ret);
-++			goto err_vdev_delete;
-++		}
-++	}
-++
-+ 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
-+ 		ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
-+ 		if (ret) {
-+-			ath10k_warn("failed to create vdev %i peer for AP: %d\n",
-++			ath10k_warn(ar, "failed to create vdev %i peer for AP: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			goto err_vdev_delete;
-+ 		}
-+ 
-+ 		ret = ath10k_mac_set_kickout(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set vdev %i kickout parameters: %d\n",
-++			ath10k_warn(ar, "failed to set vdev %i kickout parameters: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			goto err_peer_delete;
-+ 		}
-+@@ -2713,27 +3359,21 @@ static int ath10k_add_interface(struct i
-+ 		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-+ 						  param, value);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set vdev %i RX wake policy: %d\n",
-++			ath10k_warn(ar, "failed to set vdev %i RX wake policy: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			goto err_peer_delete;
-+ 		}
-+ 
-+-		param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
-+-		value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
-+-		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-+-						  param, value);
-++		ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set vdev %i TX wake thresh: %d\n",
-++			ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			goto err_peer_delete;
-+ 		}
-+ 
-+-		param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
-+-		value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
-+-		ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
-+-						  param, value);
-++		ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set vdev %i PSPOLL count: %d\n",
-++			ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			goto err_peer_delete;
-+ 		}
-+@@ -2741,15 +3381,22 @@ static int ath10k_add_interface(struct i
-+ 
-+ 	ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set rts threshold for vdev %d: %d\n",
-++		ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
-++			    arvif->vdev_id, ret);
-++		goto err_peer_delete;
-++	}
-++
-++	ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set frag threshold for vdev %d: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 		goto err_peer_delete;
-+ 	}
-+ 
-+-	ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
-++	arvif->txpower = vif->bss_conf.txpower;
-++	ret = ath10k_mac_txpower_recalc(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set frag threshold for vdev %d: %d\n",
-+-			    arvif->vdev_id, ret);
-++		ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
-+ 		goto err_peer_delete;
-+ 	}
-+ 
-+@@ -2762,10 +3409,16 @@ err_peer_delete:
-+ 
-+ err_vdev_delete:
-+ 	ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
-+-	ar->free_vdev_map &= ~BIT(arvif->vdev_id);
-++	ar->free_vdev_map |= 1LL << arvif->vdev_id;
-+ 	list_del(&arvif->list);
-+ 
-+ err:
-++	if (arvif->beacon_buf) {
-++		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-++				  arvif->beacon_buf, arvif->beacon_paddr);
-++		arvif->beacon_buf = NULL;
-++	}
-++
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 
-+ 	return ret;
-+@@ -2780,38 +3433,51 @@ static void ath10k_remove_interface(stru
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+-	cancel_work_sync(&arvif->wep_key_work);
-+-
-+ 	spin_lock_bh(&ar->data_lock);
-+-	if (arvif->beacon) {
-+-		dma_unmap_single(arvif->ar->dev,
-+-				 ATH10K_SKB_CB(arvif->beacon)->paddr,
-+-				 arvif->beacon->len, DMA_TO_DEVICE);
-+-		dev_kfree_skb_any(arvif->beacon);
-+-		arvif->beacon = NULL;
-+-	}
-++	ath10k_mac_vif_beacon_cleanup(arvif);
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-+-	ar->free_vdev_map |= 1 << (arvif->vdev_id);
-++	ret = ath10k_spectral_vif_stop(arvif);
-++	if (ret)
-++		ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++
-++	ar->free_vdev_map |= 1LL << arvif->vdev_id;
-+ 	list_del(&arvif->list);
-+ 
-+ 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
-+-		ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr);
-++		ret = ath10k_wmi_peer_delete(arvif->ar, arvif->vdev_id,
-++					     vif->addr);
-+ 		if (ret)
-+-			ath10k_warn("failed to remove peer for AP vdev %i: %d\n",
-++			ath10k_warn(ar, "failed to submit AP self-peer removal on vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 
-+ 		kfree(arvif->u.ap.noa_data);
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %i delete (remove interface)\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i delete (remove interface)\n",
-+ 		   arvif->vdev_id);
-+ 
-+ 	ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
-+ 	if (ret)
-+-		ath10k_warn("failed to delete WMI vdev %i: %d\n",
-++		ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ 
-++	/* Some firmware revisions don't notify host about self-peer removal
-++	 * until after associated vdev is deleted.
-++	 */
-++	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
-++		ret = ath10k_wait_for_peer_deleted(ar, arvif->vdev_id,
-++						   vif->addr);
-++		if (ret)
-++			ath10k_warn(ar, "failed to remove AP self-peer on vdev %i: %d\n",
-++				    arvif->vdev_id, ret);
-++
-++		spin_lock_bh(&ar->data_lock);
-++		ar->num_peers--;
-++		spin_unlock_bh(&ar->data_lock);
-++	}
-++
-+ 	ath10k_peer_cleanup(ar, arvif->vdev_id);
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+@@ -2844,18 +3510,9 @@ static void ath10k_configure_filter(stru
-+ 	*total_flags &= SUPPORTED_FILTERS;
-+ 	ar->filter_flags = *total_flags;
-+ 
-+-	if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) {
-+-		ar->promisc = true;
-+-		ret = ath10k_monitor_start(ar);
-+-		if (ret) {
-+-			ath10k_warn("failed to start monitor (promisc): %d\n",
-+-				    ret);
-+-			ar->promisc = false;
-+-		}
-+-	} else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
-+-		ar->promisc = false;
-+-		ath10k_monitor_stop(ar);
-+-	}
-++	ret = ath10k_monitor_recalc(ar);
-++	if (ret)
-++		ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+ }
-+@@ -2868,7 +3525,7 @@ static void ath10k_bss_info_changed(stru
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	int ret = 0;
-+-	u32 vdev_param, pdev_param;
-++	u32 vdev_param, pdev_param, slottime, preamble;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+@@ -2880,17 +3537,17 @@ static void ath10k_bss_info_changed(stru
-+ 		vdev_param = ar->wmi.vdev_param->beacon_interval;
-+ 		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 						arvif->beacon_interval);
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "mac vdev %d beacon_interval %d\n",
-+ 			   arvif->vdev_id, arvif->beacon_interval);
-+ 
-+ 		if (ret)
-+-			ath10k_warn("failed to set beacon interval for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to set beacon interval for vdev %d: %i\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+ 	if (changed & BSS_CHANGED_BEACON) {
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "vdev %d set beacon tx mode to staggered\n",
-+ 			   arvif->vdev_id);
-+ 
-+@@ -2898,14 +3555,26 @@ static void ath10k_bss_info_changed(stru
-+ 		ret = ath10k_wmi_pdev_set_param(ar, pdev_param,
-+ 						WMI_BEACON_STAGGERED_MODE);
-+ 		if (ret)
-+-			ath10k_warn("failed to set beacon mode for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to set beacon mode for vdev %d: %i\n",
-++				    arvif->vdev_id, ret);
-++
-++		ret = ath10k_mac_setup_bcn_tmpl(arvif);
-++		if (ret)
-++			ath10k_warn(ar, "failed to update beacon template: %d\n",
-++				    ret);
-++	}
-++
-++	if (changed & BSS_CHANGED_AP_PROBE_RESP) {
-++		ret = ath10k_mac_setup_prb_tmpl(arvif);
-++		if (ret)
-++			ath10k_warn(ar, "failed to setup probe resp template on vdev %i: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+-	if (changed & BSS_CHANGED_BEACON_INFO) {
-++	if (changed & (BSS_CHANGED_BEACON_INFO | BSS_CHANGED_BEACON)) {
-+ 		arvif->dtim_period = info->dtim_period;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "mac vdev %d dtim_period %d\n",
-+ 			   arvif->vdev_id, arvif->dtim_period);
-+ 
-+@@ -2913,7 +3582,7 @@ static void ath10k_bss_info_changed(stru
-+ 		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 						arvif->dtim_period);
-+ 		if (ret)
-+-			ath10k_warn("failed to set dtim period for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to set dtim period for vdev %d: %i\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+@@ -2925,91 +3594,48 @@ static void ath10k_bss_info_changed(stru
-+ 		arvif->u.ap.hidden_ssid = info->hidden_ssid;
-+ 	}
-+ 
-+-	if (changed & BSS_CHANGED_BSSID) {
-+-		if (!is_zero_ether_addr(info->bssid)) {
-+-			ath10k_dbg(ATH10K_DBG_MAC,
-+-				   "mac vdev %d create peer %pM\n",
-+-				   arvif->vdev_id, info->bssid);
-+-
-+-			ret = ath10k_peer_create(ar, arvif->vdev_id,
-+-						 info->bssid);
-+-			if (ret)
-+-				ath10k_warn("failed to add peer %pM for vdev %d when changing bssid: %i\n",
-+-					    info->bssid, arvif->vdev_id, ret);
-+-
-+-			if (vif->type == NL80211_IFTYPE_STATION) {
-+-				/*
-+-				 * this is never erased as we it for crypto key
-+-				 * clearing; this is FW requirement
-+-				 */
-+-				memcpy(arvif->bssid, info->bssid, ETH_ALEN);
-+-
-+-				ath10k_dbg(ATH10K_DBG_MAC,
-+-					   "mac vdev %d start %pM\n",
-+-					   arvif->vdev_id, info->bssid);
-+-
-+-				ret = ath10k_vdev_start(arvif);
-+-				if (ret) {
-+-					ath10k_warn("failed to start vdev %i: %d\n",
-+-						    arvif->vdev_id, ret);
-+-					goto exit;
-+-				}
-+-
-+-				arvif->is_started = true;
-+-			}
-+-
-+-			/*
-+-			 * Mac80211 does not keep IBSS bssid when leaving IBSS,
-+-			 * so driver need to store it. It is needed when leaving
-+-			 * IBSS in order to remove BSSID peer.
-+-			 */
-+-			if (vif->type == NL80211_IFTYPE_ADHOC)
-+-				memcpy(arvif->bssid, info->bssid,
-+-				       ETH_ALEN);
-+-		}
-+-	}
-++	if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
-++		ether_addr_copy(arvif->bssid, info->bssid);
-+ 
-+ 	if (changed & BSS_CHANGED_BEACON_ENABLED)
-+ 		ath10k_control_beaconing(arvif, info);
-+ 
-+ 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-+ 		arvif->use_cts_prot = info->use_cts_prot;
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n",
-+ 			   arvif->vdev_id, info->use_cts_prot);
-+ 
-+ 		ret = ath10k_recalc_rtscts_prot(arvif);
-+ 		if (ret)
-+-			ath10k_warn("failed to recalculate rts/cts prot for vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+ 	if (changed & BSS_CHANGED_ERP_SLOT) {
-+-		u32 slottime;
-+ 		if (info->use_short_slot)
-+ 			slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
-+ 
-+ 		else
-+ 			slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d slot_time %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d slot_time %d\n",
-+ 			   arvif->vdev_id, slottime);
-+ 
-+ 		vdev_param = ar->wmi.vdev_param->slot_time;
-+ 		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 						slottime);
-+ 		if (ret)
-+-			ath10k_warn("failed to set erp slot for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to set erp slot for vdev %d: %i\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+ 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-+-		u32 preamble;
-+ 		if (info->use_short_preamble)
-+ 			preamble = WMI_VDEV_PREAMBLE_SHORT;
-+ 		else
-+ 			preamble = WMI_VDEV_PREAMBLE_LONG;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "mac vdev %d preamble %dn",
-+ 			   arvif->vdev_id, preamble);
-+ 
-+@@ -3017,16 +3643,44 @@ static void ath10k_bss_info_changed(stru
-+ 		ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 						preamble);
-+ 		if (ret)
-+-			ath10k_warn("failed to set preamble for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to set preamble for vdev %d: %i\n",
-+ 				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+ 	if (changed & BSS_CHANGED_ASSOC) {
-+-		if (info->assoc)
-++		if (info->assoc) {
-++			/* Workaround: Make sure monitor vdev is not running
-++			 * when associating to prevent some firmware revisions
-++			 * (e.g. 10.1 and 10.2) from crashing.
-++			 */
-++			if (ar->monitor_started)
-++				ath10k_monitor_stop(ar);
-+ 			ath10k_bss_assoc(hw, vif, info);
-++			ath10k_monitor_recalc(ar);
-++		} else {
-++			ath10k_bss_disassoc(hw, vif);
-++		}
-++	}
-++
-++	if (changed & BSS_CHANGED_TXPOWER) {
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n",
-++			   arvif->vdev_id, info->txpower);
-++
-++		arvif->txpower = info->txpower;
-++		ret = ath10k_mac_txpower_recalc(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
-++	}
-++
-++	if (changed & BSS_CHANGED_PS) {
-++		arvif->ps = vif->bss_conf.ps;
-++
-++		ret = ath10k_config_ps(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
-++				    arvif->vdev_id, ret);
-+ 	}
-+ 
-+-exit:
-+ 	mutex_unlock(&ar->conf_mutex);
-+ }
-+ 
-+@@ -3043,20 +3697,26 @@ static int ath10k_hw_scan(struct ieee802
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+-	if (ar->scan.in_progress) {
-+-		spin_unlock_bh(&ar->data_lock);
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++		reinit_completion(&ar->scan.started);
-++		reinit_completion(&ar->scan.completed);
-++		ar->scan.state = ATH10K_SCAN_STARTING;
-++		ar->scan.is_roc = false;
-++		ar->scan.vdev_id = arvif->vdev_id;
-++		ret = 0;
-++		break;
-++	case ATH10K_SCAN_STARTING:
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-+ 		ret = -EBUSY;
-+-		goto exit;
-++		break;
-+ 	}
-+-
-+-	reinit_completion(&ar->scan.started);
-+-	reinit_completion(&ar->scan.completed);
-+-	ar->scan.in_progress = true;
-+-	ar->scan.aborting = false;
-+-	ar->scan.is_roc = false;
-+-	ar->scan.vdev_id = arvif->vdev_id;
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-++	if (ret)
-++		goto exit;
-++
-+ 	memset(&arg, 0, sizeof(arg));
-+ 	ath10k_wmi_start_scan_init(ar, &arg);
-+ 	arg.vdev_id = arvif->vdev_id;
-+@@ -3088,9 +3748,9 @@ static int ath10k_hw_scan(struct ieee802
-+ 
-+ 	ret = ath10k_start_scan(ar, &arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to start hw scan: %d\n", ret);
-++		ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
-+ 		spin_lock_bh(&ar->data_lock);
-+-		ar->scan.in_progress = false;
-++		ar->scan.state = ATH10K_SCAN_IDLE;
-+ 		spin_unlock_bh(&ar->data_lock);
-+ 	}
-+ 
-+@@ -3103,15 +3763,12 @@ static void ath10k_cancel_hw_scan(struct
-+ 				  struct ieee80211_vif *vif)
-+ {
-+ 	struct ath10k *ar = hw->priv;
-+-	int ret;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+-	ret = ath10k_abort_scan(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to abort scan: %d\n", ret);
-+-		ieee80211_scan_completed(hw, 1 /* aborted */);
-+-	}
-++	ath10k_scan_abort(ar);
-+ 	mutex_unlock(&ar->conf_mutex);
-++
-++	cancel_delayed_work_sync(&ar->scan.timeout);
-+ }
-+ 
-+ static void ath10k_set_key_h_def_keyidx(struct ath10k *ar,
-+@@ -3148,7 +3805,7 @@ static void ath10k_set_key_h_def_keyidx(
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-+ 					key->keyidx);
-+ 	if (ret)
-+-		ath10k_warn("failed to set vdev %i group key as default key: %d\n",
-++		ath10k_warn(ar, "failed to set vdev %i group key as default key: %d\n",
-+ 			    arvif->vdev_id, ret);
-+ }
-+ 
-+@@ -3162,6 +3819,7 @@ static int ath10k_set_key(struct ieee802
-+ 	const u8 *peer_addr;
-+ 	bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-+ 		      key->cipher == WLAN_CIPHER_SUITE_WEP104;
-++	bool def_idx = false;
-+ 	int ret = 0;
-+ 
-+ 	if (key->keyidx > WMI_MAX_KEY_INDEX)
-+@@ -3186,7 +3844,7 @@ static int ath10k_set_key(struct ieee802
-+ 
-+ 	if (!peer) {
-+ 		if (cmd == SET_KEY) {
-+-			ath10k_warn("failed to install key for non-existent peer %pM\n",
-++			ath10k_warn(ar, "failed to install key for non-existent peer %pM\n",
-+ 				    peer_addr);
-+ 			ret = -EOPNOTSUPP;
-+ 			goto exit;
-+@@ -3207,9 +3865,16 @@ static int ath10k_set_key(struct ieee802
-+ 			ath10k_clear_vdev_key(arvif, key);
-+ 	}
-+ 
-+-	ret = ath10k_install_key(arvif, key, cmd, peer_addr);
-++	/* set TX_USAGE flag for all the keys incase of dot1x-WEP. For
-++	 * static WEP, do not set this flag for the keys whose key id
-++	 * is  greater than default key id.
-++	 */
-++	if (arvif->def_wep_key_idx == -1)
-++		def_idx = true;
-++
-++	ret = ath10k_install_key(arvif, key, cmd, peer_addr, def_idx);
-+ 	if (ret) {
-+-		ath10k_warn("failed to install key for vdev %i peer %pM: %d\n",
-++		ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n",
-+ 			    arvif->vdev_id, peer_addr, ret);
-+ 		goto exit;
-+ 	}
-+@@ -3224,7 +3889,7 @@ static int ath10k_set_key(struct ieee802
-+ 		peer->keys[key->keyidx] = NULL;
-+ 	else if (peer == NULL)
-+ 		/* impossible unless FW goes crazy */
-+-		ath10k_warn("Peer %pM disappeared!\n", peer_addr);
-++		ath10k_warn(ar, "Peer %pM disappeared!\n", peer_addr);
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-+ exit:
-+@@ -3232,6 +3897,39 @@ exit:
-+ 	return ret;
-+ }
-+ 
-++static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw,
-++					   struct ieee80211_vif *vif,
-++					   int keyidx)
-++{
-++	struct ath10k *ar = hw->priv;
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++	int ret;
-++
-++	mutex_lock(&arvif->ar->conf_mutex);
-++
-++	if (arvif->ar->state != ATH10K_STATE_ON)
-++		goto unlock;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n",
-++		   arvif->vdev_id, keyidx);
-++
-++	ret = ath10k_wmi_vdev_set_param(arvif->ar,
-++					arvif->vdev_id,
-++					arvif->ar->wmi.vdev_param->def_keyid,
-++					keyidx);
-++
-++	if (ret) {
-++		ath10k_warn(ar, "failed to update wep key index for vdev %d: %d\n",
-++			    arvif->vdev_id,
-++			    ret);
-++		goto unlock;
-++	}
-++
-++	arvif->def_wep_key_idx = keyidx;
-++unlock:
-++	mutex_unlock(&arvif->ar->conf_mutex);
-++}
-++
-+ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
-+ {
-+ 	struct ath10k *ar;
-+@@ -3260,51 +3958,83 @@ static void ath10k_sta_rc_update_wk(stru
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	if (changed & IEEE80211_RC_BW_CHANGED) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM peer bw %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM peer bw %d\n",
-+ 			   sta->addr, bw);
-+ 
-+ 		err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-+ 						WMI_PEER_CHAN_WIDTH, bw);
-+ 		if (err)
-+-			ath10k_warn("failed to update STA %pM peer bw %d: %d\n",
-++			ath10k_warn(ar, "failed to update STA %pM peer bw %d: %d\n",
-+ 				    sta->addr, bw, err);
-+ 	}
-+ 
-+ 	if (changed & IEEE80211_RC_NSS_CHANGED) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM nss %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM nss %d\n",
-+ 			   sta->addr, nss);
-+ 
-+ 		err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-+ 						WMI_PEER_NSS, nss);
-+ 		if (err)
-+-			ath10k_warn("failed to update STA %pM nss %d: %d\n",
-++			ath10k_warn(ar, "failed to update STA %pM nss %d: %d\n",
-+ 				    sta->addr, nss, err);
-+ 	}
-+ 
-+ 	if (changed & IEEE80211_RC_SMPS_CHANGED) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM smps %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM smps %d\n",
-+ 			   sta->addr, smps);
-+ 
-+ 		err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-+ 						WMI_PEER_SMPS_STATE, smps);
-+ 		if (err)
-+-			ath10k_warn("failed to update STA %pM smps %d: %d\n",
-++			ath10k_warn(ar, "failed to update STA %pM smps %d: %d\n",
-+ 				    sta->addr, smps, err);
-+ 	}
-+ 
-+-	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
-++	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED ||
-++	    changed & IEEE80211_RC_NSS_CHANGED) {
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n",
-+ 			   sta->addr);
-+ 
-+-		err = ath10k_station_assoc(ar, arvif, sta, true);
-++		err = ath10k_station_assoc(ar, arvif->vif, sta, true);
-+ 		if (err)
-+-			ath10k_warn("failed to reassociate station: %pM\n",
-++			ath10k_warn(ar, "failed to reassociate station: %pM\n",
-+ 				    sta->addr);
-+ 	}
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+ }
-+ 
-++static int ath10k_mac_inc_num_stations(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
-++	    arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-++		return 0;
-++
-++	if (ar->num_stations >= ar->max_num_stations)
-++		return -ENOBUFS;
-++
-++	ar->num_stations++;
-++
-++	return 0;
-++}
-++
-++static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif)
-++{
-++	struct ath10k *ar = arvif->ar;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
-++	    arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-++		return;
-++
-++	ar->num_stations--;
-++}
-++
-+ static int ath10k_sta_state(struct ieee80211_hw *hw,
-+ 			    struct ieee80211_vif *vif,
-+ 			    struct ieee80211_sta *sta,
-+@@ -3314,7 +4044,6 @@ static int ath10k_sta_state(struct ieee8
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-+-	int max_num_peers;
-+ 	int ret = 0;
-+ 
-+ 	if (old_state == IEEE80211_STA_NOTEXIST &&
-+@@ -3332,46 +4061,72 @@ static int ath10k_sta_state(struct ieee8
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	if (old_state == IEEE80211_STA_NOTEXIST &&
-+-	    new_state == IEEE80211_STA_NONE &&
-+-	    vif->type != NL80211_IFTYPE_STATION) {
-++	    new_state == IEEE80211_STA_NONE) {
-+ 		/*
-+ 		 * New station addition.
-+ 		 */
-+-		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-			max_num_peers = TARGET_10X_NUM_PEERS_MAX - 1;
-+-		else
-+-			max_num_peers = TARGET_NUM_PEERS;
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-++			   "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n",
-++			   arvif->vdev_id, sta->addr,
-++			   ar->num_stations + 1, ar->max_num_stations,
-++			   ar->num_peers + 1, ar->max_num_peers);
-+ 
-+-		if (ar->num_peers >= max_num_peers) {
-+-			ath10k_warn("number of peers exceeded: peers number %d (max peers %d)\n",
-+-				    ar->num_peers, max_num_peers);
-+-			ret = -ENOBUFS;
-++		ret = ath10k_mac_inc_num_stations(arvif);
-++		if (ret) {
-++			ath10k_warn(ar, "refusing to associate station: too many connected already (%d)\n",
-++				    ar->max_num_stations);
-+ 			goto exit;
-+ 		}
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-+-			   "mac vdev %d peer create %pM (new sta) num_peers %d\n",
-+-			   arvif->vdev_id, sta->addr, ar->num_peers);
-+-
-+ 		ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
-+-		if (ret)
-+-			ath10k_warn("failed to add peer %pM for vdev %d when adding a new sta: %i\n",
-++		if (ret) {
-++			ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n",
-+ 				    sta->addr, arvif->vdev_id, ret);
-++			ath10k_mac_dec_num_stations(arvif);
-++			goto exit;
-++		}
-++
-++		if (vif->type == NL80211_IFTYPE_STATION) {
-++			WARN_ON(arvif->is_started);
-++
-++			ret = ath10k_vdev_start(arvif);
-++			if (ret) {
-++				ath10k_warn(ar, "failed to start vdev %i: %d\n",
-++					    arvif->vdev_id, ret);
-++				WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id,
-++							   sta->addr));
-++				ath10k_mac_dec_num_stations(arvif);
-++				goto exit;
-++			}
-++
-++			arvif->is_started = true;
-++		}
-+ 	} else if ((old_state == IEEE80211_STA_NONE &&
-+ 		    new_state == IEEE80211_STA_NOTEXIST)) {
-+ 		/*
-+ 		 * Existing station deletion.
-+ 		 */
-+-		ath10k_dbg(ATH10K_DBG_MAC,
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-+ 			   "mac vdev %d peer delete %pM (sta gone)\n",
-+ 			   arvif->vdev_id, sta->addr);
-++
-++		if (vif->type == NL80211_IFTYPE_STATION) {
-++			WARN_ON(!arvif->is_started);
-++
-++			ret = ath10k_vdev_stop(arvif);
-++			if (ret)
-++				ath10k_warn(ar, "failed to stop vdev %i: %d\n",
-++					    arvif->vdev_id, ret);
-++
-++			arvif->is_started = false;
-++		}
-++
-+ 		ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
-+ 		if (ret)
-+-			ath10k_warn("failed to delete peer %pM for vdev %d: %i\n",
-++			ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
-+ 				    sta->addr, arvif->vdev_id, ret);
-+ 
-+-		if (vif->type == NL80211_IFTYPE_STATION)
-+-			ath10k_bss_disassoc(hw, vif);
-++		ath10k_mac_dec_num_stations(arvif);
-+ 	} else if (old_state == IEEE80211_STA_AUTH &&
-+ 		   new_state == IEEE80211_STA_ASSOC &&
-+ 		   (vif->type == NL80211_IFTYPE_AP ||
-+@@ -3379,12 +4134,12 @@ static int ath10k_sta_state(struct ieee8
-+ 		/*
-+ 		 * New association.
-+ 		 */
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac sta %pM associated\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n",
-+ 			   sta->addr);
-+ 
-+-		ret = ath10k_station_assoc(ar, arvif, sta, false);
-++		ret = ath10k_station_assoc(ar, vif, sta, false);
-+ 		if (ret)
-+-			ath10k_warn("failed to associate station %pM for vdev %i: %i\n",
-++			ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
-+ 				    sta->addr, arvif->vdev_id, ret);
-+ 	} else if (old_state == IEEE80211_STA_ASSOC &&
-+ 		   new_state == IEEE80211_STA_AUTH &&
-+@@ -3393,12 +4148,12 @@ static int ath10k_sta_state(struct ieee8
-+ 		/*
-+ 		 * Disassociation.
-+ 		 */
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac sta %pM disassociated\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n",
-+ 			   sta->addr);
-+ 
-+-		ret = ath10k_station_disassoc(ar, arvif, sta);
-++		ret = ath10k_station_disassoc(ar, vif, sta);
-+ 		if (ret)
-+-			ath10k_warn("failed to disassociate station: %pM vdev %i: %i\n",
-++			ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n",
-+ 				    sta->addr, arvif->vdev_id, ret);
-+ 	}
-+ exit:
-+@@ -3407,9 +4162,11 @@ exit:
-+ }
-+ 
-+ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
-+-				 u16 ac, bool enable)
-++				u16 ac, bool enable)
-+ {
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++	struct wmi_sta_uapsd_auto_trig_arg arg = {};
-++	u32 prio = 0, acc = 0;
-+ 	u32 value = 0;
-+ 	int ret = 0;
-+ 
-+@@ -3422,18 +4179,26 @@ static int ath10k_conf_tx_uapsd(struct a
-+ 	case IEEE80211_AC_VO:
-+ 		value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
-+ 			WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
-++		prio = 7;
-++		acc = 3;
-+ 		break;
-+ 	case IEEE80211_AC_VI:
-+ 		value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
-+ 			WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
-++		prio = 5;
-++		acc = 2;
-+ 		break;
-+ 	case IEEE80211_AC_BE:
-+ 		value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
-+ 			WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
-++		prio = 2;
-++		acc = 1;
-+ 		break;
-+ 	case IEEE80211_AC_BK:
-+ 		value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
-+ 			WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
-++		prio = 0;
-++		acc = 0;
-+ 		break;
-+ 	}
-+ 
-+@@ -3446,7 +4211,7 @@ static int ath10k_conf_tx_uapsd(struct a
-+ 					  WMI_STA_PS_PARAM_UAPSD,
-+ 					  arvif->u.sta.uapsd);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set uapsd params: %d\n", ret);
-++		ath10k_warn(ar, "failed to set uapsd params: %d\n", ret);
-+ 		goto exit;
-+ 	}
-+ 
-+@@ -3459,7 +4224,44 @@ static int ath10k_conf_tx_uapsd(struct a
-+ 					  WMI_STA_PS_PARAM_RX_WAKE_POLICY,
-+ 					  value);
-+ 	if (ret)
-+-		ath10k_warn("failed to set rx wake param: %d\n", ret);
-++		ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);
-++
-++	ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++		return ret;
-++	}
-++
-++	ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
-++			    arvif->vdev_id, ret);
-++		return ret;
-++	}
-++
-++	if (test_bit(WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, ar->wmi.svc_map) ||
-++	    test_bit(WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, ar->wmi.svc_map)) {
-++		/* Only userspace can make an educated decision when to send
-++		 * trigger frame. The following effectively disables u-UAPSD
-++		 * autotrigger in firmware (which is enabled by default
-++		 * provided the autotrigger service is available).
-++		 */
-++
-++		arg.wmm_ac = acc;
-++		arg.user_priority = prio;
-++		arg.service_interval = 0;
-++		arg.suspend_interval = WMI_STA_UAPSD_MAX_INTERVAL_MSEC;
-++		arg.delay_interval = WMI_STA_UAPSD_MAX_INTERVAL_MSEC;
-++
-++		ret = ath10k_wmi_vdev_sta_uapsd(ar, arvif->vdev_id,
-++						arvif->bssid, &arg, 1);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set uapsd auto trigger %d\n",
-++				    ret);
-++			return ret;
-++		}
-++	}
-+ 
-+ exit:
-+ 	return ret;
-+@@ -3470,6 +4272,7 @@ static int ath10k_conf_tx(struct ieee802
-+ 			  const struct ieee80211_tx_queue_params *params)
-+ {
-+ 	struct ath10k *ar = hw->priv;
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	struct wmi_wmm_params_arg *p = NULL;
-+ 	int ret;
-+ 
-+@@ -3477,16 +4280,16 @@ static int ath10k_conf_tx(struct ieee802
-+ 
-+ 	switch (ac) {
-+ 	case IEEE80211_AC_VO:
-+-		p = &ar->wmm_params.ac_vo;
-++		p = &arvif->wmm_params.ac_vo;
-+ 		break;
-+ 	case IEEE80211_AC_VI:
-+-		p = &ar->wmm_params.ac_vi;
-++		p = &arvif->wmm_params.ac_vi;
-+ 		break;
-+ 	case IEEE80211_AC_BE:
-+-		p = &ar->wmm_params.ac_be;
-++		p = &arvif->wmm_params.ac_be;
-+ 		break;
-+ 	case IEEE80211_AC_BK:
-+-		p = &ar->wmm_params.ac_bk;
-++		p = &arvif->wmm_params.ac_bk;
-+ 		break;
-+ 	}
-+ 
-+@@ -3506,16 +4309,28 @@ static int ath10k_conf_tx(struct ieee802
-+ 	 */
-+ 	p->txop = params->txop * 32;
-+ 
-+-	/* FIXME: FW accepts wmm params per hw, not per vif */
-+-	ret = ath10k_wmi_pdev_set_wmm_params(ar, &ar->wmm_params);
-+-	if (ret) {
-+-		ath10k_warn("failed to set wmm params: %d\n", ret);
-+-		goto exit;
-++	if (ar->wmi.ops->gen_vdev_wmm_conf) {
-++		ret = ath10k_wmi_vdev_wmm_conf(ar, arvif->vdev_id,
-++					       &arvif->wmm_params);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set vdev wmm params on vdev %i: %d\n",
-++				    arvif->vdev_id, ret);
-++			goto exit;
-++		}
-++	} else {
-++		/* This won't work well with multi-interface cases but it's
-++		 * better than nothing.
-++		 */
-++		ret = ath10k_wmi_pdev_set_wmm_params(ar, &arvif->wmm_params);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to set wmm params: %d\n", ret);
-++			goto exit;
-++		}
-+ 	}
-+ 
-+ 	ret = ath10k_conf_tx_uapsd(ar, vif, ac, params->uapsd);
-+ 	if (ret)
-+-		ath10k_warn("failed to set sta uapsd: %d\n", ret);
-++		ath10k_warn(ar, "failed to set sta uapsd: %d\n", ret);
-+ 
-+ exit:
-+ 	mutex_unlock(&ar->conf_mutex);
-+@@ -3533,27 +4348,35 @@ static int ath10k_remain_on_channel(stru
-+ 	struct ath10k *ar = hw->priv;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 	struct wmi_start_scan_arg arg;
-+-	int ret;
-++	int ret = 0;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+-	if (ar->scan.in_progress) {
-+-		spin_unlock_bh(&ar->data_lock);
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++		reinit_completion(&ar->scan.started);
-++		reinit_completion(&ar->scan.completed);
-++		reinit_completion(&ar->scan.on_channel);
-++		ar->scan.state = ATH10K_SCAN_STARTING;
-++		ar->scan.is_roc = true;
-++		ar->scan.vdev_id = arvif->vdev_id;
-++		ar->scan.roc_freq = chan->center_freq;
-++		ret = 0;
-++		break;
-++	case ATH10K_SCAN_STARTING:
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-+ 		ret = -EBUSY;
-+-		goto exit;
-++		break;
-+ 	}
-+-
-+-	reinit_completion(&ar->scan.started);
-+-	reinit_completion(&ar->scan.completed);
-+-	reinit_completion(&ar->scan.on_channel);
-+-	ar->scan.in_progress = true;
-+-	ar->scan.aborting = false;
-+-	ar->scan.is_roc = true;
-+-	ar->scan.vdev_id = arvif->vdev_id;
-+-	ar->scan.roc_freq = chan->center_freq;
-+ 	spin_unlock_bh(&ar->data_lock);
-+ 
-++	if (ret)
-++		goto exit;
-++
-++	duration = max(duration, WMI_SCAN_CHAN_MIN_TIME_MSEC);
-++
-+ 	memset(&arg, 0, sizeof(arg));
-+ 	ath10k_wmi_start_scan_init(ar, &arg);
-+ 	arg.vdev_id = arvif->vdev_id;
-+@@ -3568,17 +4391,21 @@ static int ath10k_remain_on_channel(stru
-+ 
-+ 	ret = ath10k_start_scan(ar, &arg);
-+ 	if (ret) {
-+-		ath10k_warn("failed to start roc scan: %d\n", ret);
-++		ath10k_warn(ar, "failed to start roc scan: %d\n", ret);
-+ 		spin_lock_bh(&ar->data_lock);
-+-		ar->scan.in_progress = false;
-++		ar->scan.state = ATH10K_SCAN_IDLE;
-+ 		spin_unlock_bh(&ar->data_lock);
-+ 		goto exit;
-+ 	}
-+ 
-+ 	ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ);
-+ 	if (ret == 0) {
-+-		ath10k_warn("failed to switch to channel for roc scan\n");
-+-		ath10k_abort_scan(ar);
-++		ath10k_warn(ar, "failed to switch to channel for roc scan\n");
-++
-++		ret = ath10k_scan_stop(ar);
-++		if (ret)
-++			ath10k_warn(ar, "failed to stop scan: %d\n", ret);
-++
-+ 		ret = -ETIMEDOUT;
-+ 		goto exit;
-+ 	}
-+@@ -3594,9 +4421,11 @@ static int ath10k_cancel_remain_on_chann
-+ 	struct ath10k *ar = hw->priv;
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+-	ath10k_abort_scan(ar);
-++	ath10k_scan_abort(ar);
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 
-++	cancel_delayed_work_sync(&ar->scan.timeout);
-++
-+ 	return 0;
-+ }
-+ 
-+@@ -3613,35 +4442,12 @@ static int ath10k_set_rts_threshold(stru
-+ 
-+ 	mutex_lock(&ar->conf_mutex);
-+ 	list_for_each_entry(arvif, &ar->arvifs, list) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n",
-+-			   arvif->vdev_id, value);
-+-
-+-		ret = ath10k_mac_set_rts(arvif, value);
-+-		if (ret) {
-+-			ath10k_warn("failed to set rts threshold for vdev %d: %d\n",
-+-				    arvif->vdev_id, ret);
-+-			break;
-+-		}
-+-	}
-+-	mutex_unlock(&ar->conf_mutex);
-+-
-+-	return ret;
-+-}
-+-
-+-static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
-+-{
-+-	struct ath10k *ar = hw->priv;
-+-	struct ath10k_vif *arvif;
-+-	int ret = 0;
-+-
-+-	mutex_lock(&ar->conf_mutex);
-+-	list_for_each_entry(arvif, &ar->arvifs, list) {
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d rts threshold %d\n",
-+ 			   arvif->vdev_id, value);
-+ 
-+ 		ret = ath10k_mac_set_rts(arvif, value);
-+ 		if (ret) {
-+-			ath10k_warn("failed to set fragmentation threshold for vdev %d: %d\n",
-++			ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
-+ 				    arvif->vdev_id, ret);
-+ 			break;
-+ 		}
-+@@ -3675,13 +4481,15 @@ static void ath10k_flush(struct ieee8021
-+ 			empty = (ar->htt.num_pending_tx == 0);
-+ 			spin_unlock_bh(&ar->htt.tx_lock);
-+ 
-+-			skip = (ar->state == ATH10K_STATE_WEDGED);
-++			skip = (ar->state == ATH10K_STATE_WEDGED) ||
-++			       test_bit(ATH10K_FLAG_CRASH_FLUSH,
-++					&ar->dev_flags);
-+ 
-+ 			(empty || skip);
-+ 		}), ATH10K_FLUSH_TIMEOUT_HZ);
-+ 
-+ 	if (ret <= 0 || skip)
-+-		ath10k_warn("failed to flush transmit queue (skip %i ar-state %i): %i\n",
-++		ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %i\n",
-+ 			    skip, ar->state, ret);
-+ 
-+ skip:
-+@@ -3716,7 +4524,7 @@ static int ath10k_suspend(struct ieee802
-+ 
-+ 	ret = ath10k_hif_suspend(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to suspend hif: %d\n", ret);
-++		ath10k_warn(ar, "failed to suspend hif: %d\n", ret);
-+ 		goto resume;
-+ 	}
-+ 
-+@@ -3725,7 +4533,7 @@ static int ath10k_suspend(struct ieee802
-+ resume:
-+ 	ret = ath10k_wmi_pdev_resume_target(ar);
-+ 	if (ret)
-+-		ath10k_warn("failed to resume target: %d\n", ret);
-++		ath10k_warn(ar, "failed to resume target: %d\n", ret);
-+ 
-+ 	ret = 1;
-+ exit:
-+@@ -3742,14 +4550,14 @@ static int ath10k_resume(struct ieee8021
-+ 
-+ 	ret = ath10k_hif_resume(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to resume hif: %d\n", ret);
-++		ath10k_warn(ar, "failed to resume hif: %d\n", ret);
-+ 		ret = 1;
-+ 		goto exit;
-+ 	}
-+ 
-+ 	ret = ath10k_wmi_pdev_resume_target(ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to resume target: %d\n", ret);
-++		ath10k_warn(ar, "failed to resume target: %d\n", ret);
-+ 		ret = 1;
-+ 		goto exit;
-+ 	}
-+@@ -3770,8 +4578,9 @@ static void ath10k_restart_complete(stru
-+ 	/* If device failed to restart it will be in a different state, e.g.
-+ 	 * ATH10K_STATE_WEDGED */
-+ 	if (ar->state == ATH10K_STATE_RESTARTED) {
-+-		ath10k_info("device successfully recovered\n");
-++		ath10k_info(ar, "device successfully recovered\n");
-+ 		ar->state = ATH10K_STATE_ON;
-++		ieee80211_wake_queues(ar->hw);
-+ 	}
-+ 
-+ 	mutex_unlock(&ar->conf_mutex);
-+@@ -3807,6 +4616,9 @@ static int ath10k_get_survey(struct ieee
-+ 
-+ 	survey->channel = &sband->channels[idx];
-+ 
-++	if (ar->rx_channel == survey->channel)
-++		survey->filled |= SURVEY_INFO_IN_USE;
-++
-+ exit:
-+ 	mutex_unlock(&ar->conf_mutex);
-+ 	return ret;
-+@@ -3854,6 +4666,10 @@ ath10k_default_bitrate_mask(struct ath10
-+ 	u32 legacy = 0x00ff;
-+ 	u8 ht = 0xff, i;
-+ 	u16 vht = 0x3ff;
-++	u16 nrf = ar->num_rf_chains;
-++
-++	if (ar->cfg_tx_chainmask)
-++		nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-+ 
-+ 	switch (band) {
-+ 	case IEEE80211_BAND_2GHZ:
-+@@ -3869,11 +4685,11 @@ ath10k_default_bitrate_mask(struct ath10
-+ 	if (mask->control[band].legacy != legacy)
-+ 		return false;
-+ 
-+-	for (i = 0; i < ar->num_rf_chains; i++)
-++	for (i = 0; i < nrf; i++)
-+ 		if (mask->control[band].ht_mcs[i] != ht)
-+ 			return false;
-+ 
-+-	for (i = 0; i < ar->num_rf_chains; i++)
-++	for (i = 0; i < nrf; i++)
-+ 		if (mask->control[band].vht_mcs[i] != vht)
-+ 			return false;
-+ 
-+@@ -3897,8 +4713,8 @@ ath10k_bitrate_mask_nss(const struct cfg
-+ 			continue;
-+ 		else if (mask->control[band].ht_mcs[i] == 0x00)
-+ 			break;
-+-		else
-+-			return false;
-++
-++		return false;
-+ 	}
-+ 
-+ 	ht_nss = i;
-+@@ -3909,8 +4725,8 @@ ath10k_bitrate_mask_nss(const struct cfg
-+ 			continue;
-+ 		else if (mask->control[band].vht_mcs[i] == 0x0000)
-+ 			break;
-+-		else
-+-			return false;
-++
-++		return false;
-+ 	}
-+ 
-+ 	vht_nss = i;
-+@@ -3967,7 +4783,8 @@ ath10k_bitrate_mask_correct(const struct
-+ }
-+ 
-+ static bool
-+-ath10k_bitrate_mask_rate(const struct cfg80211_bitrate_mask *mask,
-++ath10k_bitrate_mask_rate(struct ath10k *ar,
-++			 const struct cfg80211_bitrate_mask *mask,
-+ 			 enum ieee80211_band band,
-+ 			 u8 *fixed_rate,
-+ 			 u8 *fixed_nss)
-+@@ -4025,7 +4842,7 @@ ath10k_bitrate_mask_rate(const struct cf
-+ 	nss <<= 4;
-+ 	pream <<= 6;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n",
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n",
-+ 		   pream, nss, rate);
-+ 
-+ 	*fixed_rate = pream | nss | rate;
-+@@ -4033,7 +4850,8 @@ ath10k_bitrate_mask_rate(const struct cf
-+ 	return true;
-+ }
-+ 
-+-static bool ath10k_get_fixed_rate_nss(const struct cfg80211_bitrate_mask *mask,
-++static bool ath10k_get_fixed_rate_nss(struct ath10k *ar,
-++				      const struct cfg80211_bitrate_mask *mask,
-+ 				      enum ieee80211_band band,
-+ 				      u8 *fixed_rate,
-+ 				      u8 *fixed_nss)
-+@@ -4043,7 +4861,7 @@ static bool ath10k_get_fixed_rate_nss(co
-+ 		return true;
-+ 
-+ 	/* Next Check single rate is set */
-+-	return ath10k_bitrate_mask_rate(mask, band, fixed_rate, fixed_nss);
-++	return ath10k_bitrate_mask_rate(ar, mask, band, fixed_rate, fixed_nss);
-+ }
-+ 
-+ static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif,
-+@@ -4063,16 +4881,16 @@ static int ath10k_set_fixed_rate_param(s
-+ 		goto exit;
-+ 
-+ 	if (fixed_rate == WMI_FIXED_RATE_NONE)
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n");
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n");
-+ 
-+ 	if (force_sgi)
-+-		ath10k_dbg(ATH10K_DBG_MAC, "mac force sgi\n");
-++		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac force sgi\n");
-+ 
-+ 	vdev_param = ar->wmi.vdev_param->fixed_rate;
-+ 	ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
-+ 					vdev_param, fixed_rate);
-+ 	if (ret) {
-+-		ath10k_warn("failed to set fixed rate param 0x%02x: %d\n",
-++		ath10k_warn(ar, "failed to set fixed rate param 0x%02x: %d\n",
-+ 			    fixed_rate, ret);
-+ 		ret = -EINVAL;
-+ 		goto exit;
-+@@ -4085,7 +4903,7 @@ static int ath10k_set_fixed_rate_param(s
-+ 					vdev_param, fixed_nss);
-+ 
-+ 	if (ret) {
-+-		ath10k_warn("failed to set fixed nss param %d: %d\n",
-++		ath10k_warn(ar, "failed to set fixed nss param %d: %d\n",
-+ 			    fixed_nss, ret);
-+ 		ret = -EINVAL;
-+ 		goto exit;
-+@@ -4098,7 +4916,7 @@ static int ath10k_set_fixed_rate_param(s
-+ 					force_sgi);
-+ 
-+ 	if (ret) {
-+-		ath10k_warn("failed to set sgi param %d: %d\n",
-++		ath10k_warn(ar, "failed to set sgi param %d: %d\n",
-+ 			    force_sgi, ret);
-+ 		ret = -EINVAL;
-+ 		goto exit;
-+@@ -4122,19 +4940,22 @@ static int ath10k_set_bitrate_mask(struc
-+ 	u8 fixed_nss = ar->num_rf_chains;
-+ 	u8 force_sgi;
-+ 
-++	if (ar->cfg_tx_chainmask)
-++		fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-++
-+ 	force_sgi = mask->control[band].gi;
-+ 	if (force_sgi == NL80211_TXRATE_FORCE_LGI)
-+ 		return -EINVAL;
-+ 
-+ 	if (!ath10k_default_bitrate_mask(ar, band, mask)) {
-+-		if (!ath10k_get_fixed_rate_nss(mask, band,
-++		if (!ath10k_get_fixed_rate_nss(ar, mask, band,
-+ 					       &fixed_rate,
-+ 					       &fixed_nss))
-+ 			return -EINVAL;
-+ 	}
-+ 
-+ 	if (fixed_rate == WMI_FIXED_RATE_NONE && force_sgi) {
-+-		ath10k_warn("failed to force SGI usage for default rate settings\n");
-++		ath10k_warn(ar, "failed to force SGI usage for default rate settings\n");
-+ 		return -EINVAL;
-+ 	}
-+ 
-+@@ -4153,7 +4974,7 @@ static void ath10k_sta_rc_update(struct
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MAC,
-++	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,
-+ 		   sta->smps_mode);
-+@@ -4172,7 +4993,7 @@ static void ath10k_sta_rc_update(struct
-+ 			bw = WMI_PEER_CHWIDTH_80MHZ;
-+ 			break;
-+ 		case IEEE80211_STA_RX_BW_160:
-+-			ath10k_warn("Invalid bandwith %d in rc update for %pM\n",
-++			ath10k_warn(ar, "Invalid bandwith %d in rc update for %pM\n",
-+ 				    sta->bandwidth, sta->addr);
-+ 			bw = WMI_PEER_CHWIDTH_20MHZ;
-+ 			break;
-+@@ -4199,7 +5020,7 @@ static void ath10k_sta_rc_update(struct
-+ 			smps = WMI_PEER_SMPS_DYNAMIC;
-+ 			break;
-+ 		case IEEE80211_SMPS_NUM_MODES:
-+-			ath10k_warn("Invalid smps %d in sta rc update for %pM\n",
-++			ath10k_warn(ar, "Invalid smps %d in sta rc update for %pM\n",
-+ 				    sta->smps_mode, sta->addr);
-+ 			smps = WMI_PEER_SMPS_PS_NONE;
-+ 			break;
-+@@ -4225,6 +5046,39 @@ static u64 ath10k_get_tsf(struct ieee802
-+ 	return 0;
-+ }
-+ 
-++static int ath10k_ampdu_action(struct ieee80211_hw *hw,
-++			       struct ieee80211_vif *vif,
-++			       enum ieee80211_ampdu_mlme_action action,
-++			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-++			       u8 buf_size)
-++{
-++	struct ath10k *ar = hw->priv;
-++	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n",
-++		   arvif->vdev_id, sta->addr, tid, action);
-++
-++	switch (action) {
-++	case IEEE80211_AMPDU_RX_START:
-++	case IEEE80211_AMPDU_RX_STOP:
-++		/* HTT AddBa/DelBa events trigger mac80211 Rx BA session
-++		 * creation/removal. Do we need to verify this?
-++		 */
-++		return 0;
-++	case IEEE80211_AMPDU_TX_START:
-++	case IEEE80211_AMPDU_TX_STOP_CONT:
-++	case IEEE80211_AMPDU_TX_STOP_FLUSH:
-++	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-++	case IEEE80211_AMPDU_TX_OPERATIONAL:
-++		/* Firmware offloads Tx aggregation entirely so deny mac80211
-++		 * Tx aggregation requests.
-++		 */
-++		return -EOPNOTSUPP;
-++	}
-++
-++	return -EINVAL;
-++}
-++
-+ static const struct ieee80211_ops ath10k_ops = {
-+ 	.tx				= ath10k_tx,
-+ 	.start				= ath10k_start,
-+@@ -4237,23 +5091,35 @@ static const struct ieee80211_ops ath10k
-+ 	.hw_scan			= ath10k_hw_scan,
-+ 	.cancel_hw_scan			= ath10k_cancel_hw_scan,
-+ 	.set_key			= ath10k_set_key,
-++	.set_default_unicast_key        = ath10k_set_default_unicast_key,
-+ 	.sta_state			= ath10k_sta_state,
-+ 	.conf_tx			= ath10k_conf_tx,
-+ 	.remain_on_channel		= ath10k_remain_on_channel,
-+ 	.cancel_remain_on_channel	= ath10k_cancel_remain_on_channel,
-+ 	.set_rts_threshold		= ath10k_set_rts_threshold,
-+-	.set_frag_threshold		= ath10k_set_frag_threshold,
-+ 	.flush				= ath10k_flush,
-+ 	.tx_last_beacon			= ath10k_tx_last_beacon,
-++	.set_antenna			= ath10k_set_antenna,
-++	.get_antenna			= ath10k_get_antenna,
-+ 	.restart_complete		= ath10k_restart_complete,
-+ 	.get_survey			= ath10k_get_survey,
-+ 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
-+ 	.sta_rc_update			= ath10k_sta_rc_update,
-+ 	.get_tsf			= ath10k_get_tsf,
-++	.ampdu_action			= ath10k_ampdu_action,
-++	.get_et_sset_count		= ath10k_debug_get_et_sset_count,
-++	.get_et_stats			= ath10k_debug_get_et_stats,
-++	.get_et_strings			= ath10k_debug_get_et_strings,
-++
-++	CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
-++
-+ #ifdef CONFIG_PM
-+ 	.suspend			= ath10k_suspend,
-+ 	.resume				= ath10k_resume,
-+ #endif
-++#ifdef CPTCFG_MAC80211_DEBUGFS
-++	.sta_add_debugfs		= ath10k_sta_add_debugfs,
-++#endif
-+ };
-+ 
-+ #define RATETAB_ENT(_rate, _rateid, _flags) { \
-+@@ -4324,6 +5190,9 @@ static const struct ieee80211_channel at
-+ 	CHAN5G(165, 5825, 0),
-+ };
-+ 
-++/* Note: Be careful if you re-order these. There is code which depends on this
-++ * ordering.
-++ */
-+ static struct ieee80211_rate ath10k_rates[] = {
-+ 	/* CCK */
-+ 	RATETAB_ENT(10,  0x82, 0),
-+@@ -4346,12 +5215,12 @@ static struct ieee80211_rate ath10k_rate
-+ #define ath10k_g_rates (ath10k_rates + 0)
-+ #define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates))
-+ 
-+-struct ath10k *ath10k_mac_create(void)
-++struct ath10k *ath10k_mac_create(size_t priv_size)
-+ {
-+ 	struct ieee80211_hw *hw;
-+ 	struct ath10k *ar;
-+ 
-+-	hw = ieee80211_alloc_hw(sizeof(struct ath10k), &ath10k_ops);
-++	hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, &ath10k_ops);
-+ 	if (!hw)
-+ 		return NULL;
-+ 
-+@@ -4377,6 +5246,10 @@ static const struct ieee80211_iface_limi
-+ 	.types	= BIT(NL80211_IFTYPE_P2P_GO)
-+ 	},
-+ 	{
-++	.max	= 1,
-++	.types	= BIT(NL80211_IFTYPE_P2P_DEVICE)
-++	},
-++	{
-+ 	.max	= 7,
-+ 	.types	= BIT(NL80211_IFTYPE_AP)
-+ 	},
-+@@ -4501,7 +5374,6 @@ static struct ieee80211_sta_ht_cap ath10
-+ 	return ht_cap;
-+ }
-+ 
-+-
-+ static void ath10k_get_arvif_iter(void *data, u8 *mac,
-+ 				  struct ieee80211_vif *vif)
-+ {
-+@@ -4526,7 +5398,7 @@ struct ath10k_vif *ath10k_get_arvif(stru
-+ 						   ath10k_get_arvif_iter,
-+ 						   &arvif_iter);
-+ 	if (!arvif_iter.arvif) {
-+-		ath10k_warn("No VIF found for vdev %d\n", vdev_id);
-++		ath10k_warn(ar, "No VIF found for vdev %d\n", vdev_id);
-+ 		return NULL;
-+ 	}
-+ 
-+@@ -4564,7 +5436,8 @@ int ath10k_mac_register(struct ath10k *a
-+ 		band->bitrates = ath10k_g_rates;
-+ 		band->ht_cap = ht_cap;
-+ 
-+-		/* vht is not supported in 2.4 GHz */
-++		/* Enable the VHT support at 2.4 GHz */
-++		band->vht_cap = vht_cap;
-+ 
-+ 		ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
-+ 	}
-+@@ -4590,18 +5463,20 @@ int ath10k_mac_register(struct ath10k *a
-+ 
-+ 	ar->hw->wiphy->interface_modes =
-+ 		BIT(NL80211_IFTYPE_STATION) |
-+-		BIT(NL80211_IFTYPE_ADHOC) |
-+ 		BIT(NL80211_IFTYPE_AP);
-+ 
-++	ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
-++	ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
-++
-+ 	if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
-+ 		ar->hw->wiphy->interface_modes |=
-++			BIT(NL80211_IFTYPE_P2P_DEVICE) |
-+ 			BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ 			BIT(NL80211_IFTYPE_P2P_GO);
-+ 
-+ 	ar->hw->flags = IEEE80211_HW_SIGNAL_DBM |
-+ 			IEEE80211_HW_SUPPORTS_PS |
-+ 			IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
-+-			IEEE80211_HW_SUPPORTS_UAPSD |
-+ 			IEEE80211_HW_MFP_CAPABLE |
-+ 			IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-+ 			IEEE80211_HW_HAS_RATE_CONTROL |
-+@@ -4609,10 +5484,6 @@ int ath10k_mac_register(struct ath10k *a
-+ 			IEEE80211_HW_AP_LINK_PS |
-+ 			IEEE80211_HW_SPECTRUM_MGMT;
-+ 
-+-	/* MSDU can have HTT TX fragment pushed in front. The additional 4
-+-	 * bytes is used for padding/alignment if necessary. */
-+-	ar->hw->extra_tx_headroom += sizeof(struct htt_data_tx_desc_frag)*2 + 4;
-+-
-+ 	if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
-+ 		ar->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS;
-+ 
-+@@ -4629,25 +5500,52 @@ int ath10k_mac_register(struct ath10k *a
-+ 
-+ 	ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
-+ 
-++	if (test_bit(WMI_SERVICE_BEACON_OFFLOAD, ar->wmi.svc_map)) {
-++		ar->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
-++
-++		/* Firmware delivers WPS/P2P Probe Requests frames to driver so
-++		 * that userspace (e.g. wpa_supplicant/hostapd) can generate
-++		 * correct Probe Responses. This is more of a hack advert..
-++		 */
-++		ar->hw->wiphy->probe_resp_offload |=
-++			NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
-++			NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
-++			NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
-++	}
-++
-+ 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-+ 	ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
-+ 	ar->hw->wiphy->max_remain_on_channel_duration = 5000;
-+ 
-+ 	ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-++	ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
-++
-+ 	/*
-+ 	 * on LL hardware queues are managed entirely by the FW
-+ 	 * so we only advertise to mac we can do the queues thing
-+ 	 */
-+ 	ar->hw->queues = 4;
-+ 
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-+-		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
-+-		ar->hw->wiphy->n_iface_combinations =
-+-			ARRAY_SIZE(ath10k_10x_if_comb);
-+-	} else {
-++	switch (ar->wmi.op_version) {
-++	case ATH10K_FW_WMI_OP_VERSION_MAIN:
-++	case ATH10K_FW_WMI_OP_VERSION_TLV:
-+ 		ar->hw->wiphy->iface_combinations = ath10k_if_comb;
-+ 		ar->hw->wiphy->n_iface_combinations =
-+ 			ARRAY_SIZE(ath10k_if_comb);
-++		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_10_1:
-++	case ATH10K_FW_WMI_OP_VERSION_10_2:
-++	case ATH10K_FW_WMI_OP_VERSION_10_2_4:
-++		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
-++		ar->hw->wiphy->n_iface_combinations =
-++			ARRAY_SIZE(ath10k_10x_if_comb);
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_UNSET:
-++	case ATH10K_FW_WMI_OP_VERSION_MAX:
-++		WARN_ON(1);
-++		ret = -EINVAL;
-++		goto err_free;
-+ 	}
-+ 
-+ 	ar->hw->netdev_features = NETIF_F_HW_CSUM;
-+@@ -4659,19 +5557,19 @@ int ath10k_mac_register(struct ath10k *a
-+ 							     NL80211_DFS_UNSET);
-+ 
-+ 		if (!ar->dfs_detector)
-+-			ath10k_warn("failed to initialise DFS pattern detector\n");
-++			ath10k_warn(ar, "failed to initialise DFS pattern detector\n");
-+ 	}
-+ 
-+ 	ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
-+ 			    ath10k_reg_notifier);
-+ 	if (ret) {
-+-		ath10k_err("failed to initialise regulatory: %i\n", ret);
-++		ath10k_err(ar, "failed to initialise regulatory: %i\n", ret);
-+ 		goto err_free;
-+ 	}
-+ 
-+ 	ret = ieee80211_register_hw(ar->hw);
-+ 	if (ret) {
-+-		ath10k_err("failed to register ieee80211: %d\n", ret);
-++		ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
-+ 		goto err_free;
-+ 	}
-+ 
-+--- a/drivers/net/wireless/ath/ath10k/mac.h
-++++ b/drivers/net/wireless/ath/ath10k/mac.h
-+@@ -21,33 +21,41 @@
-+ #include <net/mac80211.h>
-+ #include "core.h"
-+ 
-++#define WEP_KEYID_SHIFT 6
-++
-+ struct ath10k_generic_iter {
-+ 	struct ath10k *ar;
-+ 	int ret;
-+ };
-+ 
-+-struct ath10k *ath10k_mac_create(void);
-++struct ath10k *ath10k_mac_create(size_t priv_size);
-+ void ath10k_mac_destroy(struct ath10k *ar);
-+ int ath10k_mac_register(struct ath10k *ar);
-+ void ath10k_mac_unregister(struct ath10k *ar);
-+ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
-+-void ath10k_reset_scan(unsigned long ptr);
-++void __ath10k_scan_finish(struct ath10k *ar);
-++void ath10k_scan_finish(struct ath10k *ar);
-++void ath10k_scan_timeout_work(struct work_struct *work);
-+ void ath10k_offchan_tx_purge(struct ath10k *ar);
-+ void ath10k_offchan_tx_work(struct work_struct *work);
-+ void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
-+ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
-+ void ath10k_halt(struct ath10k *ar);
-++void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
-++void ath10k_drain_tx(struct ath10k *ar);
-++bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
-++				    u8 keyidx);
-+ 
-+ static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
-+ {
-+ 	return (struct ath10k_vif *)vif->drv_priv;
-+ }
-+ 
-+-static inline void ath10k_tx_h_seq_no(struct sk_buff *skb)
-++static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
-++				      struct sk_buff *skb)
-+ {
-+ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+-	struct ieee80211_vif *vif = info->control.vif;
-+ 	struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-+ 
-+ 	if (info->flags  & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-+--- a/drivers/net/wireless/ath/ath10k/pci.c
-++++ b/drivers/net/wireless/ath/ath10k/pci.c
-+@@ -44,13 +44,9 @@ enum ath10k_pci_reset_mode {
-+ 	ATH10K_PCI_RESET_WARM_ONLY = 1,
-+ };
-+ 
-+-static unsigned int ath10k_pci_target_ps;
-+ static unsigned int ath10k_pci_irq_mode = ATH10K_PCI_IRQ_AUTO;
-+ static unsigned int ath10k_pci_reset_mode = ATH10K_PCI_RESET_AUTO;
-+ 
-+-module_param_named(target_ps, ath10k_pci_target_ps, uint, 0644);
-+-MODULE_PARM_DESC(target_ps, "Enable ath10k Target (SoC) PS option");
-+-
-+ module_param_named(irq_mode, ath10k_pci_irq_mode, uint, 0644);
-+ MODULE_PARM_DESC(irq_mode, "0: auto, 1: legacy, 2: msi (default: 0)");
-+ 
-+@@ -59,21 +55,31 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1
-+ 
-+ /* how long wait to wait for target to initialise, in ms */
-+ #define ATH10K_PCI_TARGET_WAIT 3000
-++#define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
-+ 
-+ #define QCA988X_2_0_DEVICE_ID	(0x003c)
-++#define QCA6174_2_1_DEVICE_ID	(0x003e)
-+ 
-+-static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
-++static const struct pci_device_id ath10k_pci_id_table[] = {
-+ 	{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
-++	{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
-+ 	{0}
-+ };
-+ 
-+-static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
-+-				       u32 *data);
-++static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
-++	/* QCA988X pre 2.0 chips are not supported because they need some nasty
-++	 * hacks. ath10k doesn't have them and these devices crash horribly
-++	 * because of that.
-++	 */
-++	{ QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV },
-++	{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_1_CHIP_ID_REV },
-++	{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_2_CHIP_ID_REV },
-++	{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV },
-++	{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV },
-++	{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
-++};
-+ 
-+-static int ath10k_pci_post_rx(struct ath10k *ar);
-+-static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
-+-					     int num);
-+-static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info);
-++static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
-+ static int ath10k_pci_cold_reset(struct ath10k *ar);
-+ static int ath10k_pci_warm_reset(struct ath10k *ar);
-+ static int ath10k_pci_wait_for_target_init(struct ath10k *ar);
-+@@ -98,7 +104,7 @@ static const struct ce_attr host_ce_conf
-+ 	{
-+ 		.flags = CE_ATTR_FLAGS,
-+ 		.src_nentries = 0,
-+-		.src_sz_max = 512,
-++		.src_sz_max = 2048,
-+ 		.dest_nentries = 512,
-+ 	},
-+ 
-+@@ -155,79 +161,175 @@ static const struct ce_attr host_ce_conf
-+ static const struct ce_pipe_config target_ce_config_wlan[] = {
-+ 	/* CE0: host->target HTC control and raw streams */
-+ 	{
-+-		.pipenum = 0,
-+-		.pipedir = PIPEDIR_OUT,
-+-		.nentries = 32,
-+-		.nbytes_max = 256,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(0),
-++		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(256),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE1: target->host HTT + HTC control */
-+ 	{
-+-		.pipenum = 1,
-+-		.pipedir = PIPEDIR_IN,
-+-		.nentries = 32,
-+-		.nbytes_max = 512,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(1),
-++		.pipedir = __cpu_to_le32(PIPEDIR_IN),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(2048),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE2: target->host WMI */
-+ 	{
-+-		.pipenum = 2,
-+-		.pipedir = PIPEDIR_IN,
-+-		.nentries = 32,
-+-		.nbytes_max = 2048,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(2),
-++		.pipedir = __cpu_to_le32(PIPEDIR_IN),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(2048),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE3: host->target WMI */
-+ 	{
-+-		.pipenum = 3,
-+-		.pipedir = PIPEDIR_OUT,
-+-		.nentries = 32,
-+-		.nbytes_max = 2048,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(3),
-++		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(2048),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE4: host->target HTT */
-+ 	{
-+-		.pipenum = 4,
-+-		.pipedir = PIPEDIR_OUT,
-+-		.nentries = 256,
-+-		.nbytes_max = 256,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(4),
-++		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
-++		.nentries = __cpu_to_le32(256),
-++		.nbytes_max = __cpu_to_le32(256),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* NB: 50% of src nentries, since tx has 2 frags */
-+ 
-+ 	/* CE5: unused */
-+ 	{
-+-		.pipenum = 5,
-+-		.pipedir = PIPEDIR_OUT,
-+-		.nentries = 32,
-+-		.nbytes_max = 2048,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(5),
-++		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(2048),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE6: Reserved for target autonomous hif_memcpy */
-+ 	{
-+-		.pipenum = 6,
-+-		.pipedir = PIPEDIR_INOUT,
-+-		.nentries = 32,
-+-		.nbytes_max = 4096,
-+-		.flags = CE_ATTR_FLAGS,
-+-		.reserved = 0,
-++		.pipenum = __cpu_to_le32(6),
-++		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
-++		.nentries = __cpu_to_le32(32),
-++		.nbytes_max = __cpu_to_le32(4096),
-++		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
-++		.reserved = __cpu_to_le32(0),
-+ 	},
-+ 
-+ 	/* CE7 used only by Host */
-+ };
-+ 
-++/*
-++ * Map from service/endpoint to Copy Engine.
-++ * This table is derived from the CE_PCI TABLE, above.
-++ * It is passed to the Target at startup for use by firmware.
-++ */
-++static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(3),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(2),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(3),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(2),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(3),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(2),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(3),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(2),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(3),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(2),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(0),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(1),
-++	},
-++	{ /* not used */
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(0),
-++	},
-++	{ /* not used */
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(1),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
-++		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
-++		__cpu_to_le32(4),
-++	},
-++	{
-++		__cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
-++		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
-++		__cpu_to_le32(1),
-++	},
-++
-++	/* (Additions here) */
-++
-++	{ /* must be last */
-++		__cpu_to_le32(0),
-++		__cpu_to_le32(0),
-++		__cpu_to_le32(0),
-++	},
-++};
-++
-+ static bool ath10k_pci_irq_pending(struct ath10k *ar)
-+ {
-+ 	u32 cause;
-+@@ -253,8 +355,8 @@ static void ath10k_pci_disable_and_clear
-+ 
-+ 	/* IMPORTANT: this extra read transaction is required to
-+ 	 * flush the posted write buffer. */
-+-	(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				 PCIE_INTR_ENABLE_ADDRESS);
-++	(void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-++				PCIE_INTR_ENABLE_ADDRESS);
-+ }
-+ 
-+ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
-+@@ -265,48 +367,116 @@ static void ath10k_pci_enable_legacy_irq
-+ 
-+ 	/* IMPORTANT: this extra read transaction is required to
-+ 	 * flush the posted write buffer. */
-+-	(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				 PCIE_INTR_ENABLE_ADDRESS);
-++	(void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-++				PCIE_INTR_ENABLE_ADDRESS);
-+ }
-+ 
-+-static irqreturn_t ath10k_pci_early_irq_handler(int irq, void *arg)
-++static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar = arg;
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	if (ar_pci->num_msi_intrs == 0) {
-+-		if (!ath10k_pci_irq_pending(ar))
-+-			return IRQ_NONE;
-+-
-+-		ath10k_pci_disable_and_clear_legacy_irq(ar);
-+-	}
-++	if (ar_pci->num_msi_intrs > 1)
-++		return "msi-x";
-+ 
-+-	tasklet_schedule(&ar_pci->early_irq_tasklet);
-++	if (ar_pci->num_msi_intrs == 1)
-++		return "msi";
-+ 
-+-	return IRQ_HANDLED;
-++	return "legacy";
-+ }
-+ 
-+-static int ath10k_pci_request_early_irq(struct ath10k *ar)
-++static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
-+ {
-++	struct ath10k *ar = pipe->hif_ce_state;
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
-++	struct sk_buff *skb;
-++	dma_addr_t paddr;
-+ 	int ret;
-+ 
-+-	/* Regardless whether MSI-X/MSI/legacy irqs have been set up the first
-+-	 * interrupt from irq vector is triggered in all cases for FW
-+-	 * indication/errors */
-+-	ret = request_irq(ar_pci->pdev->irq, ath10k_pci_early_irq_handler,
-+-			  IRQF_SHARED, "ath10k_pci (early)", ar);
-++	lockdep_assert_held(&ar_pci->ce_lock);
-++
-++	skb = dev_alloc_skb(pipe->buf_sz);
-++	if (!skb)
-++		return -ENOMEM;
-++
-++	WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
-++
-++	paddr = dma_map_single(ar->dev, skb->data,
-++			       skb->len + skb_tailroom(skb),
-++			       DMA_FROM_DEVICE);
-++	if (unlikely(dma_mapping_error(ar->dev, paddr))) {
-++		ath10k_warn(ar, "failed to dma map pci rx buf\n");
-++		dev_kfree_skb_any(skb);
-++		return -EIO;
-++	}
-++
-++	ATH10K_SKB_RXCB(skb)->paddr = paddr;
-++
-++	ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request early irq: %d\n", ret);
-++		ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret);
-++		dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb),
-++				 DMA_FROM_DEVICE);
-++		dev_kfree_skb_any(skb);
-+ 		return ret;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_pci_free_early_irq(struct ath10k *ar)
-++static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
-++{
-++	struct ath10k *ar = pipe->hif_ce_state;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
-++	int ret, num;
-++
-++	lockdep_assert_held(&ar_pci->ce_lock);
-++
-++	if (pipe->buf_sz == 0)
-++		return;
-++
-++	if (!ce_pipe->dest_ring)
-++		return;
-++
-++	num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
-++	while (num--) {
-++		ret = __ath10k_pci_rx_post_buf(pipe);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret);
-++			mod_timer(&ar_pci->rx_post_retry, jiffies +
-++				  ATH10K_PCI_RX_POST_RETRY_MS);
-++			break;
-++		}
-++	}
-++}
-++
-++static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
-++{
-++	struct ath10k *ar = pipe->hif_ce_state;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++
-++	spin_lock_bh(&ar_pci->ce_lock);
-++	__ath10k_pci_rx_post_pipe(pipe);
-++	spin_unlock_bh(&ar_pci->ce_lock);
-++}
-++
-++static void ath10k_pci_rx_post(struct ath10k *ar)
-++{
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	int i;
-++
-++	spin_lock_bh(&ar_pci->ce_lock);
-++	for (i = 0; i < CE_COUNT; i++)
-++		__ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]);
-++	spin_unlock_bh(&ar_pci->ce_lock);
-++}
-++
-++static void ath10k_pci_rx_replenish_retry(unsigned long ptr)
-+ {
-+-	free_irq(ath10k_pci_priv(ar)->pdev->irq, ar);
-++	struct ath10k *ar = (void *)ptr;
-++
-++	ath10k_pci_rx_post(ar);
-+ }
-+ 
-+ /*
-+@@ -330,24 +500,7 @@ static int ath10k_pci_diag_read_mem(stru
-+ 	void *data_buf = NULL;
-+ 	int i;
-+ 
-+-	/*
-+-	 * This code cannot handle reads to non-memory space. Redirect to the
-+-	 * register read fn but preserve the multi word read capability of
-+-	 * this fn
-+-	 */
-+-	if (address < DRAM_BASE_ADDRESS) {
-+-		if (!IS_ALIGNED(address, 4) ||
-+-		    !IS_ALIGNED((unsigned long)data, 4))
-+-			return -EIO;
-+-
-+-		while ((nbytes >= 4) &&  ((ret = ath10k_pci_diag_read_access(
-+-					   ar, address, (u32 *)data)) == 0)) {
-+-			nbytes -= sizeof(u32);
-+-			address += sizeof(u32);
-+-			data += sizeof(u32);
-+-		}
-+-		return ret;
-+-	}
-++	spin_lock_bh(&ar_pci->ce_lock);
-+ 
-+ 	ce_diag = ar_pci->ce_diag;
-+ 
-+@@ -375,7 +528,7 @@ static int ath10k_pci_diag_read_mem(stru
-+ 		nbytes = min_t(unsigned int, remaining_bytes,
-+ 			       DIAG_TRANSFER_LIMIT);
-+ 
-+-		ret = ath10k_ce_recv_buf_enqueue(ce_diag, NULL, ce_data);
-++		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
-+ 		if (ret != 0)
-+ 			goto done;
-+ 
-+@@ -388,20 +541,18 @@ static int ath10k_pci_diag_read_mem(stru
-+ 		 * convert it from Target CPU virtual address space
-+ 		 * to CE address space
-+ 		 */
-+-		ath10k_pci_wake(ar);
-+ 		address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
-+ 						     address);
-+-		ath10k_pci_sleep(ar);
-+ 
-+-		ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
-+-				 0);
-++		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
-++					    0);
-+ 		if (ret)
-+ 			goto done;
-+ 
-+ 		i = 0;
-+-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-+-						     &completed_nbytes,
-+-						     &id) != 0) {
-++		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
-++							    &completed_nbytes,
-++							    &id) != 0) {
-+ 			mdelay(1);
-+ 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
-+ 				ret = -EBUSY;
-+@@ -414,15 +565,15 @@ static int ath10k_pci_diag_read_mem(stru
-+ 			goto done;
-+ 		}
-+ 
-+-		if (buf != (u32) address) {
-++		if (buf != (u32)address) {
-+ 			ret = -EIO;
-+ 			goto done;
-+ 		}
-+ 
-+ 		i = 0;
-+-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-+-						     &completed_nbytes,
-+-						     &id, &flags) != 0) {
-++		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-++							    &completed_nbytes,
-++							    &id, &flags) != 0) {
-+ 			mdelay(1);
-+ 
-+ 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
-+@@ -447,38 +598,60 @@ static int ath10k_pci_diag_read_mem(stru
-+ 	}
-+ 
-+ done:
-+-	if (ret == 0) {
-+-		/* Copy data from allocated DMA buf to caller's buf */
-+-		WARN_ON_ONCE(orig_nbytes & 3);
-+-		for (i = 0; i < orig_nbytes / sizeof(__le32); i++) {
-+-			((u32 *)data)[i] =
-+-				__le32_to_cpu(((__le32 *)data_buf)[i]);
-+-		}
-+-	} else
-+-		ath10k_warn("failed to read diag value at 0x%x: %d\n",
-++	if (ret == 0)
-++		memcpy(data, data_buf, orig_nbytes);
-++	else
-++		ath10k_warn(ar, "failed to read diag value at 0x%x: %d\n",
-+ 			    address, ret);
-+ 
-+ 	if (data_buf)
-+ 		dma_free_coherent(ar->dev, orig_nbytes, data_buf,
-+ 				  ce_data_base);
-+ 
-++	spin_unlock_bh(&ar_pci->ce_lock);
-++
-+ 	return ret;
-+ }
-+ 
-+-/* Read 4-byte aligned data from Target memory or register */
-+-static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
-+-				       u32 *data)
-+-{
-+-	/* Assume range doesn't cross this boundary */
-+-	if (address >= DRAM_BASE_ADDRESS)
-+-		return ath10k_pci_diag_read_mem(ar, address, data, sizeof(u32));
-++static int ath10k_pci_diag_read32(struct ath10k *ar, u32 address, u32 *value)
-++{
-++	__le32 val = 0;
-++	int ret;
-++
-++	ret = ath10k_pci_diag_read_mem(ar, address, &val, sizeof(val));
-++	*value = __le32_to_cpu(val);
-++
-++	return ret;
-++}
-++
-++static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
-++				     u32 src, u32 len)
-++{
-++	u32 host_addr, addr;
-++	int ret;
-++
-++	host_addr = host_interest_item_address(src);
-++
-++	ret = ath10k_pci_diag_read32(ar, host_addr, &addr);
-++	if (ret != 0) {
-++		ath10k_warn(ar, "failed to get memcpy hi address for firmware address %d: %d\n",
-++			    src, ret);
-++		return ret;
-++	}
-++
-++	ret = ath10k_pci_diag_read_mem(ar, addr, dest, len);
-++	if (ret != 0) {
-++		ath10k_warn(ar, "failed to memcpy firmware memory from %d (%d B): %d\n",
-++			    addr, len, ret);
-++		return ret;
-++	}
-+ 
-+-	ath10k_pci_wake(ar);
-+-	*data = ath10k_pci_read32(ar, address);
-+-	ath10k_pci_sleep(ar);
-+ 	return 0;
-+ }
-+ 
-++#define ath10k_pci_diag_read_hi(ar, dest, src, len)		\
-++	__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len)
-++
-+ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
-+ 				     const void *data, int nbytes)
-+ {
-+@@ -494,6 +667,8 @@ static int ath10k_pci_diag_write_mem(str
-+ 	dma_addr_t ce_data_base = 0;
-+ 	int i;
-+ 
-++	spin_lock_bh(&ar_pci->ce_lock);
-++
-+ 	ce_diag = ar_pci->ce_diag;
-+ 
-+ 	/*
-+@@ -513,9 +688,7 @@ static int ath10k_pci_diag_write_mem(str
-+ 	}
-+ 
-+ 	/* Copy caller's data to allocated DMA buf */
-+-	WARN_ON_ONCE(orig_nbytes & 3);
-+-	for (i = 0; i < orig_nbytes / sizeof(__le32); i++)
-+-		((__le32 *)data_buf)[i] = __cpu_to_le32(((u32 *)data)[i]);
-++	memcpy(data_buf, data, orig_nbytes);
-+ 
-+ 	/*
-+ 	 * The address supplied by the caller is in the
-+@@ -527,9 +700,7 @@ static int ath10k_pci_diag_write_mem(str
-+ 	 * to
-+ 	 *    CE address space
-+ 	 */
-+-	ath10k_pci_wake(ar);
-+ 	address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, address);
-+-	ath10k_pci_sleep(ar);
-+ 
-+ 	remaining_bytes = orig_nbytes;
-+ 	ce_data = ce_data_base;
-+@@ -538,7 +709,7 @@ static int ath10k_pci_diag_write_mem(str
-+ 		nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
-+ 
-+ 		/* Set up to receive directly into Target(!) address */
-+-		ret = ath10k_ce_recv_buf_enqueue(ce_diag, NULL, address);
-++		ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
-+ 		if (ret != 0)
-+ 			goto done;
-+ 
-+@@ -546,15 +717,15 @@ static int ath10k_pci_diag_write_mem(str
-+ 		 * Request CE to send caller-supplied data that
-+ 		 * was copied to bounce buffer to Target(!) address.
-+ 		 */
-+-		ret = ath10k_ce_send(ce_diag, NULL, (u32) ce_data,
-+-				     nbytes, 0, 0);
-++		ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
-++					    nbytes, 0, 0);
-+ 		if (ret != 0)
-+ 			goto done;
-+ 
-+ 		i = 0;
-+-		while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
-+-						     &completed_nbytes,
-+-						     &id) != 0) {
-++		while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
-++							    &completed_nbytes,
-++							    &id) != 0) {
-+ 			mdelay(1);
-+ 
-+ 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
-+@@ -574,9 +745,9 @@ static int ath10k_pci_diag_write_mem(str
-+ 		}
-+ 
-+ 		i = 0;
-+-		while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
-+-						     &completed_nbytes,
-+-						     &id, &flags) != 0) {
-++		while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-++							    &completed_nbytes,
-++							    &id, &flags) != 0) {
-+ 			mdelay(1);
-+ 
-+ 			if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
-+@@ -607,66 +778,36 @@ done:
-+ 	}
-+ 
-+ 	if (ret != 0)
-+-		ath10k_warn("failed to write diag value at 0x%x: %d\n",
-++		ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
-+ 			    address, ret);
-+ 
-++	spin_unlock_bh(&ar_pci->ce_lock);
-++
-+ 	return ret;
-+ }
-+ 
-+-/* Write 4B data to Target memory or register */
-+-static int ath10k_pci_diag_write_access(struct ath10k *ar, u32 address,
-+-					u32 data)
-+-{
-+-	/* Assume range doesn't cross this boundary */
-+-	if (address >= DRAM_BASE_ADDRESS)
-+-		return ath10k_pci_diag_write_mem(ar, address, &data,
-+-						 sizeof(u32));
-++static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value)
-++{
-++	__le32 val = __cpu_to_le32(value);
-+ 
-+-	ath10k_pci_wake(ar);
-+-	ath10k_pci_write32(ar, address, data);
-+-	ath10k_pci_sleep(ar);
-+-	return 0;
-++	return ath10k_pci_diag_write_mem(ar, address, &val, sizeof(val));
-+ }
-+ 
-+-static bool ath10k_pci_target_is_awake(struct ath10k *ar)
-++static bool ath10k_pci_is_awake(struct ath10k *ar)
-+ {
-+-	void __iomem *mem = ath10k_pci_priv(ar)->mem;
-+-	u32 val;
-+-	val = ioread32(mem + PCIE_LOCAL_BASE_ADDRESS +
-+-		       RTC_STATE_ADDRESS);
-+-	return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON);
-++	u32 val = ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS);
-++
-++	return RTC_STATE_V_GET(val) == RTC_STATE_V_ON;
-+ }
-+ 
-+-int ath10k_do_pci_wake(struct ath10k *ar)
-++static int ath10k_pci_wake_wait(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	void __iomem *pci_addr = ar_pci->mem;
-+ 	int tot_delay = 0;
-+ 	int curr_delay = 5;
-+ 
-+-	if (atomic_read(&ar_pci->keep_awake_count) == 0) {
-+-		/* Force AWAKE */
-+-		iowrite32(PCIE_SOC_WAKE_V_MASK,
-+-			  pci_addr + PCIE_LOCAL_BASE_ADDRESS +
-+-			  PCIE_SOC_WAKE_ADDRESS);
-+-	}
-+-	atomic_inc(&ar_pci->keep_awake_count);
-+-
-+-	if (ar_pci->verified_awake)
-+-		return 0;
-+-
-+-	for (;;) {
-+-		if (ath10k_pci_target_is_awake(ar)) {
-+-			ar_pci->verified_awake = true;
-++	while (tot_delay < PCIE_WAKE_TIMEOUT) {
-++		if (ath10k_pci_is_awake(ar))
-+ 			return 0;
-+-		}
-+-
-+-		if (tot_delay > PCIE_WAKE_TIMEOUT) {
-+-			ath10k_warn("target took longer %d us to wake up (awake count %d)\n",
-+-				    PCIE_WAKE_TIMEOUT,
-+-				    atomic_read(&ar_pci->keep_awake_count));
-+-			return -ETIMEDOUT;
-+-		}
-+ 
-+ 		udelay(curr_delay);
-+ 		tot_delay += curr_delay;
-+@@ -674,20 +815,21 @@ int ath10k_do_pci_wake(struct ath10k *ar
-+ 		if (curr_delay < 50)
-+ 			curr_delay += 5;
-+ 	}
-++
-++	return -ETIMEDOUT;
-+ }
-+ 
-+-void ath10k_do_pci_sleep(struct ath10k *ar)
-++static int ath10k_pci_wake(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	void __iomem *pci_addr = ar_pci->mem;
-++	ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
-++			       PCIE_SOC_WAKE_V_MASK);
-++	return ath10k_pci_wake_wait(ar);
-++}
-+ 
-+-	if (atomic_dec_and_test(&ar_pci->keep_awake_count)) {
-+-		/* Allow sleep */
-+-		ar_pci->verified_awake = false;
-+-		iowrite32(PCIE_SOC_WAKE_RESET,
-+-			  pci_addr + PCIE_LOCAL_BASE_ADDRESS +
-+-			  PCIE_SOC_WAKE_ADDRESS);
-+-	}
-++static void ath10k_pci_sleep(struct ath10k *ar)
-++{
-++	ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
-++			       PCIE_SOC_WAKE_RESET);
-+ }
-+ 
-+ /* Called by lower (CE) layer when a send to Target completes. */
-+@@ -696,20 +838,24 @@ static void ath10k_pci_ce_send_done(stru
-+ 	struct ath10k *ar = ce_state->ar;
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
-+-	void *transfer_context;
-++	struct sk_buff_head list;
-++	struct sk_buff *skb;
-+ 	u32 ce_data;
-+ 	unsigned int nbytes;
-+ 	unsigned int transfer_id;
-+ 
-+-	while (ath10k_ce_completed_send_next(ce_state, &transfer_context,
-+-					     &ce_data, &nbytes,
-+-					     &transfer_id) == 0) {
-++	__skb_queue_head_init(&list);
-++	while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
-++					     &nbytes, &transfer_id) == 0) {
-+ 		/* no need to call tx completion for NULL pointers */
-+-		if (transfer_context == NULL)
-++		if (skb == NULL)
-+ 			continue;
-+ 
-+-		cb->tx_completion(ar, transfer_context, transfer_id);
-++		__skb_queue_tail(&list, skb);
-+ 	}
-++
-++	while ((skb = __skb_dequeue(&list)))
-++		cb->tx_completion(ar, skb);
-+ }
-+ 
-+ /* Called by lower (CE) layer when data is received from the Target. */
-+@@ -720,38 +866,43 @@ static void ath10k_pci_ce_recv_data(stru
-+ 	struct ath10k_pci_pipe *pipe_info =  &ar_pci->pipe_info[ce_state->id];
-+ 	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
-+ 	struct sk_buff *skb;
-++	struct sk_buff_head list;
-+ 	void *transfer_context;
-+ 	u32 ce_data;
-+ 	unsigned int nbytes, max_nbytes;
-+ 	unsigned int transfer_id;
-+ 	unsigned int flags;
-+-	int err;
-+ 
-++	__skb_queue_head_init(&list);
-+ 	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
-+ 					     &ce_data, &nbytes, &transfer_id,
-+ 					     &flags) == 0) {
-+-		err = ath10k_pci_post_rx_pipe(pipe_info, 1);
-+-		if (unlikely(err)) {
-+-			/* FIXME: retry */
-+-			ath10k_warn("failed to replenish CE rx ring %d: %d\n",
-+-				    pipe_info->pipe_num, err);
-+-		}
-+-
-+ 		skb = transfer_context;
-+ 		max_nbytes = skb->len + skb_tailroom(skb);
-+-		dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
-++		dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
-+ 				 max_nbytes, DMA_FROM_DEVICE);
-+ 
-+ 		if (unlikely(max_nbytes < nbytes)) {
-+-			ath10k_warn("rxed more than expected (nbytes %d, max %d)",
-++			ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)",
-+ 				    nbytes, max_nbytes);
-+ 			dev_kfree_skb_any(skb);
-+ 			continue;
-+ 		}
-+ 
-+ 		skb_put(skb, nbytes);
-+-		cb->rx_completion(ar, skb, pipe_info->pipe_num);
-++		__skb_queue_tail(&list, skb);
-++	}
-++
-++	while ((skb = __skb_dequeue(&list))) {
-++		ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
-++			   ce_state->id, skb->len);
-++		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
-++				skb->data, skb->len);
-++
-++		cb->rx_completion(ar, skb);
-+ 	}
-++
-++	ath10k_pci_rx_post_pipe(pipe_info);
-+ }
-+ 
-+ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
-+@@ -761,24 +912,28 @@ static int ath10k_pci_hif_tx_sg(struct a
-+ 	struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id];
-+ 	struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl;
-+ 	struct ath10k_ce_ring *src_ring = ce_pipe->src_ring;
-+-	unsigned int nentries_mask = src_ring->nentries_mask;
-+-	unsigned int sw_index = src_ring->sw_index;
-+-	unsigned int write_index = src_ring->write_index;
-+-	int err, i;
-++	unsigned int nentries_mask;
-++	unsigned int sw_index;
-++	unsigned int write_index;
-++	int err, i = 0;
-+ 
-+ 	spin_lock_bh(&ar_pci->ce_lock);
-+ 
-++	nentries_mask = src_ring->nentries_mask;
-++	sw_index = src_ring->sw_index;
-++	write_index = src_ring->write_index;
-++
-+ 	if (unlikely(CE_RING_DELTA(nentries_mask,
-+ 				   write_index, sw_index - 1) < n_items)) {
-+ 		err = -ENOBUFS;
-+-		goto unlock;
-++		goto err;
-+ 	}
-+ 
-+ 	for (i = 0; i < n_items - 1; i++) {
-+-		ath10k_dbg(ATH10K_DBG_PCI,
-++		ath10k_dbg(ar, ATH10K_DBG_PCI,
-+ 			   "pci tx item %d paddr 0x%08x len %d n_items %d\n",
-+ 			   i, items[i].paddr, items[i].len, n_items);
-+-		ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, "item data: ",
-++		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci tx data: ",
-+ 				items[i].vaddr, items[i].len);
-+ 
-+ 		err = ath10k_ce_send_nolock(ce_pipe,
-+@@ -788,15 +943,15 @@ static int ath10k_pci_hif_tx_sg(struct a
-+ 					    items[i].transfer_id,
-+ 					    CE_SEND_FLAG_GATHER);
-+ 		if (err)
-+-			goto unlock;
-++			goto err;
-+ 	}
-+ 
-+ 	/* `i` is equal to `n_items -1` after for() */
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI,
-++	ath10k_dbg(ar, ATH10K_DBG_PCI,
-+ 		   "pci tx item %d paddr 0x%08x len %d n_items %d\n",
-+ 		   i, items[i].paddr, items[i].len, n_items);
-+-	ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, "item data: ",
-++	ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci tx data: ",
-+ 			items[i].vaddr, items[i].len);
-+ 
-+ 	err = ath10k_ce_send_nolock(ce_pipe,
-+@@ -806,64 +961,89 @@ static int ath10k_pci_hif_tx_sg(struct a
-+ 				    items[i].transfer_id,
-+ 				    0);
-+ 	if (err)
-+-		goto unlock;
-++		goto err;
-++
-++	spin_unlock_bh(&ar_pci->ce_lock);
-++	return 0;
-++
-++err:
-++	for (; i > 0; i--)
-++		__ath10k_ce_send_revert(ce_pipe);
-+ 
-+-	err = 0;
-+-unlock:
-+ 	spin_unlock_bh(&ar_pci->ce_lock);
-+ 	return err;
-+ }
-+ 
-++static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
-++				    size_t buf_len)
-++{
-++	return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
-++}
-++
-+ static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci hif get free queue number\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get free queue number\n");
-+ 
-+ 	return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl);
-+ }
-+ 
-+-static void ath10k_pci_hif_dump_area(struct ath10k *ar)
-++static void ath10k_pci_dump_registers(struct ath10k *ar,
-++				      struct ath10k_fw_crash_data *crash_data)
-+ {
-+-	u32 reg_dump_area = 0;
-+-	u32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {};
-+-	u32 host_addr;
-+-	int ret;
-+-	u32 i;
-+-
-+-	ath10k_err("firmware crashed!\n");
-+-	ath10k_err("hardware name %s version 0x%x\n",
-+-		   ar->hw_params.name, ar->target_version);
-+-	ath10k_err("firmware version: %s\n", ar->hw->wiphy->fw_version);
-+-
-+-	host_addr = host_interest_item_address(HI_ITEM(hi_failure_state));
-+-	ret = ath10k_pci_diag_read_mem(ar, host_addr,
-+-				       &reg_dump_area, sizeof(u32));
-+-	if (ret) {
-+-		ath10k_err("failed to read FW dump area address: %d\n", ret);
-+-		return;
-+-	}
-++	__le32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {};
-++	int i, ret;
-+ 
-+-	ath10k_err("target register Dump Location: 0x%08X\n", reg_dump_area);
-++	lockdep_assert_held(&ar->data_lock);
-+ 
-+-	ret = ath10k_pci_diag_read_mem(ar, reg_dump_area,
-+-				       &reg_dump_values[0],
-+-				       REG_DUMP_COUNT_QCA988X * sizeof(u32));
-+-	if (ret != 0) {
-+-		ath10k_err("failed to read FW dump area: %d\n", ret);
-++	ret = ath10k_pci_diag_read_hi(ar, &reg_dump_values[0],
-++				      hi_failure_state,
-++				      REG_DUMP_COUNT_QCA988X * sizeof(__le32));
-++	if (ret) {
-++		ath10k_err(ar, "failed to read firmware dump area: %d\n", ret);
-+ 		return;
-+ 	}
-+ 
-+ 	BUILD_BUG_ON(REG_DUMP_COUNT_QCA988X % 4);
-+ 
-+-	ath10k_err("target Register Dump\n");
-++	ath10k_err(ar, "firmware register dump:\n");
-+ 	for (i = 0; i < REG_DUMP_COUNT_QCA988X; i += 4)
-+-		ath10k_err("[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X\n",
-++		ath10k_err(ar, "[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X\n",
-+ 			   i,
-+-			   reg_dump_values[i],
-+-			   reg_dump_values[i + 1],
-+-			   reg_dump_values[i + 2],
-+-			   reg_dump_values[i + 3]);
-++			   __le32_to_cpu(reg_dump_values[i]),
-++			   __le32_to_cpu(reg_dump_values[i + 1]),
-++			   __le32_to_cpu(reg_dump_values[i + 2]),
-++			   __le32_to_cpu(reg_dump_values[i + 3]));
-++
-++	if (!crash_data)
-++		return;
-++
-++	for (i = 0; i < REG_DUMP_COUNT_QCA988X; i++)
-++		crash_data->registers[i] = reg_dump_values[i];
-++}
-++
-++static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
-++{
-++	struct ath10k_fw_crash_data *crash_data;
-++	char uuid[50];
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	ar->stats.fw_crash_counter++;
-++
-++	crash_data = ath10k_debug_get_new_fw_crash_data(ar);
-++
-++	if (crash_data)
-++		scnprintf(uuid, sizeof(uuid), "%pUl", &crash_data->uuid);
-++	else
-++		scnprintf(uuid, sizeof(uuid), "n/a");
-++
-++	ath10k_err(ar, "firmware crashed! (uuid %s)\n", uuid);
-++	ath10k_print_driver_info(ar);
-++	ath10k_pci_dump_registers(ar, crash_data);
-++
-++	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	queue_work(ar->workqueue, &ar->restart_work);
-+ }
-+@@ -871,7 +1051,7 @@ static void ath10k_pci_hif_dump_area(str
-+ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
-+ 					       int force)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci hif send complete check\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif send complete check\n");
-+ 
-+ 	if (!force) {
-+ 		int resources;
-+@@ -899,43 +1079,12 @@ static void ath10k_pci_hif_set_callbacks
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci hif set callbacks\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif set callbacks\n");
-+ 
-+ 	memcpy(&ar_pci->msg_callbacks_current, callbacks,
-+ 	       sizeof(ar_pci->msg_callbacks_current));
-+ }
-+ 
-+-static int ath10k_pci_setup_ce_irq(struct ath10k *ar)
-+-{
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	const struct ce_attr *attr;
-+-	struct ath10k_pci_pipe *pipe_info;
-+-	int pipe_num, disable_interrupts;
-+-
-+-	for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
-+-		pipe_info = &ar_pci->pipe_info[pipe_num];
-+-
-+-		/* Handle Diagnostic CE specially */
-+-		if (pipe_info->ce_hdl == ar_pci->ce_diag)
-+-			continue;
-+-
-+-		attr = &host_ce_config_wlan[pipe_num];
-+-
-+-		if (attr->src_nentries) {
-+-			disable_interrupts = attr->flags & CE_ATTR_DIS_INTR;
-+-			ath10k_ce_send_cb_register(pipe_info->ce_hdl,
-+-						   ath10k_pci_ce_send_done,
-+-						   disable_interrupts);
-+-		}
-+-
-+-		if (attr->dest_nentries)
-+-			ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
-+-						   ath10k_pci_ce_recv_data);
-+-	}
-+-
-+-	return 0;
-+-}
-+-
-+ static void ath10k_pci_kill_tasklet(struct ath10k *ar)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+@@ -943,82 +1092,72 @@ static void ath10k_pci_kill_tasklet(stru
-+ 
-+ 	tasklet_kill(&ar_pci->intr_tq);
-+ 	tasklet_kill(&ar_pci->msi_fw_err);
-+-	tasklet_kill(&ar_pci->early_irq_tasklet);
-+ 
-+ 	for (i = 0; i < CE_COUNT; i++)
-+ 		tasklet_kill(&ar_pci->pipe_info[i].intr);
-++
-++	del_timer_sync(&ar_pci->rx_post_retry);
-+ }
-+ 
-+-/* TODO - temporary mapping while we have too few CE's */
-+ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
-+ 					      u16 service_id, u8 *ul_pipe,
-+ 					      u8 *dl_pipe, int *ul_is_polled,
-+ 					      int *dl_is_polled)
-+ {
-+-	int ret = 0;
-++	const struct service_to_pipe *entry;
-++	bool ul_set = false, dl_set = false;
-++	int i;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci hif map service\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif map service\n");
-+ 
-+ 	/* polling for received messages not supported */
-+ 	*dl_is_polled = 0;
-+ 
-+-	switch (service_id) {
-+-	case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
-+-		/*
-+-		 * Host->target HTT gets its own pipe, so it can be polled
-+-		 * while other pipes are interrupt driven.
-+-		 */
-+-		*ul_pipe = 4;
-+-		/*
-+-		 * Use the same target->host pipe for HTC ctrl, HTC raw
-+-		 * streams, and HTT.
-+-		 */
-+-		*dl_pipe = 1;
-+-		break;
-++	for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
-++		entry = &target_service_to_ce_map_wlan[i];
-+ 
-+-	case ATH10K_HTC_SVC_ID_RSVD_CTRL:
-+-	case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
-+-		/*
-+-		 * Note: HTC_RAW_STREAMS_SVC is currently unused, and
-+-		 * HTC_CTRL_RSVD_SVC could share the same pipe as the
-+-		 * WMI services.  So, if another CE is needed, change
-+-		 * this to *ul_pipe = 3, which frees up CE 0.
-+-		 */
-+-		/* *ul_pipe = 3; */
-+-		*ul_pipe = 0;
-+-		*dl_pipe = 1;
-+-		break;
-++		if (__le32_to_cpu(entry->service_id) != service_id)
-++			continue;
-+ 
-+-	case ATH10K_HTC_SVC_ID_WMI_DATA_BK:
-+-	case ATH10K_HTC_SVC_ID_WMI_DATA_BE:
-+-	case ATH10K_HTC_SVC_ID_WMI_DATA_VI:
-+-	case ATH10K_HTC_SVC_ID_WMI_DATA_VO:
-+-
-+-	case ATH10K_HTC_SVC_ID_WMI_CONTROL:
-+-		*ul_pipe = 3;
-+-		*dl_pipe = 2;
-+-		break;
-++		switch (__le32_to_cpu(entry->pipedir)) {
-++		case PIPEDIR_NONE:
-++			break;
-++		case PIPEDIR_IN:
-++			WARN_ON(dl_set);
-++			*dl_pipe = __le32_to_cpu(entry->pipenum);
-++			dl_set = true;
-++			break;
-++		case PIPEDIR_OUT:
-++			WARN_ON(ul_set);
-++			*ul_pipe = __le32_to_cpu(entry->pipenum);
-++			ul_set = true;
-++			break;
-++		case PIPEDIR_INOUT:
-++			WARN_ON(dl_set);
-++			WARN_ON(ul_set);
-++			*dl_pipe = __le32_to_cpu(entry->pipenum);
-++			*ul_pipe = __le32_to_cpu(entry->pipenum);
-++			dl_set = true;
-++			ul_set = true;
-++			break;
-++		}
-++	}
-+ 
-+-		/* pipe 5 unused   */
-+-		/* pipe 6 reserved */
-+-		/* pipe 7 reserved */
-++	if (WARN_ON(!ul_set || !dl_set))
-++		return -ENOENT;
-+ 
-+-	default:
-+-		ret = -1;
-+-		break;
-+-	}
-+ 	*ul_is_polled =
-+ 		(host_ce_config_wlan[*ul_pipe].flags & CE_ATTR_DIS_INTR) != 0;
-+ 
-+-	return ret;
-++	return 0;
-+ }
-+ 
-+ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
-+-						u8 *ul_pipe, u8 *dl_pipe)
-++					    u8 *ul_pipe, u8 *dl_pipe)
-+ {
-+ 	int ul_is_polled, dl_is_polled;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci hif get default pipe\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n");
-+ 
-+ 	(void)ath10k_pci_hif_map_service_to_pipe(ar,
-+ 						 ATH10K_HTC_SVC_ID_RSVD_CTRL,
-+@@ -1028,209 +1167,127 @@ static void ath10k_pci_hif_get_default_p
-+ 						 &dl_is_polled);
-+ }
-+ 
-+-static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
-+-				   int num)
-++static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
-+ {
-+-	struct ath10k *ar = pipe_info->hif_ce_state;
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	struct ath10k_ce_pipe *ce_state = pipe_info->ce_hdl;
-+-	struct sk_buff *skb;
-+-	dma_addr_t ce_data;
-+-	int i, ret = 0;
-++	u32 val;
-+ 
-+-	if (pipe_info->buf_sz == 0)
-+-		return 0;
-++	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-++	val &= ~CORE_CTRL_PCIE_REG_31_MASK;
-+ 
-+-	for (i = 0; i < num; i++) {
-+-		skb = dev_alloc_skb(pipe_info->buf_sz);
-+-		if (!skb) {
-+-			ath10k_warn("failed to allocate skbuff for pipe %d\n",
-+-				    num);
-+-			ret = -ENOMEM;
-+-			goto err;
-+-		}
-++	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-++}
-+ 
-+-		WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
-++static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
-++{
-++	u32 val;
-+ 
-+-		ce_data = dma_map_single(ar->dev, skb->data,
-+-					 skb->len + skb_tailroom(skb),
-+-					 DMA_FROM_DEVICE);
-++	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-++	val |= CORE_CTRL_PCIE_REG_31_MASK;
-+ 
-+-		if (unlikely(dma_mapping_error(ar->dev, ce_data))) {
-+-			ath10k_warn("failed to DMA map sk_buff\n");
-+-			dev_kfree_skb_any(skb);
-+-			ret = -EIO;
-+-			goto err;
-+-		}
-++	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-++}
-+ 
-+-		ATH10K_SKB_CB(skb)->paddr = ce_data;
-++static void ath10k_pci_irq_disable(struct ath10k *ar)
-++{
-++	ath10k_ce_disable_interrupts(ar);
-++	ath10k_pci_disable_and_clear_legacy_irq(ar);
-++	ath10k_pci_irq_msi_fw_mask(ar);
-++}
-+ 
-+-		pci_dma_sync_single_for_device(ar_pci->pdev, ce_data,
-+-					       pipe_info->buf_sz,
-+-					       PCI_DMA_FROMDEVICE);
-+-
-+-		ret = ath10k_ce_recv_buf_enqueue(ce_state, (void *)skb,
-+-						 ce_data);
-+-		if (ret) {
-+-			ath10k_warn("failed to enqueue to pipe %d: %d\n",
-+-				    num, ret);
-+-			goto err;
-+-		}
-+-	}
-+-
-+-	return ret;
-+-
-+-err:
-+-	ath10k_pci_rx_pipe_cleanup(pipe_info);
-+-	return ret;
-+-}
-+-
-+-static int ath10k_pci_post_rx(struct ath10k *ar)
-++static void ath10k_pci_irq_sync(struct ath10k *ar)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	struct ath10k_pci_pipe *pipe_info;
-+-	const struct ce_attr *attr;
-+-	int pipe_num, ret = 0;
-+-
-+-	for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
-+-		pipe_info = &ar_pci->pipe_info[pipe_num];
-+-		attr = &host_ce_config_wlan[pipe_num];
-+-
-+-		if (attr->dest_nentries == 0)
-+-			continue;
-+-
-+-		ret = ath10k_pci_post_rx_pipe(pipe_info,
-+-					      attr->dest_nentries - 1);
-+-		if (ret) {
-+-			ath10k_warn("failed to post RX buffer for pipe %d: %d\n",
-+-				    pipe_num, ret);
-++	int i;
-+ 
-+-			for (; pipe_num >= 0; pipe_num--) {
-+-				pipe_info = &ar_pci->pipe_info[pipe_num];
-+-				ath10k_pci_rx_pipe_cleanup(pipe_info);
-+-			}
-+-			return ret;
-+-		}
-+-	}
-++	for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
-++		synchronize_irq(ar_pci->pdev->irq + i);
-++}
-+ 
-+-	return 0;
-++static void ath10k_pci_irq_enable(struct ath10k *ar)
-++{
-++	ath10k_ce_enable_interrupts(ar);
-++	ath10k_pci_enable_legacy_irq(ar);
-++	ath10k_pci_irq_msi_fw_unmask(ar);
-+ }
-+ 
-+ static int ath10k_pci_hif_start(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	int ret, ret_early;
-+-
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot hif start\n");
-+-
-+-	ath10k_pci_free_early_irq(ar);
-+-	ath10k_pci_kill_tasklet(ar);
-+-
-+-	ret = ath10k_pci_request_irq(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to post RX buffers for all pipes: %d\n",
-+-			    ret);
-+-		goto err_early_irq;
-+-	}
-+-
-+-	ret = ath10k_pci_setup_ce_irq(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to setup CE interrupts: %d\n", ret);
-+-		goto err_stop;
-+-	}
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
-+ 
-+-	/* Post buffers once to start things off. */
-+-	ret = ath10k_pci_post_rx(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to post RX buffers for all pipes: %d\n",
-+-			    ret);
-+-		goto err_stop;
-+-	}
-++	ath10k_pci_irq_enable(ar);
-++	ath10k_pci_rx_post(ar);
-+ 
-+-	ar_pci->started = 1;
-+ 	return 0;
-+-
-+-err_stop:
-+-	ath10k_ce_disable_interrupts(ar);
-+-	ath10k_pci_free_irq(ar);
-+-	ath10k_pci_kill_tasklet(ar);
-+-err_early_irq:
-+-	/* Though there should be no interrupts (device was reset)
-+-	 * power_down() expects the early IRQ to be installed as per the
-+-	 * driver lifecycle. */
-+-	ret_early = ath10k_pci_request_early_irq(ar);
-+-	if (ret_early)
-+-		ath10k_warn("failed to re-enable early irq: %d\n", ret_early);
-+-
-+-	return ret;
-+ }
-+ 
-+-static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
-++static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
-+ {
-+ 	struct ath10k *ar;
-+-	struct ath10k_pci *ar_pci;
-+-	struct ath10k_ce_pipe *ce_hdl;
-+-	u32 buf_sz;
-+-	struct sk_buff *netbuf;
-+-	u32 ce_data;
-++	struct ath10k_ce_pipe *ce_pipe;
-++	struct ath10k_ce_ring *ce_ring;
-++	struct sk_buff *skb;
-++	int i;
-+ 
-+-	buf_sz = pipe_info->buf_sz;
-++	ar = pci_pipe->hif_ce_state;
-++	ce_pipe = pci_pipe->ce_hdl;
-++	ce_ring = ce_pipe->dest_ring;
-+ 
-+-	/* Unused Copy Engine */
-+-	if (buf_sz == 0)
-++	if (!ce_ring)
-+ 		return;
-+ 
-+-	ar = pipe_info->hif_ce_state;
-+-	ar_pci = ath10k_pci_priv(ar);
-+-
-+-	if (!ar_pci->started)
-++	if (!pci_pipe->buf_sz)
-+ 		return;
-+ 
-+-	ce_hdl = pipe_info->ce_hdl;
-++	for (i = 0; i < ce_ring->nentries; i++) {
-++		skb = ce_ring->per_transfer_context[i];
-++		if (!skb)
-++			continue;
-++
-++		ce_ring->per_transfer_context[i] = NULL;
-+ 
-+-	while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf,
-+-					  &ce_data) == 0) {
-+-		dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr,
-+-				 netbuf->len + skb_tailroom(netbuf),
-++		dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
-++				 skb->len + skb_tailroom(skb),
-+ 				 DMA_FROM_DEVICE);
-+-		dev_kfree_skb_any(netbuf);
-++		dev_kfree_skb_any(skb);
-+ 	}
-+ }
-+ 
-+-static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
-++static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
-+ {
-+ 	struct ath10k *ar;
-+ 	struct ath10k_pci *ar_pci;
-+-	struct ath10k_ce_pipe *ce_hdl;
-+-	struct sk_buff *netbuf;
-+-	u32 ce_data;
-+-	unsigned int nbytes;
-++	struct ath10k_ce_pipe *ce_pipe;
-++	struct ath10k_ce_ring *ce_ring;
-++	struct ce_desc *ce_desc;
-++	struct sk_buff *skb;
-+ 	unsigned int id;
-+-	u32 buf_sz;
-++	int i;
-+ 
-+-	buf_sz = pipe_info->buf_sz;
-++	ar = pci_pipe->hif_ce_state;
-++	ar_pci = ath10k_pci_priv(ar);
-++	ce_pipe = pci_pipe->ce_hdl;
-++	ce_ring = ce_pipe->src_ring;
-+ 
-+-	/* Unused Copy Engine */
-+-	if (buf_sz == 0)
-++	if (!ce_ring)
-+ 		return;
-+ 
-+-	ar = pipe_info->hif_ce_state;
-+-	ar_pci = ath10k_pci_priv(ar);
-+-
-+-	if (!ar_pci->started)
-++	if (!pci_pipe->buf_sz)
-+ 		return;
-+ 
-+-	ce_hdl = pipe_info->ce_hdl;
-++	ce_desc = ce_ring->shadow_base;
-++	if (WARN_ON(!ce_desc))
-++		return;
-+ 
-+-	while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf,
-+-					  &ce_data, &nbytes, &id) == 0) {
-+-		/* no need to call tx completion for NULL pointers */
-+-		if (!netbuf)
-++	for (i = 0; i < ce_ring->nentries; i++) {
-++		skb = ce_ring->per_transfer_context[i];
-++		if (!skb)
-+ 			continue;
-+ 
-+-		ar_pci->msg_callbacks_current.tx_completion(ar,
-+-							    netbuf,
-+-							    id);
-++		ce_ring->per_transfer_context[i] = NULL;
-++		id = MS(__le16_to_cpu(ce_desc[i].flags),
-++			CE_DESC_FLAGS_META_DATA);
-++
-++		ar_pci->msg_callbacks_current.tx_completion(ar, skb);
-+ 	}
-+ }
-+ 
-+@@ -1264,38 +1321,32 @@ static void ath10k_pci_ce_deinit(struct
-+ 		ath10k_ce_deinit_pipe(ar, i);
-+ }
-+ 
-+-static void ath10k_pci_hif_stop(struct ath10k *ar)
-++static void ath10k_pci_flush(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	int ret;
-+-
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot hif stop\n");
-+-
-+-	ret = ath10k_ce_disable_interrupts(ar);
-+-	if (ret)
-+-		ath10k_warn("failed to disable CE interrupts: %d\n", ret);
-+-
-+-	ath10k_pci_free_irq(ar);
-+ 	ath10k_pci_kill_tasklet(ar);
-+-
-+-	ret = ath10k_pci_request_early_irq(ar);
-+-	if (ret)
-+-		ath10k_warn("failed to re-enable early irq: %d\n", ret);
-+-
-+-	/* At this point, asynchronous threads are stopped, the target should
-+-	 * not DMA nor interrupt. We process the leftovers and then free
-+-	 * everything else up. */
-+-
-+ 	ath10k_pci_buffer_cleanup(ar);
-++}
-+ 
-+-	/* Make the sure the device won't access any structures on the host by
-+-	 * resetting it. The device was fed with PCI CE ringbuffer
-+-	 * configuration during init. If ringbuffers are freed and the device
-+-	 * were to access them this could lead to memory corruption on the
-+-	 * host. */
-++static void ath10k_pci_hif_stop(struct ath10k *ar)
-++{
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
-++
-++	/* Most likely the device has HTT Rx ring configured. The only way to
-++	 * prevent the device from accessing (and possible corrupting) host
-++	 * memory is to reset the chip now.
-++	 *
-++	 * There's also no known way of masking MSI interrupts on the device.
-++	 * For ranged MSI the CE-related interrupts can be masked. However
-++	 * regardless how many MSI interrupts are assigned the first one
-++	 * is always used for firmware indications (crashes) and cannot be
-++	 * masked. To prevent the device from asserting the interrupt reset it
-++	 * before proceeding with cleanup.
-++	 */
-+ 	ath10k_pci_warm_reset(ar);
-+ 
-+-	ar_pci->started = 0;
-++	ath10k_pci_irq_disable(ar);
-++	ath10k_pci_irq_sync(ar);
-++	ath10k_pci_flush(ar);
-+ }
-+ 
-+ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
-+@@ -1346,11 +1397,9 @@ static int ath10k_pci_hif_exchange_bmi_m
-+ 		xfer.wait_for_resp = true;
-+ 		xfer.resp_len = 0;
-+ 
-+-		ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
-++		ath10k_ce_rx_post_buf(ce_rx, &xfer, resp_paddr);
-+ 	}
-+ 
-+-	init_completion(&xfer.done);
-+-
-+ 	ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
-+ 	if (ret)
-+ 		goto err_resp;
-+@@ -1401,14 +1450,12 @@ static void ath10k_pci_bmi_send_done(str
-+ 					  &nbytes, &transfer_id))
-+ 		return;
-+ 
-+-	if (xfer->wait_for_resp)
-+-		return;
-+-
-+-	complete(&xfer->done);
-++	xfer->tx_done = true;
-+ }
-+ 
-+ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
-+ {
-++	struct ath10k *ar = ce_state->ar;
-+ 	struct bmi_xfer *xfer;
-+ 	u32 ce_data;
-+ 	unsigned int nbytes;
-+@@ -1419,13 +1466,16 @@ static void ath10k_pci_bmi_recv_data(str
-+ 					  &nbytes, &transfer_id, &flags))
-+ 		return;
-+ 
-++	if (WARN_ON_ONCE(!xfer))
-++		return;
-++
-+ 	if (!xfer->wait_for_resp) {
-+-		ath10k_warn("unexpected: BMI data received; ignoring\n");
-++		ath10k_warn(ar, "unexpected: BMI data received; ignoring\n");
-+ 		return;
-+ 	}
-+ 
-+ 	xfer->resp_len = nbytes;
-+-	complete(&xfer->done);
-++	xfer->rx_done = true;
-+ }
-+ 
-+ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
-+@@ -1438,7 +1488,7 @@ static int ath10k_pci_bmi_wait(struct at
-+ 		ath10k_pci_bmi_send_done(tx_pipe);
-+ 		ath10k_pci_bmi_recv_data(rx_pipe);
-+ 
-+-		if (completion_done(&xfer->done))
-++		if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
-+ 			return 0;
-+ 
-+ 		schedule();
-+@@ -1448,131 +1498,48 @@ static int ath10k_pci_bmi_wait(struct at
-+ }
-+ 
-+ /*
-+- * Map from service/endpoint to Copy Engine.
-+- * This table is derived from the CE_PCI TABLE, above.
-+- * It is passed to the Target at startup for use by firmware.
-+- */
-+-static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_VO,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 3,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_VO,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 2,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_BK,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 3,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_BK,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 2,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_BE,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 3,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_BE,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 2,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_VI,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 3,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_DATA_VI,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 2,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_CONTROL,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 3,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_WMI_CONTROL,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 2,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_RSVD_CTRL,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 0,		/* could be moved to 3 (share with WMI) */
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_RSVD_CTRL,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 1,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS,	/* not currently used */
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 0,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS,	/* not currently used */
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 1,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_HTT_DATA_MSG,
-+-		 PIPEDIR_OUT,		/* out = UL = host -> target */
-+-		 4,
-+-	},
-+-	{
-+-		 ATH10K_HTC_SVC_ID_HTT_DATA_MSG,
-+-		 PIPEDIR_IN,		/* in = DL = target -> host */
-+-		 1,
-+-	},
-+-
-+-	/* (Additions here) */
-+-
-+-	{				/* Must be last */
-+-		 0,
-+-		 0,
-+-		 0,
-+-	},
-+-};
-+-
-+-/*
-+  * Send an interrupt to the device to wake up the Target CPU
-+  * so it has an opportunity to notice any changed state.
-+  */
-+ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
-+ {
-+-	int ret;
-+-	u32 core_ctrl;
-++	u32 addr, val;
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, SOC_CORE_BASE_ADDRESS |
-+-					      CORE_CTRL_ADDRESS,
-+-					  &core_ctrl);
-+-	if (ret) {
-+-		ath10k_warn("failed to read core_ctrl: %d\n", ret);
-+-		return ret;
-+-	}
-++	addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;
-++	val = ath10k_pci_read32(ar, addr);
-++	val |= CORE_CTRL_CPU_INTR_MASK;
-++	ath10k_pci_write32(ar, addr, val);
-+ 
-+-	/* A_INUM_FIRMWARE interrupt to Target CPU */
-+-	core_ctrl |= CORE_CTRL_CPU_INTR_MASK;
-++	return 0;
-++}
-+ 
-+-	ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS |
-+-					       CORE_CTRL_ADDRESS,
-+-					   core_ctrl);
-+-	if (ret) {
-+-		ath10k_warn("failed to set target CPU interrupt mask: %d\n",
-+-			    ret);
-+-		return ret;
-++static int ath10k_pci_get_num_banks(struct ath10k *ar)
-++{
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++
-++	switch (ar_pci->pdev->device) {
-++	case QCA988X_2_0_DEVICE_ID:
-++		return 1;
-++	case QCA6174_2_1_DEVICE_ID:
-++		switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) {
-++		case QCA6174_HW_1_0_CHIP_ID_REV:
-++		case QCA6174_HW_1_1_CHIP_ID_REV:
-++			return 3;
-++		case QCA6174_HW_1_3_CHIP_ID_REV:
-++			return 2;
-++		case QCA6174_HW_2_1_CHIP_ID_REV:
-++		case QCA6174_HW_2_2_CHIP_ID_REV:
-++			return 6;
-++		case QCA6174_HW_3_0_CHIP_ID_REV:
-++		case QCA6174_HW_3_1_CHIP_ID_REV:
-++		case QCA6174_HW_3_2_CHIP_ID_REV:
-++			return 9;
-++		}
-++		break;
-+ 	}
-+ 
-+-	return 0;
-++	ath10k_warn(ar, "unknown number of banks, assuming 1\n");
-++	return 1;
-+ }
-+ 
-+ static int ath10k_pci_init_config(struct ath10k *ar)
-+@@ -1593,144 +1560,162 @@ static int ath10k_pci_init_config(struct
-+ 		host_interest_item_address(HI_ITEM(hi_interconnect_state));
-+ 
-+ 	/* Supply Target-side CE configuration */
-+-	ret = ath10k_pci_diag_read_access(ar, interconnect_targ_addr,
-+-					  &pcie_state_targ_addr);
-++	ret = ath10k_pci_diag_read32(ar, interconnect_targ_addr,
-++				     &pcie_state_targ_addr);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to get pcie state addr: %d\n", ret);
-++		ath10k_err(ar, "Failed to get pcie state addr: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (pcie_state_targ_addr == 0) {
-+ 		ret = -EIO;
-+-		ath10k_err("Invalid pcie state addr\n");
-++		ath10k_err(ar, "Invalid pcie state addr\n");
-+ 		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
-++	ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
-+ 					  offsetof(struct pcie_state,
-+-						   pipe_cfg_addr),
-+-					  &pipe_cfg_targ_addr);
-++						   pipe_cfg_addr)),
-++				     &pipe_cfg_targ_addr);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to get pipe cfg addr: %d\n", ret);
-++		ath10k_err(ar, "Failed to get pipe cfg addr: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (pipe_cfg_targ_addr == 0) {
-+ 		ret = -EIO;
-+-		ath10k_err("Invalid pipe cfg addr\n");
-++		ath10k_err(ar, "Invalid pipe cfg addr\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr,
-+-				 target_ce_config_wlan,
-+-				 sizeof(target_ce_config_wlan));
-++					target_ce_config_wlan,
-++					sizeof(target_ce_config_wlan));
-+ 
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to write pipe cfg: %d\n", ret);
-++		ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
-++	ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
-+ 					  offsetof(struct pcie_state,
-+-						   svc_to_pipe_map),
-+-					  &svc_to_pipe_map);
-++						   svc_to_pipe_map)),
-++				     &svc_to_pipe_map);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to get svc/pipe map: %d\n", ret);
-++		ath10k_err(ar, "Failed to get svc/pipe map: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	if (svc_to_pipe_map == 0) {
-+ 		ret = -EIO;
-+-		ath10k_err("Invalid svc_to_pipe map\n");
-++		ath10k_err(ar, "Invalid svc_to_pipe map\n");
-+ 		return ret;
-+ 	}
-+ 
-+ 	ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map,
-+-				 target_service_to_ce_map_wlan,
-+-				 sizeof(target_service_to_ce_map_wlan));
-++					target_service_to_ce_map_wlan,
-++					sizeof(target_service_to_ce_map_wlan));
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to write svc/pipe map: %d\n", ret);
-++		ath10k_err(ar, "Failed to write svc/pipe map: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
-++	ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
-+ 					  offsetof(struct pcie_state,
-+-						   config_flags),
-+-					  &pcie_config_flags);
-++						   config_flags)),
-++				     &pcie_config_flags);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to get pcie config_flags: %d\n", ret);
-++		ath10k_err(ar, "Failed to get pcie config_flags: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1;
-+ 
-+-	ret = ath10k_pci_diag_write_mem(ar, pcie_state_targ_addr +
-+-				 offsetof(struct pcie_state, config_flags),
-+-				 &pcie_config_flags,
-+-				 sizeof(pcie_config_flags));
-++	ret = ath10k_pci_diag_write32(ar, (pcie_state_targ_addr +
-++					   offsetof(struct pcie_state,
-++						    config_flags)),
-++				      pcie_config_flags);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to write pcie config_flags: %d\n", ret);
-++		ath10k_err(ar, "Failed to write pcie config_flags: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* configure early allocation */
-+ 	ealloc_targ_addr = host_interest_item_address(HI_ITEM(hi_early_alloc));
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, ealloc_targ_addr, &ealloc_value);
-++	ret = ath10k_pci_diag_read32(ar, ealloc_targ_addr, &ealloc_value);
-+ 	if (ret != 0) {
-+-		ath10k_err("Faile to get early alloc val: %d\n", ret);
-++		ath10k_err(ar, "Faile to get early alloc val: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* first bank is switched to IRAM */
-+ 	ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) &
-+ 			 HI_EARLY_ALLOC_MAGIC_MASK);
-+-	ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
-++	ealloc_value |= ((ath10k_pci_get_num_banks(ar) <<
-++			  HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
-+ 			 HI_EARLY_ALLOC_IRAM_BANKS_MASK);
-+ 
-+-	ret = ath10k_pci_diag_write_access(ar, ealloc_targ_addr, ealloc_value);
-++	ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to set early alloc val: %d\n", ret);
-++		ath10k_err(ar, "Failed to set early alloc val: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	/* Tell Target to proceed with initialization */
-+ 	flag2_targ_addr = host_interest_item_address(HI_ITEM(hi_option_flag2));
-+ 
-+-	ret = ath10k_pci_diag_read_access(ar, flag2_targ_addr, &flag2_value);
-++	ret = ath10k_pci_diag_read32(ar, flag2_targ_addr, &flag2_value);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to get option val: %d\n", ret);
-++		ath10k_err(ar, "Failed to get option val: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	flag2_value |= HI_OPTION_EARLY_CFG_DONE;
-+ 
-+-	ret = ath10k_pci_diag_write_access(ar, flag2_targ_addr, flag2_value);
-++	ret = ath10k_pci_diag_write32(ar, flag2_targ_addr, flag2_value);
-+ 	if (ret != 0) {
-+-		ath10k_err("Failed to set option val: %d\n", ret);
-++		ath10k_err(ar, "Failed to set option val: %d\n", ret);
-+ 		return ret;
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_pci_alloc_ce(struct ath10k *ar)
-++static int ath10k_pci_alloc_pipes(struct ath10k *ar)
-+ {
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct ath10k_pci_pipe *pipe;
-+ 	int i, ret;
-+ 
-+ 	for (i = 0; i < CE_COUNT; i++) {
-+-		ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
-++		pipe = &ar_pci->pipe_info[i];
-++		pipe->ce_hdl = &ar_pci->ce_states[i];
-++		pipe->pipe_num = i;
-++		pipe->hif_ce_state = ar;
-++
-++		ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i],
-++					   ath10k_pci_ce_send_done,
-++					   ath10k_pci_ce_recv_data);
-+ 		if (ret) {
-+-			ath10k_err("failed to allocate copy engine pipe %d: %d\n",
-++			ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
-+ 				   i, ret);
-+ 			return ret;
-+ 		}
-++
-++		/* Last CE is Diagnostic Window */
-++		if (i == CE_COUNT - 1) {
-++			ar_pci->ce_diag = pipe->ce_hdl;
-++			continue;
-++		}
-++
-++		pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max);
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_pci_free_ce(struct ath10k *ar)
-++static void ath10k_pci_free_pipes(struct ath10k *ar)
-+ {
-+ 	int i;
-+ 
-+@@ -1738,305 +1723,319 @@ static void ath10k_pci_free_ce(struct at
-+ 		ath10k_ce_free_pipe(ar, i);
-+ }
-+ 
-+-static int ath10k_pci_ce_init(struct ath10k *ar)
-++static int ath10k_pci_init_pipes(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	struct ath10k_pci_pipe *pipe_info;
-+-	const struct ce_attr *attr;
-+-	int pipe_num, ret;
-+-
-+-	for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
-+-		pipe_info = &ar_pci->pipe_info[pipe_num];
-+-		pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num];
-+-		pipe_info->pipe_num = pipe_num;
-+-		pipe_info->hif_ce_state = ar;
-+-		attr = &host_ce_config_wlan[pipe_num];
-++	int i, ret;
-+ 
-+-		ret = ath10k_ce_init_pipe(ar, pipe_num, attr);
-++	for (i = 0; i < CE_COUNT; i++) {
-++		ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);
-+ 		if (ret) {
-+-			ath10k_err("failed to initialize copy engine pipe %d: %d\n",
-+-				   pipe_num, ret);
-++			ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",
-++				   i, ret);
-+ 			return ret;
-+ 		}
-+-
-+-		if (pipe_num == CE_COUNT - 1) {
-+-			/*
-+-			 * Reserve the ultimate CE for
-+-			 * diagnostic Window support
-+-			 */
-+-			ar_pci->ce_diag = pipe_info->ce_hdl;
-+-			continue;
-+-		}
-+-
-+-		pipe_info->buf_sz = (size_t) (attr->src_sz_max);
-+ 	}
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
-++static bool ath10k_pci_has_fw_crashed(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	u32 fw_indicator;
-+-
-+-	ath10k_pci_wake(ar);
-+-
-+-	fw_indicator = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
-+-
-+-	if (fw_indicator & FW_IND_EVENT_PENDING) {
-+-		/* ACK: clear Target-side pending event */
-+-		ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS,
-+-				   fw_indicator & ~FW_IND_EVENT_PENDING);
-+-
-+-		if (ar_pci->started) {
-+-			ath10k_pci_hif_dump_area(ar);
-+-		} else {
-+-			/*
-+-			 * Probable Target failure before we're prepared
-+-			 * to handle it.  Generally unexpected.
-+-			 */
-+-			ath10k_warn("early firmware event indicated\n");
-+-		}
-+-	}
-+-
-+-	ath10k_pci_sleep(ar);
-++	return ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS) &
-++	       FW_IND_EVENT_PENDING;
-+ }
-+ 
-+-static int ath10k_pci_warm_reset(struct ath10k *ar)
-++static void ath10k_pci_fw_crashed_clear(struct ath10k *ar)
-+ {
-+-	int ret = 0;
-+ 	u32 val;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot warm reset\n");
-++	val = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
-++	val &= ~FW_IND_EVENT_PENDING;
-++	ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, val);
-++}
-+ 
-+-	ret = ath10k_do_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to wake up target: %d\n", ret);
-+-		return ret;
-+-	}
-++/* this function effectively clears target memory controller assert line */
-++static void ath10k_pci_warm_reset_si0(struct ath10k *ar)
-++{
-++	u32 val;
-+ 
-+-	/* debug */
-+-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				PCIE_INTR_CAUSE_ADDRESS);
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", val);
-++	val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
-++	ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
-++			       val | SOC_RESET_CONTROL_SI0_RST_MASK);
-++	val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
-+ 
-+-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				CPU_INTR_ADDRESS);
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
-+-		   val);
-++	msleep(10);
-+ 
-+-	/* disable pending irqs */
-+-	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
-+-			   PCIE_INTR_ENABLE_ADDRESS, 0);
-++	val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
-++	ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
-++			       val & ~SOC_RESET_CONTROL_SI0_RST_MASK);
-++	val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
-+ 
-+-	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
-+-			   PCIE_INTR_CLR_ADDRESS, ~0);
-++	msleep(10);
-++}
-+ 
-+-	msleep(100);
-++static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
-++{
-++	u32 val;
-+ 
-+-	/* clear fw indicator */
-+ 	ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
-+ 
-+-	/* clear target LF timer interrupts */
-+ 	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+-				SOC_LF_TIMER_CONTROL0_ADDRESS);
-+-	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
-+-			   SOC_LF_TIMER_CONTROL0_ADDRESS,
-+-			   val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
-++				SOC_RESET_CONTROL_ADDRESS);
-++	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-++			   val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
-++}
-++
-++static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
-++{
-++	u32 val;
-+ 
-+-	/* reset CE */
-+ 	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+ 				SOC_RESET_CONTROL_ADDRESS);
-++
-+ 	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-+ 			   val | SOC_RESET_CONTROL_CE_RST_MASK);
-+-	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+-				SOC_RESET_CONTROL_ADDRESS);
-+ 	msleep(10);
-+-
-+-	/* unreset CE */
-+ 	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-+ 			   val & ~SOC_RESET_CONTROL_CE_RST_MASK);
-+-	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+-				SOC_RESET_CONTROL_ADDRESS);
-+-	msleep(10);
-++}
-+ 
-+-	/* debug */
-+-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				PCIE_INTR_CAUSE_ADDRESS);
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", val);
-+-
-+-	val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
-+-				CPU_INTR_ADDRESS);
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
-+-		   val);
-++static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
-++{
-++	u32 val;
-+ 
-+-	/* CPU warm reset */
-+ 	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+-				SOC_RESET_CONTROL_ADDRESS);
-+-	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-+-			   val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
-++				SOC_LF_TIMER_CONTROL0_ADDRESS);
-++	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
-++			   SOC_LF_TIMER_CONTROL0_ADDRESS,
-++			   val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
-++}
-+ 
-+-	val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-+-				SOC_RESET_CONTROL_ADDRESS);
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n", val);
-++static int ath10k_pci_warm_reset(struct ath10k *ar)
-++{
-++	int ret;
-+ 
-+-	msleep(100);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot warm reset complete\n");
-++	spin_lock_bh(&ar->data_lock);
-++	ar->stats.fw_warm_reset_counter++;
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	ath10k_pci_irq_disable(ar);
-++
-++	/* Make sure the target CPU is not doing anything dangerous, e.g. if it
-++	 * were to access copy engine while host performs copy engine reset
-++	 * then it is possible for the device to confuse pci-e controller to
-++	 * the point of bringing host system to a complete stop (i.e. hang).
-++	 */
-++	ath10k_pci_warm_reset_si0(ar);
-++	ath10k_pci_warm_reset_cpu(ar);
-++	ath10k_pci_init_pipes(ar);
-++	ath10k_pci_wait_for_target_init(ar);
-++
-++	ath10k_pci_warm_reset_clear_lf(ar);
-++	ath10k_pci_warm_reset_ce(ar);
-++	ath10k_pci_warm_reset_cpu(ar);
-++	ath10k_pci_init_pipes(ar);
-+ 
-+-	ath10k_do_pci_sleep(ar);
-+-	return ret;
-++	ret = ath10k_pci_wait_for_target_init(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to wait for target init: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n");
-++
-++	return 0;
-+ }
-+ 
-+-static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset)
-++static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	const char *irq_mode;
-+-	int ret;
-++	int i, ret;
-++	u32 val;
-+ 
-+-	/*
-+-	 * Bring the target up cleanly.
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot 988x chip reset\n");
-++
-++	/* Some hardware revisions (e.g. CUS223v2) has issues with cold reset.
-++	 * It is thus preferred to use warm reset which is safer but may not be
-++	 * able to recover the device from all possible fail scenarios.
-+ 	 *
-+-	 * The target may be in an undefined state with an AUX-powered Target
-+-	 * and a Host in WoW mode. If the Host crashes, loses power, or is
-+-	 * restarted (without unloading the driver) then the Target is left
-+-	 * (aux) powered and running. On a subsequent driver load, the Target
-+-	 * is in an unexpected state. We try to catch that here in order to
-+-	 * reset the Target and retry the probe.
-++	 * Warm reset doesn't always work on first try so attempt it a few
-++	 * times before giving up.
-+ 	 */
-+-	if (cold_reset)
-+-		ret = ath10k_pci_cold_reset(ar);
-+-	else
-++	for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
-+ 		ret = ath10k_pci_warm_reset(ar);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n",
-++				    i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS,
-++				    ret);
-++			continue;
-++		}
-++
-++		/* FIXME: Sometimes copy engine doesn't recover after warm
-++		 * reset. In most cases this needs cold reset. In some of these
-++		 * cases the device is in such a state that a cold reset may
-++		 * lock up the host.
-++		 *
-++		 * Reading any host interest register via copy engine is
-++		 * sufficient to verify if device is capable of booting
-++		 * firmware blob.
-++		 */
-++		ret = ath10k_pci_init_pipes(ar);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to init copy engine: %d\n",
-++				    ret);
-++			continue;
-++		}
-++
-++		ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS,
-++					     &val);
-++		if (ret) {
-++			ath10k_warn(ar, "failed to poke copy engine: %d\n",
-++				    ret);
-++			continue;
-++		}
-++
-++		ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n");
-++		return 0;
-++	}
-+ 
-++	if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) {
-++		ath10k_warn(ar, "refusing cold reset as requested\n");
-++		return -EPERM;
-++	}
-++
-++	ret = ath10k_pci_cold_reset(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to reset target: %d\n", ret);
-+-		goto err;
-++		ath10k_warn(ar, "failed to cold reset: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ret = ath10k_pci_wait_for_target_init(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
-++			    ret);
-++		return ret;
-+ 	}
-+ 
-+-	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
-+-		/* Force AWAKE forever */
-+-		ath10k_do_pci_wake(ar);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca988x chip reset complete (cold)\n");
-+ 
-+-	ret = ath10k_pci_ce_init(ar);
-++	return 0;
-++}
-++
-++static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar)
-++{
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset\n");
-++
-++	/* FIXME: QCA6174 requires cold + warm reset to work. */
-++
-++	ret = ath10k_pci_cold_reset(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to initialize CE: %d\n", ret);
-+-		goto err_ps;
-++		ath10k_warn(ar, "failed to cold reset: %d\n", ret);
-++		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_ce_disable_interrupts(ar);
-++	ret = ath10k_pci_wait_for_target_init(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to disable CE interrupts: %d\n", ret);
-+-		goto err_ce;
-++		ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
-++				ret);
-++		return ret;
-+ 	}
-+ 
-+-	ret = ath10k_pci_init_irq(ar);
-++	ret = ath10k_pci_warm_reset(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to warm reset: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset complete (cold)\n");
-++
-++	return 0;
-++}
-++
-++static int ath10k_pci_chip_reset(struct ath10k *ar)
-++{
-++	if (QCA_REV_988X(ar))
-++		return ath10k_pci_qca988x_chip_reset(ar);
-++	else if (QCA_REV_6174(ar))
-++		return ath10k_pci_qca6174_chip_reset(ar);
-++	else
-++		return -ENOTSUPP;
-++}
-++
-++static int ath10k_pci_hif_power_up(struct ath10k *ar)
-++{
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
-++
-++	ret = ath10k_pci_wake(ar);
-++	if (ret) {
-++		ath10k_err(ar, "failed to wake up target: %d\n", ret);
-++		return ret;
-++	}
-++
-++	/*
-++	 * Bring the target up cleanly.
-++	 *
-++	 * The target may be in an undefined state with an AUX-powered Target
-++	 * and a Host in WoW mode. If the Host crashes, loses power, or is
-++	 * restarted (without unloading the driver) then the Target is left
-++	 * (aux) powered and running. On a subsequent driver load, the Target
-++	 * is in an unexpected state. We try to catch that here in order to
-++	 * reset the Target and retry the probe.
-++	 */
-++	ret = ath10k_pci_chip_reset(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to init irqs: %d\n", ret);
-+-		goto err_ce;
-+-	}
-++		if (ath10k_pci_has_fw_crashed(ar)) {
-++			ath10k_warn(ar, "firmware crashed during chip reset\n");
-++			ath10k_pci_fw_crashed_clear(ar);
-++			ath10k_pci_fw_crashed_dump(ar);
-++		}
-+ 
-+-	ret = ath10k_pci_request_early_irq(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to request early irq: %d\n", ret);
-+-		goto err_deinit_irq;
-++		ath10k_err(ar, "failed to reset chip: %d\n", ret);
-++		goto err_sleep;
-+ 	}
-+ 
-+-	ret = ath10k_pci_wait_for_target_init(ar);
-++	ret = ath10k_pci_init_pipes(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to wait for target to init: %d\n", ret);
-+-		goto err_free_early_irq;
-++		ath10k_err(ar, "failed to initialize CE: %d\n", ret);
-++		goto err_sleep;
-+ 	}
-+ 
-+ 	ret = ath10k_pci_init_config(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to setup init config: %d\n", ret);
-+-		goto err_free_early_irq;
-++		ath10k_err(ar, "failed to setup init config: %d\n", ret);
-++		goto err_ce;
-+ 	}
-+ 
-+ 	ret = ath10k_pci_wake_target_cpu(ar);
-+ 	if (ret) {
-+-		ath10k_err("could not wake up target CPU: %d\n", ret);
-+-		goto err_free_early_irq;
-++		ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
-++		goto err_ce;
-+ 	}
-+ 
-+-	if (ar_pci->num_msi_intrs > 1)
-+-		irq_mode = "MSI-X";
-+-	else if (ar_pci->num_msi_intrs == 1)
-+-		irq_mode = "MSI";
-+-	else
-+-		irq_mode = "legacy";
-+-
-+-	if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
-+-		ath10k_info("pci irq %s irq_mode %d reset_mode %d\n",
-+-			    irq_mode, ath10k_pci_irq_mode,
-+-			    ath10k_pci_reset_mode);
-+-
-+ 	return 0;
-+ 
-+-err_free_early_irq:
-+-	ath10k_pci_free_early_irq(ar);
-+-err_deinit_irq:
-+-	ath10k_pci_deinit_irq(ar);
-+ err_ce:
-+ 	ath10k_pci_ce_deinit(ar);
-+-	ath10k_pci_warm_reset(ar);
-+-err_ps:
-+-	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
-+-		ath10k_do_pci_sleep(ar);
-+-err:
-+-	return ret;
-+-}
-+-
-+-static int ath10k_pci_hif_power_up(struct ath10k *ar)
-+-{
-+-	int ret;
-+-
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot hif power up\n");
-+-
-+-	/*
-+-	 * Hardware CUS232 version 2 has some issues with cold reset and the
-+-	 * preferred (and safer) way to perform a device reset is through a
-+-	 * warm reset.
-+-	 *
-+-	 * Warm reset doesn't always work though (notably after a firmware
-+-	 * crash) so fall back to cold reset if necessary.
-+-	 */
-+-	ret = __ath10k_pci_hif_power_up(ar, false);
-+-	if (ret) {
-+-		ath10k_warn("failed to power up target using warm reset: %d\n",
-+-			    ret);
-+-
-+-		if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
-+-			return ret;
-+ 
-+-		ath10k_warn("trying cold reset\n");
-+-
-+-		ret = __ath10k_pci_hif_power_up(ar, true);
-+-		if (ret) {
-+-			ath10k_err("failed to power up target using cold reset too (%d)\n",
-+-				   ret);
-+-			return ret;
-+-		}
-+-	}
-+-
-+-	return 0;
-++err_sleep:
-++	ath10k_pci_sleep(ar);
-++	return ret;
-+ }
-+ 
-+ static void ath10k_pci_hif_power_down(struct ath10k *ar)
-+ {
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n");
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot hif power down\n");
-+-
-+-	ath10k_pci_free_early_irq(ar);
-+-	ath10k_pci_kill_tasklet(ar);
-+-	ath10k_pci_deinit_irq(ar);
-+-	ath10k_pci_ce_deinit(ar);
-+-	ath10k_pci_warm_reset(ar);
-++	/* Currently hif_power_up performs effectively a reset and hif_stop
-++	 * resets the chip as well so there's no point in resetting here.
-++	 */
-+ 
-+-	if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
-+-		ath10k_do_pci_sleep(ar);
-++	ath10k_pci_sleep(ar);
-+ }
-+ 
-+ #ifdef CONFIG_PM
-+@@ -2090,6 +2089,8 @@ static int ath10k_pci_hif_resume(struct
-+ 
-+ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
-+ 	.tx_sg			= ath10k_pci_hif_tx_sg,
-++	.diag_read		= ath10k_pci_hif_diag_read,
-++	.diag_write		= ath10k_pci_diag_write_mem,
-+ 	.exchange_bmi_msg	= ath10k_pci_hif_exchange_bmi_msg,
-+ 	.start			= ath10k_pci_hif_start,
-+ 	.stop			= ath10k_pci_hif_stop,
-+@@ -2100,6 +2101,8 @@ static const struct ath10k_hif_ops ath10
-+ 	.get_free_queue_number	= ath10k_pci_hif_get_free_queue_number,
-+ 	.power_up		= ath10k_pci_hif_power_up,
-+ 	.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,
-+@@ -2118,7 +2121,14 @@ static void ath10k_msi_err_tasklet(unsig
-+ {
-+ 	struct ath10k *ar = (struct ath10k *)data;
-+ 
-+-	ath10k_pci_fw_interrupt_handler(ar);
-++	if (!ath10k_pci_has_fw_crashed(ar)) {
-++		ath10k_warn(ar, "received unsolicited fw crash interrupt\n");
-++		return;
-++	}
-++
-++	ath10k_pci_irq_disable(ar);
-++	ath10k_pci_fw_crashed_clear(ar);
-++	ath10k_pci_fw_crashed_dump(ar);
-+ }
-+ 
-+ /*
-+@@ -2132,7 +2142,8 @@ static irqreturn_t ath10k_pci_per_engine
-+ 	int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL;
-+ 
-+ 	if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_pci->pipe_info)) {
-+-		ath10k_warn("unexpected/invalid irq %d ce_id %d\n", irq, ce_id);
-++		ath10k_warn(ar, "unexpected/invalid irq %d ce_id %d\n", irq,
-++			    ce_id);
-+ 		return IRQ_HANDLED;
-+ 	}
-+ 
-+@@ -2179,39 +2190,18 @@ static irqreturn_t ath10k_pci_interrupt_
-+ 	return IRQ_HANDLED;
-+ }
-+ 
-+-static void ath10k_pci_early_irq_tasklet(unsigned long data)
-++static void ath10k_pci_tasklet(unsigned long data)
-+ {
-+ 	struct ath10k *ar = (struct ath10k *)data;
-+-	u32 fw_ind;
-+-	int ret;
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to wake target in early irq tasklet: %d\n",
-+-			    ret);
-++	if (ath10k_pci_has_fw_crashed(ar)) {
-++		ath10k_pci_irq_disable(ar);
-++		ath10k_pci_fw_crashed_clear(ar);
-++		ath10k_pci_fw_crashed_dump(ar);
-+ 		return;
-+ 	}
-+ 
-+-	fw_ind = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
-+-	if (fw_ind & FW_IND_EVENT_PENDING) {
-+-		ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS,
-+-				   fw_ind & ~FW_IND_EVENT_PENDING);
-+-
-+-		/* Some structures are unavailable during early boot or at
-+-		 * driver teardown so just print that the device has crashed. */
-+-		ath10k_warn("device crashed - no diagnostics available\n");
-+-	}
-+-
-+-	ath10k_pci_sleep(ar);
-+-	ath10k_pci_enable_legacy_irq(ar);
-+-}
-+-
-+-static void ath10k_pci_tasklet(unsigned long data)
-+-{
-+-	struct ath10k *ar = (struct ath10k *)data;
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-
-+-	ath10k_pci_fw_interrupt_handler(ar); /* FIXME: Handle FW error */
-+ 	ath10k_ce_per_engine_service_any(ar);
-+ 
-+ 	/* Re-enable legacy irq that was disabled in the irq handler */
-+@@ -2228,7 +2218,7 @@ static int ath10k_pci_request_irq_msix(s
-+ 			  ath10k_pci_msi_fw_handler,
-+ 			  IRQF_SHARED, "ath10k_pci", ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request MSI-X fw irq %d: %d\n",
-++		ath10k_warn(ar, "failed to request MSI-X fw irq %d: %d\n",
-+ 			    ar_pci->pdev->irq + MSI_ASSIGN_FW, ret);
-+ 		return ret;
-+ 	}
-+@@ -2238,7 +2228,7 @@ static int ath10k_pci_request_irq_msix(s
-+ 				  ath10k_pci_per_engine_handler,
-+ 				  IRQF_SHARED, "ath10k_pci", ar);
-+ 		if (ret) {
-+-			ath10k_warn("failed to request MSI-X ce irq %d: %d\n",
-++			ath10k_warn(ar, "failed to request MSI-X ce irq %d: %d\n",
-+ 				    ar_pci->pdev->irq + i, ret);
-+ 
-+ 			for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--)
-+@@ -2261,7 +2251,7 @@ static int ath10k_pci_request_irq_msi(st
-+ 			  ath10k_pci_interrupt_handler,
-+ 			  IRQF_SHARED, "ath10k_pci", ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request MSI irq %d: %d\n",
-++		ath10k_warn(ar, "failed to request MSI irq %d: %d\n",
-+ 			    ar_pci->pdev->irq, ret);
-+ 		return ret;
-+ 	}
-+@@ -2278,7 +2268,7 @@ static int ath10k_pci_request_irq_legacy
-+ 			  ath10k_pci_interrupt_handler,
-+ 			  IRQF_SHARED, "ath10k_pci", ar);
-+ 	if (ret) {
-+-		ath10k_warn("failed to request legacy irq %d: %d\n",
-++		ath10k_warn(ar, "failed to request legacy irq %d: %d\n",
-+ 			    ar_pci->pdev->irq, ret);
-+ 		return ret;
-+ 	}
-+@@ -2299,7 +2289,7 @@ static int ath10k_pci_request_irq(struct
-+ 		return ath10k_pci_request_irq_msix(ar);
-+ 	}
-+ 
-+-	ath10k_warn("unknown irq configuration upon request\n");
-++	ath10k_warn(ar, "unknown irq configuration upon request\n");
-+ 	return -EINVAL;
-+ }
-+ 
-+@@ -2322,8 +2312,6 @@ static void ath10k_pci_init_irq_tasklets
-+ 	tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
-+ 	tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet,
-+ 		     (unsigned long)ar);
-+-	tasklet_init(&ar_pci->early_irq_tasklet, ath10k_pci_early_irq_tasklet,
-+-		     (unsigned long)ar);
-+ 
-+ 	for (i = 0; i < CE_COUNT; i++) {
-+ 		ar_pci->pipe_info[i].ar_pci = ar_pci;
-+@@ -2335,21 +2323,19 @@ static void ath10k_pci_init_irq_tasklets
-+ static int ath10k_pci_init_irq(struct ath10k *ar)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-	bool msix_supported = test_bit(ATH10K_PCI_FEATURE_MSI_X,
-+-				       ar_pci->features);
-+ 	int ret;
-+ 
-+ 	ath10k_pci_init_irq_tasklets(ar);
-+ 
-+-	if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO &&
-+-	    !test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
-+-		ath10k_info("limiting irq mode to: %d\n", ath10k_pci_irq_mode);
-++	if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO)
-++		ath10k_info(ar, "limiting irq mode to: %d\n",
-++			    ath10k_pci_irq_mode);
-+ 
-+ 	/* Try MSI-X */
-+-	if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) {
-++	if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
-+ 		ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
-+ 		ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
-+-							 ar_pci->num_msi_intrs);
-++					   ar_pci->num_msi_intrs);
-+ 		if (ret > 0)
-+ 			return 0;
-+ 
-+@@ -2376,34 +2362,16 @@ static int ath10k_pci_init_irq(struct at
-+ 	 * synchronization checking. */
-+ 	ar_pci->num_msi_intrs = 0;
-+ 
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to wake target: %d\n", ret);
-+-		return ret;
-+-	}
-+-
-+ 	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
-+ 			   PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
-+-	ath10k_pci_sleep(ar);
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_pci_deinit_irq_legacy(struct ath10k *ar)
-++static void ath10k_pci_deinit_irq_legacy(struct ath10k *ar)
-+ {
-+-	int ret;
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_warn("failed to wake target: %d\n", ret);
-+-		return ret;
-+-	}
-+-
-+ 	ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
-+ 			   0);
-+-	ath10k_pci_sleep(ar);
-+-
-+-	return 0;
-+ }
-+ 
-+ static int ath10k_pci_deinit_irq(struct ath10k *ar)
-+@@ -2412,7 +2380,8 @@ static int ath10k_pci_deinit_irq(struct
-+ 
-+ 	switch (ar_pci->num_msi_intrs) {
-+ 	case 0:
-+-		return ath10k_pci_deinit_irq_legacy(ar);
-++		ath10k_pci_deinit_irq_legacy(ar);
-++		return 0;
-+ 	case 1:
-+ 		/* fall-through */
-+ 	case MSI_NUM_REQUEST:
-+@@ -2422,7 +2391,7 @@ static int ath10k_pci_deinit_irq(struct
-+ 		pci_disable_msi(ar_pci->pdev);
-+ 	}
-+ 
-+-	ath10k_warn("unknown irq configuration upon deinit\n");
-++	ath10k_warn(ar, "unknown irq configuration upon deinit\n");
-+ 	return -EINVAL;
-+ }
-+ 
-+@@ -2430,23 +2399,17 @@ static int ath10k_pci_wait_for_target_in
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 	unsigned long timeout;
-+-	int ret;
-+ 	u32 val;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot waiting target to initialise\n");
-+-
-+-	ret = ath10k_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to wake up target for init: %d\n", ret);
-+-		return ret;
-+-	}
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot waiting target to initialise\n");
-+ 
-+ 	timeout = jiffies + msecs_to_jiffies(ATH10K_PCI_TARGET_WAIT);
-+ 
-+ 	do {
-+ 		val = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
-+ 
-+-		ath10k_dbg(ATH10K_DBG_BOOT, "boot target indicator %x\n", val);
-++		ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target indicator %x\n",
-++			   val);
-+ 
-+ 		/* target should never return this */
-+ 		if (val == 0xffffffff)
-+@@ -2461,52 +2424,46 @@ static int ath10k_pci_wait_for_target_in
-+ 
-+ 		if (ar_pci->num_msi_intrs == 0)
-+ 			/* Fix potential race by repeating CORE_BASE writes */
-+-			ath10k_pci_soc_write32(ar, PCIE_INTR_ENABLE_ADDRESS,
-+-					       PCIE_INTR_FIRMWARE_MASK |
-+-					       PCIE_INTR_CE_MASK_ALL);
-++			ath10k_pci_enable_legacy_irq(ar);
-+ 
-+ 		mdelay(10);
-+ 	} while (time_before(jiffies, timeout));
-+ 
-++	ath10k_pci_disable_and_clear_legacy_irq(ar);
-++	ath10k_pci_irq_msi_fw_mask(ar);
-++
-+ 	if (val == 0xffffffff) {
-+-		ath10k_err("failed to read device register, device is gone\n");
-+-		ret = -EIO;
-+-		goto out;
-++		ath10k_err(ar, "failed to read device register, device is gone\n");
-++		return -EIO;
-+ 	}
-+ 
-+ 	if (val & FW_IND_EVENT_PENDING) {
-+-		ath10k_warn("device has crashed during init\n");
-+-		ret = -ECOMM;
-+-		goto out;
-++		ath10k_warn(ar, "device has crashed during init\n");
-++		return -ECOMM;
-+ 	}
-+ 
-+ 	if (!(val & FW_IND_INITIALIZED)) {
-+-		ath10k_err("failed to receive initialized event from target: %08x\n",
-++		ath10k_err(ar, "failed to receive initialized event from target: %08x\n",
-+ 			   val);
-+-		ret = -ETIMEDOUT;
-+-		goto out;
-++		return -ETIMEDOUT;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot target initialised\n");
-+-
-+-out:
-+-	ath10k_pci_sleep(ar);
-+-	return ret;
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target initialised\n");
-++	return 0;
-+ }
-+ 
-+ static int ath10k_pci_cold_reset(struct ath10k *ar)
-+ {
-+-	int i, ret;
-++	int i;
-+ 	u32 val;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot cold reset\n");
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
-+ 
-+-	ret = ath10k_do_pci_wake(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to wake up target: %d\n",
-+-			   ret);
-+-		return ret;
-+-	}
-++	spin_lock_bh(&ar->data_lock);
-++
-++	ar->stats.fw_cold_reset_counter++;
-++
-++	spin_unlock_bh(&ar->data_lock);
-+ 
-+ 	/* Put Target, including PCIe, into RESET. */
-+ 	val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
-+@@ -2531,181 +2488,227 @@ static int ath10k_pci_cold_reset(struct
-+ 		msleep(1);
-+ 	}
-+ 
-+-	ath10k_do_pci_sleep(ar);
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset complete\n");
-++
-++	return 0;
-++}
-++
-++static int ath10k_pci_claim(struct ath10k *ar)
-++{
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct pci_dev *pdev = ar_pci->pdev;
-++	u32 lcr_val;
-++	int ret;
-++
-++	pci_set_drvdata(pdev, ar);
-++
-++	ret = pci_enable_device(pdev);
-++	if (ret) {
-++		ath10k_err(ar, "failed to enable pci device: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ret = pci_request_region(pdev, BAR_NUM, "ath");
-++	if (ret) {
-++		ath10k_err(ar, "failed to request region BAR%d: %d\n", BAR_NUM,
-++			   ret);
-++		goto err_device;
-++	}
-++
-++	/* Target expects 32 bit DMA. Enforce it. */
-++	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-++	if (ret) {
-++		ath10k_err(ar, "failed to set dma mask to 32-bit: %d\n", ret);
-++		goto err_region;
-++	}
-++
-++	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-++	if (ret) {
-++		ath10k_err(ar, "failed to set consistent dma mask to 32-bit: %d\n",
-++			   ret);
-++		goto err_region;
-++	}
-++
-++	pci_set_master(pdev);
-++
-++	/* Workaround: Disable ASPM */
-++	pci_read_config_dword(pdev, 0x80, &lcr_val);
-++	pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00));
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot cold reset complete\n");
-++	/* Arrange for access to Target SoC registers. */
-++	ar_pci->mem = pci_iomap(pdev, BAR_NUM, 0);
-++	if (!ar_pci->mem) {
-++		ath10k_err(ar, "failed to iomap BAR%d\n", BAR_NUM);
-++		ret = -EIO;
-++		goto err_master;
-++	}
-+ 
-++	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot pci_mem 0x%p\n", ar_pci->mem);
-+ 	return 0;
-++
-++err_master:
-++	pci_clear_master(pdev);
-++
-++err_region:
-++	pci_release_region(pdev, BAR_NUM);
-++
-++err_device:
-++	pci_disable_device(pdev);
-++
-++	return ret;
-+ }
-+ 
-+-static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
-++static void ath10k_pci_release(struct ath10k *ar)
-+ {
-++	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-++	struct pci_dev *pdev = ar_pci->pdev;
-++
-++	pci_iounmap(pdev, ar_pci->mem);
-++	pci_release_region(pdev, BAR_NUM);
-++	pci_clear_master(pdev);
-++	pci_disable_device(pdev);
-++}
-++
-++static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id)
-++{
-++	const struct ath10k_pci_supp_chip *supp_chip;
-+ 	int i;
-++	u32 rev_id = MS(chip_id, SOC_CHIP_ID_REV);
-+ 
-+-	for (i = 0; i < ATH10K_PCI_FEATURE_COUNT; i++) {
-+-		if (!test_bit(i, ar_pci->features))
-+-			continue;
-++	for (i = 0; i < ARRAY_SIZE(ath10k_pci_supp_chips); i++) {
-++		supp_chip = &ath10k_pci_supp_chips[i];
-+ 
-+-		switch (i) {
-+-		case ATH10K_PCI_FEATURE_MSI_X:
-+-			ath10k_dbg(ATH10K_DBG_BOOT, "device supports MSI-X\n");
-+-			break;
-+-		case ATH10K_PCI_FEATURE_SOC_POWER_SAVE:
-+-			ath10k_dbg(ATH10K_DBG_BOOT, "QCA98XX SoC power save enabled\n");
-+-			break;
-+-		}
-++		if (supp_chip->dev_id == dev_id &&
-++		    supp_chip->rev_id == rev_id)
-++			return true;
-+ 	}
-++
-++	return false;
-+ }
-+ 
-+ static int ath10k_pci_probe(struct pci_dev *pdev,
-+ 			    const struct pci_device_id *pci_dev)
-+ {
-+-	void __iomem *mem;
-+ 	int ret = 0;
-+ 	struct ath10k *ar;
-+ 	struct ath10k_pci *ar_pci;
-+-	u32 lcr_val, chip_id;
-+-
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci probe\n");
-+-
-+-	ar_pci = kzalloc(sizeof(*ar_pci), GFP_KERNEL);
-+-	if (ar_pci == NULL)
-+-		return -ENOMEM;
-+-
-+-	ar_pci->pdev = pdev;
-+-	ar_pci->dev = &pdev->dev;
-++	enum ath10k_hw_rev hw_rev;
-++	u32 chip_id;
-+ 
-+ 	switch (pci_dev->device) {
-+ 	case QCA988X_2_0_DEVICE_ID:
-+-		set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features);
-++		hw_rev = ATH10K_HW_QCA988X;
-++		break;
-++	case QCA6174_2_1_DEVICE_ID:
-++		hw_rev = ATH10K_HW_QCA6174;
-+ 		break;
-+ 	default:
-+-		ret = -ENODEV;
-+-		ath10k_err("Unknown device ID: %d\n", pci_dev->device);
-+-		goto err_ar_pci;
-++		WARN_ON(1);
-++		return -ENOTSUPP;
-+ 	}
-+ 
-+-	if (ath10k_pci_target_ps)
-+-		set_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features);
-+-
-+-	ath10k_pci_dump_features(ar_pci);
-+-
-+-	ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
-++	ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, ATH10K_BUS_PCI,
-++				hw_rev, &ath10k_pci_hif_ops);
-+ 	if (!ar) {
-+-		ath10k_err("failed to create driver core\n");
-+-		ret = -EINVAL;
-+-		goto err_ar_pci;
-++		dev_err(&pdev->dev, "failed to allocate core\n");
-++		return -ENOMEM;
-+ 	}
-+ 
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci probe\n");
-++
-++	ar_pci = ath10k_pci_priv(ar);
-++	ar_pci->pdev = pdev;
-++	ar_pci->dev = &pdev->dev;
-+ 	ar_pci->ar = ar;
-+-	atomic_set(&ar_pci->keep_awake_count, 0);
-+ 
-+-	pci_set_drvdata(pdev, ar);
-++	spin_lock_init(&ar_pci->ce_lock);
-++	setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
-++		    (unsigned long)ar);
-+ 
-+-	/*
-+-	 * Without any knowledge of the Host, the Target may have been reset or
-+-	 * power cycled and its Config Space may no longer reflect the PCI
-+-	 * address space that was assigned earlier by the PCI infrastructure.
-+-	 * Refresh it now.
-+-	 */
-+-	ret = pci_assign_resource(pdev, BAR_NUM);
-++	ret = ath10k_pci_claim(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to assign PCI space: %d\n", ret);
-+-		goto err_ar;
-++		ath10k_err(ar, "failed to claim device: %d\n", ret);
-++		goto err_core_destroy;
-+ 	}
-+ 
-+-	ret = pci_enable_device(pdev);
-++	ret = ath10k_pci_wake(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to enable PCI device: %d\n", ret);
-+-		goto err_ar;
-++		ath10k_err(ar, "failed to wake up: %d\n", ret);
-++		goto err_release;
-+ 	}
-+ 
-+-	/* Request MMIO resources */
-+-	ret = pci_request_region(pdev, BAR_NUM, "ath");
-++	ret = ath10k_pci_alloc_pipes(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to request MMIO region: %d\n", ret);
-+-		goto err_device;
-++		ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
-++			   ret);
-++		goto err_sleep;
-+ 	}
-+ 
-+-	/*
-+-	 * Target structures have a limit of 32 bit DMA pointers.
-+-	 * DMA pointers can be wider than 32 bits by default on some systems.
-+-	 */
-+-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-+-	if (ret) {
-+-		ath10k_err("failed to set DMA mask to 32-bit: %d\n", ret);
-+-		goto err_region;
-+-	}
-++	ath10k_pci_ce_deinit(ar);
-++	ath10k_pci_irq_disable(ar);
-+ 
-+-	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-++	ret = ath10k_pci_init_irq(ar);
-+ 	if (ret) {
-+-		ath10k_err("failed to set consistent DMA mask to 32-bit\n");
-+-		goto err_region;
-++		ath10k_err(ar, "failed to init irqs: %d\n", ret);
-++		goto err_free_pipes;
-+ 	}
-+ 
-+-	/* Set bus master bit in PCI_COMMAND to enable DMA */
-+-	pci_set_master(pdev);
-+-
-+-	/*
-+-	 * Temporary FIX: disable ASPM
-+-	 * Will be removed after the OTP is programmed
-+-	 */
-+-	pci_read_config_dword(pdev, 0x80, &lcr_val);
-+-	pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00));
-++	ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n",
-++		    ath10k_pci_get_irq_method(ar), ar_pci->num_msi_intrs,
-++		    ath10k_pci_irq_mode, ath10k_pci_reset_mode);
-+ 
-+-	/* Arrange for access to Target SoC registers. */
-+-	mem = pci_iomap(pdev, BAR_NUM, 0);
-+-	if (!mem) {
-+-		ath10k_err("failed to perform IOMAP for BAR%d\n", BAR_NUM);
-+-		ret = -EIO;
-+-		goto err_master;
-++	ret = ath10k_pci_request_irq(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to request irqs: %d\n", ret);
-++		goto err_deinit_irq;
-+ 	}
-+ 
-+-	ar_pci->mem = mem;
-+-
-+-	spin_lock_init(&ar_pci->ce_lock);
-+-
-+-	ret = ath10k_do_pci_wake(ar);
-++	ret = ath10k_pci_chip_reset(ar);
-+ 	if (ret) {
-+-		ath10k_err("Failed to get chip id: %d\n", ret);
-+-		goto err_iomap;
-++		ath10k_err(ar, "failed to reset chip: %d\n", ret);
-++		goto err_free_irq;
-+ 	}
-+ 
-+ 	chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
-++	if (chip_id == 0xffffffff) {
-++		ath10k_err(ar, "failed to get chip id\n");
-++		goto err_free_irq;
-++	}
-+ 
-+-	ath10k_do_pci_sleep(ar);
-+-
-+-	ret = ath10k_pci_alloc_ce(ar);
-+-	if (ret) {
-+-		ath10k_err("failed to allocate copy engine pipes: %d\n", ret);
-+-		goto err_iomap;
-++	if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
-++		ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
-++			   pdev->device, chip_id);
-++		goto err_sleep;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_BOOT, "boot pci_mem 0x%p\n", ar_pci->mem);
-++	ath10k_pci_sleep(ar);
-+ 
-+ 	ret = ath10k_core_register(ar, chip_id);
-+ 	if (ret) {
-+-		ath10k_err("failed to register driver core: %d\n", ret);
-+-		goto err_free_ce;
-++		ath10k_err(ar, "failed to register driver core: %d\n", ret);
-++		goto err_free_irq;
-+ 	}
-+ 
-+ 	return 0;
-+ 
-+-err_free_ce:
-+-	ath10k_pci_free_ce(ar);
-+-err_iomap:
-+-	pci_iounmap(pdev, mem);
-+-err_master:
-+-	pci_clear_master(pdev);
-+-err_region:
-+-	pci_release_region(pdev, BAR_NUM);
-+-err_device:
-+-	pci_disable_device(pdev);
-+-err_ar:
-++err_free_irq:
-++	ath10k_pci_free_irq(ar);
-++	ath10k_pci_kill_tasklet(ar);
-++
-++err_deinit_irq:
-++	ath10k_pci_deinit_irq(ar);
-++
-++err_free_pipes:
-++	ath10k_pci_free_pipes(ar);
-++
-++err_sleep:
-++	ath10k_pci_sleep(ar);
-++
-++err_release:
-++	ath10k_pci_release(ar);
-++
-++err_core_destroy:
-+ 	ath10k_core_destroy(ar);
-+-err_ar_pci:
-+-	/* call HIF PCI free here */
-+-	kfree(ar_pci);
-+ 
-+ 	return ret;
-+ }
-+@@ -2715,7 +2718,7 @@ static void ath10k_pci_remove(struct pci
-+ 	struct ath10k *ar = pci_get_drvdata(pdev);
-+ 	struct ath10k_pci *ar_pci;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_PCI, "pci remove\n");
-++	ath10k_dbg(ar, ATH10K_DBG_PCI, "pci remove\n");
-+ 
-+ 	if (!ar)
-+ 		return;
-+@@ -2725,18 +2728,14 @@ static void ath10k_pci_remove(struct pci
-+ 	if (!ar_pci)
-+ 		return;
-+ 
-+-	tasklet_kill(&ar_pci->msi_fw_err);
-+-
-+ 	ath10k_core_unregister(ar);
-+-	ath10k_pci_free_ce(ar);
-+-
-+-	pci_iounmap(pdev, ar_pci->mem);
-+-	pci_release_region(pdev, BAR_NUM);
-+-	pci_clear_master(pdev);
-+-	pci_disable_device(pdev);
-+-
-++	ath10k_pci_free_irq(ar);
-++	ath10k_pci_kill_tasklet(ar);
-++	ath10k_pci_deinit_irq(ar);
-++	ath10k_pci_ce_deinit(ar);
-++	ath10k_pci_free_pipes(ar);
-++	ath10k_pci_release(ar);
-+ 	ath10k_core_destroy(ar);
-+-	kfree(ar_pci);
-+ }
-+ 
-+ MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
-+@@ -2754,7 +2753,8 @@ static int __init ath10k_pci_init(void)
-+ 
-+ 	ret = pci_register_driver(&ath10k_pci_driver);
-+ 	if (ret)
-+-		ath10k_err("failed to register PCI driver: %d\n", ret);
-++		printk(KERN_ERR "failed to register ath10k pci driver: %d\n",
-++		       ret);
-+ 
-+ 	return ret;
-+ }
-+@@ -2770,5 +2770,7 @@ module_exit(ath10k_pci_exit);
-+ MODULE_AUTHOR("Qualcomm Atheros");
-+ MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
-+ MODULE_LICENSE("Dual BSD/GPL");
-+-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_2_FILE);
-++MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
-++MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
-++MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
-+ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
-+--- a/drivers/net/wireless/ath/ath10k/pci.h
-++++ b/drivers/net/wireless/ath/ath10k/pci.h
-+@@ -23,9 +23,6 @@
-+ #include "hw.h"
-+ #include "ce.h"
-+ 
-+-/* FW dump area */
-+-#define REG_DUMP_COUNT_QCA988X 60
-+-
-+ /*
-+  * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
-+  */
-+@@ -38,7 +35,8 @@
-+ #define DIAG_TRANSFER_LIMIT 2048
-+ 
-+ struct bmi_xfer {
-+-	struct completion done;
-++	bool tx_done;
-++	bool rx_done;
-+ 	bool wait_for_resp;
-+ 	u32 resp_len;
-+ };
-+@@ -102,12 +100,12 @@ struct pcie_state {
-+  * NOTE: Structure is shared between Host software and Target firmware!
-+  */
-+ struct ce_pipe_config {
-+-	u32 pipenum;
-+-	u32 pipedir;
-+-	u32 nentries;
-+-	u32 nbytes_max;
-+-	u32 flags;
-+-	u32 reserved;
-++	__le32 pipenum;
-++	__le32 pipedir;
-++	__le32 nentries;
-++	__le32 nbytes_max;
-++	__le32 flags;
-++	__le32 reserved;
-+ };
-+ 
-+ /*
-+@@ -129,17 +127,9 @@ struct ce_pipe_config {
-+ 
-+ /* Establish a mapping between a service/direction and a pipe. */
-+ struct service_to_pipe {
-+-	u32 service_id;
-+-	u32 pipedir;
-+-	u32 pipenum;
-+-};
-+-
-+-enum ath10k_pci_features {
-+-	ATH10K_PCI_FEATURE_MSI_X		= 0,
-+-	ATH10K_PCI_FEATURE_SOC_POWER_SAVE	= 1,
-+-
-+-	/* keep last */
-+-	ATH10K_PCI_FEATURE_COUNT
-++	__le32 service_id;
-++	__le32 pipedir;
-++	__le32 pipenum;
-+ };
-+ 
-+ /* Per-pipe state. */
-+@@ -162,14 +152,17 @@ struct ath10k_pci_pipe {
-+ 	struct tasklet_struct intr;
-+ };
-+ 
-++struct ath10k_pci_supp_chip {
-++	u32 dev_id;
-++	u32 rev_id;
-++};
-++
-+ struct ath10k_pci {
-+ 	struct pci_dev *pdev;
-+ 	struct device *dev;
-+ 	struct ath10k *ar;
-+ 	void __iomem *mem;
-+ 
-+-	DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT);
-+-
-+ 	/*
-+ 	 * Number of MSI interrupts granted, 0 --> using legacy PCI line
-+ 	 * interrupts.
-+@@ -178,12 +171,6 @@ struct ath10k_pci {
-+ 
-+ 	struct tasklet_struct intr_tq;
-+ 	struct tasklet_struct msi_fw_err;
-+-	struct tasklet_struct early_irq_tasklet;
-+-
-+-	int started;
-+-
-+-	atomic_t keep_awake_count;
-+-	bool verified_awake;
-+ 
-+ 	struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
-+ 
-+@@ -197,29 +184,17 @@ struct ath10k_pci {
-+ 
-+ 	/* Map CE id to ce_state */
-+ 	struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
-++	struct timer_list rx_post_retry;
-+ };
-+ 
-+ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
-+ {
-+-	return ar->hif.priv;
-+-}
-+-
-+-static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
-+-{
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-
-+-	return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-+-}
-+-
-+-static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
-+-{
-+-	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+-
-+-	iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-++	return (struct ath10k_pci *)ar->drv_priv;
-+ }
-+ 
-++#define ATH10K_PCI_RX_POST_RETRY_MS 50
-+ #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */
-+-#define PCIE_WAKE_TIMEOUT 5000	/* 5ms */
-++#define PCIE_WAKE_TIMEOUT 10000	/* 10ms */
-+ 
-+ #define BAR_NUM 0
-+ 
-+@@ -241,35 +216,17 @@ static inline void ath10k_pci_reg_write3
-+ /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
-+ #define DIAG_ACCESS_CE_TIMEOUT_MS 10
-+ 
-+-/*
-+- * This API allows the Host to access Target registers directly
-+- * and relatively efficiently over PCIe.
-+- * This allows the Host to avoid extra overhead associated with
-+- * sending a message to firmware and waiting for a response message
-+- * from firmware, as is done on other interconnects.
-+- *
-+- * Yet there is some complexity with direct accesses because the
-+- * Target's power state is not known a priori. The Host must issue
-+- * special PCIe reads/writes in order to explicitly wake the Target
-+- * and to verify that it is awake and will remain awake.
-+- *
-+- * Usage:
-++/* Target exposes its registers for direct access. However before host can
-++ * access them it needs to make sure the target is awake (ath10k_pci_wake,
-++ * ath10k_pci_wake_wait, ath10k_pci_is_awake). Once target is awake it won't go
-++ * to sleep unless host tells it to (ath10k_pci_sleep).
-+  *
-+- *   Use ath10k_pci_read32 and ath10k_pci_write32 to access Target space.
-+- *   These calls must be bracketed by ath10k_pci_wake and
-+- *   ath10k_pci_sleep.  A single BEGIN/END pair is adequate for
-+- *   multiple READ/WRITE operations.
-++ * If host tries to access target registers without waking it up it can
-++ * scribble over host memory.
-+  *
-+- *   Use ath10k_pci_wake to put the Target in a state in
-+- *   which it is legal for the Host to directly access it. This
-+- *   may involve waking the Target from a low power state, which
-+- *   may take up to 2Ms!
-+- *
-+- *   Use ath10k_pci_sleep to tell the Target that as far as
-+- *   this code path is concerned, it no longer needs to remain
-+- *   directly accessible.  BEGIN/END is under a reference counter;
-+- *   multiple code paths may issue BEGIN/END on a single targid.
-++ * If target is asleep waking it up may take up to even 2ms.
-+  */
-++
-+ static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
-+ 				      u32 value)
-+ {
-+@@ -295,25 +252,18 @@ static inline void ath10k_pci_soc_write3
-+ 	ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
-+ }
-+ 
-+-int ath10k_do_pci_wake(struct ath10k *ar);
-+-void ath10k_do_pci_sleep(struct ath10k *ar);
-+-
-+-static inline int ath10k_pci_wake(struct ath10k *ar)
-++static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
-+-		return ath10k_do_pci_wake(ar);
-+-
-+-	return 0;
-++	return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-+ }
-+ 
-+-static inline void ath10k_pci_sleep(struct ath10k *ar)
-++static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
-+ {
-+ 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-+ 
-+-	if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
-+-		ath10k_do_pci_sleep(ar);
-++	iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
-+ }
-+ 
-+ #endif /* _PCI_H_ */
-+--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
-++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
-+@@ -839,7 +839,6 @@ struct rx_ppdu_start {
-+  *		Reserved: HW should fill with 0, FW should ignore.
-+ */
-+ 
-+-
-+ #define RX_PPDU_END_FLAGS_PHY_ERR             (1 << 0)
-+ #define RX_PPDU_END_FLAGS_RX_LOCATION         (1 << 1)
-+ #define RX_PPDU_END_FLAGS_TXBF_H_INFO         (1 << 2)
-+@@ -851,7 +850,7 @@ struct rx_ppdu_start {
-+ 
-+ #define RX_PPDU_END_INFO1_PPDU_DONE (1 << 15)
-+ 
-+-struct rx_ppdu_end {
-++struct rx_ppdu_end_common {
-+ 	__le32 evm_p0;
-+ 	__le32 evm_p1;
-+ 	__le32 evm_p2;
-+@@ -874,10 +873,33 @@ struct rx_ppdu_end {
-+ 	u8 phy_err_code;
-+ 	__le16 flags; /* %RX_PPDU_END_FLAGS_ */
-+ 	__le32 info0; /* %RX_PPDU_END_INFO0_ */
-++} __packed;
-++
-++struct rx_ppdu_end_qca988x {
-++	__le16 bb_length;
-++	__le16 info1; /* %RX_PPDU_END_INFO1_ */
-++} __packed;
-++
-++#define RX_PPDU_END_RTT_CORRELATION_VALUE_MASK 0x00ffffff
-++#define RX_PPDU_END_RTT_CORRELATION_VALUE_LSB  0
-++#define RX_PPDU_END_RTT_UNUSED_MASK            0x7f000000
-++#define RX_PPDU_END_RTT_UNUSED_LSB             24
-++#define RX_PPDU_END_RTT_NORMAL_MODE            BIT(31)
-++
-++struct rx_ppdu_end_qca6174 {
-++	__le32 rtt; /* %RX_PPDU_END_RTT_ */
-+ 	__le16 bb_length;
-+ 	__le16 info1; /* %RX_PPDU_END_INFO1_ */
-+ } __packed;
-+ 
-++struct rx_ppdu_end {
-++	struct rx_ppdu_end_common common;
-++	union {
-++		struct rx_ppdu_end_qca988x qca988x;
-++		struct rx_ppdu_end_qca6174 qca6174;
-++	} __packed;
-++} __packed;
-++
-+ /*
-+  * evm_p0
-+  *		EVM for pilot 0.  Contain EVM for streams: 0, 1, 2 and 3.
-+--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
-++++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
-+@@ -18,6 +18,8 @@
-+ #ifndef __TARGADDRS_H__
-+ #define __TARGADDRS_H__
-+ 
-++#include "hw.h"
-++
-+ /*
-+  * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the
-+  * host_interest structure.  It must match the address of the _host_interest
-+@@ -284,7 +286,6 @@ Fw Mode/SubMode Mask
-+ #define HI_OPTION_ALL_FW_SUBMODE_MASK  0xFF00
-+ #define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8
-+ 
-+-
-+ /* hi_option_flag2 options */
-+ #define HI_OPTION_OFFLOAD_AMSDU     0x01
-+ #define HI_OPTION_DFS_SUPPORT       0x02 /* Enable DFS support */
-+@@ -446,4 +447,7 @@ Fw Mode/SubMode Mask
-+ #define QCA988X_BOARD_DATA_SZ     7168
-+ #define QCA988X_BOARD_EXT_DATA_SZ 0
-+ 
-++#define QCA6174_BOARD_DATA_SZ     8192
-++#define QCA6174_BOARD_EXT_DATA_SZ 0
-++
-+ #endif /* __TARGADDRS_H__ */
-+--- a/drivers/net/wireless/ath/ath10k/trace.h
-++++ b/drivers/net/wireless/ath/ath10k/trace.h
-+@@ -18,6 +18,16 @@
-+ #if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
-+ 
-+ #include <linux/tracepoint.h>
-++#include "core.h"
-++
-++#if !defined(_TRACE_H_)
-++static inline u32 ath10k_frm_hdr_len(const void *buf)
-++{
-++	const struct ieee80211_hdr *hdr = buf;
-++
-++	return ieee80211_hdrlen(hdr->frame_control);
-++}
-++#endif
-+ 
-+ #define _TRACE_H_
-+ 
-+@@ -39,59 +49,79 @@ static inline void trace_ ## name(proto)
-+ #define ATH10K_MSG_MAX 200
-+ 
-+ DECLARE_EVENT_CLASS(ath10k_log_event,
-+-	TP_PROTO(struct va_format *vaf),
-+-	TP_ARGS(vaf),
-++	TP_PROTO(struct ath10k *ar, struct va_format *vaf),
-++	TP_ARGS(ar, vaf),
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__dynamic_array(char, msg, ATH10K_MSG_MAX)
-+ 	),
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-+ 				       ATH10K_MSG_MAX,
-+ 				       vaf->fmt,
-+ 				       *vaf->va) >= ATH10K_MSG_MAX);
-+ 	),
-+-	TP_printk("%s", __get_str(msg))
-++	TP_printk(
-++		"%s %s %s",
-++		__get_str(driver),
-++		__get_str(device),
-++		__get_str(msg)
-++	)
-+ );
-+ 
-+ DEFINE_EVENT(ath10k_log_event, ath10k_log_err,
-+-	     TP_PROTO(struct va_format *vaf),
-+-	     TP_ARGS(vaf)
-++	     TP_PROTO(struct ath10k *ar, struct va_format *vaf),
-++	     TP_ARGS(ar, vaf)
-+ );
-+ 
-+ DEFINE_EVENT(ath10k_log_event, ath10k_log_warn,
-+-	     TP_PROTO(struct va_format *vaf),
-+-	     TP_ARGS(vaf)
-++	     TP_PROTO(struct ath10k *ar, struct va_format *vaf),
-++	     TP_ARGS(ar, vaf)
-+ );
-+ 
-+ DEFINE_EVENT(ath10k_log_event, ath10k_log_info,
-+-	     TP_PROTO(struct va_format *vaf),
-+-	     TP_ARGS(vaf)
-++	     TP_PROTO(struct ath10k *ar, struct va_format *vaf),
-++	     TP_ARGS(ar, vaf)
-+ );
-+ 
-+ TRACE_EVENT(ath10k_log_dbg,
-+-	TP_PROTO(unsigned int level, struct va_format *vaf),
-+-	TP_ARGS(level, vaf),
-++	TP_PROTO(struct ath10k *ar, unsigned int level, struct va_format *vaf),
-++	TP_ARGS(ar, level, vaf),
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__field(unsigned int, level)
-+ 		__dynamic_array(char, msg, ATH10K_MSG_MAX)
-+ 	),
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__entry->level = level;
-+ 		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
-+ 				       ATH10K_MSG_MAX,
-+ 				       vaf->fmt,
-+ 				       *vaf->va) >= ATH10K_MSG_MAX);
-+ 	),
-+-	TP_printk("%s", __get_str(msg))
-++	TP_printk(
-++		"%s %s %s",
-++		__get_str(driver),
-++		__get_str(device),
-++		__get_str(msg)
-++	)
-+ );
-+ 
-+ TRACE_EVENT(ath10k_log_dbg_dump,
-+-	TP_PROTO(const char *msg, const char *prefix,
-++	TP_PROTO(struct ath10k *ar, const char *msg, const char *prefix,
-+ 		 const void *buf, size_t buf_len),
-+ 
-+-	TP_ARGS(msg, prefix, buf, buf_len),
-++	TP_ARGS(ar, msg, prefix, buf, buf_len),
-+ 
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__string(msg, msg)
-+ 		__string(prefix, prefix)
-+ 		__field(size_t, buf_len)
-+@@ -99,6 +129,8 @@ TRACE_EVENT(ath10k_log_dbg_dump,
-+ 	),
-+ 
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__assign_str(msg, msg);
-+ 		__assign_str(prefix, prefix);
-+ 		__entry->buf_len = buf_len;
-+@@ -106,16 +138,23 @@ TRACE_EVENT(ath10k_log_dbg_dump,
-+ 	),
-+ 
-+ 	TP_printk(
-+-		"%s/%s\n", __get_str(prefix), __get_str(msg)
-++		"%s %s %s/%s\n",
-++		__get_str(driver),
-++		__get_str(device),
-++		__get_str(prefix),
-++		__get_str(msg)
-+ 	)
-+ );
-+ 
-+ TRACE_EVENT(ath10k_wmi_cmd,
-+-	TP_PROTO(int id, void *buf, size_t buf_len, int ret),
-++	TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len,
-++		 int ret),
-+ 
-+-	TP_ARGS(id, buf, buf_len, ret),
-++	TP_ARGS(ar, id, buf, buf_len, ret),
-+ 
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__field(unsigned int, id)
-+ 		__field(size_t, buf_len)
-+ 		__dynamic_array(u8, buf, buf_len)
-+@@ -123,6 +162,8 @@ TRACE_EVENT(ath10k_wmi_cmd,
-+ 	),
-+ 
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__entry->id = id;
-+ 		__entry->buf_len = buf_len;
-+ 		__entry->ret = ret;
-+@@ -130,7 +171,9 @@ TRACE_EVENT(ath10k_wmi_cmd,
-+ 	),
-+ 
-+ 	TP_printk(
-+-		"id %d len %zu ret %d",
-++		"%s %s id %d len %zu ret %d",
-++		__get_str(driver),
-++		__get_str(device),
-+ 		__entry->id,
-+ 		__entry->buf_len,
-+ 		__entry->ret
-+@@ -138,71 +181,346 @@ TRACE_EVENT(ath10k_wmi_cmd,
-+ );
-+ 
-+ TRACE_EVENT(ath10k_wmi_event,
-+-	TP_PROTO(int id, void *buf, size_t buf_len),
-++	TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len),
-+ 
-+-	TP_ARGS(id, buf, buf_len),
-++	TP_ARGS(ar, id, buf, buf_len),
-+ 
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__field(unsigned int, id)
-+ 		__field(size_t, buf_len)
-+ 		__dynamic_array(u8, buf, buf_len)
-+ 	),
-+ 
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__entry->id = id;
-+ 		__entry->buf_len = buf_len;
-+ 		memcpy(__get_dynamic_array(buf), buf, buf_len);
-+ 	),
-+ 
-+ 	TP_printk(
-+-		"id %d len %zu",
-++		"%s %s id %d len %zu",
-++		__get_str(driver),
-++		__get_str(device),
-+ 		__entry->id,
-+ 		__entry->buf_len
-+ 	)
-+ );
-+ 
-+ TRACE_EVENT(ath10k_htt_stats,
-+-	TP_PROTO(void *buf, size_t buf_len),
-++	TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
-+ 
-+-	TP_ARGS(buf, buf_len),
-++	TP_ARGS(ar, buf, buf_len),
-+ 
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__field(size_t, buf_len)
-+ 		__dynamic_array(u8, buf, buf_len)
-+ 	),
-+ 
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__entry->buf_len = buf_len;
-+ 		memcpy(__get_dynamic_array(buf), buf, buf_len);
-+ 	),
-+ 
-+ 	TP_printk(
-+-		"len %zu",
-++		"%s %s len %zu",
-++		__get_str(driver),
-++		__get_str(device),
-+ 		__entry->buf_len
-+ 	)
-+ );
-+ 
-+ TRACE_EVENT(ath10k_wmi_dbglog,
-+-	TP_PROTO(void *buf, size_t buf_len),
-++	TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
-+ 
-+-	TP_ARGS(buf, buf_len),
-++	TP_ARGS(ar, buf, buf_len),
-+ 
-+ 	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-+ 		__field(size_t, buf_len)
-+ 		__dynamic_array(u8, buf, buf_len)
-+ 	),
-+ 
-+ 	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-+ 		__entry->buf_len = buf_len;
-+ 		memcpy(__get_dynamic_array(buf), buf, buf_len);
-+ 	),
-+ 
-+ 	TP_printk(
-+-		"len %zu",
-++		"%s %s len %zu",
-++		__get_str(driver),
-++		__get_str(device),
-+ 		__entry->buf_len
-+ 	)
-+ );
-+ 
-++TRACE_EVENT(ath10k_htt_pktlog,
-++	    TP_PROTO(struct ath10k *ar, const void *buf, u16 buf_len),
-++
-++	TP_ARGS(ar, buf, buf_len),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u16, buf_len)
-++		__dynamic_array(u8, pktlog, buf_len)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->buf_len = buf_len;
-++		memcpy(__get_dynamic_array(pktlog), buf, buf_len);
-++	),
-++
-++	TP_printk(
-++		"%s %s size %hu",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->buf_len
-++	 )
-++);
-++
-++TRACE_EVENT(ath10k_htt_tx,
-++	    TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len,
-++		     u8 vdev_id, u8 tid),
-++
-++	TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u16, msdu_id)
-++		__field(u16, msdu_len)
-++		__field(u8, vdev_id)
-++		__field(u8, tid)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->msdu_id = msdu_id;
-++		__entry->msdu_len = msdu_len;
-++		__entry->vdev_id = vdev_id;
-++		__entry->tid = tid;
-++	),
-++
-++	TP_printk(
-++		"%s %s msdu_id %d msdu_len %d vdev_id %d tid %d",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->msdu_id,
-++		__entry->msdu_len,
-++		__entry->vdev_id,
-++		__entry->tid
-++	 )
-++);
-++
-++TRACE_EVENT(ath10k_txrx_tx_unref,
-++	    TP_PROTO(struct ath10k *ar, u16 msdu_id),
-++
-++	TP_ARGS(ar, msdu_id),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u16, msdu_id)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->msdu_id = msdu_id;
-++	),
-++
-++	TP_printk(
-++		"%s %s msdu_id %d",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->msdu_id
-++	 )
-++);
-++
-++DECLARE_EVENT_CLASS(ath10k_hdr_event,
-++		    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++
-++	TP_ARGS(ar, data, len),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(size_t, len)
-++		__dynamic_array(u8, data, ath10k_frm_hdr_len(data))
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->len = ath10k_frm_hdr_len(data);
-++		memcpy(__get_dynamic_array(data), data, __entry->len);
-++	),
-++
-++	TP_printk(
-++		"%s %s len %zu\n",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->len
-++	)
-++);
-++
-++DECLARE_EVENT_CLASS(ath10k_payload_event,
-++		    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++
-++	TP_ARGS(ar, data, len),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(size_t, len)
-++		__dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data)))
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->len = len - ath10k_frm_hdr_len(data);
-++		memcpy(__get_dynamic_array(payload),
-++		       data + ath10k_frm_hdr_len(data), __entry->len);
-++	),
-++
-++	TP_printk(
-++		"%s %s len %zu\n",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->len
-++	)
-++);
-++
-++DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr,
-++	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++	     TP_ARGS(ar, data, len)
-++);
-++
-++DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload,
-++	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++	     TP_ARGS(ar, data, len)
-++);
-++
-++DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr,
-++	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++	     TP_ARGS(ar, data, len)
-++);
-++
-++DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload,
-++	     TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++	     TP_ARGS(ar, data, len)
-++);
-++
-++TRACE_EVENT(ath10k_htt_rx_desc,
-++	    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++
-++	TP_ARGS(ar, data, len),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u16, len)
-++		__dynamic_array(u8, rxdesc, len)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->len = len;
-++		memcpy(__get_dynamic_array(rxdesc), data, len);
-++	),
-++
-++	TP_printk(
-++		"%s %s rxdesc len %d",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->len
-++	 )
-++);
-++
-++TRACE_EVENT(ath10k_wmi_diag_container,
-++	    TP_PROTO(struct ath10k *ar,
-++		     u8 type,
-++		     u32 timestamp,
-++		     u32 code,
-++		     u16 len,
-++		     const void *data),
-++
-++	TP_ARGS(ar, type, timestamp, code, len, data),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u8, type)
-++		__field(u32, timestamp)
-++		__field(u32, code)
-++		__field(u16, len)
-++		__dynamic_array(u8, data, len)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->type = type;
-++		__entry->timestamp = timestamp;
-++		__entry->code = code;
-++		__entry->len = len;
-++		memcpy(__get_dynamic_array(data), data, len);
-++	),
-++
-++	TP_printk(
-++		"%s %s diag container type %hhu timestamp %u code %u len %d",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->type,
-++		__entry->timestamp,
-++		__entry->code,
-++		__entry->len
-++	)
-++);
-++
-++TRACE_EVENT(ath10k_wmi_diag,
-++	    TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-++
-++	TP_ARGS(ar, data, len),
-++
-++	TP_STRUCT__entry(
-++		__string(device, dev_name(ar->dev))
-++		__string(driver, dev_driver_string(ar->dev))
-++		__field(u16, len)
-++		__dynamic_array(u8, data, len)
-++	),
-++
-++	TP_fast_assign(
-++		__assign_str(device, dev_name(ar->dev));
-++		__assign_str(driver, dev_driver_string(ar->dev));
-++		__entry->len = len;
-++		memcpy(__get_dynamic_array(data), data, len);
-++	),
-++
-++	TP_printk(
-++		"%s %s tlv diag len %d",
-++		__get_str(driver),
-++		__get_str(device),
-++		__entry->len
-++	)
-++);
-++
-+ #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
-+ 
-+ /* we don't want to use include/trace/events */
-+--- a/drivers/net/wireless/ath/ath10k/txrx.c
-++++ b/drivers/net/wireless/ath/ath10k/txrx.c
-+@@ -32,14 +32,14 @@ static void ath10k_report_offchan_tx(str
-+ 	 * offchan_tx_skb. */
-+ 	spin_lock_bh(&ar->data_lock);
-+ 	if (ar->offchan_tx_skb != skb) {
-+-		ath10k_warn("completed old offchannel frame\n");
-++		ath10k_warn(ar, "completed old offchannel frame\n");
-+ 		goto out;
-+ 	}
-+ 
-+ 	complete(&ar->offchan_tx_completed);
-+ 	ar->offchan_tx_skb = NULL; /* just for sanity */
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb);
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb);
-+ out:
-+ 	spin_unlock_bh(&ar->data_lock);
-+ }
-+@@ -47,23 +47,30 @@ out:
-+ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
-+ 			  const struct htt_tx_done *tx_done)
-+ {
-+-	struct device *dev = htt->ar->dev;
-++	struct ath10k *ar = htt->ar;
-++	struct device *dev = ar->dev;
-+ 	struct ieee80211_tx_info *info;
-+ 	struct ath10k_skb_cb *skb_cb;
-+ 	struct sk_buff *msdu;
-+ 
-+ 	lockdep_assert_held(&htt->tx_lock);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n",
-+ 		   tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack);
-+ 
-+ 	if (tx_done->msdu_id >= htt->max_num_pending_tx) {
-+-		ath10k_warn("warning: msdu_id %d too big, ignoring\n",
-++		ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
-++			    tx_done->msdu_id);
-++		return;
-++	}
-++
-++	msdu = idr_find(&htt->pending_tx, tx_done->msdu_id);
-++	if (!msdu) {
-++		ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
-+ 			    tx_done->msdu_id);
-+ 		return;
-+ 	}
-+ 
-+-	msdu = htt->pending_tx[tx_done->msdu_id];
-+ 	skb_cb = ATH10K_SKB_CB(msdu);
-+ 
-+ 	dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
-+@@ -77,6 +84,7 @@ void ath10k_txrx_tx_unref(struct ath10k_
-+ 
-+ 	info = IEEE80211_SKB_CB(msdu);
-+ 	memset(&info->status, 0, sizeof(info->status));
-++	trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
-+ 
-+ 	if (tx_done->discard) {
-+ 		ieee80211_free_txskb(htt->ar->hw, msdu);
-+@@ -93,7 +101,6 @@ void ath10k_txrx_tx_unref(struct ath10k_
-+ 	/* we do not own the msdu anymore */
-+ 
-+ exit:
-+-	htt->pending_tx[tx_done->msdu_id] = NULL;
-+ 	ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
-+ 	__ath10k_htt_tx_dec_pending(htt);
-+ 	if (htt->num_pending_tx == 0)
-+@@ -119,8 +126,7 @@ struct ath10k_peer *ath10k_peer_find(str
-+ 	return NULL;
-+ }
-+ 
-+-static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar,
-+-						  int peer_id)
-++struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
-+ {
-+ 	struct ath10k_peer *peer;
-+ 
-+@@ -145,7 +151,8 @@ static int ath10k_wait_for_peer_common(s
-+ 			mapped = !!ath10k_peer_find(ar, vdev_id, addr);
-+ 			spin_unlock_bh(&ar->data_lock);
-+ 
-+-			mapped == expect_mapped;
-++			(mapped == expect_mapped ||
-++			 test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
-+ 		}), 3*HZ);
-+ 
-+ 	if (ret <= 0)
-+@@ -178,12 +185,12 @@ void ath10k_peer_map_event(struct ath10k
-+ 			goto exit;
-+ 
-+ 		peer->vdev_id = ev->vdev_id;
-+-		memcpy(peer->addr, ev->addr, ETH_ALEN);
-++		ether_addr_copy(peer->addr, ev->addr);
-+ 		list_add(&peer->list, &ar->peers);
-+ 		wake_up(&ar->peer_mapping_wq);
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
-+ 		   ev->vdev_id, ev->addr, ev->peer_id);
-+ 
-+ 	set_bit(ev->peer_id, peer->peer_ids);
-+@@ -200,12 +207,12 @@ void ath10k_peer_unmap_event(struct ath1
-+ 	spin_lock_bh(&ar->data_lock);
-+ 	peer = ath10k_peer_find_by_id(ar, ev->peer_id);
-+ 	if (!peer) {
-+-		ath10k_warn("peer-unmap-event: unknown peer id %d\n",
-++		ath10k_warn(ar, "peer-unmap-event: unknown peer id %d\n",
-+ 			    ev->peer_id);
-+ 		goto exit;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
-+ 		   peer->vdev_id, peer->addr, ev->peer_id);
-+ 
-+ 	clear_bit(ev->peer_id, peer->peer_ids);
-+--- a/drivers/net/wireless/ath/ath10k/txrx.h
-++++ b/drivers/net/wireless/ath/ath10k/txrx.h
-+@@ -24,6 +24,7 @@ void ath10k_txrx_tx_unref(struct ath10k_
-+ 
-+ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
-+ 				     const u8 *addr);
-++struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id);
-+ int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
-+ 				 const u8 *addr);
-+ int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
-+--- a/drivers/net/wireless/ath/ath10k/wmi.c
-++++ b/drivers/net/wireless/ath/ath10k/wmi.c
-+@@ -22,7 +22,10 @@
-+ #include "htc.h"
-+ #include "debug.h"
-+ #include "wmi.h"
-++#include "wmi-tlv.h"
-+ #include "mac.h"
-++#include "testmode.h"
-++#include "wmi-ops.h"
-+ 
-+ /* MAIN WMI cmd track */
-+ static struct wmi_cmd_map wmi_cmd_map = {
-+@@ -142,6 +145,7 @@ static struct wmi_cmd_map wmi_cmd_map =
-+ 	.force_fw_hang_cmdid = WMI_FORCE_FW_HANG_CMDID,
-+ 	.gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
-+ 	.gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
-++	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
-+ };
-+ 
-+ /* 10.X WMI cmd track */
-+@@ -264,6 +268,129 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
-+ 	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
-+ 	.gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
-+ 	.gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
-++	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
-++};
-++
-++/* 10.2.4 WMI cmd track */
-++static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
-++	.init_cmdid = WMI_10_2_INIT_CMDID,
-++	.start_scan_cmdid = WMI_10_2_START_SCAN_CMDID,
-++	.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
-++	.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
-++	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
-++	.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
-++	.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
-++	.pdev_pktlog_enable_cmdid = WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
-++	.pdev_pktlog_disable_cmdid = WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
-++	.pdev_set_wmm_params_cmdid = WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
-++	.pdev_set_ht_cap_ie_cmdid = WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
-++	.pdev_set_vht_cap_ie_cmdid = WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
-++	.pdev_set_quiet_mode_cmdid = WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
-++	.pdev_green_ap_ps_enable_cmdid = WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
-++	.pdev_get_tpc_config_cmdid = WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
-++	.pdev_set_base_macaddr_cmdid = WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
-++	.vdev_create_cmdid = WMI_10_2_VDEV_CREATE_CMDID,
-++	.vdev_delete_cmdid = WMI_10_2_VDEV_DELETE_CMDID,
-++	.vdev_start_request_cmdid = WMI_10_2_VDEV_START_REQUEST_CMDID,
-++	.vdev_restart_request_cmdid = WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
-++	.vdev_up_cmdid = WMI_10_2_VDEV_UP_CMDID,
-++	.vdev_stop_cmdid = WMI_10_2_VDEV_STOP_CMDID,
-++	.vdev_down_cmdid = WMI_10_2_VDEV_DOWN_CMDID,
-++	.vdev_set_param_cmdid = WMI_10_2_VDEV_SET_PARAM_CMDID,
-++	.vdev_install_key_cmdid = WMI_10_2_VDEV_INSTALL_KEY_CMDID,
-++	.peer_create_cmdid = WMI_10_2_PEER_CREATE_CMDID,
-++	.peer_delete_cmdid = WMI_10_2_PEER_DELETE_CMDID,
-++	.peer_flush_tids_cmdid = WMI_10_2_PEER_FLUSH_TIDS_CMDID,
-++	.peer_set_param_cmdid = WMI_10_2_PEER_SET_PARAM_CMDID,
-++	.peer_assoc_cmdid = WMI_10_2_PEER_ASSOC_CMDID,
-++	.peer_add_wds_entry_cmdid = WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
-++	.peer_remove_wds_entry_cmdid = WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
-++	.peer_mcast_group_cmdid = WMI_10_2_PEER_MCAST_GROUP_CMDID,
-++	.bcn_tx_cmdid = WMI_10_2_BCN_TX_CMDID,
-++	.pdev_send_bcn_cmdid = WMI_10_2_PDEV_SEND_BCN_CMDID,
-++	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.bcn_filter_rx_cmdid = WMI_10_2_BCN_FILTER_RX_CMDID,
-++	.prb_req_filter_rx_cmdid = WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
-++	.mgmt_tx_cmdid = WMI_10_2_MGMT_TX_CMDID,
-++	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.addba_clear_resp_cmdid = WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
-++	.addba_send_cmdid = WMI_10_2_ADDBA_SEND_CMDID,
-++	.addba_status_cmdid = WMI_10_2_ADDBA_STATUS_CMDID,
-++	.delba_send_cmdid = WMI_10_2_DELBA_SEND_CMDID,
-++	.addba_set_resp_cmdid = WMI_10_2_ADDBA_SET_RESP_CMDID,
-++	.send_singleamsdu_cmdid = WMI_10_2_SEND_SINGLEAMSDU_CMDID,
-++	.sta_powersave_mode_cmdid = WMI_10_2_STA_POWERSAVE_MODE_CMDID,
-++	.sta_powersave_param_cmdid = WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
-++	.sta_mimo_ps_mode_cmdid = WMI_10_2_STA_MIMO_PS_MODE_CMDID,
-++	.pdev_dfs_enable_cmdid = WMI_10_2_PDEV_DFS_ENABLE_CMDID,
-++	.pdev_dfs_disable_cmdid = WMI_10_2_PDEV_DFS_DISABLE_CMDID,
-++	.roam_scan_mode = WMI_10_2_ROAM_SCAN_MODE,
-++	.roam_scan_rssi_threshold = WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
-++	.roam_scan_period = WMI_10_2_ROAM_SCAN_PERIOD,
-++	.roam_scan_rssi_change_threshold =
-++				WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	.roam_ap_profile = WMI_10_2_ROAM_AP_PROFILE,
-++	.ofl_scan_add_ap_profile = WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
-++	.ofl_scan_remove_ap_profile = WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
-++	.ofl_scan_period = WMI_10_2_OFL_SCAN_PERIOD,
-++	.p2p_dev_set_device_info = WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
-++	.p2p_dev_set_discoverability = WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
-++	.p2p_go_set_beacon_ie = WMI_10_2_P2P_GO_SET_BEACON_IE,
-++	.p2p_go_set_probe_resp_ie = WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
-++	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
-++	.ap_ps_peer_param_cmdid = WMI_10_2_AP_PS_PEER_PARAM_CMDID,
-++	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_rate_retry_sched_cmdid = WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
-++	.wlan_profile_trigger_cmdid = WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
-++	.wlan_profile_set_hist_intvl_cmdid =
-++				WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
-++	.wlan_profile_get_profile_data_cmdid =
-++				WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
-++	.wlan_profile_enable_profile_id_cmdid =
-++				WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
-++	.wlan_profile_list_profile_id_cmdid =
-++				WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
-++	.pdev_suspend_cmdid = WMI_10_2_PDEV_SUSPEND_CMDID,
-++	.pdev_resume_cmdid = WMI_10_2_PDEV_RESUME_CMDID,
-++	.add_bcn_filter_cmdid = WMI_10_2_ADD_BCN_FILTER_CMDID,
-++	.rmv_bcn_filter_cmdid = WMI_10_2_RMV_BCN_FILTER_CMDID,
-++	.wow_add_wake_pattern_cmdid = WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
-++	.wow_del_wake_pattern_cmdid = WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
-++	.wow_enable_disable_wake_event_cmdid =
-++				WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
-++	.wow_enable_cmdid = WMI_10_2_WOW_ENABLE_CMDID,
-++	.wow_hostwakeup_from_sleep_cmdid =
-++				WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
-++	.rtt_measreq_cmdid = WMI_10_2_RTT_MEASREQ_CMDID,
-++	.rtt_tsf_cmdid = WMI_10_2_RTT_TSF_CMDID,
-++	.vdev_spectral_scan_configure_cmdid =
-++				WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
-++	.vdev_spectral_scan_enable_cmdid =
-++				WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
-++	.request_stats_cmdid = WMI_10_2_REQUEST_STATS_CMDID,
-++	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
-++	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
-++	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
-++	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
-++	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
-++	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
-++	.echo_cmdid = WMI_10_2_ECHO_CMDID,
-++	.pdev_utf_cmdid = WMI_10_2_PDEV_UTF_CMDID,
-++	.dbglog_cfg_cmdid = WMI_10_2_DBGLOG_CFG_CMDID,
-++	.pdev_qvit_cmdid = WMI_10_2_PDEV_QVIT_CMDID,
-++	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
-++	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
-++	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
-++	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
-++	.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
-++	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
-++	.pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
-+ };
-+ 
-+ /* MAIN WMI VDEV param map */
-+@@ -384,6 +511,64 @@ static struct wmi_vdev_param_map wmi_10x
-+ 		WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
-+ };
-+ 
-++static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
-++	.rts_threshold = WMI_10X_VDEV_PARAM_RTS_THRESHOLD,
-++	.fragmentation_threshold = WMI_10X_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
-++	.beacon_interval = WMI_10X_VDEV_PARAM_BEACON_INTERVAL,
-++	.listen_interval = WMI_10X_VDEV_PARAM_LISTEN_INTERVAL,
-++	.multicast_rate = WMI_10X_VDEV_PARAM_MULTICAST_RATE,
-++	.mgmt_tx_rate = WMI_10X_VDEV_PARAM_MGMT_TX_RATE,
-++	.slot_time = WMI_10X_VDEV_PARAM_SLOT_TIME,
-++	.preamble = WMI_10X_VDEV_PARAM_PREAMBLE,
-++	.swba_time = WMI_10X_VDEV_PARAM_SWBA_TIME,
-++	.wmi_vdev_stats_update_period = WMI_10X_VDEV_STATS_UPDATE_PERIOD,
-++	.wmi_vdev_pwrsave_ageout_time = WMI_10X_VDEV_PWRSAVE_AGEOUT_TIME,
-++	.wmi_vdev_host_swba_interval = WMI_10X_VDEV_HOST_SWBA_INTERVAL,
-++	.dtim_period = WMI_10X_VDEV_PARAM_DTIM_PERIOD,
-++	.wmi_vdev_oc_scheduler_air_time_limit =
-++				WMI_10X_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
-++	.wds = WMI_10X_VDEV_PARAM_WDS,
-++	.atim_window = WMI_10X_VDEV_PARAM_ATIM_WINDOW,
-++	.bmiss_count_max = WMI_10X_VDEV_PARAM_BMISS_COUNT_MAX,
-++	.bmiss_first_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.bmiss_final_bcnt = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.feature_wmm = WMI_10X_VDEV_PARAM_FEATURE_WMM,
-++	.chwidth = WMI_10X_VDEV_PARAM_CHWIDTH,
-++	.chextoffset = WMI_10X_VDEV_PARAM_CHEXTOFFSET,
-++	.disable_htprotection = WMI_10X_VDEV_PARAM_DISABLE_HTPROTECTION,
-++	.sta_quickkickout = WMI_10X_VDEV_PARAM_STA_QUICKKICKOUT,
-++	.mgmt_rate = WMI_10X_VDEV_PARAM_MGMT_RATE,
-++	.protection_mode = WMI_10X_VDEV_PARAM_PROTECTION_MODE,
-++	.fixed_rate = WMI_10X_VDEV_PARAM_FIXED_RATE,
-++	.sgi = WMI_10X_VDEV_PARAM_SGI,
-++	.ldpc = WMI_10X_VDEV_PARAM_LDPC,
-++	.tx_stbc = WMI_10X_VDEV_PARAM_TX_STBC,
-++	.rx_stbc = WMI_10X_VDEV_PARAM_RX_STBC,
-++	.intra_bss_fwd = WMI_10X_VDEV_PARAM_INTRA_BSS_FWD,
-++	.def_keyid = WMI_10X_VDEV_PARAM_DEF_KEYID,
-++	.nss = WMI_10X_VDEV_PARAM_NSS,
-++	.bcast_data_rate = WMI_10X_VDEV_PARAM_BCAST_DATA_RATE,
-++	.mcast_data_rate = WMI_10X_VDEV_PARAM_MCAST_DATA_RATE,
-++	.mcast_indicate = WMI_10X_VDEV_PARAM_MCAST_INDICATE,
-++	.dhcp_indicate = WMI_10X_VDEV_PARAM_DHCP_INDICATE,
-++	.unknown_dest_indicate = WMI_10X_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
-++	.ap_keepalive_min_idle_inactive_time_secs =
-++		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
-++	.ap_keepalive_max_idle_inactive_time_secs =
-++		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
-++	.ap_keepalive_max_unresponsive_time_secs =
-++		WMI_10X_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
-++	.ap_enable_nawds = WMI_10X_VDEV_PARAM_AP_ENABLE_NAWDS,
-++	.mcast2ucast_set = WMI_10X_VDEV_PARAM_MCAST2UCAST_SET,
-++	.enable_rtscts = WMI_10X_VDEV_PARAM_ENABLE_RTSCTS,
-++	.txbf = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED,
-++	.ap_detect_out_of_sync_sleeping_sta_time_secs =
-++		WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
-++};
-++
-+ static struct wmi_pdev_param_map wmi_pdev_param_map = {
-+ 	.tx_chain_mask = WMI_PDEV_PARAM_TX_CHAIN_MASK,
-+ 	.rx_chain_mask = WMI_PDEV_PARAM_RX_CHAIN_MASK,
-+@@ -433,6 +618,7 @@ static struct wmi_pdev_param_map wmi_pde
-+ 	.fast_channel_reset = WMI_PDEV_PARAM_UNSUPPORTED,
-+ 	.burst_dur = WMI_PDEV_PARAM_UNSUPPORTED,
-+ 	.burst_enable = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
-+ };
-+ 
-+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
-+@@ -485,11 +671,221 @@ static struct wmi_pdev_param_map wmi_10x
-+ 	.fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET,
-+ 	.burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
-+ 	.burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
-++	.cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
-++};
-++
-++static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
-++	.tx_chain_mask = WMI_10X_PDEV_PARAM_TX_CHAIN_MASK,
-++	.rx_chain_mask = WMI_10X_PDEV_PARAM_RX_CHAIN_MASK,
-++	.txpower_limit2g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT2G,
-++	.txpower_limit5g = WMI_10X_PDEV_PARAM_TXPOWER_LIMIT5G,
-++	.txpower_scale = WMI_10X_PDEV_PARAM_TXPOWER_SCALE,
-++	.beacon_gen_mode = WMI_10X_PDEV_PARAM_BEACON_GEN_MODE,
-++	.beacon_tx_mode = WMI_10X_PDEV_PARAM_BEACON_TX_MODE,
-++	.resmgr_offchan_mode = WMI_10X_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
-++	.protection_mode = WMI_10X_PDEV_PARAM_PROTECTION_MODE,
-++	.dynamic_bw = WMI_10X_PDEV_PARAM_DYNAMIC_BW,
-++	.non_agg_sw_retry_th = WMI_10X_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
-++	.agg_sw_retry_th = WMI_10X_PDEV_PARAM_AGG_SW_RETRY_TH,
-++	.sta_kickout_th = WMI_10X_PDEV_PARAM_STA_KICKOUT_TH,
-++	.ac_aggrsize_scaling = WMI_10X_PDEV_PARAM_AC_AGGRSIZE_SCALING,
-++	.ltr_enable = WMI_10X_PDEV_PARAM_LTR_ENABLE,
-++	.ltr_ac_latency_be = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BE,
-++	.ltr_ac_latency_bk = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_BK,
-++	.ltr_ac_latency_vi = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VI,
-++	.ltr_ac_latency_vo = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_VO,
-++	.ltr_ac_latency_timeout = WMI_10X_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
-++	.ltr_sleep_override = WMI_10X_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
-++	.ltr_rx_override = WMI_10X_PDEV_PARAM_LTR_RX_OVERRIDE,
-++	.ltr_tx_activity_timeout = WMI_10X_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
-++	.l1ss_enable = WMI_10X_PDEV_PARAM_L1SS_ENABLE,
-++	.dsleep_enable = WMI_10X_PDEV_PARAM_DSLEEP_ENABLE,
-++	.pcielp_txbuf_flush = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.pcielp_txbuf_watermark = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.pcielp_txbuf_tmo_en = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.pcielp_txbuf_tmo_value = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.pdev_stats_update_period = WMI_10X_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
-++	.vdev_stats_update_period = WMI_10X_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
-++	.peer_stats_update_period = WMI_10X_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
-++	.bcnflt_stats_update_period =
-++				WMI_10X_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
-++	.pmf_qos = WMI_10X_PDEV_PARAM_PMF_QOS,
-++	.arp_ac_override = WMI_10X_PDEV_PARAM_ARPDHCP_AC_OVERRIDE,
-++	.dcs = WMI_10X_PDEV_PARAM_DCS,
-++	.ani_enable = WMI_10X_PDEV_PARAM_ANI_ENABLE,
-++	.ani_poll_period = WMI_10X_PDEV_PARAM_ANI_POLL_PERIOD,
-++	.ani_listen_period = WMI_10X_PDEV_PARAM_ANI_LISTEN_PERIOD,
-++	.ani_ofdm_level = WMI_10X_PDEV_PARAM_ANI_OFDM_LEVEL,
-++	.ani_cck_level = WMI_10X_PDEV_PARAM_ANI_CCK_LEVEL,
-++	.dyntxchain = WMI_10X_PDEV_PARAM_DYNTXCHAIN,
-++	.proxy_sta = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.idle_ps_config = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.power_gating_sleep = WMI_PDEV_PARAM_UNSUPPORTED,
-++	.fast_channel_reset = WMI_10X_PDEV_PARAM_FAST_CHANNEL_RESET,
-++	.burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
-++	.burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
-++	.cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
-++};
-++
-++/* firmware 10.2 specific mappings */
-++static struct wmi_cmd_map wmi_10_2_cmd_map = {
-++	.init_cmdid = WMI_10_2_INIT_CMDID,
-++	.start_scan_cmdid = WMI_10_2_START_SCAN_CMDID,
-++	.stop_scan_cmdid = WMI_10_2_STOP_SCAN_CMDID,
-++	.scan_chan_list_cmdid = WMI_10_2_SCAN_CHAN_LIST_CMDID,
-++	.scan_sch_prio_tbl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.pdev_set_regdomain_cmdid = WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
-++	.pdev_set_channel_cmdid = WMI_10_2_PDEV_SET_CHANNEL_CMDID,
-++	.pdev_set_param_cmdid = WMI_10_2_PDEV_SET_PARAM_CMDID,
-++	.pdev_pktlog_enable_cmdid = WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
-++	.pdev_pktlog_disable_cmdid = WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
-++	.pdev_set_wmm_params_cmdid = WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
-++	.pdev_set_ht_cap_ie_cmdid = WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
-++	.pdev_set_vht_cap_ie_cmdid = WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
-++	.pdev_set_quiet_mode_cmdid = WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
-++	.pdev_green_ap_ps_enable_cmdid = WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
-++	.pdev_get_tpc_config_cmdid = WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
-++	.pdev_set_base_macaddr_cmdid = WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
-++	.vdev_create_cmdid = WMI_10_2_VDEV_CREATE_CMDID,
-++	.vdev_delete_cmdid = WMI_10_2_VDEV_DELETE_CMDID,
-++	.vdev_start_request_cmdid = WMI_10_2_VDEV_START_REQUEST_CMDID,
-++	.vdev_restart_request_cmdid = WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
-++	.vdev_up_cmdid = WMI_10_2_VDEV_UP_CMDID,
-++	.vdev_stop_cmdid = WMI_10_2_VDEV_STOP_CMDID,
-++	.vdev_down_cmdid = WMI_10_2_VDEV_DOWN_CMDID,
-++	.vdev_set_param_cmdid = WMI_10_2_VDEV_SET_PARAM_CMDID,
-++	.vdev_install_key_cmdid = WMI_10_2_VDEV_INSTALL_KEY_CMDID,
-++	.peer_create_cmdid = WMI_10_2_PEER_CREATE_CMDID,
-++	.peer_delete_cmdid = WMI_10_2_PEER_DELETE_CMDID,
-++	.peer_flush_tids_cmdid = WMI_10_2_PEER_FLUSH_TIDS_CMDID,
-++	.peer_set_param_cmdid = WMI_10_2_PEER_SET_PARAM_CMDID,
-++	.peer_assoc_cmdid = WMI_10_2_PEER_ASSOC_CMDID,
-++	.peer_add_wds_entry_cmdid = WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
-++	.peer_remove_wds_entry_cmdid = WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
-++	.peer_mcast_group_cmdid = WMI_10_2_PEER_MCAST_GROUP_CMDID,
-++	.bcn_tx_cmdid = WMI_10_2_BCN_TX_CMDID,
-++	.pdev_send_bcn_cmdid = WMI_10_2_PDEV_SEND_BCN_CMDID,
-++	.bcn_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.bcn_filter_rx_cmdid = WMI_10_2_BCN_FILTER_RX_CMDID,
-++	.prb_req_filter_rx_cmdid = WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
-++	.mgmt_tx_cmdid = WMI_10_2_MGMT_TX_CMDID,
-++	.prb_tmpl_cmdid = WMI_CMD_UNSUPPORTED,
-++	.addba_clear_resp_cmdid = WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
-++	.addba_send_cmdid = WMI_10_2_ADDBA_SEND_CMDID,
-++	.addba_status_cmdid = WMI_10_2_ADDBA_STATUS_CMDID,
-++	.delba_send_cmdid = WMI_10_2_DELBA_SEND_CMDID,
-++	.addba_set_resp_cmdid = WMI_10_2_ADDBA_SET_RESP_CMDID,
-++	.send_singleamsdu_cmdid = WMI_10_2_SEND_SINGLEAMSDU_CMDID,
-++	.sta_powersave_mode_cmdid = WMI_10_2_STA_POWERSAVE_MODE_CMDID,
-++	.sta_powersave_param_cmdid = WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
-++	.sta_mimo_ps_mode_cmdid = WMI_10_2_STA_MIMO_PS_MODE_CMDID,
-++	.pdev_dfs_enable_cmdid = WMI_10_2_PDEV_DFS_ENABLE_CMDID,
-++	.pdev_dfs_disable_cmdid = WMI_10_2_PDEV_DFS_DISABLE_CMDID,
-++	.roam_scan_mode = WMI_10_2_ROAM_SCAN_MODE,
-++	.roam_scan_rssi_threshold = WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
-++	.roam_scan_period = WMI_10_2_ROAM_SCAN_PERIOD,
-++	.roam_scan_rssi_change_threshold =
-++				WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	.roam_ap_profile = WMI_10_2_ROAM_AP_PROFILE,
-++	.ofl_scan_add_ap_profile = WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
-++	.ofl_scan_remove_ap_profile = WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
-++	.ofl_scan_period = WMI_10_2_OFL_SCAN_PERIOD,
-++	.p2p_dev_set_device_info = WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
-++	.p2p_dev_set_discoverability = WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
-++	.p2p_go_set_beacon_ie = WMI_10_2_P2P_GO_SET_BEACON_IE,
-++	.p2p_go_set_probe_resp_ie = WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
-++	.p2p_set_vendor_ie_data_cmdid = WMI_CMD_UNSUPPORTED,
-++	.ap_ps_peer_param_cmdid = WMI_10_2_AP_PS_PEER_PARAM_CMDID,
-++	.ap_ps_peer_uapsd_coex_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_rate_retry_sched_cmdid = WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
-++	.wlan_profile_trigger_cmdid = WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
-++	.wlan_profile_set_hist_intvl_cmdid =
-++				WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
-++	.wlan_profile_get_profile_data_cmdid =
-++				WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
-++	.wlan_profile_enable_profile_id_cmdid =
-++				WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
-++	.wlan_profile_list_profile_id_cmdid =
-++				WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
-++	.pdev_suspend_cmdid = WMI_10_2_PDEV_SUSPEND_CMDID,
-++	.pdev_resume_cmdid = WMI_10_2_PDEV_RESUME_CMDID,
-++	.add_bcn_filter_cmdid = WMI_10_2_ADD_BCN_FILTER_CMDID,
-++	.rmv_bcn_filter_cmdid = WMI_10_2_RMV_BCN_FILTER_CMDID,
-++	.wow_add_wake_pattern_cmdid = WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
-++	.wow_del_wake_pattern_cmdid = WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
-++	.wow_enable_disable_wake_event_cmdid =
-++				WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
-++	.wow_enable_cmdid = WMI_10_2_WOW_ENABLE_CMDID,
-++	.wow_hostwakeup_from_sleep_cmdid =
-++				WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
-++	.rtt_measreq_cmdid = WMI_10_2_RTT_MEASREQ_CMDID,
-++	.rtt_tsf_cmdid = WMI_10_2_RTT_TSF_CMDID,
-++	.vdev_spectral_scan_configure_cmdid =
-++				WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
-++	.vdev_spectral_scan_enable_cmdid =
-++				WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
-++	.request_stats_cmdid = WMI_10_2_REQUEST_STATS_CMDID,
-++	.set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
-++	.network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
-++	.gtk_offload_cmdid = WMI_CMD_UNSUPPORTED,
-++	.csa_offload_enable_cmdid = WMI_CMD_UNSUPPORTED,
-++	.csa_offload_chanswitch_cmdid = WMI_CMD_UNSUPPORTED,
-++	.chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
-++	.peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
-++	.sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
-++	.echo_cmdid = WMI_10_2_ECHO_CMDID,
-++	.pdev_utf_cmdid = WMI_10_2_PDEV_UTF_CMDID,
-++	.dbglog_cfg_cmdid = WMI_10_2_DBGLOG_CFG_CMDID,
-++	.pdev_qvit_cmdid = WMI_10_2_PDEV_QVIT_CMDID,
-++	.pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
-++	.vdev_set_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
-++	.vdev_get_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
-++	.force_fw_hang_cmdid = WMI_CMD_UNSUPPORTED,
-++	.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
-++	.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
-++	.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
-+ };
-+ 
-++void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
-++				const struct wmi_channel_arg *arg)
-++{
-++	u32 flags = 0;
-++
-++	memset(ch, 0, sizeof(*ch));
-++
-++	if (arg->passive)
-++		flags |= WMI_CHAN_FLAG_PASSIVE;
-++	if (arg->allow_ibss)
-++		flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
-++	if (arg->allow_ht)
-++		flags |= WMI_CHAN_FLAG_ALLOW_HT;
-++	if (arg->allow_vht)
-++		flags |= WMI_CHAN_FLAG_ALLOW_VHT;
-++	if (arg->ht40plus)
-++		flags |= WMI_CHAN_FLAG_HT40_PLUS;
-++	if (arg->chan_radar)
-++		flags |= WMI_CHAN_FLAG_DFS;
-++
-++	ch->mhz = __cpu_to_le32(arg->freq);
-++	ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
-++	ch->band_center_freq2 = 0;
-++	ch->min_power = arg->min_power;
-++	ch->max_power = arg->max_power;
-++	ch->reg_power = arg->max_reg_power;
-++	ch->antenna_max = arg->max_antenna_gain;
-++
-++	/* mode & flags share storage */
-++	ch->mode = arg->mode;
-++	ch->flags |= __cpu_to_le32(flags);
-++}
-++
-+ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
-+ {
-+ 	int ret;
-++
-+ 	ret = wait_for_completion_timeout(&ar->wmi.service_ready,
-+ 					  WMI_SERVICE_READY_TIMEOUT_HZ);
-+ 	return ret;
-+@@ -498,23 +894,24 @@ int ath10k_wmi_wait_for_service_ready(st
-+ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
-+ {
-+ 	int ret;
-++
-+ 	ret = wait_for_completion_timeout(&ar->wmi.unified_ready,
-+ 					  WMI_UNIFIED_READY_TIMEOUT_HZ);
-+ 	return ret;
-+ }
-+ 
-+-static struct sk_buff *ath10k_wmi_alloc_skb(u32 len)
-++struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
-+ {
-+ 	struct sk_buff *skb;
-+ 	u32 round_len = roundup(len, 4);
-+ 
-+-	skb = ath10k_htc_alloc_skb(WMI_SKB_HEADROOM + round_len);
-++	skb = ath10k_htc_alloc_skb(ar, WMI_SKB_HEADROOM + round_len);
-+ 	if (!skb)
-+ 		return NULL;
-+ 
-+ 	skb_reserve(skb, WMI_SKB_HEADROOM);
-+ 	if (!IS_ALIGNED((unsigned long)skb->data, 4))
-+-		ath10k_warn("Unaligned WMI skb\n");
-++		ath10k_warn(ar, "Unaligned WMI skb\n");
-+ 
-+ 	skb_put(skb, round_len);
-+ 	memset(skb->data, 0, round_len);
-+@@ -527,8 +924,8 @@ static void ath10k_wmi_htc_tx_complete(s
-+ 	dev_kfree_skb(skb);
-+ }
-+ 
-+-static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
-+-				      u32 cmd_id)
-++int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
-++			       u32 cmd_id)
-+ {
-+ 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
-+ 	struct wmi_cmd_hdr *cmd_hdr;
-+@@ -545,7 +942,7 @@ static int ath10k_wmi_cmd_send_nowait(st
-+ 
-+ 	memset(skb_cb, 0, sizeof(*skb_cb));
-+ 	ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
-+-	trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret);
-++	trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len, ret);
-+ 
-+ 	if (ret)
-+ 		goto err_pull;
-+@@ -559,23 +956,45 @@ err_pull:
-+ 
-+ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
-+ {
-++	struct ath10k *ar = arvif->ar;
-++	struct ath10k_skb_cb *cb;
-++	struct sk_buff *bcn;
-+ 	int ret;
-+ 
-+-	lockdep_assert_held(&arvif->ar->data_lock);
-++	spin_lock_bh(&ar->data_lock);
-+ 
-+-	if (arvif->beacon == NULL)
-+-		return;
-++	bcn = arvif->beacon;
-+ 
-+-	if (arvif->beacon_sent)
-+-		return;
-++	if (!bcn)
-++		goto unlock;
-+ 
-+-	ret = ath10k_wmi_beacon_send_ref_nowait(arvif);
-+-	if (ret)
-+-		return;
-++	cb = ATH10K_SKB_CB(bcn);
-++
-++	switch (arvif->beacon_state) {
-++	case ATH10K_BEACON_SENDING:
-++	case ATH10K_BEACON_SENT:
-++		break;
-++	case ATH10K_BEACON_SCHEDULED:
-++		arvif->beacon_state = ATH10K_BEACON_SENDING;
-++		spin_unlock_bh(&ar->data_lock);
-++
-++		ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
-++							arvif->vdev_id,
-++							bcn->data, bcn->len,
-++							cb->paddr,
-++							cb->bcn.dtim_zero,
-++							cb->bcn.deliver_cab);
-++
-++		spin_lock_bh(&ar->data_lock);
-+ 
-+-	/* We need to retain the arvif->beacon reference for DMA unmapping and
-+-	 * freeing the skbuff later. */
-+-	arvif->beacon_sent = true;
-++		if (ret == 0)
-++			arvif->beacon_state = ATH10K_BEACON_SENT;
-++		else
-++			arvif->beacon_state = ATH10K_BEACON_SCHEDULED;
-++	}
-++
-++unlock:
-++	spin_unlock_bh(&ar->data_lock);
-+ }
-+ 
-+ static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
-+@@ -588,12 +1007,10 @@ static void ath10k_wmi_tx_beacons_iter(v
-+ 
-+ static void ath10k_wmi_tx_beacons_nowait(struct ath10k *ar)
-+ {
-+-	spin_lock_bh(&ar->data_lock);
-+ 	ieee80211_iterate_active_interfaces_atomic(ar->hw,
-+ 						   IEEE80211_IFACE_ITER_NORMAL,
-+ 						   ath10k_wmi_tx_beacons_iter,
-+ 						   NULL);
-+-	spin_unlock_bh(&ar->data_lock);
-+ }
-+ 
-+ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
-+@@ -604,15 +1021,14 @@ static void ath10k_wmi_op_ep_tx_credits(
-+ 	wake_up(&ar->wmi.tx_credits_wq);
-+ }
-+ 
-+-static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
-+-			       u32 cmd_id)
-++int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
-+ {
-+ 	int ret = -EOPNOTSUPP;
-+ 
-+ 	might_sleep();
-+ 
-+ 	if (cmd_id == WMI_CMD_UNSUPPORTED) {
-+-		ath10k_warn("wmi command %d is not supported by firmware\n",
-++		ath10k_warn(ar, "wmi command %d is not supported by firmware\n",
-+ 			    cmd_id);
-+ 		return ret;
-+ 	}
-+@@ -622,6 +1038,10 @@ static int ath10k_wmi_cmd_send(struct at
-+ 		ath10k_wmi_tx_beacons_nowait(ar);
-+ 
-+ 		ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
-++
-++		if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
-++			ret = -ESHUTDOWN;
-++
-+ 		(ret != -EAGAIN);
-+ 	}), 3*HZ);
-+ 
-+@@ -631,147 +1051,270 @@ static int ath10k_wmi_cmd_send(struct at
-+ 	return ret;
-+ }
-+ 
-+-int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
-+ {
-+-	int ret = 0;
-+ 	struct wmi_mgmt_tx_cmd *cmd;
-+ 	struct ieee80211_hdr *hdr;
-+-	struct sk_buff *wmi_skb;
-+-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-++	struct sk_buff *skb;
-+ 	int len;
-++	u32 buf_len = msdu->len;
-+ 	u16 fc;
-+ 
-+-	hdr = (struct ieee80211_hdr *)skb->data;
-++	hdr = (struct ieee80211_hdr *)msdu->data;
-+ 	fc = le16_to_cpu(hdr->frame_control);
-+ 
-+ 	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-++
-++	len = sizeof(cmd->hdr) + msdu->len;
-++
-++	if ((ieee80211_is_action(hdr->frame_control) ||
-++	     ieee80211_is_deauth(hdr->frame_control) ||
-++	     ieee80211_is_disassoc(hdr->frame_control)) &&
-++	     ieee80211_has_protected(hdr->frame_control)) {
-++		len += IEEE80211_CCMP_MIC_LEN;
-++		buf_len += IEEE80211_CCMP_MIC_LEN;
-++	}
-+ 
-+-	len = sizeof(cmd->hdr) + skb->len;
-+ 	len = round_up(len, 4);
-+ 
-+-	wmi_skb = ath10k_wmi_alloc_skb(len);
-+-	if (!wmi_skb)
-+-		return -ENOMEM;
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-+ 
-+-	cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data;
-++	cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
-+ 
-+-	cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id);
-++	cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
-+ 	cmd->hdr.tx_rate = 0;
-+ 	cmd->hdr.tx_power = 0;
-+-	cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len));
-++	cmd->hdr.buf_len = __cpu_to_le32(buf_len);
-+ 
-+-	memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
-+-	memcpy(cmd->buf, skb->data, skb->len);
-++	ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
-++	memcpy(cmd->buf, msdu->data, msdu->len);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
-+-		   wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
-++		   msdu, skb->len, fc & IEEE80211_FCTL_FTYPE,
-+ 		   fc & IEEE80211_FCTL_STYPE);
-++	trace_ath10k_tx_hdr(ar, skb->data, skb->len);
-++	trace_ath10k_tx_payload(ar, skb->data, skb->len);
-+ 
-+-	/* Send the management frame buffer to the target */
-+-	ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
-+-	if (ret)
-+-		return ret;
-+-
-+-	/* TODO: report tx status to mac80211 - temporary just ACK */
-+-	info->flags |= IEEE80211_TX_STAT_ACK;
-+-	ieee80211_tx_status_irqsafe(ar->hw, skb);
-+-
-+-	return ret;
-++	return skb;
-+ }
-+ 
-+-static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
-++static void ath10k_wmi_event_scan_started(struct ath10k *ar)
-+ {
-+-	struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data;
-+-	enum wmi_scan_event_type event_type;
-+-	enum wmi_scan_completion_reason reason;
-+-	u32 freq;
-+-	u32 req_id;
-+-	u32 scan_id;
-+-	u32 vdev_id;
-+-
-+-	event_type = __le32_to_cpu(event->event_type);
-+-	reason     = __le32_to_cpu(event->reason);
-+-	freq       = __le32_to_cpu(event->channel_freq);
-+-	req_id     = __le32_to_cpu(event->scan_req_id);
-+-	scan_id    = __le32_to_cpu(event->scan_id);
-+-	vdev_id    = __le32_to_cpu(event->vdev_id);
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENTID\n");
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "scan event type %d reason %d freq %d req_id %d "
-+-		   "scan_id %d vdev_id %d\n",
-+-		   event_type, reason, freq, req_id, scan_id, vdev_id);
-++	lockdep_assert_held(&ar->data_lock);
-+ 
-+-	spin_lock_bh(&ar->data_lock);
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-++		ath10k_warn(ar, "received scan started event in an invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-++		break;
-++	case ATH10K_SCAN_STARTING:
-++		ar->scan.state = ATH10K_SCAN_RUNNING;
-+ 
-+-	switch (event_type) {
-+-	case WMI_SCAN_EVENT_STARTED:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n");
-+-		if (ar->scan.in_progress && ar->scan.is_roc)
-++		if (ar->scan.is_roc)
-+ 			ieee80211_ready_on_channel(ar->hw);
-+ 
-+ 		complete(&ar->scan.started);
-+ 		break;
-+-	case WMI_SCAN_EVENT_COMPLETED:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n");
-+-		switch (reason) {
-+-		case WMI_SCAN_REASON_COMPLETED:
-+-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_COMPLETED\n");
-+-			break;
-+-		case WMI_SCAN_REASON_CANCELLED:
-+-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_CANCELED\n");
-+-			break;
-+-		case WMI_SCAN_REASON_PREEMPTED:
-+-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_PREEMPTED\n");
-+-			break;
-+-		case WMI_SCAN_REASON_TIMEDOUT:
-+-			ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_TIMEDOUT\n");
-+-			break;
-+-		default:
-+-			break;
-+-		}
-+-
-+-		ar->scan_channel = NULL;
-+-		if (!ar->scan.in_progress) {
-+-			ath10k_warn("no scan requested, ignoring\n");
-+-			break;
-+-		}
-+-
-+-		if (ar->scan.is_roc) {
-+-			ath10k_offchan_tx_purge(ar);
-++	}
-++}
-+ 
-+-			if (!ar->scan.aborting)
-+-				ieee80211_remain_on_channel_expired(ar->hw);
-+-		} else {
-+-			ieee80211_scan_completed(ar->hw, ar->scan.aborting);
-+-		}
-++static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar)
-++{
-++	lockdep_assert_held(&ar->data_lock);
-+ 
-+-		del_timer(&ar->scan.timeout);
-+-		complete_all(&ar->scan.completed);
-+-		ar->scan.in_progress = false;
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-++		ath10k_warn(ar, "received scan start failed event in an invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-+ 		break;
-+-	case WMI_SCAN_EVENT_BSS_CHANNEL:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n");
-+-		ar->scan_channel = NULL;
-++	case ATH10K_SCAN_STARTING:
-++		complete(&ar->scan.started);
-++		__ath10k_scan_finish(ar);
-+ 		break;
-+-	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n");
-++	}
-++}
-++
-++static void ath10k_wmi_event_scan_completed(struct ath10k *ar)
-++{
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_STARTING:
-++		/* One suspected reason scan can be completed while starting is
-++		 * if firmware fails to deliver all scan events to the host,
-++		 * e.g. when transport pipe is full. This has been observed
-++		 * with spectral scan phyerr events starving wmi transport
-++		 * pipe. In such case the "scan completed" event should be (and
-++		 * is) ignored by the host as it may be just firmware's scan
-++		 * state machine recovering.
-++		 */
-++		ath10k_warn(ar, "received scan completed event in an invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-++		break;
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-++		__ath10k_scan_finish(ar);
-++		break;
-++	}
-++}
-++
-++static void ath10k_wmi_event_scan_bss_chan(struct ath10k *ar)
-++{
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_STARTING:
-++		ath10k_warn(ar, "received scan bss chan event in an invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-++		break;
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-++		ar->scan_channel = NULL;
-++		break;
-++	}
-++}
-++
-++static void ath10k_wmi_event_scan_foreign_chan(struct ath10k *ar, u32 freq)
-++{
-++	lockdep_assert_held(&ar->data_lock);
-++
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_STARTING:
-++		ath10k_warn(ar, "received scan foreign chan event in an invalid scan state: %s (%d)\n",
-++			    ath10k_scan_state_str(ar->scan.state),
-++			    ar->scan.state);
-++		break;
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-+ 		ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
-+-		if (ar->scan.in_progress && ar->scan.is_roc &&
-+-		    ar->scan.roc_freq == freq) {
-++
-++		if (ar->scan.is_roc && ar->scan.roc_freq == freq)
-+ 			complete(&ar->scan.on_channel);
-+-		}
-+ 		break;
-++	}
-++}
-++
-++static const char *
-++ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
-++			       enum wmi_scan_completion_reason reason)
-++{
-++	switch (type) {
-++	case WMI_SCAN_EVENT_STARTED:
-++		return "started";
-++	case WMI_SCAN_EVENT_COMPLETED:
-++		switch (reason) {
-++		case WMI_SCAN_REASON_COMPLETED:
-++			return "completed";
-++		case WMI_SCAN_REASON_CANCELLED:
-++			return "completed [cancelled]";
-++		case WMI_SCAN_REASON_PREEMPTED:
-++			return "completed [preempted]";
-++		case WMI_SCAN_REASON_TIMEDOUT:
-++			return "completed [timedout]";
-++		case WMI_SCAN_REASON_MAX:
-++			break;
-++		}
-++		return "completed [unknown]";
-++	case WMI_SCAN_EVENT_BSS_CHANNEL:
-++		return "bss channel";
-++	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
-++		return "foreign channel";
-+ 	case WMI_SCAN_EVENT_DEQUEUED:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n");
-+-		break;
-++		return "dequeued";
-+ 	case WMI_SCAN_EVENT_PREEMPTED:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_PREEMPTED\n");
-++		return "preempted";
-++	case WMI_SCAN_EVENT_START_FAILED:
-++		return "start failed";
-++	default:
-++		return "unknown";
-++	}
-++}
-++
-++static int ath10k_wmi_op_pull_scan_ev(struct ath10k *ar, struct sk_buff *skb,
-++				      struct wmi_scan_ev_arg *arg)
-++{
-++	struct wmi_scan_event *ev = (void *)skb->data;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->event_type = ev->event_type;
-++	arg->reason = ev->reason;
-++	arg->channel_freq = ev->channel_freq;
-++	arg->scan_req_id = ev->scan_req_id;
-++	arg->scan_id = ev->scan_id;
-++	arg->vdev_id = ev->vdev_id;
-++
-++	return 0;
-++}
-++
-++int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_scan_ev_arg arg = {};
-++	enum wmi_scan_event_type event_type;
-++	enum wmi_scan_completion_reason reason;
-++	u32 freq;
-++	u32 req_id;
-++	u32 scan_id;
-++	u32 vdev_id;
-++	int ret;
-++
-++	ret = ath10k_wmi_pull_scan(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse scan event: %d\n", ret);
-++		return ret;
-++	}
-++
-++	event_type = __le32_to_cpu(arg.event_type);
-++	reason = __le32_to_cpu(arg.reason);
-++	freq = __le32_to_cpu(arg.channel_freq);
-++	req_id = __le32_to_cpu(arg.scan_req_id);
-++	scan_id = __le32_to_cpu(arg.scan_id);
-++	vdev_id = __le32_to_cpu(arg.vdev_id);
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "scan event %s type %d reason %d freq %d req_id %d scan_id %d vdev_id %d state %s (%d)\n",
-++		   ath10k_wmi_event_scan_type_str(event_type, reason),
-++		   event_type, reason, freq, req_id, scan_id, vdev_id,
-++		   ath10k_scan_state_str(ar->scan.state), ar->scan.state);
-++
-++	switch (event_type) {
-++	case WMI_SCAN_EVENT_STARTED:
-++		ath10k_wmi_event_scan_started(ar);
-++		break;
-++	case WMI_SCAN_EVENT_COMPLETED:
-++		ath10k_wmi_event_scan_completed(ar);
-++		break;
-++	case WMI_SCAN_EVENT_BSS_CHANNEL:
-++		ath10k_wmi_event_scan_bss_chan(ar);
-++		break;
-++	case WMI_SCAN_EVENT_FOREIGN_CHANNEL:
-++		ath10k_wmi_event_scan_foreign_chan(ar, freq);
-+ 		break;
-+ 	case WMI_SCAN_EVENT_START_FAILED:
-+-		ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_START_FAILED\n");
-++		ath10k_warn(ar, "received scan start failure event\n");
-++		ath10k_wmi_event_scan_start_failed(ar);
-+ 		break;
-++	case WMI_SCAN_EVENT_DEQUEUED:
-++	case WMI_SCAN_EVENT_PREEMPTED:
-+ 	default:
-+ 		break;
-+ 	}
-+@@ -865,13 +1408,86 @@ static inline u8 get_rate_idx(u32 rate,
-+ 	return rate_idx;
-+ }
-+ 
-+-static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
-++/* If keys are configured, HW decrypts all frames
-++ * with protected bit set. Mark such frames as decrypted.
-++ */
-++static void ath10k_wmi_handle_wep_reauth(struct ath10k *ar,
-++					 struct sk_buff *skb,
-++					 struct ieee80211_rx_status *status)
-++{
-++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-++	unsigned int hdrlen;
-++	bool peer_key;
-++	u8 *addr, keyidx;
-++
-++	if (!ieee80211_is_auth(hdr->frame_control) ||
-++	    !ieee80211_has_protected(hdr->frame_control))
-++		return;
-++
-++	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-++	if (skb->len < (hdrlen + IEEE80211_WEP_IV_LEN))
-++		return;
-++
-++	keyidx = skb->data[hdrlen + (IEEE80211_WEP_IV_LEN - 1)] >> WEP_KEYID_SHIFT;
-++	addr = ieee80211_get_SA(hdr);
-++
-++	spin_lock_bh(&ar->data_lock);
-++	peer_key = ath10k_mac_is_peer_wep_key_set(ar, addr, keyidx);
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	if (peer_key) {
-++		ath10k_dbg(ar, ATH10K_DBG_MAC,
-++			   "mac wep key present for peer %pM\n", addr);
-++		status->flag |= RX_FLAG_DECRYPTED;
-++	}
-++}
-++
-++static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
-++					 struct wmi_mgmt_rx_ev_arg *arg)
-+ {
-+ 	struct wmi_mgmt_rx_event_v1 *ev_v1;
-+ 	struct wmi_mgmt_rx_event_v2 *ev_v2;
-+ 	struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
-++	size_t pull_len;
-++	u32 msdu_len;
-++
-++	if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
-++		ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
-++		ev_hdr = &ev_v2->hdr.v1;
-++		pull_len = sizeof(*ev_v2);
-++	} else {
-++		ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
-++		ev_hdr = &ev_v1->hdr;
-++		pull_len = sizeof(*ev_v1);
-++	}
-++
-++	if (skb->len < pull_len)
-++		return -EPROTO;
-++
-++	skb_pull(skb, pull_len);
-++	arg->channel = ev_hdr->channel;
-++	arg->buf_len = ev_hdr->buf_len;
-++	arg->status = ev_hdr->status;
-++	arg->snr = ev_hdr->snr;
-++	arg->phy_mode = ev_hdr->phy_mode;
-++	arg->rate = ev_hdr->rate;
-++
-++	msdu_len = __le32_to_cpu(arg->buf_len);
-++	if (skb->len < msdu_len)
-++		return -EPROTO;
-++
-++	/* the WMI buffer might've ended up being padded to 4 bytes due to HTC
-++	 * trailer with credit update. Trim the excess garbage.
-++	 */
-++	skb_trim(skb, msdu_len);
-++
-++	return 0;
-++}
-++
-++int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_mgmt_rx_ev_arg arg = {};
-+ 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+-	struct ieee80211_channel *ch;
-+ 	struct ieee80211_hdr *hdr;
-+ 	u32 rx_status;
-+ 	u32 channel;
-+@@ -880,28 +1496,24 @@ static int ath10k_wmi_event_mgmt_rx(stru
-+ 	u32 rate;
-+ 	u32 buf_len;
-+ 	u16 fc;
-+-	int pull_len;
-++	int ret;
-+ 
-+-	if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
-+-		ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
-+-		ev_hdr = &ev_v2->hdr.v1;
-+-		pull_len = sizeof(*ev_v2);
-+-	} else {
-+-		ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
-+-		ev_hdr = &ev_v1->hdr;
-+-		pull_len = sizeof(*ev_v1);
-++	ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret);
-++		return ret;
-+ 	}
-+ 
-+-	channel   = __le32_to_cpu(ev_hdr->channel);
-+-	buf_len   = __le32_to_cpu(ev_hdr->buf_len);
-+-	rx_status = __le32_to_cpu(ev_hdr->status);
-+-	snr       = __le32_to_cpu(ev_hdr->snr);
-+-	phy_mode  = __le32_to_cpu(ev_hdr->phy_mode);
-+-	rate	  = __le32_to_cpu(ev_hdr->rate);
-++	channel = __le32_to_cpu(arg.channel);
-++	buf_len = __le32_to_cpu(arg.buf_len);
-++	rx_status = __le32_to_cpu(arg.status);
-++	snr = __le32_to_cpu(arg.snr);
-++	phy_mode = __le32_to_cpu(arg.phy_mode);
-++	rate = __le32_to_cpu(arg.rate);
-+ 
-+ 	memset(status, 0, sizeof(*status));
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT,
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT,
-+ 		   "event mgmt rx status %08x\n", rx_status);
-+ 
-+ 	if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
-+@@ -919,66 +1531,70 @@ static int ath10k_wmi_event_mgmt_rx(stru
-+ 		return 0;
-+ 	}
-+ 
-+-	if (rx_status & WMI_RX_STATUS_ERR_CRC)
-+-		status->flag |= RX_FLAG_FAILED_FCS_CRC;
-++	if (rx_status & WMI_RX_STATUS_ERR_CRC) {
-++		dev_kfree_skb(skb);
-++		return 0;
-++	}
-++
-+ 	if (rx_status & WMI_RX_STATUS_ERR_MIC)
-+ 		status->flag |= RX_FLAG_MMIC_ERROR;
-+ 
-+-	/* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to
-++	/* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
-+ 	 * MODE_11B. This means phy_mode is not a reliable source for the band
-+-	 * of mgmt rx. */
-+-
-+-	ch = ar->scan_channel;
-+-	if (!ch)
-+-		ch = ar->rx_channel;
-+-
-+-	if (ch) {
-+-		status->band = ch->band;
-+-
-+-		if (phy_mode == MODE_11B &&
-+-		    status->band == IEEE80211_BAND_5GHZ)
-+-			ath10k_dbg(ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
-++	 * of mgmt rx.
-++	 */
-++	if (channel >= 1 && channel <= 14) {
-++		status->band = IEEE80211_BAND_2GHZ;
-++	} else if (channel >= 36 && channel <= 165) {
-++		status->band = IEEE80211_BAND_5GHZ;
-+ 	} else {
-+-		ath10k_warn("using (unreliable) phy_mode to extract band for mgmt rx\n");
-+-		status->band = phy_mode_to_band(phy_mode);
-++		/* Shouldn't happen unless list of advertised channels to
-++		 * mac80211 has been changed.
-++		 */
-++		WARN_ON_ONCE(1);
-++		dev_kfree_skb(skb);
-++		return 0;
-+ 	}
-+ 
-++	if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ)
-++		ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
-++
-+ 	status->freq = ieee80211_channel_to_frequency(channel, status->band);
-+ 	status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
-+ 	status->rate_idx = get_rate_idx(rate, status->band);
-+ 
-+-	skb_pull(skb, pull_len);
-+-
-+ 	hdr = (struct ieee80211_hdr *)skb->data;
-+ 	fc = le16_to_cpu(hdr->frame_control);
-+ 
-++	ath10k_wmi_handle_wep_reauth(ar, skb, status);
-++
-+ 	/* FW delivers WEP Shared Auth frame with Protected Bit set and
-+ 	 * encrypted payload. However in case of PMF it delivers decrypted
-+ 	 * frames with Protected Bit set. */
-+ 	if (ieee80211_has_protected(hdr->frame_control) &&
-+ 	    !ieee80211_is_auth(hdr->frame_control)) {
-+-		status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED |
-+-				RX_FLAG_MMIC_STRIPPED;
-+-		hdr->frame_control = __cpu_to_le16(fc &
-++		status->flag |= RX_FLAG_DECRYPTED;
-++
-++		if (!ieee80211_is_action(hdr->frame_control) &&
-++		    !ieee80211_is_deauth(hdr->frame_control) &&
-++		    !ieee80211_is_disassoc(hdr->frame_control)) {
-++			status->flag |= RX_FLAG_IV_STRIPPED |
-++					RX_FLAG_MMIC_STRIPPED;
-++			hdr->frame_control = __cpu_to_le16(fc &
-+ 					~IEEE80211_FCTL_PROTECTED);
-++		}
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT,
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT,
-+ 		   "event mgmt rx skb %p len %d ftype %02x stype %02x\n",
-+ 		   skb, skb->len,
-+ 		   fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT,
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT,
-+ 		   "event mgmt rx freq %d band %d snr %d, rate_idx %d\n",
-+ 		   status->freq, status->band, status->signal,
-+ 		   status->rate_idx);
-+ 
-+-	/*
-+-	 * packets from HTC come aligned to 4byte boundaries
-+-	 * because they can originally come in along with a trailer
-+-	 */
-+-	skb_trim(skb, buf_len);
-+-
-+ 	ieee80211_rx(ar->hw, skb);
-+ 	return 0;
-+ }
-+@@ -1002,37 +1618,65 @@ exit:
-+ 	return idx;
-+ }
-+ 
-+-static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
-++static int ath10k_wmi_op_pull_ch_info_ev(struct ath10k *ar, struct sk_buff *skb,
-++					 struct wmi_ch_info_ev_arg *arg)
-++{
-++	struct wmi_chan_info_event *ev = (void *)skb->data;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->err_code = ev->err_code;
-++	arg->freq = ev->freq;
-++	arg->cmd_flags = ev->cmd_flags;
-++	arg->noise_floor = ev->noise_floor;
-++	arg->rx_clear_count = ev->rx_clear_count;
-++	arg->cycle_count = ev->cycle_count;
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	struct wmi_chan_info_event *ev;
-++	struct wmi_ch_info_ev_arg arg = {};
-+ 	struct survey_info *survey;
-+ 	u32 err_code, freq, cmd_flags, noise_floor, rx_clear_count, cycle_count;
-+-	int idx;
-++	int idx, ret;
-+ 
-+-	ev = (struct wmi_chan_info_event *)skb->data;
-++	ret = ath10k_wmi_pull_ch_info(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse chan info event: %d\n", ret);
-++		return;
-++	}
-+ 
-+-	err_code = __le32_to_cpu(ev->err_code);
-+-	freq = __le32_to_cpu(ev->freq);
-+-	cmd_flags = __le32_to_cpu(ev->cmd_flags);
-+-	noise_floor = __le32_to_cpu(ev->noise_floor);
-+-	rx_clear_count = __le32_to_cpu(ev->rx_clear_count);
-+-	cycle_count = __le32_to_cpu(ev->cycle_count);
-++	err_code = __le32_to_cpu(arg.err_code);
-++	freq = __le32_to_cpu(arg.freq);
-++	cmd_flags = __le32_to_cpu(arg.cmd_flags);
-++	noise_floor = __le32_to_cpu(arg.noise_floor);
-++	rx_clear_count = __le32_to_cpu(arg.rx_clear_count);
-++	cycle_count = __le32_to_cpu(arg.cycle_count);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "chan info err_code %d freq %d cmd_flags %d noise_floor %d rx_clear_count %d cycle_count %d\n",
-+ 		   err_code, freq, cmd_flags, noise_floor, rx_clear_count,
-+ 		   cycle_count);
-+ 
-+ 	spin_lock_bh(&ar->data_lock);
-+ 
-+-	if (!ar->scan.in_progress) {
-+-		ath10k_warn("chan info event without a scan request?\n");
-++	switch (ar->scan.state) {
-++	case ATH10K_SCAN_IDLE:
-++	case ATH10K_SCAN_STARTING:
-++		ath10k_warn(ar, "received chan info event without a scan request, ignoring\n");
-+ 		goto exit;
-++	case ATH10K_SCAN_RUNNING:
-++	case ATH10K_SCAN_ABORTING:
-++		break;
-+ 	}
-+ 
-+ 	idx = freq_to_idx(ar, freq);
-+ 	if (idx >= ARRAY_SIZE(ar->survey)) {
-+-		ath10k_warn("chan info: invalid frequency %d (idx %d out of bounds)\n",
-++		ath10k_warn(ar, "chan info: invalid frequency %d (idx %d out of bounds)\n",
-+ 			    freq, idx);
-+ 		goto exit;
-+ 	}
-+@@ -1061,191 +1705,579 @@ exit:
-+ 	spin_unlock_bh(&ar->data_lock);
-+ }
-+ 
-+-static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb)
-++void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n");
-+ }
-+ 
-+-static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
-++int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug mesg len %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug mesg len %d\n",
-+ 		   skb->len);
-+ 
-+-	trace_ath10k_wmi_dbglog(skb->data, skb->len);
-++	trace_ath10k_wmi_dbglog(ar, skb->data, skb->len);
-+ 
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_wmi_event_update_stats(struct ath10k *ar,
-+-					  struct sk_buff *skb)
-++void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src,
-++				     struct ath10k_fw_stats_pdev *dst)
-+ {
-+-	struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data;
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
-+-
-+-	ath10k_debug_read_target_stats(ar, ev);
-+-}
-+-
-+-static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar,
-+-					     struct sk_buff *skb)
-++	dst->ch_noise_floor = __le32_to_cpu(src->chan_nf);
-++	dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count);
-++	dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count);
-++	dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count);
-++	dst->cycle_count = __le32_to_cpu(src->cycle_count);
-++	dst->phy_err_count = __le32_to_cpu(src->phy_err_count);
-++	dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr);
-++}
-++
-++void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
-++				   struct ath10k_fw_stats_pdev *dst)
-++{
-++	dst->comp_queued = __le32_to_cpu(src->comp_queued);
-++	dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
-++	dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
-++	dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
-++	dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
-++	dst->local_enqued = __le32_to_cpu(src->local_enqued);
-++	dst->local_freed = __le32_to_cpu(src->local_freed);
-++	dst->hw_queued = __le32_to_cpu(src->hw_queued);
-++	dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
-++	dst->underrun = __le32_to_cpu(src->underrun);
-++	dst->tx_abort = __le32_to_cpu(src->tx_abort);
-++	dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
-++	dst->tx_ko = __le32_to_cpu(src->tx_ko);
-++	dst->data_rc = __le32_to_cpu(src->data_rc);
-++	dst->self_triggers = __le32_to_cpu(src->self_triggers);
-++	dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
-++	dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
-++	dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
-++	dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
-++	dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
-++	dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
-++	dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
-++}
-++
-++void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
-++				   struct ath10k_fw_stats_pdev *dst)
-++{
-++	dst->mid_ppdu_route_change = __le32_to_cpu(src->mid_ppdu_route_change);
-++	dst->status_rcvd = __le32_to_cpu(src->status_rcvd);
-++	dst->r0_frags = __le32_to_cpu(src->r0_frags);
-++	dst->r1_frags = __le32_to_cpu(src->r1_frags);
-++	dst->r2_frags = __le32_to_cpu(src->r2_frags);
-++	dst->r3_frags = __le32_to_cpu(src->r3_frags);
-++	dst->htt_msdus = __le32_to_cpu(src->htt_msdus);
-++	dst->htt_mpdus = __le32_to_cpu(src->htt_mpdus);
-++	dst->loc_msdus = __le32_to_cpu(src->loc_msdus);
-++	dst->loc_mpdus = __le32_to_cpu(src->loc_mpdus);
-++	dst->oversize_amsdu = __le32_to_cpu(src->oversize_amsdu);
-++	dst->phy_errs = __le32_to_cpu(src->phy_errs);
-++	dst->phy_err_drop = __le32_to_cpu(src->phy_err_drop);
-++	dst->mpdu_errs = __le32_to_cpu(src->mpdu_errs);
-++}
-++
-++void ath10k_wmi_pull_pdev_stats_extra(const struct wmi_pdev_stats_extra *src,
-++				      struct ath10k_fw_stats_pdev *dst)
-++{
-++	dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
-++	dst->rts_bad = __le32_to_cpu(src->rts_bad);
-++	dst->rts_good = __le32_to_cpu(src->rts_good);
-++	dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
-++	dst->no_beacons = __le32_to_cpu(src->no_beacons);
-++	dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
-++}
-++
-++void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
-++				struct ath10k_fw_stats_peer *dst)
-++{
-++	ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
-++	dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
-++	dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
-++}
-++
-++static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
-++					    struct sk_buff *skb,
-++					    struct ath10k_fw_stats *stats)
-+ {
-+-	struct wmi_vdev_start_response_event *ev;
-++	const struct wmi_stats_event *ev = (void *)skb->data;
-++	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
-++	int i;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n");
-++	if (!skb_pull(skb, sizeof(*ev)))
-++		return -EPROTO;
-+ 
-+-	ev = (struct wmi_vdev_start_response_event *)skb->data;
-++	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-++	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-++	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-++
-++	for (i = 0; i < num_pdev_stats; i++) {
-++		const struct wmi_pdev_stats *src;
-++		struct ath10k_fw_stats_pdev *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-+ 
-+-	if (WARN_ON(__le32_to_cpu(ev->status)))
-+-		return;
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-+ 
-+-	complete(&ar->vdev_setup_done);
-+-}
-++		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
-++		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
-++		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
-+ 
-+-static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar,
-+-					  struct sk_buff *skb)
-+-{
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n");
-+-	complete(&ar->vdev_setup_done);
-+-}
-++		list_add_tail(&dst->list, &stats->pdevs);
-++	}
-+ 
-+-static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar,
-+-					      struct sk_buff *skb)
-+-{
-+-	struct wmi_peer_sta_kickout_event *ev;
-+-	struct ieee80211_sta *sta;
-++	/* fw doesn't implement vdev stats */
-+ 
-+-	ev = (struct wmi_peer_sta_kickout_event *)skb->data;
-++	for (i = 0; i < num_peer_stats; i++) {
-++		const struct wmi_peer_stats *src;
-++		struct ath10k_fw_stats_peer *dst;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n",
-+-		   ev->peer_macaddr.addr);
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-+ 
-+-	rcu_read_lock();
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-+ 
-+-	sta = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL);
-+-	if (!sta) {
-+-		ath10k_warn("Spurious quick kickout for STA %pM\n",
-+-			    ev->peer_macaddr.addr);
-+-		goto exit;
-++		ath10k_wmi_pull_peer_stats(src, dst);
-++		list_add_tail(&dst->list, &stats->peers);
-+ 	}
-+ 
-+-	ieee80211_report_low_ack(sta, 10);
-+-
-+-exit:
-+-	rcu_read_unlock();
-++	return 0;
-+ }
-+ 
-+-/*
-+- * FIXME
-+- *
-+- * We don't report to mac80211 sleep state of connected
-+- * stations. Due to this mac80211 can't fill in TIM IE
-+- * correctly.
-+- *
-+- * I know of no way of getting nullfunc frames that contain
-+- * sleep transition from connected stations - these do not
-+- * seem to be sent from the target to the host. There also
-+- * doesn't seem to be a dedicated event for that. So the
-+- * only way left to do this would be to read tim_bitmap
-+- * during SWBA.
-+- *
-+- * We could probably try using tim_bitmap from SWBA to tell
-+- * mac80211 which stations are asleep and which are not. The
-+- * problem here is calling mac80211 functions so many times
-+- * could take too long and make us miss the time to submit
-+- * the beacon to the target.
-+- *
-+- * So as a workaround we try to extend the TIM IE if there
-+- * is unicast buffered for stations with aid > 7 and fill it
-+- * in ourselves.
-+- */
-+-static void ath10k_wmi_update_tim(struct ath10k *ar,
-+-				  struct ath10k_vif *arvif,
-+-				  struct sk_buff *bcn,
-+-				  struct wmi_bcn_info *bcn_info)
-++static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar,
-++					   struct sk_buff *skb,
-++					   struct ath10k_fw_stats *stats)
-+ {
-+-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data;
-+-	struct ieee80211_tim_ie *tim;
-+-	u8 *ies, *ie;
-+-	u8 ie_len, pvm_len;
-++	const struct wmi_stats_event *ev = (void *)skb->data;
-++	u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
-++	int i;
-+ 
-+-	/* if next SWBA has no tim_changed the tim_bitmap is garbage.
-+-	 * we must copy the bitmap upon change and reuse it later */
-+-	if (__le32_to_cpu(bcn_info->tim_info.tim_changed)) {
-+-		int i;
-++	if (!skb_pull(skb, sizeof(*ev)))
-++		return -EPROTO;
-+ 
-+-		BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) !=
-+-			     sizeof(bcn_info->tim_info.tim_bitmap));
-++	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-++	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-++	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-++
-++	for (i = 0; i < num_pdev_stats; i++) {
-++		const struct wmi_10x_pdev_stats *src;
-++		struct ath10k_fw_stats_pdev *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-+ 
-+-		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
-+-			__le32 t = bcn_info->tim_info.tim_bitmap[i / 4];
-+-			u32 v = __le32_to_cpu(t);
-+-			arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
-+-		}
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-+ 
-+-		/* FW reports either length 0 or 16
-+-		 * so we calculate this on our own */
-+-		arvif->u.ap.tim_len = 0;
-+-		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++)
-+-			if (arvif->u.ap.tim_bitmap[i])
-+-				arvif->u.ap.tim_len = i;
-++		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
-++		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
-++		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
-++		ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
-+ 
-+-		arvif->u.ap.tim_len++;
-++		list_add_tail(&dst->list, &stats->pdevs);
-+ 	}
-+ 
-+-	ies = bcn->data;
-+-	ies += ieee80211_hdrlen(hdr->frame_control);
-+-	ies += 12; /* fixed parameters */
-++	/* fw doesn't implement vdev stats */
-+ 
-+-	ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies,
-+-				    (u8 *)skb_tail_pointer(bcn) - ies);
-+-	if (!ie) {
-+-		if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-+-			ath10k_warn("no tim ie found;\n");
-+-		return;
-+-	}
-++	for (i = 0; i < num_peer_stats; i++) {
-++		const struct wmi_10x_peer_stats *src;
-++		struct ath10k_fw_stats_peer *dst;
-+ 
-+-	tim = (void *)ie + 2;
-+-	ie_len = ie[1];
-+-	pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-+ 
-+-	if (pvm_len < arvif->u.ap.tim_len) {
-+-		int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len;
-+-		int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len);
-+-		void *next_ie = ie + 2 + ie_len;
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-+ 
-+-		if (skb_put(bcn, expand_size)) {
-+-			memmove(next_ie + expand_size, next_ie, move_size);
-++		ath10k_wmi_pull_peer_stats(&src->old, dst);
-+ 
-+-			ie[1] += expand_size;
-+-			ie_len += expand_size;
-+-			pvm_len += expand_size;
-+-		} else {
-+-			ath10k_warn("tim expansion failed\n");
-+-		}
-+-	}
-++		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
-+ 
-+-	if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) {
-+-		ath10k_warn("tim pvm length is too great (%d)\n", pvm_len);
-+-		return;
-++		list_add_tail(&dst->list, &stats->peers);
-+ 	}
-+ 
-+-	tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast);
-+-	memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
-++	return 0;
-++}
-+ 
-+-	if (tim->dtim_count == 0) {
-+-		ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
-++static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar,
-++					    struct sk_buff *skb,
-++					    struct ath10k_fw_stats *stats)
-++{
-++	const struct wmi_10_2_stats_event *ev = (void *)skb->data;
-++	u32 num_pdev_stats;
-++	u32 num_pdev_ext_stats;
-++	u32 num_vdev_stats;
-++	u32 num_peer_stats;
-++	int i;
-+ 
-+-		if (__le32_to_cpu(bcn_info->tim_info.tim_mcast) == 1)
-+-			ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
-+-	}
-++	if (!skb_pull(skb, sizeof(*ev)))
-++		return -EPROTO;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
-+-		   tim->dtim_count, tim->dtim_period,
-+-		   tim->bitmap_ctrl, pvm_len);
-++	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-++	num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
-++	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-++	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-++
-++	for (i = 0; i < num_pdev_stats; i++) {
-++		const struct wmi_10_2_pdev_stats *src;
-++		struct ath10k_fw_stats_pdev *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
-++		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
-++		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
-++		ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
-++		/* FIXME: expose 10.2 specific values */
-++
-++		list_add_tail(&dst->list, &stats->pdevs);
-++	}
-++
-++	for (i = 0; i < num_pdev_ext_stats; i++) {
-++		const struct wmi_10_2_pdev_ext_stats *src;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		/* FIXME: expose values to userspace
-++		 *
-++		 * Note: Even though this loop seems to do nothing it is
-++		 * required to parse following sub-structures properly.
-++		 */
-++	}
-++
-++	/* fw doesn't implement vdev stats */
-++
-++	for (i = 0; i < num_peer_stats; i++) {
-++		const struct wmi_10_2_peer_stats *src;
-++		struct ath10k_fw_stats_peer *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_peer_stats(&src->old, dst);
-++
-++		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
-++		/* FIXME: expose 10.2 specific values */
-++
-++		list_add_tail(&dst->list, &stats->peers);
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
-++					      struct sk_buff *skb,
-++					      struct ath10k_fw_stats *stats)
-++{
-++	const struct wmi_10_2_stats_event *ev = (void *)skb->data;
-++	u32 num_pdev_stats;
-++	u32 num_pdev_ext_stats;
-++	u32 num_vdev_stats;
-++	u32 num_peer_stats;
-++	int i;
-++
-++	if (!skb_pull(skb, sizeof(*ev)))
-++		return -EPROTO;
-++
-++	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-++	num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
-++	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-++	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-++
-++	for (i = 0; i < num_pdev_stats; i++) {
-++		const struct wmi_10_2_pdev_stats *src;
-++		struct ath10k_fw_stats_pdev *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
-++		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
-++		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
-++		ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
-++		/* FIXME: expose 10.2 specific values */
-++
-++		list_add_tail(&dst->list, &stats->pdevs);
-++	}
-++
-++	for (i = 0; i < num_pdev_ext_stats; i++) {
-++		const struct wmi_10_2_pdev_ext_stats *src;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		/* FIXME: expose values to userspace
-++		 *
-++		 * Note: Even though this loop seems to do nothing it is
-++		 * required to parse following sub-structures properly.
-++		 */
-++	}
-++
-++	/* fw doesn't implement vdev stats */
-++
-++	for (i = 0; i < num_peer_stats; i++) {
-++		const struct wmi_10_2_4_peer_stats *src;
-++		struct ath10k_fw_stats_peer *dst;
-++
-++		src = (void *)skb->data;
-++		if (!skb_pull(skb, sizeof(*src)))
-++			return -EPROTO;
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_peer_stats(&src->common.old, dst);
-++
-++		dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate);
-++		/* FIXME: expose 10.2 specific values */
-++
-++		list_add_tail(&dst->list, &stats->peers);
-++	}
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
-++	ath10k_debug_fw_stats_process(ar, skb);
-++}
-++
-++static int
-++ath10k_wmi_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
-++				 struct wmi_vdev_start_ev_arg *arg)
-++{
-++	struct wmi_vdev_start_response_event *ev = (void *)skb->data;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->vdev_id = ev->vdev_id;
-++	arg->req_id = ev->req_id;
-++	arg->resp_type = ev->resp_type;
-++	arg->status = ev->status;
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_vdev_start_ev_arg arg = {};
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n");
-++
-++	ret = ath10k_wmi_pull_vdev_start(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse vdev start event: %d\n", ret);
-++		return;
-++	}
-++
-++	if (WARN_ON(__le32_to_cpu(arg.status)))
-++		return;
-++
-++	complete(&ar->vdev_setup_done);
-++}
-++
-++void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n");
-++	complete(&ar->vdev_setup_done);
-++}
-++
-++static int
-++ath10k_wmi_op_pull_peer_kick_ev(struct ath10k *ar, struct sk_buff *skb,
-++				struct wmi_peer_kick_ev_arg *arg)
-++{
-++	struct wmi_peer_sta_kickout_event *ev = (void *)skb->data;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->mac_addr = ev->peer_macaddr.addr;
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_peer_kick_ev_arg arg = {};
-++	struct ieee80211_sta *sta;
-++	int ret;
-++
-++	ret = ath10k_wmi_pull_peer_kick(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse peer kickout event: %d\n",
-++			    ret);
-++		return;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event peer sta kickout %pM\n",
-++		   arg.mac_addr);
-++
-++	rcu_read_lock();
-++
-++	sta = ieee80211_find_sta_by_ifaddr(ar->hw, arg.mac_addr, NULL);
-++	if (!sta) {
-++		ath10k_warn(ar, "Spurious quick kickout for STA %pM\n",
-++			    arg.mac_addr);
-++		goto exit;
-++	}
-++
-++	ieee80211_report_low_ack(sta, 10);
-++
-++exit:
-++	rcu_read_unlock();
-++}
-++
-++/*
-++ * FIXME
-++ *
-++ * We don't report to mac80211 sleep state of connected
-++ * stations. Due to this mac80211 can't fill in TIM IE
-++ * correctly.
-++ *
-++ * I know of no way of getting nullfunc frames that contain
-++ * sleep transition from connected stations - these do not
-++ * seem to be sent from the target to the host. There also
-++ * doesn't seem to be a dedicated event for that. So the
-++ * only way left to do this would be to read tim_bitmap
-++ * during SWBA.
-++ *
-++ * We could probably try using tim_bitmap from SWBA to tell
-++ * mac80211 which stations are asleep and which are not. The
-++ * problem here is calling mac80211 functions so many times
-++ * could take too long and make us miss the time to submit
-++ * the beacon to the target.
-++ *
-++ * So as a workaround we try to extend the TIM IE if there
-++ * is unicast buffered for stations with aid > 7 and fill it
-++ * in ourselves.
-++ */
-++static void ath10k_wmi_update_tim(struct ath10k *ar,
-++				  struct ath10k_vif *arvif,
-++				  struct sk_buff *bcn,
-++				  const struct wmi_tim_info *tim_info)
-++{
-++	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data;
-++	struct ieee80211_tim_ie *tim;
-++	u8 *ies, *ie;
-++	u8 ie_len, pvm_len;
-++	__le32 t;
-++	u32 v;
-++
-++	/* if next SWBA has no tim_changed the tim_bitmap is garbage.
-++	 * we must copy the bitmap upon change and reuse it later */
-++	if (__le32_to_cpu(tim_info->tim_changed)) {
-++		int i;
-++
-++		BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) !=
-++			     sizeof(tim_info->tim_bitmap));
-++
-++		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
-++			t = tim_info->tim_bitmap[i / 4];
-++			v = __le32_to_cpu(t);
-++			arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
-++		}
-++
-++		/* FW reports either length 0 or 16
-++		 * so we calculate this on our own */
-++		arvif->u.ap.tim_len = 0;
-++		for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++)
-++			if (arvif->u.ap.tim_bitmap[i])
-++				arvif->u.ap.tim_len = i;
-++
-++		arvif->u.ap.tim_len++;
-++	}
-++
-++	ies = bcn->data;
-++	ies += ieee80211_hdrlen(hdr->frame_control);
-++	ies += 12; /* fixed parameters */
-++
-++	ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies,
-++				    (u8 *)skb_tail_pointer(bcn) - ies);
-++	if (!ie) {
-++		if (arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
-++			ath10k_warn(ar, "no tim ie found;\n");
-++		return;
-++	}
-++
-++	tim = (void *)ie + 2;
-++	ie_len = ie[1];
-++	pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */
-++
-++	if (pvm_len < arvif->u.ap.tim_len) {
-++		int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len;
-++		int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len);
-++		void *next_ie = ie + 2 + ie_len;
-++
-++		if (skb_put(bcn, expand_size)) {
-++			memmove(next_ie + expand_size, next_ie, move_size);
-++
-++			ie[1] += expand_size;
-++			ie_len += expand_size;
-++			pvm_len += expand_size;
-++		} else {
-++			ath10k_warn(ar, "tim expansion failed\n");
-++		}
-++	}
-++
-++	if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) {
-++		ath10k_warn(ar, "tim pvm length is too great (%d)\n", pvm_len);
-++		return;
-++	}
-++
-++	tim->bitmap_ctrl = !!__le32_to_cpu(tim_info->tim_mcast);
-++	memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
-++
-++	if (tim->dtim_count == 0) {
-++		ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
-++
-++		if (__le32_to_cpu(tim_info->tim_mcast) == 1)
-++			ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
-++	}
-++
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
-++		   tim->dtim_count, tim->dtim_period,
-++		   tim->bitmap_ctrl, pvm_len);
-+ }
-+ 
-+ static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len,
-+-				   struct wmi_p2p_noa_info *noa)
-++				   const struct wmi_p2p_noa_info *noa)
-+ {
-+ 	struct ieee80211_p2p_noa_attr *noa_attr;
-+ 	u8  ctwindow_oppps = noa->ctwindow_oppps;
-+@@ -1287,14 +2319,13 @@ static void ath10k_p2p_fill_noa_ie(u8 *d
-+ 	*noa_attr_len = __cpu_to_le16(attr_len);
-+ }
-+ 
-+-static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa)
-++static u32 ath10k_p2p_calc_noa_ie_len(const struct wmi_p2p_noa_info *noa)
-+ {
-+ 	u32 len = 0;
-+ 	u8 noa_descriptors = noa->num_descriptors;
-+ 	u8 opp_ps_info = noa->ctwindow_oppps;
-+ 	bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
-+ 
-+-
-+ 	if (!noa_descriptors && !opps_enabled)
-+ 		return len;
-+ 
-+@@ -1308,16 +2339,15 @@ static u32 ath10k_p2p_calc_noa_ie_len(st
-+ 
-+ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
-+ 				  struct sk_buff *bcn,
-+-				  struct wmi_bcn_info *bcn_info)
-++				  const struct wmi_p2p_noa_info *noa)
-+ {
-+-	struct wmi_p2p_noa_info *noa = &bcn_info->p2p_noa_info;
-+ 	u8 *new_data, *old_data = arvif->u.ap.noa_data;
-+ 	u32 new_len;
-+ 
-+ 	if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO)
-+ 		return;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed);
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed);
-+ 	if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) {
-+ 		new_len = ath10k_p2p_calc_noa_ie_len(noa);
-+ 		if (!new_len)
-+@@ -1351,22 +2381,59 @@ cleanup:
-+ 	kfree(old_data);
-+ }
-+ 
-++static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
-++				      struct wmi_swba_ev_arg *arg)
-++{
-++	struct wmi_host_swba_event *ev = (void *)skb->data;
-++	u32 map;
-++	size_t i;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->vdev_map = ev->vdev_map;
-++
-++	for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) {
-++		if (!(map & BIT(0)))
-++			continue;
-++
-++		/* If this happens there were some changes in firmware and
-++		 * ath10k should update the max size of tim_info array.
-++		 */
-++		if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info)))
-++			break;
-++
-++		arg->tim_info[i] = &ev->bcn_info[i].tim_info;
-++		arg->noa_info[i] = &ev->bcn_info[i].p2p_noa_info;
-++		i++;
-++	}
-++
-++	return 0;
-++}
-+ 
-+-static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
-++void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	struct wmi_host_swba_event *ev;
-++	struct wmi_swba_ev_arg arg = {};
-+ 	u32 map;
-+ 	int i = -1;
-+-	struct wmi_bcn_info *bcn_info;
-++	const struct wmi_tim_info *tim_info;
-++	const struct wmi_p2p_noa_info *noa_info;
-+ 	struct ath10k_vif *arvif;
-+ 	struct sk_buff *bcn;
-++	dma_addr_t paddr;
-+ 	int ret, vdev_id = 0;
-+ 
-+-	ev = (struct wmi_host_swba_event *)skb->data;
-+-	map = __le32_to_cpu(ev->vdev_map);
-++	ret = ath10k_wmi_pull_swba(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse swba event: %d\n", ret);
-++		return;
-++	}
-++
-++	map = __le32_to_cpu(arg.vdev_map);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_MGMT, "mgmt swba vdev_map 0x%x\n",
-+-		   ev->vdev_map);
-++	ath10k_dbg(ar, ATH10K_DBG_MGMT, "mgmt swba vdev_map 0x%x\n",
-++		   map);
-+ 
-+ 	for (; map; map >>= 1, vdev_id++) {
-+ 		if (!(map & 0x1))
-+@@ -1375,27 +2442,29 @@ static void ath10k_wmi_event_host_swba(s
-+ 		i++;
-+ 
-+ 		if (i >= WMI_MAX_AP_VDEV) {
-+-			ath10k_warn("swba has corrupted vdev map\n");
-++			ath10k_warn(ar, "swba has corrupted vdev map\n");
-+ 			break;
-+ 		}
-+ 
-+-		bcn_info = &ev->bcn_info[i];
-++		tim_info = arg.tim_info[i];
-++		noa_info = arg.noa_info[i];
-+ 
-+-		ath10k_dbg(ATH10K_DBG_MGMT,
-++		ath10k_dbg(ar, ATH10K_DBG_MGMT,
-+ 			   "mgmt event bcn_info %d tim_len %d mcast %d changed %d num_ps_pending %d bitmap 0x%08x%08x%08x%08x\n",
-+ 			   i,
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_len),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_mcast),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_changed),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_num_ps_pending),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_bitmap[3]),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_bitmap[2]),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_bitmap[1]),
-+-			   __le32_to_cpu(bcn_info->tim_info.tim_bitmap[0]));
-++			   __le32_to_cpu(tim_info->tim_len),
-++			   __le32_to_cpu(tim_info->tim_mcast),
-++			   __le32_to_cpu(tim_info->tim_changed),
-++			   __le32_to_cpu(tim_info->tim_num_ps_pending),
-++			   __le32_to_cpu(tim_info->tim_bitmap[3]),
-++			   __le32_to_cpu(tim_info->tim_bitmap[2]),
-++			   __le32_to_cpu(tim_info->tim_bitmap[1]),
-++			   __le32_to_cpu(tim_info->tim_bitmap[0]));
-+ 
-+ 		arvif = ath10k_get_arvif(ar, vdev_id);
-+ 		if (arvif == NULL) {
-+-			ath10k_warn("no vif for vdev_id %d found\n", vdev_id);
-++			ath10k_warn(ar, "no vif for vdev_id %d found\n",
-++				    vdev_id);
-+ 			continue;
-+ 		}
-+ 
-+@@ -1412,57 +2481,77 @@ static void ath10k_wmi_event_host_swba(s
-+ 
-+ 		bcn = ieee80211_beacon_get(ar->hw, arvif->vif);
-+ 		if (!bcn) {
-+-			ath10k_warn("could not get mac80211 beacon\n");
-++			ath10k_warn(ar, "could not get mac80211 beacon\n");
-+ 			continue;
-+ 		}
-+ 
-+-		ath10k_tx_h_seq_no(bcn);
-+-		ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info);
-+-		ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info);
-++		ath10k_tx_h_seq_no(arvif->vif, bcn);
-++		ath10k_wmi_update_tim(ar, arvif, bcn, tim_info);
-++		ath10k_wmi_update_noa(ar, arvif, bcn, noa_info);
-+ 
-+ 		spin_lock_bh(&ar->data_lock);
-+ 
-+ 		if (arvif->beacon) {
-+-			if (!arvif->beacon_sent)
-+-				ath10k_warn("SWBA overrun on vdev %d\n",
-++			switch (arvif->beacon_state) {
-++			case ATH10K_BEACON_SENT:
-++				break;
-++			case ATH10K_BEACON_SCHEDULED:
-++				ath10k_warn(ar, "SWBA overrun on vdev %d, skipped old beacon\n",
-+ 					    arvif->vdev_id);
-++				break;
-++			case ATH10K_BEACON_SENDING:
-++				ath10k_warn(ar, "SWBA overrun on vdev %d, skipped new beacon\n",
-++					    arvif->vdev_id);
-++				dev_kfree_skb(bcn);
-++				goto skip;
-++			}
-+ 
-+-			dma_unmap_single(arvif->ar->dev,
-+-					 ATH10K_SKB_CB(arvif->beacon)->paddr,
-+-					 arvif->beacon->len, DMA_TO_DEVICE);
-+-			dev_kfree_skb_any(arvif->beacon);
-+-			arvif->beacon = NULL;
-++			ath10k_mac_vif_beacon_free(arvif);
-+ 		}
-+ 
-+-		ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
-+-							   bcn->data, bcn->len,
-+-							   DMA_TO_DEVICE);
-+-		ret = dma_mapping_error(arvif->ar->dev,
-+-					ATH10K_SKB_CB(bcn)->paddr);
-+-		if (ret) {
-+-			ath10k_warn("failed to map beacon: %d\n", ret);
-+-			dev_kfree_skb_any(bcn);
-+-			goto skip;
-++		if (!arvif->beacon_buf) {
-++			paddr = dma_map_single(arvif->ar->dev, bcn->data,
-++					       bcn->len, DMA_TO_DEVICE);
-++			ret = dma_mapping_error(arvif->ar->dev, paddr);
-++			if (ret) {
-++				ath10k_warn(ar, "failed to map beacon: %d\n",
-++					    ret);
-++				dev_kfree_skb_any(bcn);
-++				goto skip;
-++			}
-++
-++			ATH10K_SKB_CB(bcn)->paddr = paddr;
-++		} else {
-++			if (bcn->len > IEEE80211_MAX_FRAME_LEN) {
-++				ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n",
-++					    bcn->len, IEEE80211_MAX_FRAME_LEN);
-++				skb_trim(bcn, IEEE80211_MAX_FRAME_LEN);
-++			}
-++			memcpy(arvif->beacon_buf, bcn->data, bcn->len);
-++			ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr;
-+ 		}
-+ 
-+ 		arvif->beacon = bcn;
-+-		arvif->beacon_sent = false;
-++		arvif->beacon_state = ATH10K_BEACON_SCHEDULED;
-++
-++		trace_ath10k_tx_hdr(ar, bcn->data, bcn->len);
-++		trace_ath10k_tx_payload(ar, bcn->data, bcn->len);
-+ 
-+-		ath10k_wmi_tx_beacon_nowait(arvif);
-+ skip:
-+ 		spin_unlock_bh(&ar->data_lock);
-+ 	}
-++
-++	ath10k_wmi_tx_beacons_nowait(ar);
-+ }
-+ 
-+-static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar,
-+-					       struct sk_buff *skb)
-++void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
-+ }
-+ 
-+ static void ath10k_dfs_radar_report(struct ath10k *ar,
-+-				    struct wmi_single_phyerr_rx_event *event,
-+-				    struct phyerr_radar_report *rr,
-++				    const struct wmi_phyerr *phyerr,
-++				    const struct phyerr_radar_report *rr,
-+ 				    u64 tsf)
-+ {
-+ 	u32 reg0, reg1, tsf32l;
-+@@ -1473,20 +2562,20 @@ static void ath10k_dfs_radar_report(stru
-+ 	reg0 = __le32_to_cpu(rr->reg0);
-+ 	reg1 = __le32_to_cpu(rr->reg1);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n",
-+ 		   MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP),
-+ 		   MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH),
-+ 		   MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN),
-+ 		   MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF));
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n",
-+ 		   MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK),
-+ 		   MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX),
-+ 		   MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID),
-+ 		   MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN),
-+ 		   MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK));
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n",
-+ 		   MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET),
-+ 		   MS(reg1, RADAR_REPORT_REG1_PULSE_DUR));
-+@@ -1495,12 +2584,12 @@ static void ath10k_dfs_radar_report(stru
-+ 		return;
-+ 
-+ 	/* report event to DFS pattern detector */
-+-	tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
-++	tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
-+ 	tsf64 = tsf & (~0xFFFFFFFFULL);
-+ 	tsf64 |= tsf32l;
-+ 
-+ 	width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
-+-	rssi = event->hdr.rssi_combined;
-++	rssi = phyerr->rssi_combined;
-+ 
-+ 	/* hardware store this as 8 bit signed value,
-+ 	 * set to zero if negative number
-+@@ -1513,25 +2602,25 @@ static void ath10k_dfs_radar_report(stru
-+ 	pe.width = width;
-+ 	pe.rssi = rssi;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n",
-+ 		   pe.freq, pe.width, pe.rssi, pe.ts);
-+ 
-+ 	ATH10K_DFS_STAT_INC(ar, pulses_detected);
-+ 
-+ 	if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
-+-		ath10k_dbg(ATH10K_DBG_REGULATORY,
-++		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 			   "dfs no pulse pattern detected, yet\n");
-+ 		return;
-+ 	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n");
-++	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("DFS Radar detected, but ignored as requested\n");
-++		ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
-+ 		return;
-+ 	}
-+ 
-+@@ -1539,8 +2628,8 @@ static void ath10k_dfs_radar_report(stru
-+ }
-+ 
-+ static int ath10k_dfs_fft_report(struct ath10k *ar,
-+-				 struct wmi_single_phyerr_rx_event *event,
-+-				 struct phyerr_fft_report *fftr,
-++				 const struct wmi_phyerr *phyerr,
-++				 const struct phyerr_fft_report *fftr,
-+ 				 u64 tsf)
-+ {
-+ 	u32 reg0, reg1;
-+@@ -1548,15 +2637,15 @@ static int ath10k_dfs_fft_report(struct
-+ 
-+ 	reg0 = __le32_to_cpu(fftr->reg0);
-+ 	reg1 = __le32_to_cpu(fftr->reg1);
-+-	rssi = event->hdr.rssi_combined;
-++	rssi = phyerr->rssi_combined;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
-+ 		   MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB),
-+ 		   MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB),
-+ 		   MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX),
-+ 		   MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX));
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n",
-+ 		   MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB),
-+ 		   MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB),
-+@@ -1568,7 +2657,7 @@ static int ath10k_dfs_fft_report(struct
-+ 	/* false event detection */
-+ 	if (rssi == DFS_RSSI_POSSIBLY_FALSE &&
-+ 	    peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) {
-+-		ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs false pulse detected\n");
-++		ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs false pulse detected\n");
-+ 		ATH10K_DFS_STAT_INC(ar, pulses_discarded);
-+ 		return -EINVAL;
-+ 	}
-+@@ -1576,21 +2665,21 @@ static int ath10k_dfs_fft_report(struct
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_wmi_event_dfs(struct ath10k *ar,
-+-				 struct wmi_single_phyerr_rx_event *event,
-+-				 u64 tsf)
-++void ath10k_wmi_event_dfs(struct ath10k *ar,
-++			  const struct wmi_phyerr *phyerr,
-++			  u64 tsf)
-+ {
-+ 	int buf_len, tlv_len, res, i = 0;
-+-	struct phyerr_tlv *tlv;
-+-	struct phyerr_radar_report *rr;
-+-	struct phyerr_fft_report *fftr;
-+-	u8 *tlv_buf;
-++	const struct phyerr_tlv *tlv;
-++	const struct phyerr_radar_report *rr;
-++	const struct phyerr_fft_report *fftr;
-++	const u8 *tlv_buf;
-+ 
-+-	buf_len = __le32_to_cpu(event->hdr.buf_len);
-+-	ath10k_dbg(ATH10K_DBG_REGULATORY,
-++	buf_len = __le32_to_cpu(phyerr->buf_len);
-++	ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 		   "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
-+-		   event->hdr.phy_err_code, event->hdr.rssi_combined,
-+-		   __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
-++		   phyerr->phy_err_code, phyerr->rssi_combined,
-++		   __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
-+ 
-+ 	/* Skip event if DFS disabled */
-+ 	if (!config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED))
-+@@ -1600,36 +2689,38 @@ static void ath10k_wmi_event_dfs(struct
-+ 
-+ 	while (i < buf_len) {
-+ 		if (i + sizeof(*tlv) > buf_len) {
-+-			ath10k_warn("too short buf for tlv header (%d)\n", i);
-++			ath10k_warn(ar, "too short buf for tlv header (%d)\n",
-++				    i);
-+ 			return;
-+ 		}
-+ 
-+-		tlv = (struct phyerr_tlv *)&event->bufp[i];
-++		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
-+ 		tlv_len = __le16_to_cpu(tlv->len);
-+-		tlv_buf = &event->bufp[i + sizeof(*tlv)];
-+-		ath10k_dbg(ATH10K_DBG_REGULATORY,
-++		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
-++		ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ 			   "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
-+ 			   tlv_len, tlv->tag, tlv->sig);
-+ 
-+ 		switch (tlv->tag) {
-+ 		case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY:
-+ 			if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) {
-+-				ath10k_warn("too short radar pulse summary (%d)\n",
-++				ath10k_warn(ar, "too short radar pulse summary (%d)\n",
-+ 					    i);
-+ 				return;
-+ 			}
-+ 
-+ 			rr = (struct phyerr_radar_report *)tlv_buf;
-+-			ath10k_dfs_radar_report(ar, event, rr, tsf);
-++			ath10k_dfs_radar_report(ar, phyerr, rr, tsf);
-+ 			break;
-+ 		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
-+ 			if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
-+-				ath10k_warn("too short fft report (%d)\n", i);
-++				ath10k_warn(ar, "too short fft report (%d)\n",
-++					    i);
-+ 				return;
-+ 			}
-+ 
-+ 			fftr = (struct phyerr_fft_report *)tlv_buf;
-+-			res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
-++			res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf);
-+ 			if (res)
-+ 				return;
-+ 			break;
-+@@ -1639,58 +2730,122 @@ static void ath10k_wmi_event_dfs(struct
-+ 	}
-+ }
-+ 
-+-static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-+-				struct wmi_single_phyerr_rx_event *event,
-+-				u64 tsf)
-+-{
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
-+-}
-+-
-+-static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
-++void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-++				    const struct wmi_phyerr *phyerr,
-++				    u64 tsf)
-+ {
-+-	struct wmi_comb_phyerr_rx_event *comb_event;
-+-	struct wmi_single_phyerr_rx_event *event;
-+-	u32 count, i, buf_len, phy_err_code;
-+-	u64 tsf;
-+-	int left_len = skb->len;
-+-
-+-	ATH10K_DFS_STAT_INC(ar, phy_errors);
-+-
-+-	/* Check if combined event available */
-+-	if (left_len < sizeof(*comb_event)) {
-+-		ath10k_warn("wmi phyerr combined event wrong len\n");
-+-		return;
-+-	}
-+-
-+-	left_len -= sizeof(*comb_event);
-++	int buf_len, tlv_len, res, i = 0;
-++	struct phyerr_tlv *tlv;
-++	const void *tlv_buf;
-++	const struct phyerr_fft_report *fftr;
-++	size_t fftr_len;
-+ 
-+-	/* Check number of included events */
-+-	comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
-+-	count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
-++	buf_len = __le32_to_cpu(phyerr->buf_len);
-+ 
-+-	tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
-+-	tsf <<= 32;
-+-	tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
-++	while (i < buf_len) {
-++		if (i + sizeof(*tlv) > buf_len) {
-++			ath10k_warn(ar, "failed to parse phyerr tlv header at byte %d\n",
-++				    i);
-++			return;
-++		}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi event phyerr count %d tsf64 0x%llX\n",
-+-		   count, tsf);
-++		tlv = (struct phyerr_tlv *)&phyerr->buf[i];
-++		tlv_len = __le16_to_cpu(tlv->len);
-++		tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
-+ 
-+-	event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
-+-	for (i = 0; i < count; i++) {
-+-		/* Check if we can read event header */
-+-		if (left_len < sizeof(*event)) {
-+-			ath10k_warn("single event (%d) wrong head len\n", i);
-++		if (i + sizeof(*tlv) + tlv_len > buf_len) {
-++			ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n",
-++				    i);
-+ 			return;
-+ 		}
-+ 
-+-		left_len -= sizeof(*event);
-+-
-+-		buf_len = __le32_to_cpu(event->hdr.buf_len);
-+-		phy_err_code = event->hdr.phy_err_code;
-++		switch (tlv->tag) {
-++		case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
-++			if (sizeof(*fftr) > tlv_len) {
-++				ath10k_warn(ar, "failed to parse fft report at byte %d\n",
-++					    i);
-++				return;
-++			}
-++
-++			fftr_len = tlv_len - sizeof(*fftr);
-++			fftr = tlv_buf;
-++			res = ath10k_spectral_process_fft(ar, phyerr,
-++							  fftr, fftr_len,
-++							  tsf);
-++			if (res < 0) {
-++				ath10k_warn(ar, "failed to process fft report: %d\n",
-++					    res);
-++				return;
-++			}
-++			break;
-++		}
-++
-++		i += sizeof(*tlv) + tlv_len;
-++	}
-++}
-++
-++static int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, struct sk_buff *skb,
-++					struct wmi_phyerr_ev_arg *arg)
-++{
-++	struct wmi_phyerr_event *ev = (void *)skb->data;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	arg->num_phyerrs = ev->num_phyerrs;
-++	arg->tsf_l32 = ev->tsf_l32;
-++	arg->tsf_u32 = ev->tsf_u32;
-++	arg->buf_len = __cpu_to_le32(skb->len - sizeof(*ev));
-++	arg->phyerrs = ev->phyerrs;
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_phyerr_ev_arg arg = {};
-++	const struct wmi_phyerr *phyerr;
-++	u32 count, i, buf_len, phy_err_code;
-++	u64 tsf;
-++	int left_len, ret;
-++
-++	ATH10K_DFS_STAT_INC(ar, phy_errors);
-++
-++	ret = ath10k_wmi_pull_phyerr(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse phyerr event: %d\n", ret);
-++		return;
-++	}
-++
-++	left_len = __le32_to_cpu(arg.buf_len);
-++
-++	/* Check number of included events */
-++	count = __le32_to_cpu(arg.num_phyerrs);
-++
-++	tsf = __le32_to_cpu(arg.tsf_u32);
-++	tsf <<= 32;
-++	tsf |= __le32_to_cpu(arg.tsf_l32);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi event phyerr count %d tsf64 0x%llX\n",
-++		   count, tsf);
-++
-++	phyerr = arg.phyerrs;
-++	for (i = 0; i < count; i++) {
-++		/* Check if we can read event header */
-++		if (left_len < sizeof(*phyerr)) {
-++			ath10k_warn(ar, "single event (%d) wrong head len\n",
-++				    i);
-++			return;
-++		}
-++
-++		left_len -= sizeof(*phyerr);
-++
-++		buf_len = __le32_to_cpu(phyerr->buf_len);
-++		phy_err_code = phyerr->phy_err_code;
-+ 
-+ 		if (left_len < buf_len) {
-+-			ath10k_warn("single event (%d) wrong buf len\n", i);
-++			ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
-+ 			return;
-+ 		}
-+ 
-+@@ -1698,36 +2853,34 @@ static void ath10k_wmi_event_phyerr(stru
-+ 
-+ 		switch (phy_err_code) {
-+ 		case PHY_ERROR_RADAR:
-+-			ath10k_wmi_event_dfs(ar, event, tsf);
-++			ath10k_wmi_event_dfs(ar, phyerr, tsf);
-+ 			break;
-+ 		case PHY_ERROR_SPECTRAL_SCAN:
-+-			ath10k_wmi_event_spectral_scan(ar, event, tsf);
-++			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
-+ 			break;
-+ 		case PHY_ERROR_FALSE_RADAR_EXT:
-+-			ath10k_wmi_event_dfs(ar, event, tsf);
-+-			ath10k_wmi_event_spectral_scan(ar, event, tsf);
-++			ath10k_wmi_event_dfs(ar, phyerr, tsf);
-++			ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
-+ 			break;
-+ 		default:
-+ 			break;
-+ 		}
-+ 
-+-		event += sizeof(*event) + buf_len;
-++		phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
-+ 	}
-+ }
-+ 
-+-static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
-++void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_profile_match(struct ath10k *ar,
-+-				    struct sk_buff *skb)
-++void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_debug_print(struct ath10k *ar,
-+-					 struct sk_buff *skb)
-++void ath10k_wmi_event_debug_print(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+ 	char buf[101], c;
-+ 	int i;
-+@@ -1748,7 +2901,7 @@ static void ath10k_wmi_event_debug_print
-+ 	}
-+ 
-+ 	if (i == sizeof(buf) - 1)
-+-		ath10k_warn("wmi debug print truncated: %d\n", skb->len);
-++		ath10k_warn(ar, "wmi debug print truncated: %d\n", skb->len);
-+ 
-+ 	/* for some reason the debug prints end with \n, remove that */
-+ 	if (skb->data[i - 1] == '\n')
-+@@ -1757,112 +2910,99 @@ static void ath10k_wmi_event_debug_print
-+ 	/* the last byte is always reserved for the null character */
-+ 	buf[i] = '\0';
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI_PRINT, "wmi print '%s'\n", buf);
-+ }
-+ 
-+-static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
-++void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar,
-+-					       struct sk_buff *skb)
-++void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
-++void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
-+ 					     struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
-++void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
-+ 					     struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_rtt_error_report(struct ath10k *ar,
-+-					      struct sk_buff *skb)
-++void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar,
-+-					     struct sk_buff *skb)
-++void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_dcs_interference(struct ath10k *ar,
-+-					      struct sk_buff *skb)
-++void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar,
-+-					     struct sk_buff *skb)
-++void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar,
-+-					   struct sk_buff *skb)
-++void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
-+-					 struct sk_buff *skb)
-++void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar,
-+-					    struct sk_buff *skb)
-++void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_delba_complete(struct ath10k *ar,
-+-					    struct sk_buff *skb)
-++void ath10k_wmi_event_delba_complete(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_addba_complete(struct ath10k *ar,
-+-					    struct sk_buff *skb)
-++void ath10k_wmi_event_addba_complete(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
-++void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
-+ 						struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar,
-+-					     struct sk_buff *skb)
-++void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_INST_RSSI_STATS_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar,
-+-					      struct sk_buff *skb)
-++void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_STANDBY_REQ_EVENTID\n");
-+ }
-+ 
-+-static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar,
-+-					     struct sk_buff *skb)
-++void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
-+ }
-+ 
-+ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
-+-				      u32 num_units, u32 unit_len)
-++				     u32 num_units, u32 unit_len)
-+ {
-+ 	dma_addr_t paddr;
-+ 	u32 pool_size;
-+@@ -1878,7 +3018,7 @@ static int ath10k_wmi_alloc_host_mem(str
-+ 							   &paddr,
-+ 							   GFP_ATOMIC);
-+ 	if (!ar->wmi.mem_chunks[idx].vaddr) {
-+-		ath10k_warn("failed to allocate memory chunk\n");
-++		ath10k_warn(ar, "failed to allocate memory chunk\n");
-+ 		return -ENOMEM;
-+ 	}
-+ 
-+@@ -1892,45 +3032,124 @@ static int ath10k_wmi_alloc_host_mem(str
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
-+-					      struct sk_buff *skb)
-++static int
-++ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
-++				   struct wmi_svc_rdy_ev_arg *arg)
-++{
-++	struct wmi_service_ready_event *ev;
-++	size_t i, n;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	ev = (void *)skb->data;
-++	skb_pull(skb, sizeof(*ev));
-++	arg->min_tx_power = ev->hw_min_tx_power;
-++	arg->max_tx_power = ev->hw_max_tx_power;
-++	arg->ht_cap = ev->ht_cap_info;
-++	arg->vht_cap = ev->vht_cap_info;
-++	arg->sw_ver0 = ev->sw_version;
-++	arg->sw_ver1 = ev->sw_version_1;
-++	arg->phy_capab = ev->phy_capability;
-++	arg->num_rf_chains = ev->num_rf_chains;
-++	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
-++	arg->num_mem_reqs = ev->num_mem_reqs;
-++	arg->service_map = ev->wmi_service_bitmap;
-++	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-++
-++	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
-++		  ARRAY_SIZE(arg->mem_reqs));
-++	for (i = 0; i < n; i++)
-++		arg->mem_reqs[i] = &ev->mem_reqs[i];
-++
-++	if (skb->len <
-++	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
-++		return -EPROTO;
-++
-++	return 0;
-++}
-++
-++static int
-++ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
-++				  struct wmi_svc_rdy_ev_arg *arg)
-++{
-++	struct wmi_10x_service_ready_event *ev;
-++	int i, n;
-++
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	ev = (void *)skb->data;
-++	skb_pull(skb, sizeof(*ev));
-++	arg->min_tx_power = ev->hw_min_tx_power;
-++	arg->max_tx_power = ev->hw_max_tx_power;
-++	arg->ht_cap = ev->ht_cap_info;
-++	arg->vht_cap = ev->vht_cap_info;
-++	arg->sw_ver0 = ev->sw_version;
-++	arg->phy_capab = ev->phy_capability;
-++	arg->num_rf_chains = ev->num_rf_chains;
-++	arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
-++	arg->num_mem_reqs = ev->num_mem_reqs;
-++	arg->service_map = ev->wmi_service_bitmap;
-++	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-++
-++	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
-++		  ARRAY_SIZE(arg->mem_reqs));
-++	for (i = 0; i < n; i++)
-++		arg->mem_reqs[i] = &ev->mem_reqs[i];
-++
-++	if (skb->len <
-++	    __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
-++		return -EPROTO;
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	struct wmi_service_ready_event *ev = (void *)skb->data;
-++	struct wmi_svc_rdy_ev_arg arg = {};
-++	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
-++	int ret;
-+ 
-+-	if (skb->len < sizeof(*ev)) {
-+-		ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
-+-			    skb->len, sizeof(*ev));
-++	ret = ath10k_wmi_pull_svc_rdy(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
-+ 		return;
-+ 	}
-+ 
-+-	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
-+-	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
-+-	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
-+-	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
-++	memset(&ar->wmi.svc_map, 0, sizeof(ar->wmi.svc_map));
-++	ath10k_wmi_map_svc(ar, arg.service_map, ar->wmi.svc_map,
-++			   arg.service_map_len);
-++
-++	ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
-++	ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
-++	ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
-++	ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
-+ 	ar->fw_version_major =
-+-		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
-+-	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
-++		(__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
-++	ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
-+ 	ar->fw_version_release =
-+-		(__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16;
-+-	ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff);
-+-	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
-+-	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
-++		(__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
-++	ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
-++	ar->phy_capability = __le32_to_cpu(arg.phy_capab);
-++	ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
-++	ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
-++
-++	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
-++			arg.service_map, arg.service_map_len);
-+ 
-+ 	/* only manually set fw features when not using FW IE format */
-+ 	if (ar->fw_api == 1 && ar->fw_version_build > 636)
-+ 		set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
-+ 
-+ 	if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
-+-		ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n",
-++		ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
-+ 			    ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
-+ 		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
-+ 	}
-+ 
-+-	ar->ath_common.regulatory.current_rd =
-+-		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
-+-
-+-	ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap,
-+-				      sizeof(ev->wmi_service_bitmap));
-++	ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
-++	ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
-+ 
-+ 	if (strlen(ar->hw->wiphy->fw_version) == 0) {
-+ 		snprintf(ar->hw->wiphy->fw_version,
-+@@ -1942,90 +3161,18 @@ static void ath10k_wmi_service_ready_eve
-+ 			 ar->fw_version_build);
-+ 	}
-+ 
-+-	/* FIXME: it probably should be better to support this */
-+-	if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
-+-		ath10k_warn("target requested %d memory chunks; ignoring\n",
-+-			    __le32_to_cpu(ev->num_mem_reqs));
-+-	}
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
-+-		   __le32_to_cpu(ev->sw_version),
-+-		   __le32_to_cpu(ev->sw_version_1),
-+-		   __le32_to_cpu(ev->abi_version),
-+-		   __le32_to_cpu(ev->phy_capability),
-+-		   __le32_to_cpu(ev->ht_cap_info),
-+-		   __le32_to_cpu(ev->vht_cap_info),
-+-		   __le32_to_cpu(ev->vht_supp_mcs),
-+-		   __le32_to_cpu(ev->sys_cap_info),
-+-		   __le32_to_cpu(ev->num_mem_reqs),
-+-		   __le32_to_cpu(ev->num_rf_chains));
-+-
-+-	complete(&ar->wmi.service_ready);
-+-}
-+-
-+-static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
-+-						  struct sk_buff *skb)
-+-{
-+-	u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
-+-	int ret;
-+-	struct wmi_service_ready_event_10x *ev = (void *)skb->data;
-+-
-+-	if (skb->len < sizeof(*ev)) {
-+-		ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
-+-			    skb->len, sizeof(*ev));
-+-		return;
-+-	}
-+-
-+-	ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
-+-	ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
-+-	ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
-+-	ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
-+-	ar->fw_version_major =
-+-		(__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
-+-	ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
-+-	ar->phy_capability = __le32_to_cpu(ev->phy_capability);
-+-	ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
-+-
-+-	if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
-+-		ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n",
-+-			    ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
-+-		ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
-+-	}
-+-
-+-	ar->ath_common.regulatory.current_rd =
-+-		__le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
-+-
-+-	ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap,
-+-				      sizeof(ev->wmi_service_bitmap));
-+-
-+-	if (strlen(ar->hw->wiphy->fw_version) == 0) {
-+-		snprintf(ar->hw->wiphy->fw_version,
-+-			 sizeof(ar->hw->wiphy->fw_version),
-+-			 "%u.%u",
-+-			 ar->fw_version_major,
-+-			 ar->fw_version_minor);
-+-	}
-+-
-+-	num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs);
-+-
-+-	if (num_mem_reqs > ATH10K_MAX_MEM_REQS) {
-+-		ath10k_warn("requested memory chunks number (%d) exceeds the limit\n",
-++	num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
-++	if (num_mem_reqs > WMI_MAX_MEM_REQS) {
-++		ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
-+ 			    num_mem_reqs);
-+ 		return;
-+ 	}
-+ 
-+-	if (!num_mem_reqs)
-+-		goto exit;
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n",
-+-		   num_mem_reqs);
-+-
-+ 	for (i = 0; i < num_mem_reqs; ++i) {
-+-		req_id = __le32_to_cpu(ev->mem_reqs[i].req_id);
-+-		num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
-+-		unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size);
-+-		num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info);
-++		req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
-++		num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
-++		unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
-++		num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
-+ 
-+ 		if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
-+ 			/* number of units to allocate is number of
-+@@ -2036,10 +3183,10 @@ static void ath10k_wmi_10x_service_ready
-+ 		else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS)
-+ 			num_units = TARGET_10X_NUM_VDEVS + 1;
-+ 
-+-		ath10k_dbg(ATH10K_DBG_WMI,
-++		ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 			   "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
-+ 			   req_id,
-+-			   __le32_to_cpu(ev->mem_reqs[i].num_units),
-++			   __le32_to_cpu(arg.mem_reqs[i]->num_units),
-+ 			   num_unit_info,
-+ 			   unit_size,
-+ 			   num_units);
-+@@ -2050,47 +3197,79 @@ static void ath10k_wmi_10x_service_ready
-+ 			return;
-+ 	}
-+ 
-+-exit:
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
-+-		   __le32_to_cpu(ev->sw_version),
-+-		   __le32_to_cpu(ev->abi_version),
-+-		   __le32_to_cpu(ev->phy_capability),
-+-		   __le32_to_cpu(ev->ht_cap_info),
-+-		   __le32_to_cpu(ev->vht_cap_info),
-+-		   __le32_to_cpu(ev->vht_supp_mcs),
-+-		   __le32_to_cpu(ev->sys_cap_info),
-+-		   __le32_to_cpu(ev->num_mem_reqs),
-+-		   __le32_to_cpu(ev->num_rf_chains));
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
-++		   __le32_to_cpu(arg.min_tx_power),
-++		   __le32_to_cpu(arg.max_tx_power),
-++		   __le32_to_cpu(arg.ht_cap),
-++		   __le32_to_cpu(arg.vht_cap),
-++		   __le32_to_cpu(arg.sw_ver0),
-++		   __le32_to_cpu(arg.sw_ver1),
-++		   __le32_to_cpu(arg.fw_build),
-++		   __le32_to_cpu(arg.phy_capab),
-++		   __le32_to_cpu(arg.num_rf_chains),
-++		   __le32_to_cpu(arg.eeprom_rd),
-++		   __le32_to_cpu(arg.num_mem_reqs));
-+ 
-+ 	complete(&ar->wmi.service_ready);
-+ }
-+ 
-+-static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
-++static int ath10k_wmi_op_pull_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
-++				     struct wmi_rdy_ev_arg *arg)
-+ {
-+-	struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data;
-++	struct wmi_ready_event *ev = (void *)skb->data;
-+ 
-+-	if (WARN_ON(skb->len < sizeof(*ev)))
-+-		return -EINVAL;
-++	if (skb->len < sizeof(*ev))
-++		return -EPROTO;
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->sw_version = ev->sw_version;
-++	arg->abi_version = ev->abi_version;
-++	arg->status = ev->status;
-++	arg->mac_addr = ev->mac_addr.addr;
-++
-++	return 0;
-++}
-++
-++int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_rdy_ev_arg arg = {};
-++	int ret;
-+ 
-+-	memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN);
-++	ret = ath10k_wmi_pull_rdy(ar, skb, &arg);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse ready event: %d\n", ret);
-++		return ret;
-++	}
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n",
-+-		   __le32_to_cpu(ev->sw_version),
-+-		   __le32_to_cpu(ev->abi_version),
-+-		   ev->mac_addr.addr,
-+-		   __le32_to_cpu(ev->status), skb->len, sizeof(*ev));
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n",
-++		   __le32_to_cpu(arg.sw_version),
-++		   __le32_to_cpu(arg.abi_version),
-++		   arg.mac_addr,
-++		   __le32_to_cpu(arg.status));
-+ 
-++	ether_addr_copy(ar->mac_addr, arg.mac_addr);
-+ 	complete(&ar->wmi.unified_ready);
-+ 	return 0;
-+ }
-+ 
-+-static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
-++static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	const struct wmi_pdev_temperature_event *ev;
-++
-++	ev = (struct wmi_pdev_temperature_event *)skb->data;
-++	if (WARN_ON(skb->len < sizeof(*ev)))
-++		return -EPROTO;
-++
-++	ath10k_thermal_event_temperature(ar, __le32_to_cpu(ev->temperature));
-++	return 0;
-++}
-++
-++static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+ 	struct wmi_cmd_hdr *cmd_hdr;
-+ 	enum wmi_event_id id;
-+-	u16 len;
-+ 
-+ 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
-+ 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
-+@@ -2098,9 +3277,7 @@ static void ath10k_wmi_main_process_rx(s
-+ 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-+ 		return;
-+ 
-+-	len = skb->len;
-+-
-+-	trace_ath10k_wmi_event(id, skb->data, skb->len);
-++	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
-+ 
-+ 	switch (id) {
-+ 	case WMI_MGMT_RX_EVENTID:
-+@@ -2192,24 +3369,24 @@ static void ath10k_wmi_main_process_rx(s
-+ 		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
-+ 		break;
-+ 	case WMI_SERVICE_READY_EVENTID:
-+-		ath10k_wmi_service_ready_event_rx(ar, skb);
-++		ath10k_wmi_event_service_ready(ar, skb);
-+ 		break;
-+ 	case WMI_READY_EVENTID:
-+-		ath10k_wmi_ready_event_rx(ar, skb);
-++		ath10k_wmi_event_ready(ar, skb);
-+ 		break;
-+ 	default:
-+-		ath10k_warn("Unknown eventid: %d\n", id);
-++		ath10k_warn(ar, "Unknown eventid: %d\n", id);
-+ 		break;
-+ 	}
-+ 
-+ 	dev_kfree_skb(skb);
-+ }
-+ 
-+-static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
-++static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+ 	struct wmi_cmd_hdr *cmd_hdr;
-+ 	enum wmi_10x_event_id id;
-+-	u16 len;
-++	bool consumed;
-+ 
-+ 	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
-+ 	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
-+@@ -2217,9 +3394,19 @@ static void ath10k_wmi_10x_process_rx(st
-+ 	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-+ 		return;
-+ 
-+-	len = skb->len;
-++	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
-++
-++	consumed = ath10k_tm_event_wmi(ar, id, skb);
-+ 
-+-	trace_ath10k_wmi_event(id, skb->data, skb->len);
-++	/* Ready event must be handled normally also in UTF mode so that we
-++	 * know the UTF firmware has booted, others we are just bypass WMI
-++	 * events to testmode.
-++	 */
-++	if (consumed && id != WMI_10X_READY_EVENTID) {
-++		ath10k_dbg(ar, ATH10K_DBG_WMI,
-++			   "wmi testmode consumed 0x%x\n", id);
-++		goto out;
-++	}
-+ 
-+ 	switch (id) {
-+ 	case WMI_10X_MGMT_RX_EVENTID:
-+@@ -2302,64 +3489,153 @@ static void ath10k_wmi_10x_process_rx(st
-+ 		ath10k_wmi_event_vdev_resume_req(ar, skb);
-+ 		break;
-+ 	case WMI_10X_SERVICE_READY_EVENTID:
-+-		ath10k_wmi_10x_service_ready_event_rx(ar, skb);
-++		ath10k_wmi_event_service_ready(ar, skb);
-+ 		break;
-+ 	case WMI_10X_READY_EVENTID:
-+-		ath10k_wmi_ready_event_rx(ar, skb);
-++		ath10k_wmi_event_ready(ar, skb);
-++		break;
-++	case WMI_10X_PDEV_UTF_EVENTID:
-++		/* ignore utf events */
-+ 		break;
-+ 	default:
-+-		ath10k_warn("Unknown eventid: %d\n", id);
-++		ath10k_warn(ar, "Unknown eventid: %d\n", id);
-+ 		break;
-+ 	}
-+ 
-++out:
-+ 	dev_kfree_skb(skb);
-+ }
-+ 
-+-
-+-static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
-++static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-		ath10k_wmi_10x_process_rx(ar, skb);
-+-	else
-+-		ath10k_wmi_main_process_rx(ar, skb);
-+-}
-++	struct wmi_cmd_hdr *cmd_hdr;
-++	enum wmi_10_2_event_id id;
-+ 
-+-/* WMI Initialization functions */
-+-int ath10k_wmi_attach(struct ath10k *ar)
-+-{
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-+-		ar->wmi.cmd = &wmi_10x_cmd_map;
-+-		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
-+-		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
-+-	} else {
-+-		ar->wmi.cmd = &wmi_cmd_map;
-+-		ar->wmi.vdev_param = &wmi_vdev_param_map;
-+-		ar->wmi.pdev_param = &wmi_pdev_param_map;
-+-	}
-++	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
-++	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
-+ 
-+-	init_completion(&ar->wmi.service_ready);
-+-	init_completion(&ar->wmi.unified_ready);
-+-	init_waitqueue_head(&ar->wmi.tx_credits_wq);
-++	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-++		return;
-+ 
-+-	return 0;
-++	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
-++
-++	switch (id) {
-++	case WMI_10_2_MGMT_RX_EVENTID:
-++		ath10k_wmi_event_mgmt_rx(ar, skb);
-++		/* mgmt_rx() owns the skb now! */
-++		return;
-++	case WMI_10_2_SCAN_EVENTID:
-++		ath10k_wmi_event_scan(ar, skb);
-++		break;
-++	case WMI_10_2_CHAN_INFO_EVENTID:
-++		ath10k_wmi_event_chan_info(ar, skb);
-++		break;
-++	case WMI_10_2_ECHO_EVENTID:
-++		ath10k_wmi_event_echo(ar, skb);
-++		break;
-++	case WMI_10_2_DEBUG_MESG_EVENTID:
-++		ath10k_wmi_event_debug_mesg(ar, skb);
-++		break;
-++	case WMI_10_2_UPDATE_STATS_EVENTID:
-++		ath10k_wmi_event_update_stats(ar, skb);
-++		break;
-++	case WMI_10_2_VDEV_START_RESP_EVENTID:
-++		ath10k_wmi_event_vdev_start_resp(ar, skb);
-++		break;
-++	case WMI_10_2_VDEV_STOPPED_EVENTID:
-++		ath10k_wmi_event_vdev_stopped(ar, skb);
-++		break;
-++	case WMI_10_2_PEER_STA_KICKOUT_EVENTID:
-++		ath10k_wmi_event_peer_sta_kickout(ar, skb);
-++		break;
-++	case WMI_10_2_HOST_SWBA_EVENTID:
-++		ath10k_wmi_event_host_swba(ar, skb);
-++		break;
-++	case WMI_10_2_TBTTOFFSET_UPDATE_EVENTID:
-++		ath10k_wmi_event_tbttoffset_update(ar, skb);
-++		break;
-++	case WMI_10_2_PHYERR_EVENTID:
-++		ath10k_wmi_event_phyerr(ar, skb);
-++		break;
-++	case WMI_10_2_ROAM_EVENTID:
-++		ath10k_wmi_event_roam(ar, skb);
-++		break;
-++	case WMI_10_2_PROFILE_MATCH:
-++		ath10k_wmi_event_profile_match(ar, skb);
-++		break;
-++	case WMI_10_2_DEBUG_PRINT_EVENTID:
-++		ath10k_wmi_event_debug_print(ar, skb);
-++		break;
-++	case WMI_10_2_PDEV_QVIT_EVENTID:
-++		ath10k_wmi_event_pdev_qvit(ar, skb);
-++		break;
-++	case WMI_10_2_WLAN_PROFILE_DATA_EVENTID:
-++		ath10k_wmi_event_wlan_profile_data(ar, skb);
-++		break;
-++	case WMI_10_2_RTT_MEASUREMENT_REPORT_EVENTID:
-++		ath10k_wmi_event_rtt_measurement_report(ar, skb);
-++		break;
-++	case WMI_10_2_TSF_MEASUREMENT_REPORT_EVENTID:
-++		ath10k_wmi_event_tsf_measurement_report(ar, skb);
-++		break;
-++	case WMI_10_2_RTT_ERROR_REPORT_EVENTID:
-++		ath10k_wmi_event_rtt_error_report(ar, skb);
-++		break;
-++	case WMI_10_2_WOW_WAKEUP_HOST_EVENTID:
-++		ath10k_wmi_event_wow_wakeup_host(ar, skb);
-++		break;
-++	case WMI_10_2_DCS_INTERFERENCE_EVENTID:
-++		ath10k_wmi_event_dcs_interference(ar, skb);
-++		break;
-++	case WMI_10_2_PDEV_TPC_CONFIG_EVENTID:
-++		ath10k_wmi_event_pdev_tpc_config(ar, skb);
-++		break;
-++	case WMI_10_2_INST_RSSI_STATS_EVENTID:
-++		ath10k_wmi_event_inst_rssi_stats(ar, skb);
-++		break;
-++	case WMI_10_2_VDEV_STANDBY_REQ_EVENTID:
-++		ath10k_wmi_event_vdev_standby_req(ar, skb);
-++		break;
-++	case WMI_10_2_VDEV_RESUME_REQ_EVENTID:
-++		ath10k_wmi_event_vdev_resume_req(ar, skb);
-++		break;
-++	case WMI_10_2_SERVICE_READY_EVENTID:
-++		ath10k_wmi_event_service_ready(ar, skb);
-++		break;
-++	case WMI_10_2_READY_EVENTID:
-++		ath10k_wmi_event_ready(ar, skb);
-++		break;
-++	case WMI_10_2_PDEV_TEMPERATURE_EVENTID:
-++		ath10k_wmi_event_temperature(ar, skb);
-++		break;
-++	case WMI_10_2_RTT_KEEPALIVE_EVENTID:
-++	case WMI_10_2_GPIO_INPUT_EVENTID:
-++	case WMI_10_2_PEER_RATECODE_LIST_EVENTID:
-++	case WMI_10_2_GENERIC_BUFFER_EVENTID:
-++	case WMI_10_2_MCAST_BUF_RELEASE_EVENTID:
-++	case WMI_10_2_MCAST_LIST_AGEOUT_EVENTID:
-++	case WMI_10_2_WDS_PEER_EVENTID:
-++		ath10k_dbg(ar, ATH10K_DBG_WMI,
-++			   "received event id %d not implemented\n", id);
-++		break;
-++	default:
-++		ath10k_warn(ar, "Unknown eventid: %d\n", id);
-++		break;
-++	}
-++
-++	dev_kfree_skb(skb);
-+ }
-+ 
-+-void ath10k_wmi_detach(struct ath10k *ar)
-++static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
-+ {
-+-	int i;
-+-
-+-	/* free the host memory chunks requested by firmware */
-+-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-+-		dma_free_coherent(ar->dev,
-+-				  ar->wmi.mem_chunks[i].len,
-+-				  ar->wmi.mem_chunks[i].vaddr,
-+-				  ar->wmi.mem_chunks[i].paddr);
-+-	}
-++	int ret;
-+ 
-+-	ar->wmi.num_mem_chunks = 0;
-++	ret = ath10k_wmi_rx(ar, skb);
-++	if (ret)
-++		ath10k_warn(ar, "failed to process wmi rx: %d\n", ret);
-+ }
-+ 
-+-int ath10k_wmi_connect_htc_service(struct ath10k *ar)
-++int ath10k_wmi_connect(struct ath10k *ar)
-+ {
-+ 	int status;
-+ 	struct ath10k_htc_svc_conn_req conn_req;
-+@@ -2378,7 +3654,7 @@ int ath10k_wmi_connect_htc_service(struc
-+ 
-+ 	status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
-+ 	if (status) {
-+-		ath10k_warn("failed to connect to WMI CONTROL service status: %d\n",
-++		ath10k_warn(ar, "failed to connect to WMI CONTROL service status: %d\n",
-+ 			    status);
-+ 		return status;
-+ 	}
-+@@ -2387,16 +3663,17 @@ int ath10k_wmi_connect_htc_service(struc
-+ 	return 0;
-+ }
-+ 
-+-static int ath10k_wmi_main_pdev_set_regdomain(struct ath10k *ar, u16 rd,
-+-					      u16 rd2g, u16 rd5g, u16 ctl2g,
-+-					      u16 ctl5g)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
-++			      u16 ctl2g, u16 ctl5g,
-++			      enum wmi_dfs_region dfs_reg)
-+ {
-+ 	struct wmi_pdev_set_regdomain_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data;
-+ 	cmd->reg_domain = __cpu_to_le32(rd);
-+@@ -2405,25 +3682,23 @@ static int ath10k_wmi_main_pdev_set_regd
-+ 	cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g);
-+ 	cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n",
-+ 		   rd, rd2g, rd5g, ctl2g, ctl5g);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->pdev_set_regdomain_cmdid);
-++	return skb;
-+ }
-+ 
-+-static int ath10k_wmi_10x_pdev_set_regdomain(struct ath10k *ar, u16 rd,
-+-					     u16 rd2g, u16 rd5g,
-+-					     u16 ctl2g, u16 ctl5g,
-+-					     enum wmi_dfs_region dfs_reg)
-++static struct sk_buff *
-++ath10k_wmi_10x_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16
-++				  rd5g, u16 ctl2g, u16 ctl5g,
-++				  enum wmi_dfs_region dfs_reg)
-+ {
-+ 	struct wmi_pdev_set_regdomain_cmd_10x *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_pdev_set_regdomain_cmd_10x *)skb->data;
-+ 	cmd->reg_domain = __cpu_to_le32(rd);
-+@@ -2433,121 +3708,96 @@ static int ath10k_wmi_10x_pdev_set_regdo
-+ 	cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g);
-+ 	cmd->dfs_domain = __cpu_to_le32(dfs_reg);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x dfs_region %x\n",
-+ 		   rd, rd2g, rd5g, ctl2g, ctl5g, dfs_reg);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->pdev_set_regdomain_cmdid);
-+-}
-+-
-+-int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
-+-				  u16 rd5g, u16 ctl2g, u16 ctl5g,
-+-				  enum wmi_dfs_region dfs_reg)
-+-{
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-		return ath10k_wmi_10x_pdev_set_regdomain(ar, rd, rd2g, rd5g,
-+-							ctl2g, ctl5g, dfs_reg);
-+-	else
-+-		return ath10k_wmi_main_pdev_set_regdomain(ar, rd, rd2g, rd5g,
-+-							 ctl2g, ctl5g);
-+-}
-+-
-+-int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
-+-				const struct wmi_channel_arg *arg)
-+-{
-+-	struct wmi_set_channel_cmd *cmd;
-+-	struct sk_buff *skb;
-+-	u32 ch_flags = 0;
-+-
-+-	if (arg->passive)
-+-		return -EINVAL;
-+-
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-+-	if (!skb)
-+-		return -ENOMEM;
-+-
-+-	if (arg->chan_radar)
-+-		ch_flags |= WMI_CHAN_FLAG_DFS;
-+-
-+-	cmd = (struct wmi_set_channel_cmd *)skb->data;
-+-	cmd->chan.mhz               = __cpu_to_le32(arg->freq);
-+-	cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
-+-	cmd->chan.mode              = arg->mode;
-+-	cmd->chan.flags		   |= __cpu_to_le32(ch_flags);
-+-	cmd->chan.min_power         = arg->min_power;
-+-	cmd->chan.max_power         = arg->max_power;
-+-	cmd->chan.reg_power         = arg->max_reg_power;
-+-	cmd->chan.reg_classid       = arg->reg_class_id;
-+-	cmd->chan.antenna_max       = arg->max_antenna_gain;
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi set channel mode %d freq %d\n",
-+-		   arg->mode, arg->freq);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->pdev_set_channel_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_suspend(struct ath10k *ar, u32 suspend_opt)
-+ {
-+ 	struct wmi_pdev_suspend_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_pdev_suspend_cmd *)skb->data;
-+ 	cmd->suspend_opt = __cpu_to_le32(suspend_opt);
-+ 
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_pdev_resume_target(struct ath10k *ar)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_resume(struct ath10k *ar)
-+ {
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(0);
-+-	if (skb == NULL)
-+-		return -ENOMEM;
-++	skb = ath10k_wmi_alloc_skb(ar, 0);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-+ 
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
-+ {
-+ 	struct wmi_pdev_set_param_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+ 	if (id == WMI_PDEV_PARAM_UNSUPPORTED) {
-+-		ath10k_warn("pdev param %d not supported by firmware\n", id);
-+-		return -EOPNOTSUPP;
-++		ath10k_warn(ar, "pdev param %d not supported by firmware\n",
-++			    id);
-++		return ERR_PTR(-EOPNOTSUPP);
-+ 	}
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_pdev_set_param_cmd *)skb->data;
-+ 	cmd->param_id    = __cpu_to_le32(id);
-+ 	cmd->param_value = __cpu_to_le32(value);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n",
-+ 		   id, value);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
-++	return skb;
-+ }
-+ 
-+-static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
-++void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
-++				    struct wmi_host_mem_chunks *chunks)
-+ {
-+-	struct wmi_init_cmd *cmd;
-+-	struct sk_buff *buf;
-+-	struct wmi_resource_config config = {};
-+-	u32 len, val;
-++	struct host_memory_chunk *chunk;
-+ 	int i;
-+ 
-+-	config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
-+-	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS);
-++	chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks);
-++
-++	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-++		chunk = &chunks->items[i];
-++		chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
-++		chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
-++		chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
-++
-++		ath10k_dbg(ar, ATH10K_DBG_WMI,
-++			   "wmi chunk %d len %d requested, addr 0x%llx\n",
-++			   i,
-++			   ar->wmi.mem_chunks[i].len,
-++			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
-++	}
-++}
-++
-++static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
-++{
-++	struct wmi_init_cmd *cmd;
-++	struct sk_buff *buf;
-++	struct wmi_resource_config config = {};
-++	u32 len, val;
-++
-++	config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
-++	config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
-+ 	config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS);
-+ 
-+ 	config.num_offload_reorder_bufs =
-+@@ -2600,50 +3850,25 @@ static int ath10k_wmi_main_cmd_init(stru
-+ 	len = sizeof(*cmd) +
-+ 	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
-+ 
-+-	buf = ath10k_wmi_alloc_skb(len);
-++	buf = ath10k_wmi_alloc_skb(ar, len);
-+ 	if (!buf)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_init_cmd *)buf->data;
-+ 
-+-	if (ar->wmi.num_mem_chunks == 0) {
-+-		cmd->num_host_mem_chunks = 0;
-+-		goto out;
-+-	}
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-+-		   ar->wmi.num_mem_chunks);
-+-
-+-	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
-+-
-+-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-+-		cmd->host_mem_chunks[i].ptr =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
-+-		cmd->host_mem_chunks[i].size =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
-+-		cmd->host_mem_chunks[i].req_id =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
-+-
-+-		ath10k_dbg(ATH10K_DBG_WMI,
-+-			   "wmi chunk %d len %d requested, addr 0x%llx\n",
-+-			   i,
-+-			   ar->wmi.mem_chunks[i].len,
-+-			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
-+-	}
-+-out:
-+ 	memcpy(&cmd->resource_config, &config, sizeof(config));
-++	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n");
-+-	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n");
-++	return buf;
-+ }
-+ 
-+-static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
-++static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
-+ {
-+ 	struct wmi_init_cmd_10x *cmd;
-+ 	struct sk_buff *buf;
-+ 	struct wmi_resource_config_10x config = {};
-+ 	u32 len, val;
-+-	int i;
-+ 
-+ 	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
-+ 	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
-+@@ -2691,101 +3916,132 @@ static int ath10k_wmi_10x_cmd_init(struc
-+ 	len = sizeof(*cmd) +
-+ 	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
-+ 
-+-	buf = ath10k_wmi_alloc_skb(len);
-++	buf = ath10k_wmi_alloc_skb(ar, len);
-+ 	if (!buf)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_init_cmd_10x *)buf->data;
-+ 
-+-	if (ar->wmi.num_mem_chunks == 0) {
-+-		cmd->num_host_mem_chunks = 0;
-+-		goto out;
-+-	}
-++	memcpy(&cmd->resource_config, &config, sizeof(config));
-++	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-+-		   ar->wmi.num_mem_chunks);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n");
-++	return buf;
-++}
-+ 
-+-	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
-++static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
-++{
-++	struct wmi_init_cmd_10_2 *cmd;
-++	struct sk_buff *buf;
-++	struct wmi_resource_config_10x config = {};
-++	u32 len, val, features;
-+ 
-+-	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-+-		cmd->host_mem_chunks[i].ptr =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
-+-		cmd->host_mem_chunks[i].size =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].len);
-+-		cmd->host_mem_chunks[i].req_id =
-+-			__cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
-++	config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
-++	config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
-++	config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
-++	config.num_tids = __cpu_to_le32(TARGET_10X_NUM_TIDS);
-++	config.ast_skid_limit = __cpu_to_le32(TARGET_10X_AST_SKID_LIMIT);
-++	config.tx_chain_mask = __cpu_to_le32(TARGET_10X_TX_CHAIN_MASK);
-++	config.rx_chain_mask = __cpu_to_le32(TARGET_10X_RX_CHAIN_MASK);
-++	config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
-++	config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
-++	config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
-++	config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
-++	config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
-+ 
-+-		ath10k_dbg(ATH10K_DBG_WMI,
-+-			   "wmi chunk %d len %d requested, addr 0x%llx\n",
-+-			   i,
-+-			   ar->wmi.mem_chunks[i].len,
-+-			   (unsigned long long)ar->wmi.mem_chunks[i].paddr);
-+-	}
-+-out:
-+-	memcpy(&cmd->resource_config, &config, sizeof(config));
-++	config.scan_max_pending_reqs =
-++		__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
-++
-++	config.bmiss_offload_max_vdev =
-++		__cpu_to_le32(TARGET_10X_BMISS_OFFLOAD_MAX_VDEV);
-++
-++	config.roam_offload_max_vdev =
-++		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_VDEV);
-++
-++	config.roam_offload_max_ap_profiles =
-++		__cpu_to_le32(TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES);
-++
-++	config.num_mcast_groups = __cpu_to_le32(TARGET_10X_NUM_MCAST_GROUPS);
-++	config.num_mcast_table_elems =
-++		__cpu_to_le32(TARGET_10X_NUM_MCAST_TABLE_ELEMS);
-++
-++	config.mcast2ucast_mode = __cpu_to_le32(TARGET_10X_MCAST2UCAST_MODE);
-++	config.tx_dbg_log_size = __cpu_to_le32(TARGET_10X_TX_DBG_LOG_SIZE);
-++	config.num_wds_entries = __cpu_to_le32(TARGET_10X_NUM_WDS_ENTRIES);
-++	config.dma_burst_size = __cpu_to_le32(TARGET_10_2_DMA_BURST_SIZE);
-++	config.mac_aggr_delim = __cpu_to_le32(TARGET_10X_MAC_AGGR_DELIM);
-++
-++	val = TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
-++	config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val);
-++
-++	config.vow_config = __cpu_to_le32(TARGET_10X_VOW_CONFIG);
-++
-++	config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
-++	config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi init 10x\n");
-+-	return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
-++	len = sizeof(*cmd) +
-++	      (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
-++
-++	buf = ath10k_wmi_alloc_skb(ar, len);
-++	if (!buf)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_init_cmd_10_2 *)buf->data;
-++
-++	features = WMI_10_2_RX_BATCH_MODE;
-++	cmd->resource_config.feature_mask = __cpu_to_le32(features);
-++
-++	memcpy(&cmd->resource_config.common, &config, sizeof(config));
-++	ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n");
-++	return buf;
-+ }
-+ 
-+-int ath10k_wmi_cmd_init(struct ath10k *ar)
-++int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
-+ {
-+-	int ret;
-++	if (arg->ie_len && !arg->ie)
-++		return -EINVAL;
-++	if (arg->n_channels && !arg->channels)
-++		return -EINVAL;
-++	if (arg->n_ssids && !arg->ssids)
-++		return -EINVAL;
-++	if (arg->n_bssids && !arg->bssids)
-++		return -EINVAL;
-+ 
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-		ret = ath10k_wmi_10x_cmd_init(ar);
-+-	else
-+-		ret = ath10k_wmi_main_cmd_init(ar);
-++	if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
-++		return -EINVAL;
-++	if (arg->n_channels > ARRAY_SIZE(arg->channels))
-++		return -EINVAL;
-++	if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
-++		return -EINVAL;
-++	if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
-++		return -EINVAL;
-+ 
-+-	return ret;
-++	return 0;
-+ }
-+ 
-+-static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
-+-					  const struct wmi_start_scan_arg *arg)
-++static size_t
-++ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
-+ {
-+-	int len;
-+-
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-		len = sizeof(struct wmi_start_scan_cmd_10x);
-+-	else
-+-		len = sizeof(struct wmi_start_scan_cmd);
-++	int len = 0;
-+ 
-+ 	if (arg->ie_len) {
-+-		if (!arg->ie)
-+-			return -EINVAL;
-+-		if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
-+-			return -EINVAL;
-+-
-+ 		len += sizeof(struct wmi_ie_data);
-+ 		len += roundup(arg->ie_len, 4);
-+ 	}
-+ 
-+ 	if (arg->n_channels) {
-+-		if (!arg->channels)
-+-			return -EINVAL;
-+-		if (arg->n_channels > ARRAY_SIZE(arg->channels))
-+-			return -EINVAL;
-+-
-+ 		len += sizeof(struct wmi_chan_list);
-+ 		len += sizeof(__le32) * arg->n_channels;
-+ 	}
-+ 
-+ 	if (arg->n_ssids) {
-+-		if (!arg->ssids)
-+-			return -EINVAL;
-+-		if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
-+-			return -EINVAL;
-+-
-+ 		len += sizeof(struct wmi_ssid_list);
-+ 		len += sizeof(struct wmi_ssid) * arg->n_ssids;
-+ 	}
-+ 
-+ 	if (arg->n_bssids) {
-+-		if (!arg->bssids)
-+-			return -EINVAL;
-+-		if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
-+-			return -EINVAL;
-+-
-+ 		len += sizeof(struct wmi_bssid_list);
-+ 		len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
-+ 	}
-+@@ -2793,28 +4049,11 @@ static int ath10k_wmi_start_scan_calc_le
-+ 	return len;
-+ }
-+ 
-+-int ath10k_wmi_start_scan(struct ath10k *ar,
-+-			  const struct wmi_start_scan_arg *arg)
-++void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
-++				      const struct wmi_start_scan_arg *arg)
-+ {
-+-	struct wmi_start_scan_cmd *cmd;
-+-	struct sk_buff *skb;
-+-	struct wmi_ie_data *ie;
-+-	struct wmi_chan_list *channels;
-+-	struct wmi_ssid_list *ssids;
-+-	struct wmi_bssid_list *bssids;
-+ 	u32 scan_id;
-+ 	u32 scan_req_id;
-+-	int off;
-+-	int len = 0;
-+-	int i;
-+-
-+-	len = ath10k_wmi_start_scan_calc_len(ar, arg);
-+-	if (len < 0)
-+-		return len; /* len contains error code here */
-+-
-+-	skb = ath10k_wmi_alloc_skb(len);
-+-	if (!skb)
-+-		return -ENOMEM;
-+ 
-+ 	scan_id  = WMI_HOST_SCAN_REQ_ID_PREFIX;
-+ 	scan_id |= arg->scan_id;
-+@@ -2822,48 +4061,49 @@ int ath10k_wmi_start_scan(struct ath10k
-+ 	scan_req_id  = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
-+ 	scan_req_id |= arg->scan_req_id;
-+ 
-+-	cmd = (struct wmi_start_scan_cmd *)skb->data;
-+-	cmd->scan_id            = __cpu_to_le32(scan_id);
-+-	cmd->scan_req_id        = __cpu_to_le32(scan_req_id);
-+-	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
-+-	cmd->scan_priority      = __cpu_to_le32(arg->scan_priority);
-+-	cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
-+-	cmd->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
-+-	cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
-+-	cmd->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
-+-	cmd->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
-+-	cmd->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
-+-	cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
-+-	cmd->idle_time          = __cpu_to_le32(arg->idle_time);
-+-	cmd->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
-+-	cmd->probe_delay        = __cpu_to_le32(arg->probe_delay);
-+-	cmd->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
-+-
-+-	/* TLV list starts after fields included in the struct */
-+-	/* There's just one filed that differes the two start_scan
-+-	 * structures - burst_duration, which we are not using btw,
-+-	   no point to make the split here, just shift the buffer to fit with
-+-	   given FW */
-+-	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
-+-		off = sizeof(struct wmi_start_scan_cmd_10x);
-+-	else
-+-		off = sizeof(struct wmi_start_scan_cmd);
-++	cmn->scan_id            = __cpu_to_le32(scan_id);
-++	cmn->scan_req_id        = __cpu_to_le32(scan_req_id);
-++	cmn->vdev_id            = __cpu_to_le32(arg->vdev_id);
-++	cmn->scan_priority      = __cpu_to_le32(arg->scan_priority);
-++	cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
-++	cmn->dwell_time_active  = __cpu_to_le32(arg->dwell_time_active);
-++	cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
-++	cmn->min_rest_time      = __cpu_to_le32(arg->min_rest_time);
-++	cmn->max_rest_time      = __cpu_to_le32(arg->max_rest_time);
-++	cmn->repeat_probe_time  = __cpu_to_le32(arg->repeat_probe_time);
-++	cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
-++	cmn->idle_time          = __cpu_to_le32(arg->idle_time);
-++	cmn->max_scan_time      = __cpu_to_le32(arg->max_scan_time);
-++	cmn->probe_delay        = __cpu_to_le32(arg->probe_delay);
-++	cmn->scan_ctrl_flags    = __cpu_to_le32(arg->scan_ctrl_flags);
-++}
-++
-++static void
-++ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
-++			       const struct wmi_start_scan_arg *arg)
-++{
-++	struct wmi_ie_data *ie;
-++	struct wmi_chan_list *channels;
-++	struct wmi_ssid_list *ssids;
-++	struct wmi_bssid_list *bssids;
-++	void *ptr = tlvs->tlvs;
-++	int i;
-+ 
-+ 	if (arg->n_channels) {
-+-		channels = (void *)skb->data + off;
-++		channels = ptr;
-+ 		channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
-+ 		channels->num_chan = __cpu_to_le32(arg->n_channels);
-+ 
-+ 		for (i = 0; i < arg->n_channels; i++)
-+-			channels->channel_list[i] =
-+-				__cpu_to_le32(arg->channels[i]);
-++			channels->channel_list[i].freq =
-++				__cpu_to_le16(arg->channels[i]);
-+ 
-+-		off += sizeof(*channels);
-+-		off += sizeof(__le32) * arg->n_channels;
-++		ptr += sizeof(*channels);
-++		ptr += sizeof(__le32) * arg->n_channels;
-+ 	}
-+ 
-+ 	if (arg->n_ssids) {
-+-		ssids = (void *)skb->data + off;
-++		ssids = ptr;
-+ 		ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
-+ 		ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
-+ 
-+@@ -2875,12 +4115,12 @@ int ath10k_wmi_start_scan(struct ath10k
-+ 			       arg->ssids[i].len);
-+ 		}
-+ 
-+-		off += sizeof(*ssids);
-+-		off += sizeof(struct wmi_ssid) * arg->n_ssids;
-++		ptr += sizeof(*ssids);
-++		ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
-+ 	}
-+ 
-+ 	if (arg->n_bssids) {
-+-		bssids = (void *)skb->data + off;
-++		bssids = ptr;
-+ 		bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
-+ 		bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
-+ 
-+@@ -2889,27 +4129,75 @@ int ath10k_wmi_start_scan(struct ath10k
-+ 			       arg->bssids[i].bssid,
-+ 			       ETH_ALEN);
-+ 
-+-		off += sizeof(*bssids);
-+-		off += sizeof(struct wmi_mac_addr) * arg->n_bssids;
-++		ptr += sizeof(*bssids);
-++		ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
-+ 	}
-+ 
-+ 	if (arg->ie_len) {
-+-		ie = (void *)skb->data + off;
-++		ie = ptr;
-+ 		ie->tag = __cpu_to_le32(WMI_IE_TAG);
-+ 		ie->ie_len = __cpu_to_le32(arg->ie_len);
-+ 		memcpy(ie->ie_data, arg->ie, arg->ie_len);
-+ 
-+-		off += sizeof(*ie);
-+-		off += roundup(arg->ie_len, 4);
-++		ptr += sizeof(*ie);
-++		ptr += roundup(arg->ie_len, 4);
-+ 	}
-++}
-+ 
-+-	if (off != skb->len) {
-+-		dev_kfree_skb(skb);
-+-		return -EINVAL;
-+-	}
-++static struct sk_buff *
-++ath10k_wmi_op_gen_start_scan(struct ath10k *ar,
-++			     const struct wmi_start_scan_arg *arg)
-++{
-++	struct wmi_start_scan_cmd *cmd;
-++	struct sk_buff *skb;
-++	size_t len;
-++	int ret;
-++
-++	ret = ath10k_wmi_start_scan_verify(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n");
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid);
-++	len = sizeof(*cmd) + ath10k_wmi_start_scan_tlvs_len(arg);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_start_scan_cmd *)skb->data;
-++
-++	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
-++	ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
-++
-++	cmd->burst_duration_ms = __cpu_to_le32(0);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_10x_op_gen_start_scan(struct ath10k *ar,
-++				 const struct wmi_start_scan_arg *arg)
-++{
-++	struct wmi_10x_start_scan_cmd *cmd;
-++	struct sk_buff *skb;
-++	size_t len;
-++	int ret;
-++
-++	ret = ath10k_wmi_start_scan_verify(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-++
-++	len = sizeof(*cmd) + ath10k_wmi_start_scan_tlvs_len(arg);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
-++
-++	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
-++	ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi 10x start scan\n");
-++	return skb;
-+ }
-+ 
-+ void ath10k_wmi_start_scan_init(struct ath10k *ar,
-+@@ -2938,7 +4226,9 @@ void ath10k_wmi_start_scan_init(struct a
-+ 	arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF";
-+ }
-+ 
-+-int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_stop_scan(struct ath10k *ar,
-++			    const struct wmi_stop_scan_arg *arg)
-+ {
-+ 	struct wmi_stop_scan_cmd *cmd;
-+ 	struct sk_buff *skb;
-+@@ -2946,13 +4236,13 @@ int ath10k_wmi_stop_scan(struct ath10k *
-+ 	u32 req_id;
-+ 
-+ 	if (arg->req_id > 0xFFF)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	scan_id = arg->u.scan_id;
-+ 	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
-+@@ -2966,92 +4256,85 @@ int ath10k_wmi_stop_scan(struct ath10k *
-+ 	cmd->scan_id     = __cpu_to_le32(scan_id);
-+ 	cmd->scan_req_id = __cpu_to_le32(req_id);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n",
-+ 		   arg->req_id, arg->req_type, arg->u.scan_id);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
-+-			   enum wmi_vdev_type type,
-+-			   enum wmi_vdev_subtype subtype,
-+-			   const u8 macaddr[ETH_ALEN])
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_create(struct ath10k *ar, u32 vdev_id,
-++			      enum wmi_vdev_type type,
-++			      enum wmi_vdev_subtype subtype,
-++			      const u8 macaddr[ETH_ALEN])
-+ {
-+ 	struct wmi_vdev_create_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_create_cmd *)skb->data;
-+ 	cmd->vdev_id      = __cpu_to_le32(vdev_id);
-+ 	cmd->vdev_type    = __cpu_to_le32(type);
-+ 	cmd->vdev_subtype = __cpu_to_le32(subtype);
-+-	memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN);
-++	ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "WMI vdev create: id %d type %d subtype %d macaddr %pM\n",
-+ 		   vdev_id, type, subtype, macaddr);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
-+ {
-+ 	struct wmi_vdev_delete_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_delete_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "WMI vdev delete id %d\n", vdev_id);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
-++	return skb;
-+ }
-+ 
-+-static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
-+-				const struct wmi_vdev_start_request_arg *arg,
-+-				u32 cmd_id)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_start(struct ath10k *ar,
-++			     const struct wmi_vdev_start_request_arg *arg,
-++			     bool restart)
-+ {
-+ 	struct wmi_vdev_start_request_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 	const char *cmdname;
-+ 	u32 flags = 0;
-+-	u32 ch_flags = 0;
-+ 
-+-	if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
-+-	    cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
-+-		return -EINVAL;
-+ 	if (WARN_ON(arg->ssid && arg->ssid_len == 0))
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 
-+-	if (cmd_id == ar->wmi.cmd->vdev_start_request_cmdid)
-+-		cmdname = "start";
-+-	else if (cmd_id == ar->wmi.cmd->vdev_restart_request_cmdid)
-++	if (restart)
-+ 		cmdname = "restart";
-+ 	else
-+-		return -EINVAL; /* should not happen, we already check cmd_id */
-++		cmdname = "start";
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	if (arg->hidden_ssid)
-+ 		flags |= WMI_VDEV_START_HIDDEN_SSID;
-+ 	if (arg->pmf_enabled)
-+ 		flags |= WMI_VDEV_START_PMF_ENABLED;
-+-	if (arg->channel.chan_radar)
-+-		ch_flags |= WMI_CHAN_FLAG_DFS;
-+ 
-+ 	cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
-+ 	cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
-+@@ -3067,143 +4350,118 @@ static int ath10k_wmi_vdev_start_restart
-+ 		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
-+ 	}
-+ 
-+-	cmd->chan.mhz = __cpu_to_le32(arg->channel.freq);
-++	ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel);
-+ 
-+-	cmd->chan.band_center_freq1 =
-+-		__cpu_to_le32(arg->channel.band_center_freq1);
-+-
-+-	cmd->chan.mode = arg->channel.mode;
-+-	cmd->chan.flags |= __cpu_to_le32(ch_flags);
-+-	cmd->chan.min_power = arg->channel.min_power;
-+-	cmd->chan.max_power = arg->channel.max_power;
-+-	cmd->chan.reg_power = arg->channel.max_reg_power;
-+-	cmd->chan.reg_classid = arg->channel.reg_class_id;
-+-	cmd->chan.antenna_max = arg->channel.max_antenna_gain;
-+-
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-+-		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, "
-+-		   "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
-++		   cmdname, arg->vdev_id,
-+ 		   flags, arg->channel.freq, arg->channel.mode,
-+ 		   cmd->chan.flags, arg->channel.max_power);
-+ 
-+-	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-+-}
-+-
-+-int ath10k_wmi_vdev_start(struct ath10k *ar,
-+-			  const struct wmi_vdev_start_request_arg *arg)
-+-{
-+-	u32 cmd_id = ar->wmi.cmd->vdev_start_request_cmdid;
-+-
-+-	return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id);
-+-}
-+-
-+-int ath10k_wmi_vdev_restart(struct ath10k *ar,
-+-		     const struct wmi_vdev_start_request_arg *arg)
-+-{
-+-	u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid;
-+-
-+-	return ath10k_wmi_vdev_start_restart(ar, arg, cmd_id);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
-+ {
-+ 	struct wmi_vdev_stop_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_stop_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
-++			  const u8 *bssid)
-+ {
-+ 	struct wmi_vdev_up_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_up_cmd *)skb->data;
-+ 	cmd->vdev_id       = __cpu_to_le32(vdev_id);
-+ 	cmd->vdev_assoc_id = __cpu_to_le32(aid);
-+-	memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN);
-++	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
-+ 		   vdev_id, aid, bssid);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
-+ {
-+ 	struct wmi_vdev_down_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_down_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi mgmt vdev down id 0x%x\n", vdev_id);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
-+-			      u32 param_id, u32 param_value)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
-++				 u32 param_id, u32 param_value)
-+ {
-+ 	struct wmi_vdev_set_param_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+ 	if (param_id == WMI_VDEV_PARAM_UNSUPPORTED) {
-+-		ath10k_dbg(ATH10K_DBG_WMI,
-++		ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 			   "vdev param %d not supported by firmware\n",
-+ 			    param_id);
-+-		return -EOPNOTSUPP;
-++		return ERR_PTR(-EOPNOTSUPP);
-+ 	}
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_set_param_cmd *)skb->data;
-+ 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
-+ 	cmd->param_id    = __cpu_to_le32(param_id);
-+ 	cmd->param_value = __cpu_to_le32(param_value);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi vdev id 0x%x set param %d value %d\n",
-+ 		   vdev_id, param_id, param_value);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_vdev_install_key(struct ath10k *ar,
-+-				const struct wmi_vdev_install_key_arg *arg)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_install_key(struct ath10k *ar,
-++				   const struct wmi_vdev_install_key_arg *arg)
-+ {
-+ 	struct wmi_vdev_install_key_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+ 	if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 	if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->key_len);
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + arg->key_len);
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
-+ 	cmd->vdev_id       = __cpu_to_le32(arg->vdev_id);
-+@@ -3215,176 +4473,232 @@ int ath10k_wmi_vdev_install_key(struct a
-+ 	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
-+ 
-+ 	if (arg->macaddr)
-+-		memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN);
-++		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
-+ 	if (arg->key_data)
-+ 		memcpy(cmd->key_data, arg->key_data, arg->key_len);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi vdev install key idx %d cipher %d len %d\n",
-+ 		   arg->key_idx, arg->key_cipher, arg->key_len);
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->vdev_install_key_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
-+-			   const u8 peer_addr[ETH_ALEN])
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_spectral_conf(struct ath10k *ar,
-++				     const struct wmi_vdev_spectral_conf_arg *arg)
-++{
-++	struct wmi_vdev_spectral_conf_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_vdev_spectral_conf_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
-++	cmd->scan_count = __cpu_to_le32(arg->scan_count);
-++	cmd->scan_period = __cpu_to_le32(arg->scan_period);
-++	cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
-++	cmd->scan_fft_size = __cpu_to_le32(arg->scan_fft_size);
-++	cmd->scan_gc_ena = __cpu_to_le32(arg->scan_gc_ena);
-++	cmd->scan_restart_ena = __cpu_to_le32(arg->scan_restart_ena);
-++	cmd->scan_noise_floor_ref = __cpu_to_le32(arg->scan_noise_floor_ref);
-++	cmd->scan_init_delay = __cpu_to_le32(arg->scan_init_delay);
-++	cmd->scan_nb_tone_thr = __cpu_to_le32(arg->scan_nb_tone_thr);
-++	cmd->scan_str_bin_thr = __cpu_to_le32(arg->scan_str_bin_thr);
-++	cmd->scan_wb_rpt_mode = __cpu_to_le32(arg->scan_wb_rpt_mode);
-++	cmd->scan_rssi_rpt_mode = __cpu_to_le32(arg->scan_rssi_rpt_mode);
-++	cmd->scan_rssi_thr = __cpu_to_le32(arg->scan_rssi_thr);
-++	cmd->scan_pwr_format = __cpu_to_le32(arg->scan_pwr_format);
-++	cmd->scan_rpt_mode = __cpu_to_le32(arg->scan_rpt_mode);
-++	cmd->scan_bin_scale = __cpu_to_le32(arg->scan_bin_scale);
-++	cmd->scan_dbm_adj = __cpu_to_le32(arg->scan_dbm_adj);
-++	cmd->scan_chn_mask = __cpu_to_le32(arg->scan_chn_mask);
-++
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id,
-++				       u32 trigger, u32 enable)
-++{
-++	struct wmi_vdev_spectral_enable_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_vdev_spectral_enable_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->trigger_cmd = __cpu_to_le32(trigger);
-++	cmd->enable_cmd = __cpu_to_le32(enable);
-++
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
-++			      const u8 peer_addr[ETH_ALEN])
-+ {
-+ 	struct wmi_peer_create_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_peer_create_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi peer create vdev_id %d peer_addr %pM\n",
-+ 		   vdev_id, peer_addr);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
-+-			   const u8 peer_addr[ETH_ALEN])
-++static struct sk_buff *
-++ath10k_wmi_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
-++			      const u8 peer_addr[ETH_ALEN])
-+ {
-+ 	struct wmi_peer_delete_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_peer_delete_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi peer delete vdev_id %d peer_addr %pM\n",
-+ 		   vdev_id, peer_addr);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
-+-			  const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
-++			     const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
-+ {
-+ 	struct wmi_peer_flush_tids_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;
-+ 	cmd->vdev_id         = __cpu_to_le32(vdev_id);
-+ 	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
-+-	memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n",
-+ 		   vdev_id, peer_addr, tid_bitmap);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
-+-			      const u8 *peer_addr, enum wmi_peer_param param_id,
-+-			      u32 param_value)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
-++				 const u8 *peer_addr,
-++				 enum wmi_peer_param param_id,
-++				 u32 param_value)
-+ {
-+ 	struct wmi_peer_set_param_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_peer_set_param_cmd *)skb->data;
-+ 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
-+ 	cmd->param_id    = __cpu_to_le32(param_id);
-+ 	cmd->param_value = __cpu_to_le32(param_value);
-+-	memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi vdev %d peer 0x%pM set param %d value %d\n",
-+ 		   vdev_id, peer_addr, param_id, param_value);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
-+-			  enum wmi_sta_ps_mode psmode)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
-++			     enum wmi_sta_ps_mode psmode)
-+ {
-+ 	struct wmi_sta_powersave_mode_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_sta_powersave_mode_cmd *)skb->data;
-+ 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
-+ 	cmd->sta_ps_mode = __cpu_to_le32(psmode);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi set powersave id 0x%x mode %d\n",
-+ 		   vdev_id, psmode);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->sta_powersave_mode_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
-+-				enum wmi_sta_powersave_param param_id,
-+-				u32 value)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
-++			     enum wmi_sta_powersave_param param_id,
-++			     u32 value)
-+ {
-+ 	struct wmi_sta_powersave_param_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_sta_powersave_param_cmd *)skb->data;
-+ 	cmd->vdev_id     = __cpu_to_le32(vdev_id);
-+ 	cmd->param_id    = __cpu_to_le32(param_id);
-+ 	cmd->param_value = __cpu_to_le32(value);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi sta ps param vdev_id 0x%x param %d value %d\n",
-+ 		   vdev_id, param_id, value);
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->sta_powersave_param_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-+-			       enum wmi_ap_ps_peer_param param_id, u32 value)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++			    enum wmi_ap_ps_peer_param param_id, u32 value)
-+ {
-+ 	struct wmi_ap_ps_peer_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+ 	if (!mac)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_ap_ps_peer_cmd *)skb->data;
-+ 	cmd->vdev_id = __cpu_to_le32(vdev_id);
-+ 	cmd->param_id = __cpu_to_le32(param_id);
-+ 	cmd->param_value = __cpu_to_le32(value);
-+-	memcpy(&cmd->peer_macaddr, mac, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n",
-+ 		   vdev_id, param_id, value, mac);
-+-
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->ap_ps_peer_param_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_scan_chan_list(struct ath10k *ar,
-+-			      const struct wmi_scan_chan_list_arg *arg)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_scan_chan_list(struct ath10k *ar,
-++				 const struct wmi_scan_chan_list_arg *arg)
-+ {
-+ 	struct wmi_scan_chan_list_cmd *cmd;
-+ 	struct sk_buff *skb;
-+@@ -3395,66 +4709,29 @@ int ath10k_wmi_scan_chan_list(struct ath
-+ 
-+ 	len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel);
-+ 
-+-	skb = ath10k_wmi_alloc_skb(len);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-+ 	if (!skb)
-+-		return -EINVAL;
-++		return ERR_PTR(-EINVAL);
-+ 
-+ 	cmd = (struct wmi_scan_chan_list_cmd *)skb->data;
-+ 	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
-+ 
-+ 	for (i = 0; i < arg->n_channels; i++) {
-+-		u32 flags = 0;
-+-
-+ 		ch = &arg->channels[i];
-+ 		ci = &cmd->chan_info[i];
-+ 
-+-		if (ch->passive)
-+-			flags |= WMI_CHAN_FLAG_PASSIVE;
-+-		if (ch->allow_ibss)
-+-			flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
-+-		if (ch->allow_ht)
-+-			flags |= WMI_CHAN_FLAG_ALLOW_HT;
-+-		if (ch->allow_vht)
-+-			flags |= WMI_CHAN_FLAG_ALLOW_VHT;
-+-		if (ch->ht40plus)
-+-			flags |= WMI_CHAN_FLAG_HT40_PLUS;
-+-		if (ch->chan_radar)
-+-			flags |= WMI_CHAN_FLAG_DFS;
-+-
-+-		ci->mhz               = __cpu_to_le32(ch->freq);
-+-		ci->band_center_freq1 = __cpu_to_le32(ch->freq);
-+-		ci->band_center_freq2 = 0;
-+-		ci->min_power         = ch->min_power;
-+-		ci->max_power         = ch->max_power;
-+-		ci->reg_power         = ch->max_reg_power;
-+-		ci->antenna_max       = ch->max_antenna_gain;
-+-
-+-		/* mode & flags share storage */
-+-		ci->mode              = ch->mode;
-+-		ci->flags            |= __cpu_to_le32(flags);
-++		ath10k_wmi_put_wmi_channel(ci, ch);
-+ 	}
-+ 
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_peer_assoc(struct ath10k *ar,
-+-			  const struct wmi_peer_assoc_complete_arg *arg)
-++static void
-++ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
-++			   const struct wmi_peer_assoc_complete_arg *arg)
-+ {
-+-	struct wmi_peer_assoc_complete_cmd *cmd;
-+-	struct sk_buff *skb;
-++	struct wmi_common_peer_assoc_complete_cmd *cmd = buf;
-+ 
-+-	if (arg->peer_mpdu_density > 16)
-+-		return -EINVAL;
-+-	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
-+-		return -EINVAL;
-+-	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
-+-		return -EINVAL;
-+-
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-+-	if (!skb)
-+-		return -ENOMEM;
-+-
-+-	cmd = (struct wmi_peer_assoc_complete_cmd *)skb->data;
-+ 	cmd->vdev_id            = __cpu_to_le32(arg->vdev_id);
-+ 	cmd->peer_new_assoc     = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
-+ 	cmd->peer_associd       = __cpu_to_le32(arg->peer_aid);
-+@@ -3469,7 +4746,7 @@ int ath10k_wmi_peer_assoc(struct ath10k
-+ 	cmd->peer_vht_caps      = __cpu_to_le32(arg->peer_vht_caps);
-+ 	cmd->peer_phymode       = __cpu_to_le32(arg->peer_phymode);
-+ 
-+-	memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN);
-++	ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
-+ 
-+ 	cmd->peer_legacy_rates.num_rates =
-+ 		__cpu_to_le32(arg->peer_legacy_rates.num_rates);
-+@@ -3489,57 +4766,183 @@ int ath10k_wmi_peer_assoc(struct ath10k
-+ 		__cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
-+ 	cmd->peer_vht_rates.tx_mcs_set =
-+ 		__cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
-++}
-++
-++static void
-++ath10k_wmi_peer_assoc_fill_main(struct ath10k *ar, void *buf,
-++				const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	struct wmi_main_peer_assoc_complete_cmd *cmd = buf;
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
-++	memset(cmd->peer_ht_info, 0, sizeof(cmd->peer_ht_info));
-++}
-++
-++static void
-++ath10k_wmi_peer_assoc_fill_10_1(struct ath10k *ar, void *buf,
-++				const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
-++}
-++
-++static void
-++ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
-++				const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	struct wmi_10_2_peer_assoc_complete_cmd *cmd = buf;
-++	int max_mcs, max_nss;
-++	u32 info0;
-++
-++	/* TODO: Is using max values okay with firmware? */
-++	max_mcs = 0xf;
-++	max_nss = 0xf;
-++
-++	info0 = SM(max_mcs, WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX) |
-++		SM(max_nss, WMI_PEER_ASSOC_INFO0_MAX_NSS);
-++
-++	ath10k_wmi_peer_assoc_fill(ar, buf, arg);
-++	cmd->info0 = __cpu_to_le32(info0);
-++}
-++
-++static int
-++ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	if (arg->peer_mpdu_density > 16)
-++		return -EINVAL;
-++	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
-++		return -EINVAL;
-++	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
-++		return -EINVAL;
-++
-++	return 0;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_peer_assoc(struct ath10k *ar,
-++			     const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	size_t len = sizeof(struct wmi_main_peer_assoc_complete_cmd);
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	ret = ath10k_wmi_peer_assoc_check_arg(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi peer assoc vdev %d addr %pM (%s)\n",
-++		   arg->vdev_id, arg->addr,
-++		   arg->peer_reassoc ? "reassociate" : "new");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_10_1_op_gen_peer_assoc(struct ath10k *ar,
-++				  const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	size_t len = sizeof(struct wmi_10_1_peer_assoc_complete_cmd);
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	ret = ath10k_wmi_peer_assoc_check_arg(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi peer assoc vdev %d addr %pM (%s)\n",
-++		   arg->vdev_id, arg->addr,
-++		   arg->peer_reassoc ? "reassociate" : "new");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
-++				  const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	size_t len = sizeof(struct wmi_10_2_peer_assoc_complete_cmd);
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	ret = ath10k_wmi_peer_assoc_check_arg(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi peer assoc vdev %d addr %pM (%s)\n",
-+ 		   arg->vdev_id, arg->addr,
-+ 		   arg->peer_reassoc ? "reassociate" : "new");
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, 0);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev get temperature\n");
-++	return skb;
-+ }
-+ 
-+ /* This function assumes the beacon is already DMA mapped */
-+-int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, const void *bcn,
-++			     size_t bcn_len, u32 bcn_paddr, bool dtim_zero,
-++			     bool deliver_cab)
-+ {
-+ 	struct wmi_bcn_tx_ref_cmd *cmd;
-+ 	struct sk_buff *skb;
-+-	struct sk_buff *beacon = arvif->beacon;
-+-	struct ath10k *ar = arvif->ar;
-+ 	struct ieee80211_hdr *hdr;
-+-	int ret;
-+ 	u16 fc;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+-	hdr = (struct ieee80211_hdr *)beacon->data;
-++	hdr = (struct ieee80211_hdr *)bcn;
-+ 	fc = le16_to_cpu(hdr->frame_control);
-+ 
-+ 	cmd = (struct wmi_bcn_tx_ref_cmd *)skb->data;
-+-	cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
-+-	cmd->data_len = __cpu_to_le32(beacon->len);
-+-	cmd->data_ptr = __cpu_to_le32(ATH10K_SKB_CB(beacon)->paddr);
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->data_len = __cpu_to_le32(bcn_len);
-++	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
-+ 	cmd->msdu_id = 0;
-+ 	cmd->frame_control = __cpu_to_le32(fc);
-+ 	cmd->flags = 0;
-++	cmd->antenna_mask = __cpu_to_le32(WMI_BCN_TX_REF_DEF_ANTENNA);
-+ 
-+-	if (ATH10K_SKB_CB(beacon)->bcn.dtim_zero)
-++	if (dtim_zero)
-+ 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
-+ 
-+-	if (ATH10K_SKB_CB(beacon)->bcn.deliver_cab)
-++	if (deliver_cab)
-+ 		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
-+ 
-+-	ret = ath10k_wmi_cmd_send_nowait(ar, skb,
-+-					 ar->wmi.cmd->pdev_send_bcn_cmdid);
-+-
-+-	if (ret)
-+-		dev_kfree_skb(skb);
-+-
-+-	return ret;
-++	return skb;
-+ }
-+ 
-+-static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
-+-					  const struct wmi_wmm_params_arg *arg)
-++void ath10k_wmi_set_wmm_param(struct wmi_wmm_params *params,
-++			      const struct wmi_wmm_params_arg *arg)
-+ {
-+ 	params->cwmin  = __cpu_to_le32(arg->cwmin);
-+ 	params->cwmax  = __cpu_to_le32(arg->cwmax);
-+@@ -3549,76 +4952,81 @@ static void ath10k_wmi_pdev_set_wmm_para
-+ 	params->no_ack = __cpu_to_le32(arg->no_ack);
-+ }
-+ 
-+-int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
-+-			const struct wmi_pdev_set_wmm_params_arg *arg)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_set_wmm(struct ath10k *ar,
-++			       const struct wmi_wmm_params_all_arg *arg)
-+ {
-+ 	struct wmi_pdev_set_wmm_params *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_pdev_set_wmm_params *)skb->data;
-+-	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be);
-+-	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk);
-+-	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi);
-+-	ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo);
-++	ath10k_wmi_set_wmm_param(&cmd->ac_be, &arg->ac_be);
-++	ath10k_wmi_set_wmm_param(&cmd->ac_bk, &arg->ac_bk);
-++	ath10k_wmi_set_wmm_param(&cmd->ac_vi, &arg->ac_vi);
-++	ath10k_wmi_set_wmm_param(&cmd->ac_vo, &arg->ac_vo);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n");
-+-	return ath10k_wmi_cmd_send(ar, skb,
-+-				   ar->wmi.cmd->pdev_set_wmm_params_cmdid);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi pdev set wmm params\n");
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
-+ {
-+ 	struct wmi_request_stats_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_request_stats_cmd *)skb->data;
-+-	cmd->stats_id = __cpu_to_le32(stats_id);
-++	cmd->stats_id = __cpu_to_le32(stats_mask);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid);
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi request stats 0x%08x\n",
-++		   stats_mask);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_force_fw_hang(struct ath10k *ar,
-+-			     enum wmi_force_fw_hang_type type, u32 delay_ms)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_force_fw_hang(struct ath10k *ar,
-++				enum wmi_force_fw_hang_type type, u32 delay_ms)
-+ {
-+ 	struct wmi_force_fw_hang_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_force_fw_hang_cmd *)skb->data;
-+ 	cmd->type = __cpu_to_le32(type);
-+ 	cmd->delay_ms = __cpu_to_le32(delay_ms);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n",
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi force fw hang %d delay %d\n",
-+ 		   type, delay_ms);
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
-++	return skb;
-+ }
-+ 
-+-int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable)
-++static struct sk_buff *
-++ath10k_wmi_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable,
-++			     u32 log_level)
-+ {
-+ 	struct wmi_dbglog_cfg_cmd *cmd;
-+ 	struct sk_buff *skb;
-+ 	u32 cfg;
-+ 
-+-	skb = ath10k_wmi_alloc_skb(sizeof(*cmd));
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ 	if (!skb)
-+-		return -ENOMEM;
-++		return ERR_PTR(-ENOMEM);
-+ 
-+ 	cmd = (struct wmi_dbglog_cfg_cmd *)skb->data;
-+ 
-+ 	if (module_enable) {
-+-		cfg = SM(ATH10K_DBGLOG_LEVEL_VERBOSE,
-++		cfg = SM(log_level,
-+ 			 ATH10K_DBGLOG_CFG_LOG_LVL);
-+ 	} else {
-+ 		/* set back defaults, all modules with WARN level */
-+@@ -3632,12 +5040,474 @@ int ath10k_wmi_dbglog_cfg(struct ath10k
-+ 	cmd->config_enable = __cpu_to_le32(cfg);
-+ 	cmd->config_valid = __cpu_to_le32(ATH10K_DBGLOG_CFG_LOG_LVL_MASK);
-+ 
-+-	ath10k_dbg(ATH10K_DBG_WMI,
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ 		   "wmi dbglog cfg modules %08x %08x config %08x %08x\n",
-+ 		   __le32_to_cpu(cmd->module_enable),
-+ 		   __le32_to_cpu(cmd->module_valid),
-+ 		   __le32_to_cpu(cmd->config_enable),
-+ 		   __le32_to_cpu(cmd->config_valid));
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pktlog_enable(struct ath10k *ar, u32 ev_bitmap)
-++{
-++	struct wmi_pdev_pktlog_enable_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ev_bitmap &= ATH10K_PKTLOG_ANY;
-++
-++	cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data;
-++	cmd->ev_bitmap = __cpu_to_le32(ev_bitmap);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi enable pktlog filter 0x%08x\n",
-++		   ev_bitmap);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pktlog_disable(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-+ 
-+-	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
-++	skb = ath10k_wmi_alloc_skb(ar, 0);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period,
-++				      u32 duration, u32 next_offset,
-++				      u32 enabled)
-++{
-++	struct wmi_pdev_set_quiet_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_pdev_set_quiet_cmd *)skb->data;
-++	cmd->period = __cpu_to_le32(period);
-++	cmd->duration = __cpu_to_le32(duration);
-++	cmd->next_start = __cpu_to_le32(next_offset);
-++	cmd->enabled = __cpu_to_le32(enabled);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi quiet param: period %u duration %u enabled %d\n",
-++		   period, duration, enabled);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_addba_clear_resp(struct ath10k *ar, u32 vdev_id,
-++				   const u8 *mac)
-++{
-++	struct wmi_addba_clear_resp_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	if (!mac)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_addba_clear_resp_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi addba clear resp vdev_id 0x%X mac_addr %pM\n",
-++		   vdev_id, mac);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_addba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++			     u32 tid, u32 buf_size)
-++{
-++	struct wmi_addba_send_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	if (!mac)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_addba_send_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-++	cmd->tid = __cpu_to_le32(tid);
-++	cmd->buffersize = __cpu_to_le32(buf_size);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi addba send vdev_id 0x%X mac_addr %pM tid %u bufsize %u\n",
-++		   vdev_id, mac, tid, buf_size);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_addba_set_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++				 u32 tid, u32 status)
-++{
-++	struct wmi_addba_setresponse_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	if (!mac)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_addba_setresponse_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-++	cmd->tid = __cpu_to_le32(tid);
-++	cmd->statuscode = __cpu_to_le32(status);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi addba set resp vdev_id 0x%X mac_addr %pM tid %u status %u\n",
-++		   vdev_id, mac, tid, status);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++			     u32 tid, u32 initiator, u32 reason)
-++{
-++	struct wmi_delba_send_cmd *cmd;
-++	struct sk_buff *skb;
-++
-++	if (!mac)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	cmd = (struct wmi_delba_send_cmd *)skb->data;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-++	cmd->tid = __cpu_to_le32(tid);
-++	cmd->initiator = __cpu_to_le32(initiator);
-++	cmd->reasoncode = __cpu_to_le32(reason);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi delba send vdev_id 0x%X mac_addr %pM tid %u initiator %u reason %u\n",
-++		   vdev_id, mac, tid, initiator, reason);
-++	return skb;
-++}
-++
-++static const struct wmi_ops wmi_ops = {
-++	.rx = ath10k_wmi_op_rx,
-++	.map_svc = wmi_main_svc_map,
-++
-++	.pull_scan = ath10k_wmi_op_pull_scan_ev,
-++	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
-++	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
-++	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
-++	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
-++	.pull_swba = ath10k_wmi_op_pull_swba_ev,
-++	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
-++	.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
-++	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
-++	.pull_fw_stats = ath10k_wmi_main_op_pull_fw_stats,
-++
-++	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
-++	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
-++	.gen_pdev_set_rd = ath10k_wmi_op_gen_pdev_set_rd,
-++	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
-++	.gen_init = ath10k_wmi_op_gen_init,
-++	.gen_start_scan = ath10k_wmi_op_gen_start_scan,
-++	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
-++	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
-++	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
-++	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
-++	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
-++	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
-++	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
-++	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
-++	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
-++	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
-++	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
-++	/* .gen_vdev_wmm_conf not implemented */
-++	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
-++	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
-++	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
-++	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
-++	.gen_peer_assoc = ath10k_wmi_op_gen_peer_assoc,
-++	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
-++	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
-++	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
-++	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
-++	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
-++	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
-++	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
-++	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
-++	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
-++	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
-++	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
-++	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
-++	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
-++	/* .gen_pdev_get_temperature not implemented */
-++	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
-++	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
-++	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
-++	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
-++	/* .gen_bcn_tmpl not implemented */
-++	/* .gen_prb_tmpl not implemented */
-++	/* .gen_p2p_go_bcn_ie not implemented */
-++};
-++
-++static const struct wmi_ops wmi_10_1_ops = {
-++	.rx = ath10k_wmi_10_1_op_rx,
-++	.map_svc = wmi_10x_svc_map,
-++	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
-++	.pull_fw_stats = ath10k_wmi_10x_op_pull_fw_stats,
-++	.gen_init = ath10k_wmi_10_1_op_gen_init,
-++	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
-++	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
-++	.gen_peer_assoc = ath10k_wmi_10_1_op_gen_peer_assoc,
-++	/* .gen_pdev_get_temperature not implemented */
-++
-++	/* shared with main branch */
-++	.pull_scan = ath10k_wmi_op_pull_scan_ev,
-++	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
-++	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
-++	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
-++	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
-++	.pull_swba = ath10k_wmi_op_pull_swba_ev,
-++	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
-++	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
-++
-++	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
-++	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
-++	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
-++	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
-++	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
-++	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
-++	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
-++	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
-++	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
-++	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
-++	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
-++	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
-++	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
-++	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
-++	/* .gen_vdev_wmm_conf not implemented */
-++	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
-++	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
-++	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
-++	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
-++	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
-++	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
-++	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
-++	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
-++	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
-++	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
-++	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
-++	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
-++	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
-++	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
-++	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
-++	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
-++	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
-++	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
-++	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
-++	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
-++	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
-++	/* .gen_bcn_tmpl not implemented */
-++	/* .gen_prb_tmpl not implemented */
-++	/* .gen_p2p_go_bcn_ie not implemented */
-++};
-++
-++static const struct wmi_ops wmi_10_2_ops = {
-++	.rx = ath10k_wmi_10_2_op_rx,
-++	.pull_fw_stats = ath10k_wmi_10_2_op_pull_fw_stats,
-++	.gen_init = ath10k_wmi_10_2_op_gen_init,
-++	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
-++	/* .gen_pdev_get_temperature not implemented */
-++
-++	/* shared with 10.1 */
-++	.map_svc = wmi_10x_svc_map,
-++	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
-++	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
-++	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
-++
-++	.pull_scan = ath10k_wmi_op_pull_scan_ev,
-++	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
-++	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
-++	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
-++	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
-++	.pull_swba = ath10k_wmi_op_pull_swba_ev,
-++	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
-++	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
-++
-++	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
-++	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
-++	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
-++	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
-++	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
-++	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
-++	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
-++	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
-++	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
-++	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
-++	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
-++	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
-++	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
-++	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
-++	/* .gen_vdev_wmm_conf not implemented */
-++	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
-++	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
-++	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
-++	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
-++	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
-++	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
-++	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
-++	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
-++	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
-++	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
-++	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
-++	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
-++	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
-++	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
-++	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
-++	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
-++	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
-++	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
-++	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
-++	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
-++	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
-++};
-++
-++static const struct wmi_ops wmi_10_2_4_ops = {
-++	.rx = ath10k_wmi_10_2_op_rx,
-++	.pull_fw_stats = ath10k_wmi_10_2_4_op_pull_fw_stats,
-++	.gen_init = ath10k_wmi_10_2_op_gen_init,
-++	.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
-++	.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
-++
-++	/* shared with 10.1 */
-++	.map_svc = wmi_10x_svc_map,
-++	.pull_svc_rdy = ath10k_wmi_10x_op_pull_svc_rdy_ev,
-++	.gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
-++	.gen_start_scan = ath10k_wmi_10x_op_gen_start_scan,
-++
-++	.pull_scan = ath10k_wmi_op_pull_scan_ev,
-++	.pull_mgmt_rx = ath10k_wmi_op_pull_mgmt_rx_ev,
-++	.pull_ch_info = ath10k_wmi_op_pull_ch_info_ev,
-++	.pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
-++	.pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
-++	.pull_swba = ath10k_wmi_op_pull_swba_ev,
-++	.pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
-++	.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
-++
-++	.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
-++	.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
-++	.gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
-++	.gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
-++	.gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
-++	.gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
-++	.gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
-++	.gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
-++	.gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
-++	.gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
-++	.gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
-++	.gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
-++	.gen_vdev_spectral_conf = ath10k_wmi_op_gen_vdev_spectral_conf,
-++	.gen_vdev_spectral_enable = ath10k_wmi_op_gen_vdev_spectral_enable,
-++	.gen_peer_create = ath10k_wmi_op_gen_peer_create,
-++	.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
-++	.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
-++	.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
-++	.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
-++	.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
-++	.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
-++	.gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
-++	.gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
-++	.gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
-++	.gen_request_stats = ath10k_wmi_op_gen_request_stats,
-++	.gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
-++	.gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
-++	.gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
-++	.gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
-++	.gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
-++	.gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
-++	.gen_addba_clear_resp = ath10k_wmi_op_gen_addba_clear_resp,
-++	.gen_addba_send = ath10k_wmi_op_gen_addba_send,
-++	.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
-++	.gen_delba_send = ath10k_wmi_op_gen_delba_send,
-++	/* .gen_bcn_tmpl not implemented */
-++	/* .gen_prb_tmpl not implemented */
-++	/* .gen_p2p_go_bcn_ie not implemented */
-++};
-++
-++int ath10k_wmi_attach(struct ath10k *ar)
-++{
-++	switch (ar->wmi.op_version) {
-++	case ATH10K_FW_WMI_OP_VERSION_10_2_4:
-++		ar->wmi.cmd = &wmi_10_2_4_cmd_map;
-++		ar->wmi.ops = &wmi_10_2_4_ops;
-++		ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
-++		ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_10_2:
-++		ar->wmi.cmd = &wmi_10_2_cmd_map;
-++		ar->wmi.ops = &wmi_10_2_ops;
-++		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
-++		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_10_1:
-++		ar->wmi.cmd = &wmi_10x_cmd_map;
-++		ar->wmi.ops = &wmi_10_1_ops;
-++		ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
-++		ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_MAIN:
-++		ar->wmi.cmd = &wmi_cmd_map;
-++		ar->wmi.ops = &wmi_ops;
-++		ar->wmi.vdev_param = &wmi_vdev_param_map;
-++		ar->wmi.pdev_param = &wmi_pdev_param_map;
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_TLV:
-++		ath10k_wmi_tlv_attach(ar);
-++		break;
-++	case ATH10K_FW_WMI_OP_VERSION_UNSET:
-++	case ATH10K_FW_WMI_OP_VERSION_MAX:
-++		ath10k_err(ar, "unsupported WMI op version: %d\n",
-++			   ar->wmi.op_version);
-++		return -EINVAL;
-++	}
-++
-++	init_completion(&ar->wmi.service_ready);
-++	init_completion(&ar->wmi.unified_ready);
-++
-++	return 0;
-++}
-++
-++void ath10k_wmi_detach(struct ath10k *ar)
-++{
-++	int i;
-++
-++	/* free the host memory chunks requested by firmware */
-++	for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
-++		dma_free_coherent(ar->dev,
-++				  ar->wmi.mem_chunks[i].len,
-++				  ar->wmi.mem_chunks[i].vaddr,
-++				  ar->wmi.mem_chunks[i].paddr);
-++	}
-++
-++	ar->wmi.num_mem_chunks = 0;
-+ }
-+--- a/drivers/net/wireless/ath/ath10k/wmi.h
-++++ b/drivers/net/wireless/ath/ath10k/wmi.h
-+@@ -73,119 +73,361 @@ struct wmi_cmd_hdr {
-+ #define HTC_PROTOCOL_VERSION    0x0002
-+ #define WMI_PROTOCOL_VERSION    0x0002
-+ 
-+-enum wmi_service_id {
-+-	WMI_SERVICE_BEACON_OFFLOAD = 0,   /* beacon offload */
-+-	WMI_SERVICE_SCAN_OFFLOAD,	  /* scan offload */
-+-	WMI_SERVICE_ROAM_OFFLOAD,	  /* roam offload */
-+-	WMI_SERVICE_BCN_MISS_OFFLOAD,     /* beacon miss offload */
-+-	WMI_SERVICE_STA_PWRSAVE,	  /* fake sleep + basic power save */
-+-	WMI_SERVICE_STA_ADVANCED_PWRSAVE, /* uapsd, pspoll, force sleep */
-+-	WMI_SERVICE_AP_UAPSD,		  /* uapsd on AP */
-+-	WMI_SERVICE_AP_DFS,		  /* DFS on AP */
-+-	WMI_SERVICE_11AC,		  /* supports 11ac */
-+-	WMI_SERVICE_BLOCKACK,	/* Supports triggering ADDBA/DELBA from host*/
-+-	WMI_SERVICE_PHYERR,		  /* PHY error */
-+-	WMI_SERVICE_BCN_FILTER,		  /* Beacon filter support */
-+-	WMI_SERVICE_RTT,		  /* RTT (round trip time) support */
-+-	WMI_SERVICE_RATECTRL,		  /* Rate-control */
-+-	WMI_SERVICE_WOW,		  /* WOW Support */
-+-	WMI_SERVICE_RATECTRL_CACHE,       /* Rate-control caching */
-+-	WMI_SERVICE_IRAM_TIDS,            /* TIDs in IRAM */
-+-	WMI_SERVICE_ARPNS_OFFLOAD,	  /* ARP NS Offload support */
-+-	WMI_SERVICE_NLO,		  /* Network list offload service */
-+-	WMI_SERVICE_GTK_OFFLOAD,	  /* GTK offload */
-+-	WMI_SERVICE_SCAN_SCH,		  /* Scan Scheduler Service */
-+-	WMI_SERVICE_CSA_OFFLOAD,	  /* CSA offload service */
-+-	WMI_SERVICE_CHATTER,		  /* Chatter service */
-+-	WMI_SERVICE_COEX_FREQAVOID,	  /* FW report freq range to avoid */
-+-	WMI_SERVICE_PACKET_POWER_SAVE,	  /* packet power save service */
-+-	WMI_SERVICE_FORCE_FW_HANG,        /* To test fw recovery mechanism */
-+-	WMI_SERVICE_GPIO,                 /* GPIO service */
-+-	WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, /* Modulated DTIM support */
-+-	WMI_STA_UAPSD_BASIC_AUTO_TRIG,    /* UAPSD AC Trigger Generation  */
-+-	WMI_STA_UAPSD_VAR_AUTO_TRIG,      /* -do- */
-+-	WMI_SERVICE_STA_KEEP_ALIVE,       /* STA keep alive mechanism support */
-+-	WMI_SERVICE_TX_ENCAP,             /* Packet type for TX encapsulation */
-+-
-+-	WMI_SERVICE_LAST,
-+-	WMI_MAX_SERVICE = 64		  /* max service */
-++enum wmi_service {
-++	WMI_SERVICE_BEACON_OFFLOAD = 0,
-++	WMI_SERVICE_SCAN_OFFLOAD,
-++	WMI_SERVICE_ROAM_OFFLOAD,
-++	WMI_SERVICE_BCN_MISS_OFFLOAD,
-++	WMI_SERVICE_STA_PWRSAVE,
-++	WMI_SERVICE_STA_ADVANCED_PWRSAVE,
-++	WMI_SERVICE_AP_UAPSD,
-++	WMI_SERVICE_AP_DFS,
-++	WMI_SERVICE_11AC,
-++	WMI_SERVICE_BLOCKACK,
-++	WMI_SERVICE_PHYERR,
-++	WMI_SERVICE_BCN_FILTER,
-++	WMI_SERVICE_RTT,
-++	WMI_SERVICE_RATECTRL,
-++	WMI_SERVICE_WOW,
-++	WMI_SERVICE_RATECTRL_CACHE,
-++	WMI_SERVICE_IRAM_TIDS,
-++	WMI_SERVICE_ARPNS_OFFLOAD,
-++	WMI_SERVICE_NLO,
-++	WMI_SERVICE_GTK_OFFLOAD,
-++	WMI_SERVICE_SCAN_SCH,
-++	WMI_SERVICE_CSA_OFFLOAD,
-++	WMI_SERVICE_CHATTER,
-++	WMI_SERVICE_COEX_FREQAVOID,
-++	WMI_SERVICE_PACKET_POWER_SAVE,
-++	WMI_SERVICE_FORCE_FW_HANG,
-++	WMI_SERVICE_GPIO,
-++	WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-++	WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-++	WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-++	WMI_SERVICE_STA_KEEP_ALIVE,
-++	WMI_SERVICE_TX_ENCAP,
-++	WMI_SERVICE_BURST,
-++	WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
-++	WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
-++	WMI_SERVICE_ROAM_SCAN_OFFLOAD,
-++	WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
-++	WMI_SERVICE_EARLY_RX,
-++	WMI_SERVICE_STA_SMPS,
-++	WMI_SERVICE_FWTEST,
-++	WMI_SERVICE_STA_WMMAC,
-++	WMI_SERVICE_TDLS,
-++	WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE,
-++	WMI_SERVICE_ADAPTIVE_OCS,
-++	WMI_SERVICE_BA_SSN_SUPPORT,
-++	WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
-++	WMI_SERVICE_WLAN_HB,
-++	WMI_SERVICE_LTE_ANT_SHARE_SUPPORT,
-++	WMI_SERVICE_BATCH_SCAN,
-++	WMI_SERVICE_QPOWER,
-++	WMI_SERVICE_PLMREQ,
-++	WMI_SERVICE_THERMAL_MGMT,
-++	WMI_SERVICE_RMC,
-++	WMI_SERVICE_MHF_OFFLOAD,
-++	WMI_SERVICE_COEX_SAR,
-++	WMI_SERVICE_BCN_TXRATE_OVERRIDE,
-++	WMI_SERVICE_NAN,
-++	WMI_SERVICE_L1SS_STAT,
-++	WMI_SERVICE_ESTIMATE_LINKSPEED,
-++	WMI_SERVICE_OBSS_SCAN,
-++	WMI_SERVICE_TDLS_OFFCHAN,
-++	WMI_SERVICE_TDLS_UAPSD_BUFFER_STA,
-++	WMI_SERVICE_TDLS_UAPSD_SLEEP_STA,
-++	WMI_SERVICE_IBSS_PWRSAVE,
-++	WMI_SERVICE_LPASS,
-++	WMI_SERVICE_EXTSCAN,
-++	WMI_SERVICE_D0WOW,
-++	WMI_SERVICE_HSOFFLOAD,
-++	WMI_SERVICE_ROAM_HO_OFFLOAD,
-++	WMI_SERVICE_RX_FULL_REORDER,
-++	WMI_SERVICE_DHCP_OFFLOAD,
-++	WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
-++	WMI_SERVICE_MDNS_OFFLOAD,
-++	WMI_SERVICE_SAP_AUTH_OFFLOAD,
-++
-++	/* keep last */
-++	WMI_SERVICE_MAX,
-++};
-++
-++enum wmi_10x_service {
-++	WMI_10X_SERVICE_BEACON_OFFLOAD = 0,
-++	WMI_10X_SERVICE_SCAN_OFFLOAD,
-++	WMI_10X_SERVICE_ROAM_OFFLOAD,
-++	WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
-++	WMI_10X_SERVICE_STA_PWRSAVE,
-++	WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
-++	WMI_10X_SERVICE_AP_UAPSD,
-++	WMI_10X_SERVICE_AP_DFS,
-++	WMI_10X_SERVICE_11AC,
-++	WMI_10X_SERVICE_BLOCKACK,
-++	WMI_10X_SERVICE_PHYERR,
-++	WMI_10X_SERVICE_BCN_FILTER,
-++	WMI_10X_SERVICE_RTT,
-++	WMI_10X_SERVICE_RATECTRL,
-++	WMI_10X_SERVICE_WOW,
-++	WMI_10X_SERVICE_RATECTRL_CACHE,
-++	WMI_10X_SERVICE_IRAM_TIDS,
-++	WMI_10X_SERVICE_BURST,
-++
-++	/* introduced in 10.2 */
-++	WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
-++	WMI_10X_SERVICE_FORCE_FW_HANG,
-++	WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
-++};
-++
-++enum wmi_main_service {
-++	WMI_MAIN_SERVICE_BEACON_OFFLOAD = 0,
-++	WMI_MAIN_SERVICE_SCAN_OFFLOAD,
-++	WMI_MAIN_SERVICE_ROAM_OFFLOAD,
-++	WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
-++	WMI_MAIN_SERVICE_STA_PWRSAVE,
-++	WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
-++	WMI_MAIN_SERVICE_AP_UAPSD,
-++	WMI_MAIN_SERVICE_AP_DFS,
-++	WMI_MAIN_SERVICE_11AC,
-++	WMI_MAIN_SERVICE_BLOCKACK,
-++	WMI_MAIN_SERVICE_PHYERR,
-++	WMI_MAIN_SERVICE_BCN_FILTER,
-++	WMI_MAIN_SERVICE_RTT,
-++	WMI_MAIN_SERVICE_RATECTRL,
-++	WMI_MAIN_SERVICE_WOW,
-++	WMI_MAIN_SERVICE_RATECTRL_CACHE,
-++	WMI_MAIN_SERVICE_IRAM_TIDS,
-++	WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
-++	WMI_MAIN_SERVICE_NLO,
-++	WMI_MAIN_SERVICE_GTK_OFFLOAD,
-++	WMI_MAIN_SERVICE_SCAN_SCH,
-++	WMI_MAIN_SERVICE_CSA_OFFLOAD,
-++	WMI_MAIN_SERVICE_CHATTER,
-++	WMI_MAIN_SERVICE_COEX_FREQAVOID,
-++	WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
-++	WMI_MAIN_SERVICE_FORCE_FW_HANG,
-++	WMI_MAIN_SERVICE_GPIO,
-++	WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-++	WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-++	WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-++	WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
-++	WMI_MAIN_SERVICE_TX_ENCAP,
-+ };
-+ 
-+ static inline char *wmi_service_name(int service_id)
-+ {
-++#define SVCSTR(x) case x: return #x
-++
-+ 	switch (service_id) {
-+-	case WMI_SERVICE_BEACON_OFFLOAD:
-+-		return "BEACON_OFFLOAD";
-+-	case WMI_SERVICE_SCAN_OFFLOAD:
-+-		return "SCAN_OFFLOAD";
-+-	case WMI_SERVICE_ROAM_OFFLOAD:
-+-		return "ROAM_OFFLOAD";
-+-	case WMI_SERVICE_BCN_MISS_OFFLOAD:
-+-		return "BCN_MISS_OFFLOAD";
-+-	case WMI_SERVICE_STA_PWRSAVE:
-+-		return "STA_PWRSAVE";
-+-	case WMI_SERVICE_STA_ADVANCED_PWRSAVE:
-+-		return "STA_ADVANCED_PWRSAVE";
-+-	case WMI_SERVICE_AP_UAPSD:
-+-		return "AP_UAPSD";
-+-	case WMI_SERVICE_AP_DFS:
-+-		return "AP_DFS";
-+-	case WMI_SERVICE_11AC:
-+-		return "11AC";
-+-	case WMI_SERVICE_BLOCKACK:
-+-		return "BLOCKACK";
-+-	case WMI_SERVICE_PHYERR:
-+-		return "PHYERR";
-+-	case WMI_SERVICE_BCN_FILTER:
-+-		return "BCN_FILTER";
-+-	case WMI_SERVICE_RTT:
-+-		return "RTT";
-+-	case WMI_SERVICE_RATECTRL:
-+-		return "RATECTRL";
-+-	case WMI_SERVICE_WOW:
-+-		return "WOW";
-+-	case WMI_SERVICE_RATECTRL_CACHE:
-+-		return "RATECTRL CACHE";
-+-	case WMI_SERVICE_IRAM_TIDS:
-+-		return "IRAM TIDS";
-+-	case WMI_SERVICE_ARPNS_OFFLOAD:
-+-		return "ARPNS_OFFLOAD";
-+-	case WMI_SERVICE_NLO:
-+-		return "NLO";
-+-	case WMI_SERVICE_GTK_OFFLOAD:
-+-		return "GTK_OFFLOAD";
-+-	case WMI_SERVICE_SCAN_SCH:
-+-		return "SCAN_SCH";
-+-	case WMI_SERVICE_CSA_OFFLOAD:
-+-		return "CSA_OFFLOAD";
-+-	case WMI_SERVICE_CHATTER:
-+-		return "CHATTER";
-+-	case WMI_SERVICE_COEX_FREQAVOID:
-+-		return "COEX_FREQAVOID";
-+-	case WMI_SERVICE_PACKET_POWER_SAVE:
-+-		return "PACKET_POWER_SAVE";
-+-	case WMI_SERVICE_FORCE_FW_HANG:
-+-		return "FORCE FW HANG";
-+-	case WMI_SERVICE_GPIO:
-+-		return "GPIO";
-+-	case WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM:
-+-		return "MODULATED DTIM";
-+-	case WMI_STA_UAPSD_BASIC_AUTO_TRIG:
-+-		return "BASIC UAPSD";
-+-	case WMI_STA_UAPSD_VAR_AUTO_TRIG:
-+-		return "VAR UAPSD";
-+-	case WMI_SERVICE_STA_KEEP_ALIVE:
-+-		return "STA KEEP ALIVE";
-+-	case WMI_SERVICE_TX_ENCAP:
-+-		return "TX ENCAP";
-++	SVCSTR(WMI_SERVICE_BEACON_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_SCAN_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_ROAM_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_BCN_MISS_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_STA_PWRSAVE);
-++	SVCSTR(WMI_SERVICE_STA_ADVANCED_PWRSAVE);
-++	SVCSTR(WMI_SERVICE_AP_UAPSD);
-++	SVCSTR(WMI_SERVICE_AP_DFS);
-++	SVCSTR(WMI_SERVICE_11AC);
-++	SVCSTR(WMI_SERVICE_BLOCKACK);
-++	SVCSTR(WMI_SERVICE_PHYERR);
-++	SVCSTR(WMI_SERVICE_BCN_FILTER);
-++	SVCSTR(WMI_SERVICE_RTT);
-++	SVCSTR(WMI_SERVICE_RATECTRL);
-++	SVCSTR(WMI_SERVICE_WOW);
-++	SVCSTR(WMI_SERVICE_RATECTRL_CACHE);
-++	SVCSTR(WMI_SERVICE_IRAM_TIDS);
-++	SVCSTR(WMI_SERVICE_ARPNS_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_NLO);
-++	SVCSTR(WMI_SERVICE_GTK_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_SCAN_SCH);
-++	SVCSTR(WMI_SERVICE_CSA_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_CHATTER);
-++	SVCSTR(WMI_SERVICE_COEX_FREQAVOID);
-++	SVCSTR(WMI_SERVICE_PACKET_POWER_SAVE);
-++	SVCSTR(WMI_SERVICE_FORCE_FW_HANG);
-++	SVCSTR(WMI_SERVICE_GPIO);
-++	SVCSTR(WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM);
-++	SVCSTR(WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG);
-++	SVCSTR(WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG);
-++	SVCSTR(WMI_SERVICE_STA_KEEP_ALIVE);
-++	SVCSTR(WMI_SERVICE_TX_ENCAP);
-++	SVCSTR(WMI_SERVICE_BURST);
-++	SVCSTR(WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
-++	SVCSTR(WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
-++	SVCSTR(WMI_SERVICE_ROAM_SCAN_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC);
-++	SVCSTR(WMI_SERVICE_EARLY_RX);
-++	SVCSTR(WMI_SERVICE_STA_SMPS);
-++	SVCSTR(WMI_SERVICE_FWTEST);
-++	SVCSTR(WMI_SERVICE_STA_WMMAC);
-++	SVCSTR(WMI_SERVICE_TDLS);
-++	SVCSTR(WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE);
-++	SVCSTR(WMI_SERVICE_ADAPTIVE_OCS);
-++	SVCSTR(WMI_SERVICE_BA_SSN_SUPPORT);
-++	SVCSTR(WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE);
-++	SVCSTR(WMI_SERVICE_WLAN_HB);
-++	SVCSTR(WMI_SERVICE_LTE_ANT_SHARE_SUPPORT);
-++	SVCSTR(WMI_SERVICE_BATCH_SCAN);
-++	SVCSTR(WMI_SERVICE_QPOWER);
-++	SVCSTR(WMI_SERVICE_PLMREQ);
-++	SVCSTR(WMI_SERVICE_THERMAL_MGMT);
-++	SVCSTR(WMI_SERVICE_RMC);
-++	SVCSTR(WMI_SERVICE_MHF_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_COEX_SAR);
-++	SVCSTR(WMI_SERVICE_BCN_TXRATE_OVERRIDE);
-++	SVCSTR(WMI_SERVICE_NAN);
-++	SVCSTR(WMI_SERVICE_L1SS_STAT);
-++	SVCSTR(WMI_SERVICE_ESTIMATE_LINKSPEED);
-++	SVCSTR(WMI_SERVICE_OBSS_SCAN);
-++	SVCSTR(WMI_SERVICE_TDLS_OFFCHAN);
-++	SVCSTR(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA);
-++	SVCSTR(WMI_SERVICE_TDLS_UAPSD_SLEEP_STA);
-++	SVCSTR(WMI_SERVICE_IBSS_PWRSAVE);
-++	SVCSTR(WMI_SERVICE_LPASS);
-++	SVCSTR(WMI_SERVICE_EXTSCAN);
-++	SVCSTR(WMI_SERVICE_D0WOW);
-++	SVCSTR(WMI_SERVICE_HSOFFLOAD);
-++	SVCSTR(WMI_SERVICE_ROAM_HO_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_RX_FULL_REORDER);
-++	SVCSTR(WMI_SERVICE_DHCP_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT);
-++	SVCSTR(WMI_SERVICE_MDNS_OFFLOAD);
-++	SVCSTR(WMI_SERVICE_SAP_AUTH_OFFLOAD);
-+ 	default:
-+-		return "UNKNOWN SERVICE\n";
-++		return NULL;
-+ 	}
-++
-++#undef SVCSTR
-+ }
-+ 
-++#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
-++	((svc_id) < (len) && \
-++	 __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
-++	 BIT((svc_id)%(sizeof(u32))))
-++
-++#define SVCMAP(x, y, len) \
-++	do { \
-++		if (WMI_SERVICE_IS_ENABLED((in), (x), (len))) \
-++			__set_bit(y, out); \
-++	} while (0)
-++
-++static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
-++				   size_t len)
-++{
-++	SVCMAP(WMI_10X_SERVICE_BEACON_OFFLOAD,
-++	       WMI_SERVICE_BEACON_OFFLOAD, len);
-++	SVCMAP(WMI_10X_SERVICE_SCAN_OFFLOAD,
-++	       WMI_SERVICE_SCAN_OFFLOAD, len);
-++	SVCMAP(WMI_10X_SERVICE_ROAM_OFFLOAD,
-++	       WMI_SERVICE_ROAM_OFFLOAD, len);
-++	SVCMAP(WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
-++	       WMI_SERVICE_BCN_MISS_OFFLOAD, len);
-++	SVCMAP(WMI_10X_SERVICE_STA_PWRSAVE,
-++	       WMI_SERVICE_STA_PWRSAVE, len);
-++	SVCMAP(WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
-++	       WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
-++	SVCMAP(WMI_10X_SERVICE_AP_UAPSD,
-++	       WMI_SERVICE_AP_UAPSD, len);
-++	SVCMAP(WMI_10X_SERVICE_AP_DFS,
-++	       WMI_SERVICE_AP_DFS, len);
-++	SVCMAP(WMI_10X_SERVICE_11AC,
-++	       WMI_SERVICE_11AC, len);
-++	SVCMAP(WMI_10X_SERVICE_BLOCKACK,
-++	       WMI_SERVICE_BLOCKACK, len);
-++	SVCMAP(WMI_10X_SERVICE_PHYERR,
-++	       WMI_SERVICE_PHYERR, len);
-++	SVCMAP(WMI_10X_SERVICE_BCN_FILTER,
-++	       WMI_SERVICE_BCN_FILTER, len);
-++	SVCMAP(WMI_10X_SERVICE_RTT,
-++	       WMI_SERVICE_RTT, len);
-++	SVCMAP(WMI_10X_SERVICE_RATECTRL,
-++	       WMI_SERVICE_RATECTRL, len);
-++	SVCMAP(WMI_10X_SERVICE_WOW,
-++	       WMI_SERVICE_WOW, len);
-++	SVCMAP(WMI_10X_SERVICE_RATECTRL_CACHE,
-++	       WMI_SERVICE_RATECTRL_CACHE, len);
-++	SVCMAP(WMI_10X_SERVICE_IRAM_TIDS,
-++	       WMI_SERVICE_IRAM_TIDS, len);
-++	SVCMAP(WMI_10X_SERVICE_BURST,
-++	       WMI_SERVICE_BURST, len);
-++	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
-++	       WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT, len);
-++	SVCMAP(WMI_10X_SERVICE_FORCE_FW_HANG,
-++	       WMI_SERVICE_FORCE_FW_HANG, len);
-++	SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
-++	       WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT, len);
-++}
-++
-++static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
-++				    size_t len)
-++{
-++	SVCMAP(WMI_MAIN_SERVICE_BEACON_OFFLOAD,
-++	       WMI_SERVICE_BEACON_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_SCAN_OFFLOAD,
-++	       WMI_SERVICE_SCAN_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_ROAM_OFFLOAD,
-++	       WMI_SERVICE_ROAM_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
-++	       WMI_SERVICE_BCN_MISS_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_PWRSAVE,
-++	       WMI_SERVICE_STA_PWRSAVE, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
-++	       WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
-++	SVCMAP(WMI_MAIN_SERVICE_AP_UAPSD,
-++	       WMI_SERVICE_AP_UAPSD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_AP_DFS,
-++	       WMI_SERVICE_AP_DFS, len);
-++	SVCMAP(WMI_MAIN_SERVICE_11AC,
-++	       WMI_SERVICE_11AC, len);
-++	SVCMAP(WMI_MAIN_SERVICE_BLOCKACK,
-++	       WMI_SERVICE_BLOCKACK, len);
-++	SVCMAP(WMI_MAIN_SERVICE_PHYERR,
-++	       WMI_SERVICE_PHYERR, len);
-++	SVCMAP(WMI_MAIN_SERVICE_BCN_FILTER,
-++	       WMI_SERVICE_BCN_FILTER, len);
-++	SVCMAP(WMI_MAIN_SERVICE_RTT,
-++	       WMI_SERVICE_RTT, len);
-++	SVCMAP(WMI_MAIN_SERVICE_RATECTRL,
-++	       WMI_SERVICE_RATECTRL, len);
-++	SVCMAP(WMI_MAIN_SERVICE_WOW,
-++	       WMI_SERVICE_WOW, len);
-++	SVCMAP(WMI_MAIN_SERVICE_RATECTRL_CACHE,
-++	       WMI_SERVICE_RATECTRL_CACHE, len);
-++	SVCMAP(WMI_MAIN_SERVICE_IRAM_TIDS,
-++	       WMI_SERVICE_IRAM_TIDS, len);
-++	SVCMAP(WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
-++	       WMI_SERVICE_ARPNS_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_NLO,
-++	       WMI_SERVICE_NLO, len);
-++	SVCMAP(WMI_MAIN_SERVICE_GTK_OFFLOAD,
-++	       WMI_SERVICE_GTK_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_SCAN_SCH,
-++	       WMI_SERVICE_SCAN_SCH, len);
-++	SVCMAP(WMI_MAIN_SERVICE_CSA_OFFLOAD,
-++	       WMI_SERVICE_CSA_OFFLOAD, len);
-++	SVCMAP(WMI_MAIN_SERVICE_CHATTER,
-++	       WMI_SERVICE_CHATTER, len);
-++	SVCMAP(WMI_MAIN_SERVICE_COEX_FREQAVOID,
-++	       WMI_SERVICE_COEX_FREQAVOID, len);
-++	SVCMAP(WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
-++	       WMI_SERVICE_PACKET_POWER_SAVE, len);
-++	SVCMAP(WMI_MAIN_SERVICE_FORCE_FW_HANG,
-++	       WMI_SERVICE_FORCE_FW_HANG, len);
-++	SVCMAP(WMI_MAIN_SERVICE_GPIO,
-++	       WMI_SERVICE_GPIO, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-++	       WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-++	       WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-++	       WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, len);
-++	SVCMAP(WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
-++	       WMI_SERVICE_STA_KEEP_ALIVE, len);
-++	SVCMAP(WMI_MAIN_SERVICE_TX_ENCAP,
-++	       WMI_SERVICE_TX_ENCAP, len);
-++}
-+ 
-+-#define WMI_SERVICE_BM_SIZE \
-+-	((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32))
-++#undef SVCMAP
-+ 
-+ /* 2 word representation of MAC addr */
-+ struct wmi_mac_addr {
-+@@ -308,6 +550,8 @@ struct wmi_cmd_map {
-+ 	u32 force_fw_hang_cmdid;
-+ 	u32 gpio_config_cmdid;
-+ 	u32 gpio_output_cmdid;
-++	u32 pdev_get_temperature_cmdid;
-++	u32 vdev_set_wmm_params_cmdid;
-+ };
-+ 
-+ /*
-+@@ -803,6 +1047,166 @@ enum wmi_10x_event_id {
-+ 	WMI_10X_PDEV_UTF_EVENTID = WMI_10X_END_EVENTID-1,
-+ };
-+ 
-++enum wmi_10_2_cmd_id {
-++	WMI_10_2_START_CMDID = 0x9000,
-++	WMI_10_2_END_CMDID = 0x9FFF,
-++	WMI_10_2_INIT_CMDID,
-++	WMI_10_2_START_SCAN_CMDID = WMI_10_2_START_CMDID,
-++	WMI_10_2_STOP_SCAN_CMDID,
-++	WMI_10_2_SCAN_CHAN_LIST_CMDID,
-++	WMI_10_2_ECHO_CMDID,
-++	WMI_10_2_PDEV_SET_REGDOMAIN_CMDID,
-++	WMI_10_2_PDEV_SET_CHANNEL_CMDID,
-++	WMI_10_2_PDEV_SET_PARAM_CMDID,
-++	WMI_10_2_PDEV_PKTLOG_ENABLE_CMDID,
-++	WMI_10_2_PDEV_PKTLOG_DISABLE_CMDID,
-++	WMI_10_2_PDEV_SET_WMM_PARAMS_CMDID,
-++	WMI_10_2_PDEV_SET_HT_CAP_IE_CMDID,
-++	WMI_10_2_PDEV_SET_VHT_CAP_IE_CMDID,
-++	WMI_10_2_PDEV_SET_BASE_MACADDR_CMDID,
-++	WMI_10_2_PDEV_SET_QUIET_MODE_CMDID,
-++	WMI_10_2_PDEV_GREEN_AP_PS_ENABLE_CMDID,
-++	WMI_10_2_PDEV_GET_TPC_CONFIG_CMDID,
-++	WMI_10_2_VDEV_CREATE_CMDID,
-++	WMI_10_2_VDEV_DELETE_CMDID,
-++	WMI_10_2_VDEV_START_REQUEST_CMDID,
-++	WMI_10_2_VDEV_RESTART_REQUEST_CMDID,
-++	WMI_10_2_VDEV_UP_CMDID,
-++	WMI_10_2_VDEV_STOP_CMDID,
-++	WMI_10_2_VDEV_DOWN_CMDID,
-++	WMI_10_2_VDEV_STANDBY_RESPONSE_CMDID,
-++	WMI_10_2_VDEV_RESUME_RESPONSE_CMDID,
-++	WMI_10_2_VDEV_SET_PARAM_CMDID,
-++	WMI_10_2_VDEV_INSTALL_KEY_CMDID,
-++	WMI_10_2_VDEV_SET_DSCP_TID_MAP_CMDID,
-++	WMI_10_2_PEER_CREATE_CMDID,
-++	WMI_10_2_PEER_DELETE_CMDID,
-++	WMI_10_2_PEER_FLUSH_TIDS_CMDID,
-++	WMI_10_2_PEER_SET_PARAM_CMDID,
-++	WMI_10_2_PEER_ASSOC_CMDID,
-++	WMI_10_2_PEER_ADD_WDS_ENTRY_CMDID,
-++	WMI_10_2_PEER_UPDATE_WDS_ENTRY_CMDID,
-++	WMI_10_2_PEER_REMOVE_WDS_ENTRY_CMDID,
-++	WMI_10_2_PEER_MCAST_GROUP_CMDID,
-++	WMI_10_2_BCN_TX_CMDID,
-++	WMI_10_2_BCN_PRB_TMPL_CMDID,
-++	WMI_10_2_BCN_FILTER_RX_CMDID,
-++	WMI_10_2_PRB_REQ_FILTER_RX_CMDID,
-++	WMI_10_2_MGMT_TX_CMDID,
-++	WMI_10_2_ADDBA_CLEAR_RESP_CMDID,
-++	WMI_10_2_ADDBA_SEND_CMDID,
-++	WMI_10_2_ADDBA_STATUS_CMDID,
-++	WMI_10_2_DELBA_SEND_CMDID,
-++	WMI_10_2_ADDBA_SET_RESP_CMDID,
-++	WMI_10_2_SEND_SINGLEAMSDU_CMDID,
-++	WMI_10_2_STA_POWERSAVE_MODE_CMDID,
-++	WMI_10_2_STA_POWERSAVE_PARAM_CMDID,
-++	WMI_10_2_STA_MIMO_PS_MODE_CMDID,
-++	WMI_10_2_DBGLOG_CFG_CMDID,
-++	WMI_10_2_PDEV_DFS_ENABLE_CMDID,
-++	WMI_10_2_PDEV_DFS_DISABLE_CMDID,
-++	WMI_10_2_PDEV_QVIT_CMDID,
-++	WMI_10_2_ROAM_SCAN_MODE,
-++	WMI_10_2_ROAM_SCAN_RSSI_THRESHOLD,
-++	WMI_10_2_ROAM_SCAN_PERIOD,
-++	WMI_10_2_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	WMI_10_2_ROAM_AP_PROFILE,
-++	WMI_10_2_OFL_SCAN_ADD_AP_PROFILE,
-++	WMI_10_2_OFL_SCAN_REMOVE_AP_PROFILE,
-++	WMI_10_2_OFL_SCAN_PERIOD,
-++	WMI_10_2_P2P_DEV_SET_DEVICE_INFO,
-++	WMI_10_2_P2P_DEV_SET_DISCOVERABILITY,
-++	WMI_10_2_P2P_GO_SET_BEACON_IE,
-++	WMI_10_2_P2P_GO_SET_PROBE_RESP_IE,
-++	WMI_10_2_AP_PS_PEER_PARAM_CMDID,
-++	WMI_10_2_AP_PS_PEER_UAPSD_COEX_CMDID,
-++	WMI_10_2_PEER_RATE_RETRY_SCHED_CMDID,
-++	WMI_10_2_WLAN_PROFILE_TRIGGER_CMDID,
-++	WMI_10_2_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
-++	WMI_10_2_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
-++	WMI_10_2_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
-++	WMI_10_2_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
-++	WMI_10_2_PDEV_SUSPEND_CMDID,
-++	WMI_10_2_PDEV_RESUME_CMDID,
-++	WMI_10_2_ADD_BCN_FILTER_CMDID,
-++	WMI_10_2_RMV_BCN_FILTER_CMDID,
-++	WMI_10_2_WOW_ADD_WAKE_PATTERN_CMDID,
-++	WMI_10_2_WOW_DEL_WAKE_PATTERN_CMDID,
-++	WMI_10_2_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
-++	WMI_10_2_WOW_ENABLE_CMDID,
-++	WMI_10_2_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
-++	WMI_10_2_RTT_MEASREQ_CMDID,
-++	WMI_10_2_RTT_TSF_CMDID,
-++	WMI_10_2_RTT_KEEPALIVE_CMDID,
-++	WMI_10_2_PDEV_SEND_BCN_CMDID,
-++	WMI_10_2_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
-++	WMI_10_2_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
-++	WMI_10_2_REQUEST_STATS_CMDID,
-++	WMI_10_2_GPIO_CONFIG_CMDID,
-++	WMI_10_2_GPIO_OUTPUT_CMDID,
-++	WMI_10_2_VDEV_RATEMASK_CMDID,
-++	WMI_10_2_PDEV_SMART_ANT_ENABLE_CMDID,
-++	WMI_10_2_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID,
-++	WMI_10_2_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID,
-++	WMI_10_2_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID,
-++	WMI_10_2_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID,
-++	WMI_10_2_FORCE_FW_HANG_CMDID,
-++	WMI_10_2_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID,
-++	WMI_10_2_PDEV_SET_CTL_TABLE_CMDID,
-++	WMI_10_2_PDEV_SET_MIMOGAIN_TABLE_CMDID,
-++	WMI_10_2_PDEV_RATEPWR_TABLE_CMDID,
-++	WMI_10_2_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
-++	WMI_10_2_PDEV_GET_INFO,
-++	WMI_10_2_VDEV_GET_INFO,
-++	WMI_10_2_VDEV_ATF_REQUEST_CMDID,
-++	WMI_10_2_PEER_ATF_REQUEST_CMDID,
-++	WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
-++	WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
-++};
-++
-++enum wmi_10_2_event_id {
-++	WMI_10_2_SERVICE_READY_EVENTID = 0x8000,
-++	WMI_10_2_READY_EVENTID,
-++	WMI_10_2_DEBUG_MESG_EVENTID,
-++	WMI_10_2_START_EVENTID = 0x9000,
-++	WMI_10_2_END_EVENTID = 0x9FFF,
-++	WMI_10_2_SCAN_EVENTID = WMI_10_2_START_EVENTID,
-++	WMI_10_2_ECHO_EVENTID,
-++	WMI_10_2_UPDATE_STATS_EVENTID,
-++	WMI_10_2_INST_RSSI_STATS_EVENTID,
-++	WMI_10_2_VDEV_START_RESP_EVENTID,
-++	WMI_10_2_VDEV_STANDBY_REQ_EVENTID,
-++	WMI_10_2_VDEV_RESUME_REQ_EVENTID,
-++	WMI_10_2_VDEV_STOPPED_EVENTID,
-++	WMI_10_2_PEER_STA_KICKOUT_EVENTID,
-++	WMI_10_2_HOST_SWBA_EVENTID,
-++	WMI_10_2_TBTTOFFSET_UPDATE_EVENTID,
-++	WMI_10_2_MGMT_RX_EVENTID,
-++	WMI_10_2_CHAN_INFO_EVENTID,
-++	WMI_10_2_PHYERR_EVENTID,
-++	WMI_10_2_ROAM_EVENTID,
-++	WMI_10_2_PROFILE_MATCH,
-++	WMI_10_2_DEBUG_PRINT_EVENTID,
-++	WMI_10_2_PDEV_QVIT_EVENTID,
-++	WMI_10_2_WLAN_PROFILE_DATA_EVENTID,
-++	WMI_10_2_RTT_MEASUREMENT_REPORT_EVENTID,
-++	WMI_10_2_TSF_MEASUREMENT_REPORT_EVENTID,
-++	WMI_10_2_RTT_ERROR_REPORT_EVENTID,
-++	WMI_10_2_RTT_KEEPALIVE_EVENTID,
-++	WMI_10_2_WOW_WAKEUP_HOST_EVENTID,
-++	WMI_10_2_DCS_INTERFERENCE_EVENTID,
-++	WMI_10_2_PDEV_TPC_CONFIG_EVENTID,
-++	WMI_10_2_GPIO_INPUT_EVENTID,
-++	WMI_10_2_PEER_RATECODE_LIST_EVENTID,
-++	WMI_10_2_GENERIC_BUFFER_EVENTID,
-++	WMI_10_2_MCAST_BUF_RELEASE_EVENTID,
-++	WMI_10_2_MCAST_LIST_AGEOUT_EVENTID,
-++	WMI_10_2_WDS_PEER_EVENTID,
-++	WMI_10_2_PEER_STA_PS_STATECHG_EVENTID,
-++	WMI_10_2_PDEV_TEMPERATURE_EVENTID,
-++	WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
-++};
-++
-+ enum wmi_phy_mode {
-+ 	MODE_11A        = 0,   /* 11a Mode */
-+ 	MODE_11G        = 1,   /* 11b/g Mode */
-+@@ -955,7 +1359,6 @@ enum wmi_channel_change_cause {
-+ 				WMI_HT_CAP_RX_STBC       | \
-+ 				WMI_HT_CAP_LDPC)
-+ 
-+-
-+ /*
-+  * WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information
-+  * field. The fields not defined here are not supported, or reserved.
-+@@ -1076,10 +1479,6 @@ struct wlan_host_mem_req {
-+ 	__le32 num_units;
-+ } __packed;
-+ 
-+-#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
-+-	((((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
-+-	(1 << ((svc_id)%(sizeof(u32))))) != 0)
-+-
-+ /*
-+  * The following struct holds optional payload for
-+  * wmi_service_ready_event,e.g., 11ac pass some of the
-+@@ -1093,7 +1492,7 @@ struct wmi_service_ready_event {
-+ 	__le32 phy_capability;
-+ 	/* Maximum number of frag table entries that SW will populate less 1 */
-+ 	__le32 max_frag_entry;
-+-	__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
-++	__le32 wmi_service_bitmap[16];
-+ 	__le32 num_rf_chains;
-+ 	/*
-+ 	 * The following field is only valid for service type
-+@@ -1119,11 +1518,11 @@ struct wmi_service_ready_event {
-+ 	 * where FW can access this memory directly (or) by DMA.
-+ 	 */
-+ 	__le32 num_mem_reqs;
-+-	struct wlan_host_mem_req mem_reqs[1];
-++	struct wlan_host_mem_req mem_reqs[0];
-+ } __packed;
-+ 
-+ /* This is the definition from 10.X firmware branch */
-+-struct wmi_service_ready_event_10x {
-++struct wmi_10x_service_ready_event {
-+ 	__le32 sw_version;
-+ 	__le32 abi_version;
-+ 
-+@@ -1132,7 +1531,7 @@ struct wmi_service_ready_event_10x {
-+ 
-+ 	/* Maximum number of frag table entries that SW will populate less 1 */
-+ 	__le32 max_frag_entry;
-+-	__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
-++	__le32 wmi_service_bitmap[16];
-+ 	__le32 num_rf_chains;
-+ 
-+ 	/*
-+@@ -1158,10 +1557,9 @@ struct wmi_service_ready_event_10x {
-+ 	 */
-+ 	__le32 num_mem_reqs;
-+ 
-+-	struct wlan_host_mem_req mem_reqs[1];
-++	struct wlan_host_mem_req mem_reqs[0];
-+ } __packed;
-+ 
-+-
-+ #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
-+ #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
-+ 
-+@@ -1255,7 +1653,7 @@ struct wmi_resource_config {
-+ 	 */
-+ 	__le32 rx_decap_mode;
-+ 
-+-	/* what is the maximum scan requests than can be queued */
-++	/* what is the maximum number of scan requests that can be queued */
-+ 	__le32 scan_max_pending_reqs;
-+ 
-+ 	/* maximum VDEV that could use BMISS offload */
-+@@ -1440,7 +1838,7 @@ struct wmi_resource_config_10x {
-+ 	 */
-+ 	__le32 rx_decap_mode;
-+ 
-+-	/* what is the maximum scan requests than can be queued */
-++	/* what is the maximum number of scan requests that can be queued */
-+ 	__le32 scan_max_pending_reqs;
-+ 
-+ 	/* maximum VDEV that could use BMISS offload */
-+@@ -1551,6 +1949,21 @@ struct wmi_resource_config_10x {
-+ 	__le32 max_frag_entries;
-+ } __packed;
-+ 
-++enum wmi_10_2_feature_mask {
-++	WMI_10_2_RX_BATCH_MODE = BIT(0),
-++	WMI_10_2_ATF_CONFIG    = BIT(1),
-++};
-++
-++struct wmi_resource_config_10_2 {
-++	struct wmi_resource_config_10x common;
-++	__le32 max_peer_ext_stats;
-++	__le32 smart_ant_cap; /* 0-disable, 1-enable */
-++	__le32 bk_min_free;
-++	__le32 be_min_free;
-++	__le32 vi_min_free;
-++	__le32 vo_min_free;
-++	__le32 feature_mask;
-++} __packed;
-+ 
-+ #define NUM_UNITS_IS_NUM_VDEVS   0x1
-+ #define NUM_UNITS_IS_NUM_PEERS   0x2
-+@@ -1565,34 +1978,39 @@ struct host_memory_chunk {
-+ 	__le32 size;
-+ } __packed;
-+ 
-++struct wmi_host_mem_chunks {
-++	__le32 count;
-++	/* some fw revisions require at least 1 chunk regardless of count */
-++	struct host_memory_chunk items[1];
-++} __packed;
-++
-+ struct wmi_init_cmd {
-+ 	struct wmi_resource_config resource_config;
-+-	__le32 num_host_mem_chunks;
-+-
-+-	/*
-+-	 * variable number of host memory chunks.
-+-	 * This should be the last element in the structure
-+-	 */
-+-	struct host_memory_chunk host_mem_chunks[1];
-++	struct wmi_host_mem_chunks mem_chunks;
-+ } __packed;
-+ 
-+ /* _10x stucture is from 10.X FW API */
-+ struct wmi_init_cmd_10x {
-+ 	struct wmi_resource_config_10x resource_config;
-+-	__le32 num_host_mem_chunks;
-++	struct wmi_host_mem_chunks mem_chunks;
-++} __packed;
-+ 
-+-	/*
-+-	 * variable number of host memory chunks.
-+-	 * This should be the last element in the structure
-+-	 */
-+-	struct host_memory_chunk host_mem_chunks[1];
-++struct wmi_init_cmd_10_2 {
-++	struct wmi_resource_config_10_2 resource_config;
-++	struct wmi_host_mem_chunks mem_chunks;
-++} __packed;
-++
-++struct wmi_chan_list_entry {
-++	__le16 freq;
-++	u8 phy_mode; /* valid for 10.2 only */
-++	u8 reserved;
-+ } __packed;
-+ 
-+ /* TLV for channel list */
-+ struct wmi_chan_list {
-+ 	__le32 tag; /* WMI_CHAN_LIST_TAG */
-+ 	__le32 num_chan;
-+-	__le32 channel_list[0];
-++	struct wmi_chan_list_entry channel_list[0];
-+ } __packed;
-+ 
-+ struct wmi_bssid_list {
-+@@ -1629,6 +2047,11 @@ struct wmi_ssid_list {
-+ #define WLAN_SCAN_PARAMS_MAX_BSSID   4
-+ #define WLAN_SCAN_PARAMS_MAX_IE_LEN  256
-+ 
-++/* Values lower than this may be refused by some firmware revisions with a scan
-++ * completion with a timedout reason.
-++ */
-++#define WMI_SCAN_CHAN_MIN_TIME_MSEC 40
-++
-+ /* Scan priority numbers must be sequential, starting with 0 */
-+ enum wmi_scan_priority {
-+ 	WMI_SCAN_PRIORITY_VERY_LOW = 0,
-+@@ -1639,7 +2062,7 @@ enum wmi_scan_priority {
-+ 	WMI_SCAN_PRIORITY_COUNT   /* number of priorities supported */
-+ };
-+ 
-+-struct wmi_start_scan_cmd {
-++struct wmi_start_scan_common {
-+ 	/* Scan ID */
-+ 	__le32 scan_id;
-+ 	/* Scan requestor ID */
-+@@ -1697,97 +2120,26 @@ struct wmi_start_scan_cmd {
-+ 	__le32 probe_delay;
-+ 	/* Scan control flags */
-+ 	__le32 scan_ctrl_flags;
-+-
-+-	/* Burst duration time in msecs */
-+-	__le32 burst_duration;
-+-	/*
-+-	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
-+-	 * TLV can contain channel list, bssid list, ssid list and
-+-	 * ie. the TLV tags are defined above;
-+-	 */
-+ } __packed;
-+ 
-+-/* This is the definition from 10.X firmware branch */
-+-struct wmi_start_scan_cmd_10x {
-+-	/* Scan ID */
-+-	__le32 scan_id;
-+-
-+-	/* Scan requestor ID */
-+-	__le32 scan_req_id;
-+-
-+-	/* VDEV id(interface) that is requesting scan */
-+-	__le32 vdev_id;
-+-
-+-	/* Scan Priority, input to scan scheduler */
-+-	__le32 scan_priority;
-+-
-+-	/* Scan events subscription */
-+-	__le32 notify_scan_events;
-+-
-+-	/* dwell time in msec on active channels */
-+-	__le32 dwell_time_active;
-+-
-+-	/* dwell time in msec on passive channels */
-+-	__le32 dwell_time_passive;
-+-
-+-	/*
-+-	 * min time in msec on the BSS channel,only valid if atleast one
-+-	 * VDEV is active
-+-	 */
-+-	__le32 min_rest_time;
-+-
-+-	/*
-+-	 * max rest time in msec on the BSS channel,only valid if at least
-+-	 * one VDEV is active
-+-	 */
-+-	/*
-+-	 * the scanner will rest on the bss channel at least min_rest_time
-+-	 * after min_rest_time the scanner will start checking for tx/rx
-+-	 * activity on all VDEVs. if there is no activity the scanner will
-+-	 * switch to off channel. if there is activity the scanner will let
-+-	 * the radio on the bss channel until max_rest_time expires.at
-+-	 * max_rest_time scanner will switch to off channel irrespective of
-+-	 * activity. activity is determined by the idle_time parameter.
-+-	 */
-+-	__le32 max_rest_time;
-+-
-+-	/*
-+-	 * time before sending next set of probe requests.
-+-	 * The scanner keeps repeating probe requests transmission with
-+-	 * period specified by repeat_probe_time.
-+-	 * The number of probe requests specified depends on the ssid_list
-+-	 * and bssid_list
-+-	 */
-+-	__le32 repeat_probe_time;
-+-
-+-	/* time in msec between 2 consequetive probe requests with in a set. */
-+-	__le32 probe_spacing_time;
-+-
-+-	/*
-+-	 * data inactivity time in msec on bss channel that will be used by
-+-	 * scanner for measuring the inactivity.
-++struct wmi_start_scan_tlvs {
-++	/* TLV parameters. These includes channel list, ssid list, bssid list,
-++	 * extra ies.
-+ 	 */
-+-	__le32 idle_time;
-+-
-+-	/* maximum time in msec allowed for scan  */
-+-	__le32 max_scan_time;
-+-
-+-	/*
-+-	 * delay in msec before sending first probe request after switching
-+-	 * to a channel
-+-	 */
-+-	__le32 probe_delay;
-+-
-+-	/* Scan control flags */
-+-	__le32 scan_ctrl_flags;
-++	u8 tlvs[0];
-++} __packed;
-+ 
-+-	/*
-+-	 * TLV (tag length value )  paramerters follow the scan_cmd structure.
-+-	 * TLV can contain channel list, bssid list, ssid list and
-+-	 * ie. the TLV tags are defined above;
-+-	 */
-++struct wmi_start_scan_cmd {
-++	struct wmi_start_scan_common common;
-++	__le32 burst_duration_ms;
-++	struct wmi_start_scan_tlvs tlvs;
-+ } __packed;
-+ 
-++/* This is the definition from 10.X firmware branch */
-++struct wmi_10x_start_scan_cmd {
-++	struct wmi_start_scan_common common;
-++	struct wmi_start_scan_tlvs tlvs;
-++} __packed;
-+ 
-+ struct wmi_ssid_arg {
-+ 	int len;
-+@@ -1821,7 +2173,7 @@ struct wmi_start_scan_arg {
-+ 	u32 n_bssids;
-+ 
-+ 	u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN];
-+-	u32 channels[64];
-++	u16 channels[64];
-+ 	struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID];
-+ 	struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID];
-+ };
-+@@ -1849,7 +2201,6 @@ struct wmi_start_scan_arg {
-+ /* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
-+ #define WMI_SCAN_CLASS_MASK 0xFF000000
-+ 
-+-
-+ enum wmi_stop_scan_type {
-+ 	WMI_SCAN_STOP_ONE	= 0x00000000, /* stop by scan_id */
-+ 	WMI_SCAN_STOP_VDEV_ALL	= 0x01000000, /* stop by vdev_id */
-+@@ -1973,100 +2324,31 @@ struct wmi_mgmt_rx_event_v2 {
-+ #define PHY_ERROR_FALSE_RADAR_EXT		0x24
-+ #define PHY_ERROR_RADAR				0x05
-+ 
-+-struct wmi_single_phyerr_rx_hdr {
-+-	/* TSF timestamp */
-++struct wmi_phyerr {
-+ 	__le32 tsf_timestamp;
-+-
-+-	/*
-+-	 * Current freq1, freq2
-+-	 *
-+-	 * [7:0]:    freq1[lo]
-+-	 * [15:8] :   freq1[hi]
-+-	 * [23:16]:   freq2[lo]
-+-	 * [31:24]:   freq2[hi]
-+-	 */
-+ 	__le16 freq1;
-+ 	__le16 freq2;
-+-
-+-	/*
-+-	 * Combined RSSI over all chains and channel width for this PHY error
-+-	 *
-+-	 * [7:0]: RSSI combined
-+-	 * [15:8]: Channel width (MHz)
-+-	 * [23:16]: PHY error code
-+-	 * [24:16]: reserved (future use)
-+-	 */
-+ 	u8 rssi_combined;
-+ 	u8 chan_width_mhz;
-+ 	u8 phy_err_code;
-+ 	u8 rsvd0;
-+-
-+-	/*
-+-	 * RSSI on chain 0 through 3
-+-	 *
-+-	 * This is formatted the same as the PPDU_START RX descriptor
-+-	 * field:
-+-	 *
-+-	 * [7:0]:   pri20
-+-	 * [15:8]:  sec20
-+-	 * [23:16]: sec40
-+-	 * [31:24]: sec80
-+-	 */
-+-
-+-	__le32 rssi_chain0;
-+-	__le32 rssi_chain1;
-+-	__le32 rssi_chain2;
-+-	__le32 rssi_chain3;
-+-
-+-	/*
-+-	 * Last calibrated NF value for chain 0 through 3
-+-	 *
-+-	 * nf_list_1:
-+-	 *
-+-	 * + [15:0] - chain 0
-+-	 * + [31:16] - chain 1
-+-	 *
-+-	 * nf_list_2:
-+-	 *
-+-	 * + [15:0] - chain 2
-+-	 * + [31:16] - chain 3
-+-	 */
-+-	__le32 nf_list_1;
-+-	__le32 nf_list_2;
-+-
-+-
-+-	/* Length of the frame */
-++	__le32 rssi_chains[4];
-++	__le16 nf_chains[4];
-+ 	__le32 buf_len;
-++	u8 buf[0];
-+ } __packed;
-+ 
-+-struct wmi_single_phyerr_rx_event {
-+-	/* Phy error event header */
-+-	struct wmi_single_phyerr_rx_hdr hdr;
-+-	/* frame buffer */
-+-	u8 bufp[0];
-+-} __packed;
-+-
-+-struct wmi_comb_phyerr_rx_hdr {
-+-	/* Phy error phy error count */
-+-	__le32 num_phyerr_events;
-++struct wmi_phyerr_event {
-++	__le32 num_phyerrs;
-+ 	__le32 tsf_l32;
-+ 	__le32 tsf_u32;
-+-} __packed;
-+-
-+-struct wmi_comb_phyerr_rx_event {
-+-	/* Phy error phy error count */
-+-	struct wmi_comb_phyerr_rx_hdr hdr;
-+-	/*
-+-	 * frame buffer - contains multiple payloads in the order:
-+-	 *                    header - payload, header - payload...
-+-	 *  (The header is of type: wmi_single_phyerr_rx_hdr)
-+-	 */
-+-	u8 bufp[0];
-++	struct wmi_phyerr phyerrs[0];
-+ } __packed;
-+ 
-+ #define PHYERR_TLV_SIG				0xBB
-+ #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT	0xFB
-+ #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY	0xF8
-++#define PHYERR_TLV_TAG_SPECTRAL_SUMMARY_REPORT	0xF9
-+ 
-+ struct phyerr_radar_report {
-+ 	__le32 reg0; /* RADAR_REPORT_REG0_* */
-+@@ -2135,7 +2417,6 @@ struct phyerr_fft_report {
-+ #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK	0x000000FF
-+ #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB	0
-+ 
-+-
-+ struct phyerr_tlv {
-+ 	__le16 len;
-+ 	u8 tag;
-+@@ -2166,7 +2447,6 @@ struct wmi_echo_cmd {
-+ 	__le32 value;
-+ } __packed;
-+ 
-+-
-+ struct wmi_pdev_set_regdomain_cmd {
-+ 	__le32 reg_domain;
-+ 	__le32 reg_domain_2G;
-+@@ -2215,7 +2495,6 @@ struct wmi_pdev_set_quiet_cmd {
-+ 	__le32 enabled;
-+ } __packed;
-+ 
-+-
-+ /*
-+  * 802.11g protection mode.
-+  */
-+@@ -2318,14 +2597,15 @@ struct wmi_pdev_param_map {
-+ 	u32 fast_channel_reset;
-+ 	u32 burst_dur;
-+ 	u32 burst_enable;
-++	u32 cal_period;
-+ };
-+ 
-+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
-+ 
-+ enum wmi_pdev_param {
-+-	/* TX chian mask */
-++	/* TX chain mask */
-+ 	WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1,
-+-	/* RX chian mask */
-++	/* RX chain mask */
-+ 	WMI_PDEV_PARAM_RX_CHAIN_MASK,
-+ 	/* TX power limit for 2G Radio */
-+ 	WMI_PDEV_PARAM_TXPOWER_LIMIT2G,
-+@@ -2515,6 +2795,22 @@ enum wmi_10x_pdev_param {
-+ 	WMI_10X_PDEV_PARAM_BURST_DUR,
-+ 	/* Set Bursting Enable*/
-+ 	WMI_10X_PDEV_PARAM_BURST_ENABLE,
-++
-++	/* following are available as of firmware 10.2 */
-++	WMI_10X_PDEV_PARAM_SMART_ANTENNA_DEFAULT_ANTENNA,
-++	WMI_10X_PDEV_PARAM_IGMPMLD_OVERRIDE,
-++	WMI_10X_PDEV_PARAM_IGMPMLD_TID,
-++	WMI_10X_PDEV_PARAM_ANTENNA_GAIN,
-++	WMI_10X_PDEV_PARAM_RX_DECAP_MODE,
-++	WMI_10X_PDEV_PARAM_RX_FILTER,
-++	WMI_10X_PDEV_PARAM_SET_MCAST_TO_UCAST_TID,
-++	WMI_10X_PDEV_PARAM_PROXY_STA_MODE,
-++	WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_MODE,
-++	WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
-++	WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
-++	WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
-++	WMI_10X_PDEV_PARAM_RTS_FIXED_RATE,
-++	WMI_10X_PDEV_PARAM_CAL_PERIOD
-+ };
-+ 
-+ struct wmi_pdev_set_param_cmd {
-+@@ -2522,6 +2818,9 @@ struct wmi_pdev_set_param_cmd {
-+ 	__le32 param_value;
-+ } __packed;
-+ 
-++/* valid period is 1 ~ 60000ms, unit in millisecond */
-++#define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
-++
-+ struct wmi_pdev_get_tpc_config_cmd {
-+ 	/* parameter   */
-+ 	__le32 param;
-+@@ -2565,11 +2864,6 @@ enum wmi_tp_scale {
-+ 	WMI_TP_SCALE_SIZE   = 5,	/* max num of enum     */
-+ };
-+ 
-+-struct wmi_set_channel_cmd {
-+-	/* channel (only frequency and mode info are used) */
-+-	struct wmi_channel chan;
-+-} __packed;
-+-
-+ struct wmi_pdev_chanlist_update_event {
-+ 	/* number of channels */
-+ 	__le32 num_chan;
-+@@ -2600,6 +2894,10 @@ struct wmi_pdev_set_channel_cmd {
-+ 	struct wmi_channel chan;
-+ } __packed;
-+ 
-++struct wmi_pdev_pktlog_enable_cmd {
-++	__le32 ev_bitmap;
-++} __packed;
-++
-+ /* Customize the DSCP (bit) to TID (0-7) mapping for QOS */
-+ #define WMI_DSCP_MAP_MAX    (64)
-+ struct wmi_pdev_set_dscp_tid_map_cmd {
-+@@ -2642,14 +2940,14 @@ struct wmi_wmm_params_arg {
-+ 	u32 no_ack;
-+ };
-+ 
-+-struct wmi_pdev_set_wmm_params_arg {
-++struct wmi_wmm_params_all_arg {
-+ 	struct wmi_wmm_params_arg ac_be;
-+ 	struct wmi_wmm_params_arg ac_bk;
-+ 	struct wmi_wmm_params_arg ac_vi;
-+ 	struct wmi_wmm_params_arg ac_vo;
-+ };
-+ 
-+-struct wal_dbg_tx_stats {
-++struct wmi_pdev_stats_tx {
-+ 	/* Num HTT cookies queued to dispatch list */
-+ 	__le32 comp_queued;
-+ 
-+@@ -2719,7 +3017,7 @@ struct wal_dbg_tx_stats {
-+ 	__le32 txop_ovf;
-+ } __packed;
-+ 
-+-struct wal_dbg_rx_stats {
-++struct wmi_pdev_stats_rx {
-+ 	/* Cnts any change in ring routing mid-ppdu */
-+ 	__le32 mid_ppdu_route_change;
-+ 
-+@@ -2753,20 +3051,18 @@ struct wal_dbg_rx_stats {
-+ 	__le32 mpdu_errs;
-+ } __packed;
-+ 
-+-struct wal_dbg_peer_stats {
-++struct wmi_pdev_stats_peer {
-+ 	/* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */
-+ 	__le32 dummy;
-+ } __packed;
-+ 
-+-struct wal_dbg_stats {
-+-	struct wal_dbg_tx_stats tx;
-+-	struct wal_dbg_rx_stats rx;
-+-	struct wal_dbg_peer_stats peer;
-+-} __packed;
-+-
-+ enum wmi_stats_id {
-+-	WMI_REQUEST_PEER_STAT	= 0x01,
-+-	WMI_REQUEST_AP_STAT	= 0x02
-++	WMI_STAT_PEER = BIT(0),
-++	WMI_STAT_AP = BIT(1),
-++	WMI_STAT_PDEV = BIT(2),
-++	WMI_STAT_VDEV = BIT(3),
-++	WMI_STAT_BCNFLT = BIT(4),
-++	WMI_STAT_VDEV_RATE = BIT(5),
-+ };
-+ 
-+ struct wlan_inst_rssi_args {
-+@@ -2801,7 +3097,7 @@ struct wmi_pdev_suspend_cmd {
-+ } __packed;
-+ 
-+ struct wmi_stats_event {
-+-	__le32 stats_id; /* %WMI_REQUEST_ */
-++	__le32 stats_id; /* WMI_STAT_ */
-+ 	/*
-+ 	 * number of pdev stats event structures
-+ 	 * (wmi_pdev_stats) 0 or 1
-+@@ -2830,30 +3126,38 @@ struct wmi_stats_event {
-+ 	u8 data[0];
-+ } __packed;
-+ 
-++struct wmi_10_2_stats_event {
-++	__le32 stats_id; /* %WMI_REQUEST_ */
-++	__le32 num_pdev_stats;
-++	__le32 num_pdev_ext_stats;
-++	__le32 num_vdev_stats;
-++	__le32 num_peer_stats;
-++	__le32 num_bcnflt_stats;
-++	u8 data[0];
-++} __packed;
-++
-+ /*
-+  * PDEV statistics
-+  * TODO: add all PDEV stats here
-+  */
-+-struct wmi_pdev_stats_old {
-+-	__le32 chan_nf;        /* Channel noise floor */
-+-	__le32 tx_frame_count; /* TX frame count */
-+-	__le32 rx_frame_count; /* RX frame count */
-+-	__le32 rx_clear_count; /* rx clear count */
-+-	__le32 cycle_count;    /* cycle count */
-+-	__le32 phy_err_count;  /* Phy error count */
-+-	__le32 chan_tx_pwr;    /* channel tx power */
-+-	struct wal_dbg_stats wal; /* WAL dbg stats */
-+-} __packed;
-+-
-+-struct wmi_pdev_stats_10x {
-+-	__le32 chan_nf;        /* Channel noise floor */
-+-	__le32 tx_frame_count; /* TX frame count */
-+-	__le32 rx_frame_count; /* RX frame count */
-+-	__le32 rx_clear_count; /* rx clear count */
-+-	__le32 cycle_count;    /* cycle count */
-+-	__le32 phy_err_count;  /* Phy error count */
-+-	__le32 chan_tx_pwr;    /* channel tx power */
-+-	struct wal_dbg_stats wal; /* WAL dbg stats */
-++struct wmi_pdev_stats_base {
-++	__le32 chan_nf;
-++	__le32 tx_frame_count;
-++	__le32 rx_frame_count;
-++	__le32 rx_clear_count;
-++	__le32 cycle_count;
-++	__le32 phy_err_count;
-++	__le32 chan_tx_pwr;
-++} __packed;
-++
-++struct wmi_pdev_stats {
-++	struct wmi_pdev_stats_base base;
-++	struct wmi_pdev_stats_tx tx;
-++	struct wmi_pdev_stats_rx rx;
-++	struct wmi_pdev_stats_peer peer;
-++} __packed;
-++
-++struct wmi_pdev_stats_extra {
-+ 	__le32 ack_rx_bad;
-+ 	__le32 rts_bad;
-+ 	__le32 rts_good;
-+@@ -2862,6 +3166,30 @@ struct wmi_pdev_stats_10x {
-+ 	__le32 mib_int_count;
-+ } __packed;
-+ 
-++struct wmi_10x_pdev_stats {
-++	struct wmi_pdev_stats_base base;
-++	struct wmi_pdev_stats_tx tx;
-++	struct wmi_pdev_stats_rx rx;
-++	struct wmi_pdev_stats_peer peer;
-++	struct wmi_pdev_stats_extra extra;
-++} __packed;
-++
-++struct wmi_pdev_stats_mem {
-++	__le32 dram_free;
-++	__le32 iram_free;
-++} __packed;
-++
-++struct wmi_10_2_pdev_stats {
-++	struct wmi_pdev_stats_base base;
-++	struct wmi_pdev_stats_tx tx;
-++	__le32 mc_drop;
-++	struct wmi_pdev_stats_rx rx;
-++	__le32 pdev_rx_timeout;
-++	struct wmi_pdev_stats_mem mem;
-++	struct wmi_pdev_stats_peer peer;
-++	struct wmi_pdev_stats_extra extra;
-++} __packed;
-++
-+ /*
-+  * VDEV statistics
-+  * TODO: add all VDEV stats here
-+@@ -2874,19 +3202,43 @@ struct wmi_vdev_stats {
-+  * peer statistics.
-+  * TODO: add more stats
-+  */
-+-struct wmi_peer_stats_old {
-++struct wmi_peer_stats {
-+ 	struct wmi_mac_addr peer_macaddr;
-+ 	__le32 peer_rssi;
-+ 	__le32 peer_tx_rate;
-+ } __packed;
-+ 
-+-struct wmi_peer_stats_10x {
-+-	struct wmi_mac_addr peer_macaddr;
-+-	__le32 peer_rssi;
-+-	__le32 peer_tx_rate;
-++struct wmi_10x_peer_stats {
-++	struct wmi_peer_stats old;
-+ 	__le32 peer_rx_rate;
-+ } __packed;
-+ 
-++struct wmi_10_2_peer_stats {
-++	struct wmi_peer_stats old;
-++	__le32 peer_rx_rate;
-++	__le32 current_per;
-++	__le32 retries;
-++	__le32 tx_rate_count;
-++	__le32 max_4ms_frame_len;
-++	__le32 total_sub_frames;
-++	__le32 tx_bytes;
-++	__le32 num_pkt_loss_overflow[4];
-++	__le32 num_pkt_loss_excess_retry[4];
-++} __packed;
-++
-++struct wmi_10_2_4_peer_stats {
-++	struct wmi_10_2_peer_stats common;
-++	__le32 unknown_value; /* FIXME: what is this word? */
-++} __packed;
-++
-++struct wmi_10_2_pdev_ext_stats {
-++	__le32 rx_rssi_comb;
-++	__le32 rx_rssi[4];
-++	__le32 rx_mcs[10];
-++	__le32 tx_mcs[10];
-++	__le32 ack_rssi;
-++} __packed;
-++
-+ struct wmi_vdev_create_cmd {
-+ 	__le32 vdev_id;
-+ 	__le32 vdev_type;
-+@@ -3387,8 +3739,21 @@ enum wmi_10x_vdev_param {
-+ 	WMI_10X_VDEV_PARAM_ENABLE_RTSCTS,
-+ 
-+ 	WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
-++
-++	/* following are available as of firmware 10.2 */
-++	WMI_10X_VDEV_PARAM_TX_ENCAP_TYPE,
-++	WMI_10X_VDEV_PARAM_CABQ_MAXDUR,
-++	WMI_10X_VDEV_PARAM_MFPTEST_SET,
-++	WMI_10X_VDEV_PARAM_RTS_FIXED_RATE,
-++	WMI_10X_VDEV_PARAM_VHT_SGIMASK,
-++	WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
-+ };
-+ 
-++#define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
-++#define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
-++#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
-++#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
-++
-+ /* slot time long */
-+ #define WMI_VDEV_SLOT_TIME_LONG		0x1
-+ /* slot time short */
-+@@ -3444,6 +3809,98 @@ struct wmi_vdev_simple_event {
-+ /* unsupported VDEV combination */
-+ #define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED	0x2
-+ 
-++/* TODO: please add more comments if you have in-depth information */
-++struct wmi_vdev_spectral_conf_cmd {
-++	__le32 vdev_id;
-++
-++	/* number of fft samples to send (0 for infinite) */
-++	__le32 scan_count;
-++	__le32 scan_period;
-++	__le32 scan_priority;
-++
-++	/* number of bins in the FFT: 2^(fft_size - bin_scale) */
-++	__le32 scan_fft_size;
-++	__le32 scan_gc_ena;
-++	__le32 scan_restart_ena;
-++	__le32 scan_noise_floor_ref;
-++	__le32 scan_init_delay;
-++	__le32 scan_nb_tone_thr;
-++	__le32 scan_str_bin_thr;
-++	__le32 scan_wb_rpt_mode;
-++	__le32 scan_rssi_rpt_mode;
-++	__le32 scan_rssi_thr;
-++	__le32 scan_pwr_format;
-++
-++	/* rpt_mode: Format of FFT report to software for spectral scan
-++	 * triggered FFTs:
-++	 *	0: No FFT report (only spectral scan summary report)
-++	 *	1: 2-dword summary of metrics for each completed FFT + spectral
-++	 *	   scan	summary report
-++	 *	2: 2-dword summary of metrics for each completed FFT +
-++	 *	   1x- oversampled bins(in-band) per FFT + spectral scan summary
-++	 *	   report
-++	 *	3: 2-dword summary of metrics for each completed FFT +
-++	 *	   2x- oversampled bins	(all) per FFT + spectral scan summary
-++	 */
-++	__le32 scan_rpt_mode;
-++	__le32 scan_bin_scale;
-++	__le32 scan_dbm_adj;
-++	__le32 scan_chn_mask;
-++} __packed;
-++
-++struct wmi_vdev_spectral_conf_arg {
-++	u32 vdev_id;
-++	u32 scan_count;
-++	u32 scan_period;
-++	u32 scan_priority;
-++	u32 scan_fft_size;
-++	u32 scan_gc_ena;
-++	u32 scan_restart_ena;
-++	u32 scan_noise_floor_ref;
-++	u32 scan_init_delay;
-++	u32 scan_nb_tone_thr;
-++	u32 scan_str_bin_thr;
-++	u32 scan_wb_rpt_mode;
-++	u32 scan_rssi_rpt_mode;
-++	u32 scan_rssi_thr;
-++	u32 scan_pwr_format;
-++	u32 scan_rpt_mode;
-++	u32 scan_bin_scale;
-++	u32 scan_dbm_adj;
-++	u32 scan_chn_mask;
-++};
-++
-++#define WMI_SPECTRAL_ENABLE_DEFAULT              0
-++#define WMI_SPECTRAL_COUNT_DEFAULT               0
-++#define WMI_SPECTRAL_PERIOD_DEFAULT             35
-++#define WMI_SPECTRAL_PRIORITY_DEFAULT            1
-++#define WMI_SPECTRAL_FFT_SIZE_DEFAULT            7
-++#define WMI_SPECTRAL_GC_ENA_DEFAULT              1
-++#define WMI_SPECTRAL_RESTART_ENA_DEFAULT         0
-++#define WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT   -96
-++#define WMI_SPECTRAL_INIT_DELAY_DEFAULT         80
-++#define WMI_SPECTRAL_NB_TONE_THR_DEFAULT        12
-++#define WMI_SPECTRAL_STR_BIN_THR_DEFAULT         8
-++#define WMI_SPECTRAL_WB_RPT_MODE_DEFAULT         0
-++#define WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT       0
-++#define WMI_SPECTRAL_RSSI_THR_DEFAULT         0xf0
-++#define WMI_SPECTRAL_PWR_FORMAT_DEFAULT          0
-++#define WMI_SPECTRAL_RPT_MODE_DEFAULT            2
-++#define WMI_SPECTRAL_BIN_SCALE_DEFAULT           1
-++#define WMI_SPECTRAL_DBM_ADJ_DEFAULT             1
-++#define WMI_SPECTRAL_CHN_MASK_DEFAULT            1
-++
-++struct wmi_vdev_spectral_enable_cmd {
-++	__le32 vdev_id;
-++	__le32 trigger_cmd;
-++	__le32 enable_cmd;
-++} __packed;
-++
-++#define WMI_SPECTRAL_TRIGGER_CMD_TRIGGER  1
-++#define WMI_SPECTRAL_TRIGGER_CMD_CLEAR    2
-++#define WMI_SPECTRAL_ENABLE_CMD_ENABLE    1
-++#define WMI_SPECTRAL_ENABLE_CMD_DISABLE   2
-++
-+ /* Beacon processing related command and event structures */
-+ struct wmi_bcn_tx_hdr {
-+ 	__le32 vdev_id;
-+@@ -3470,6 +3927,11 @@ enum wmi_bcn_tx_ref_flags {
-+ 	WMI_BCN_TX_REF_FLAG_DELIVER_CAB = 0x2,
-+ };
-+ 
-++/* TODO: It is unclear why "no antenna" works while any other seemingly valid
-++ * chainmask yields no beacons on the air at all.
-++ */
-++#define WMI_BCN_TX_REF_DEF_ANTENNA 0
-++
-+ struct wmi_bcn_tx_ref_cmd {
-+ 	__le32 vdev_id;
-+ 	__le32 data_len;
-+@@ -3481,6 +3943,8 @@ struct wmi_bcn_tx_ref_cmd {
-+ 	__le32 frame_control;
-+ 	/* to control CABQ traffic: WMI_BCN_TX_REF_FLAG_ */
-+ 	__le32 flags;
-++	/* introduced in 10.2 */
-++	__le32 antenna_mask;
-+ } __packed;
-+ 
-+ /* Beacon filter */
-+@@ -3633,6 +4097,13 @@ enum wmi_sta_ps_param_pspoll_count {
-+ 	 * Values greater than 0 indicate the maximum numer of PS-Poll frames
-+ 	 * FW will send before waking up.
-+ 	 */
-++
-++	/* When u-APSD is enabled the firmware will be very reluctant to exit
-++	 * STA PS. This could result in very poor Rx performance with STA doing
-++	 * PS-Poll for each and every buffered frame. This value is a bit
-++	 * arbitrary.
-++	 */
-++	WMI_STA_PS_PSPOLL_COUNT_UAPSD = 3,
-+ };
-+ 
-+ /*
-+@@ -3658,6 +4129,30 @@ enum wmi_sta_ps_param_uapsd {
-+ 	WMI_STA_PS_UAPSD_AC3_TRIGGER_EN  = (1 << 7),
-+ };
-+ 
-++#define WMI_STA_UAPSD_MAX_INTERVAL_MSEC UINT_MAX
-++
-++struct wmi_sta_uapsd_auto_trig_param {
-++	__le32 wmm_ac;
-++	__le32 user_priority;
-++	__le32 service_interval;
-++	__le32 suspend_interval;
-++	__le32 delay_interval;
-++};
-++
-++struct wmi_sta_uapsd_auto_trig_cmd_fixed_param {
-++	__le32 vdev_id;
-++	struct wmi_mac_addr peer_macaddr;
-++	__le32 num_ac;
-++};
-++
-++struct wmi_sta_uapsd_auto_trig_arg {
-++	u32 wmm_ac;
-++	u32 user_priority;
-++	u32 service_interval;
-++	u32 suspend_interval;
-++	u32 delay_interval;
-++};
-++
-+ enum wmi_sta_powersave_param {
-+ 	/*
-+ 	 * Controls how frames are retrievd from AP while STA is sleeping
-+@@ -3823,7 +4318,7 @@ struct wmi_bcn_info {
-+ 
-+ struct wmi_host_swba_event {
-+ 	__le32 vdev_map;
-+-	struct wmi_bcn_info bcn_info[1];
-++	struct wmi_bcn_info bcn_info[0];
-+ } __packed;
-+ 
-+ #define WMI_MAX_AP_VDEV 16
-+@@ -3833,7 +4328,6 @@ struct wmi_tbtt_offset_event {
-+ 	__le32 tbttoffset_list[WMI_MAX_AP_VDEV];
-+ } __packed;
-+ 
-+-
-+ struct wmi_peer_create_cmd {
-+ 	__le32 vdev_id;
-+ 	struct wmi_mac_addr peer_macaddr;
-+@@ -3951,7 +4445,8 @@ enum wmi_peer_param {
-+ 	WMI_PEER_AUTHORIZE  = 0x3,
-+ 	WMI_PEER_CHAN_WIDTH = 0x4,
-+ 	WMI_PEER_NSS        = 0x5,
-+-	WMI_PEER_USE_4ADDR  = 0x6
-++	WMI_PEER_USE_4ADDR  = 0x6,
-++	WMI_PEER_DUMMY_VAR  = 0xff, /* dummy parameter for STA PS workaround */
-+ };
-+ 
-+ struct wmi_peer_set_param_cmd {
-+@@ -4029,7 +4524,7 @@ struct wmi_peer_set_q_empty_callback_cmd
-+ #define WMI_PEER_SPATIAL_MUX    0x00200000
-+ #define WMI_PEER_VHT            0x02000000
-+ #define WMI_PEER_80MHZ          0x04000000
-+-#define WMI_PEER_PMF            0x08000000
-++#define WMI_PEER_VHT_2G         0x08000000
-+ 
-+ /*
-+  * Peer rate capabilities.
-+@@ -4053,7 +4548,7 @@ struct wmi_peer_set_q_empty_callback_cmd
-+ /* Maximum listen interval supported by hw in units of beacon interval */
-+ #define ATH10K_MAX_HW_LISTEN_INTERVAL 5
-+ 
-+-struct wmi_peer_assoc_complete_cmd {
-++struct wmi_common_peer_assoc_complete_cmd {
-+ 	struct wmi_mac_addr peer_macaddr;
-+ 	__le32 vdev_id;
-+ 	__le32 peer_new_assoc; /* 1=assoc, 0=reassoc */
-+@@ -4071,11 +4566,30 @@ struct wmi_peer_assoc_complete_cmd {
-+ 	__le32 peer_vht_caps;
-+ 	__le32 peer_phymode;
-+ 	struct wmi_vht_rate_set peer_vht_rates;
-++};
-++
-++struct wmi_main_peer_assoc_complete_cmd {
-++	struct wmi_common_peer_assoc_complete_cmd cmd;
-++
-+ 	/* HT Operation Element of the peer. Five bytes packed in 2
-+ 	 *  INT32 array and filled from lsb to msb. */
-+ 	__le32 peer_ht_info[2];
-+ } __packed;
-+ 
-++struct wmi_10_1_peer_assoc_complete_cmd {
-++	struct wmi_common_peer_assoc_complete_cmd cmd;
-++} __packed;
-++
-++#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_LSB 0
-++#define WMI_PEER_ASSOC_INFO0_MAX_MCS_IDX_MASK 0x0f
-++#define WMI_PEER_ASSOC_INFO0_MAX_NSS_LSB 4
-++#define WMI_PEER_ASSOC_INFO0_MAX_NSS_MASK 0xf0
-++
-++struct wmi_10_2_peer_assoc_complete_cmd {
-++	struct wmi_common_peer_assoc_complete_cmd cmd;
-++	__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
-++} __packed;
-++
-+ struct wmi_peer_assoc_complete_arg {
-+ 	u8 addr[ETH_ALEN];
-+ 	u32 vdev_id;
-+@@ -4161,6 +4675,11 @@ enum wmi_sta_keepalive_method {
-+ 	WMI_STA_KEEPALIVE_METHOD_UNSOLICITATED_ARP_RESPONSE = 2,
-+ };
-+ 
-++#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
-++
-++/* Firmware crashes if keepalive interval exceeds this limit */
-++#define WMI_STA_KEEPALIVE_INTERVAL_MAX_SECONDS 0xffff
-++
-+ /* note: ip4 addresses are in network byte order, i.e. big endian */
-+ struct wmi_sta_keepalive_arp_resp {
-+ 	__be32 src_ip4_addr;
-+@@ -4176,6 +4695,16 @@ struct wmi_sta_keepalive_cmd {
-+ 	struct wmi_sta_keepalive_arp_resp arp_resp;
-+ } __packed;
-+ 
-++struct wmi_sta_keepalive_arg {
-++	u32 vdev_id;
-++	u32 enabled;
-++	u32 method;
-++	u32 interval;
-++	__be32 src_ip4_addr;
-++	__be32 dest_ip4_addr;
-++	const u8 dest_mac_addr[ETH_ALEN];
-++};
-++
-+ enum wmi_force_fw_hang_type {
-+ 	WMI_FORCE_FW_HANG_ASSERT = 1,
-+ 	WMI_FORCE_FW_HANG_NO_DETECT,
-+@@ -4240,7 +4769,6 @@ struct wmi_dbglog_cfg_cmd {
-+ 	__le32 config_valid;
-+ } __packed;
-+ 
-+-#define ATH10K_RTS_MAX		2347
-+ #define ATH10K_FRAGMT_THRESHOLD_MIN	540
-+ #define ATH10K_FRAGMT_THRESHOLD_MAX	2346
-+ 
-+@@ -4251,72 +4779,170 @@ struct wmi_dbglog_cfg_cmd {
-+ /* By default disable power save for IBSS */
-+ #define ATH10K_DEFAULT_ATIM 0
-+ 
-++#define WMI_MAX_MEM_REQS 16
-++
-++struct wmi_scan_ev_arg {
-++	__le32 event_type; /* %WMI_SCAN_EVENT_ */
-++	__le32 reason; /* %WMI_SCAN_REASON_ */
-++	__le32 channel_freq; /* only valid for WMI_SCAN_EVENT_FOREIGN_CHANNEL */
-++	__le32 scan_req_id;
-++	__le32 scan_id;
-++	__le32 vdev_id;
-++};
-++
-++struct wmi_mgmt_rx_ev_arg {
-++	__le32 channel;
-++	__le32 snr;
-++	__le32 rate;
-++	__le32 phy_mode;
-++	__le32 buf_len;
-++	__le32 status; /* %WMI_RX_STATUS_ */
-++};
-++
-++struct wmi_ch_info_ev_arg {
-++	__le32 err_code;
-++	__le32 freq;
-++	__le32 cmd_flags;
-++	__le32 noise_floor;
-++	__le32 rx_clear_count;
-++	__le32 cycle_count;
-++};
-++
-++struct wmi_vdev_start_ev_arg {
-++	__le32 vdev_id;
-++	__le32 req_id;
-++	__le32 resp_type; /* %WMI_VDEV_RESP_ */
-++	__le32 status;
-++};
-++
-++struct wmi_peer_kick_ev_arg {
-++	const u8 *mac_addr;
-++};
-++
-++struct wmi_swba_ev_arg {
-++	__le32 vdev_map;
-++	const struct wmi_tim_info *tim_info[WMI_MAX_AP_VDEV];
-++	const struct wmi_p2p_noa_info *noa_info[WMI_MAX_AP_VDEV];
-++};
-++
-++struct wmi_phyerr_ev_arg {
-++	__le32 num_phyerrs;
-++	__le32 tsf_l32;
-++	__le32 tsf_u32;
-++	__le32 buf_len;
-++	const struct wmi_phyerr *phyerrs;
-++};
-++
-++struct wmi_svc_rdy_ev_arg {
-++	__le32 min_tx_power;
-++	__le32 max_tx_power;
-++	__le32 ht_cap;
-++	__le32 vht_cap;
-++	__le32 sw_ver0;
-++	__le32 sw_ver1;
-++	__le32 fw_build;
-++	__le32 phy_capab;
-++	__le32 num_rf_chains;
-++	__le32 eeprom_rd;
-++	__le32 num_mem_reqs;
-++	const __le32 *service_map;
-++	size_t service_map_len;
-++	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
-++};
-++
-++struct wmi_rdy_ev_arg {
-++	__le32 sw_version;
-++	__le32 abi_version;
-++	__le32 status;
-++	const u8 *mac_addr;
-++};
-++
-++struct wmi_pdev_temperature_event {
-++	/* temperature value in Celcius degree */
-++	__le32 temperature;
-++} __packed;
-++
-+ struct ath10k;
-+ struct ath10k_vif;
-++struct ath10k_fw_stats_pdev;
-++struct ath10k_fw_stats_peer;
-+ 
-+ int ath10k_wmi_attach(struct ath10k *ar);
-+ void ath10k_wmi_detach(struct ath10k *ar);
-+ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
-+ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
-+ 
-+-int ath10k_wmi_connect_htc_service(struct ath10k *ar);
-+-int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
-+-				const struct wmi_channel_arg *);
-+-int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
-+-int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
-+-int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
-+-				  u16 rd5g, u16 ctl2g, u16 ctl5g,
-+-				  enum wmi_dfs_region dfs_reg);
-+-int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value);
-+-int ath10k_wmi_cmd_init(struct ath10k *ar);
-+-int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *);
-++struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
-++int ath10k_wmi_connect(struct ath10k *ar);
-++
-++struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
-++int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
-++int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
-++			       u32 cmd_id);
-+ void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *);
-+-int ath10k_wmi_stop_scan(struct ath10k *ar,
-+-			 const struct wmi_stop_scan_arg *arg);
-+-int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
-+-			   enum wmi_vdev_type type,
-+-			   enum wmi_vdev_subtype subtype,
-+-			   const u8 macaddr[ETH_ALEN]);
-+-int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id);
-+-int ath10k_wmi_vdev_start(struct ath10k *ar,
-+-			  const struct wmi_vdev_start_request_arg *);
-+-int ath10k_wmi_vdev_restart(struct ath10k *ar,
-+-			    const struct wmi_vdev_start_request_arg *);
-+-int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id);
-+-int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
-+-		       const u8 *bssid);
-+-int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id);
-+-int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
-+-			      u32 param_id, u32 param_value);
-+-int ath10k_wmi_vdev_install_key(struct ath10k *ar,
-+-				const struct wmi_vdev_install_key_arg *arg);
-+-int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
-+-		    const u8 peer_addr[ETH_ALEN]);
-+-int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
-+-		    const u8 peer_addr[ETH_ALEN]);
-+-int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
-+-		   const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
-+-int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
-+-			      const u8 *peer_addr,
-+-			      enum wmi_peer_param param_id, u32 param_value);
-+-int ath10k_wmi_peer_assoc(struct ath10k *ar,
-+-			  const struct wmi_peer_assoc_complete_arg *arg);
-+-int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
-+-			  enum wmi_sta_ps_mode psmode);
-+-int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
-+-				enum wmi_sta_powersave_param param_id,
-+-				u32 value);
-+-int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-+-			       enum wmi_ap_ps_peer_param param_id, u32 value);
-+-int ath10k_wmi_scan_chan_list(struct ath10k *ar,
-+-			      const struct wmi_scan_chan_list_arg *arg);
-+-int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
-+-int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
-+-			const struct wmi_pdev_set_wmm_params_arg *arg);
-+-int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
-+-int ath10k_wmi_force_fw_hang(struct ath10k *ar,
-+-			     enum wmi_force_fw_hang_type type, u32 delay_ms);
-+-int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
-+-int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
-++
-++void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src,
-++				     struct ath10k_fw_stats_pdev *dst);
-++void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
-++				   struct ath10k_fw_stats_pdev *dst);
-++void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
-++				   struct ath10k_fw_stats_pdev *dst);
-++void ath10k_wmi_pull_pdev_stats_extra(const struct wmi_pdev_stats_extra *src,
-++				      struct ath10k_fw_stats_pdev *dst);
-++void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
-++				struct ath10k_fw_stats_peer *dst);
-++void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
-++				    struct wmi_host_mem_chunks *chunks);
-++void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
-++				      const struct wmi_start_scan_arg *arg);
-++void ath10k_wmi_set_wmm_param(struct wmi_wmm_params *params,
-++			      const struct wmi_wmm_params_arg *arg);
-++void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
-++				const struct wmi_channel_arg *arg);
-++int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
-++
-++int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
-++int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
-++int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_dfs(struct ath10k *ar,
-++			  const struct wmi_phyerr *phyerr, u64 tsf);
-++void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
-++				    const struct wmi_phyerr *phyerr,
-++				    u64 tsf);
-++void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_debug_print(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
-++					     struct sk_buff *skb);
-++void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
-++					     struct sk_buff *skb);
-++void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
-++					 struct sk_buff *skb);
-++void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_delba_complete(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_addba_complete(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
-++						struct sk_buff *skb);
-++void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb);
-++void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
-++int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
-+ 
-+ #endif /* _WMI_H_ */
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/spectral.c
-+@@ -0,0 +1,552 @@
-++/*
-++ * Copyright (c) 2013 Qualcomm Atheros, Inc.
-++ *
-++ * 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/relay.h>
-++#include "core.h"
-++#include "debug.h"
-++#include "wmi-ops.h"
-++
-++static void send_fft_sample(struct ath10k *ar,
-++			    const struct fft_sample_tlv *fft_sample_tlv)
-++{
-++	int length;
-++
-++	if (!ar->spectral.rfs_chan_spec_scan)
-++		return;
-++
-++	length = __be16_to_cpu(fft_sample_tlv->length) +
-++		 sizeof(*fft_sample_tlv);
-++	relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
-++}
-++
-++static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
-++			   u8 *data)
-++{
-++	int dc_pos;
-++	u8 max_exp;
-++
-++	dc_pos = bin_len / 2;
-++
-++	/* peak index outside of bins */
-++	if (dc_pos < max_index || -dc_pos >= max_index)
-++		return 0;
-++
-++	for (max_exp = 0; max_exp < 8; max_exp++) {
-++		if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
-++			break;
-++	}
-++
-++	/* max_exp not found */
-++	if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
-++		return 0;
-++
-++	return max_exp;
-++}
-++
-++int ath10k_spectral_process_fft(struct ath10k *ar,
-++				const struct wmi_phyerr *phyerr,
-++				const struct phyerr_fft_report *fftr,
-++				size_t bin_len, u64 tsf)
-++{
-++	struct fft_sample_ath10k *fft_sample;
-++	u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
-++	u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
-++	u32 reg0, reg1;
-++	u8 chain_idx, *bins;
-++	int dc_pos;
-++
-++	fft_sample = (struct fft_sample_ath10k *)&buf;
-++
-++	if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
-++		return -EINVAL;
-++
-++	reg0 = __le32_to_cpu(fftr->reg0);
-++	reg1 = __le32_to_cpu(fftr->reg1);
-++
-++	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
-++	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
-++	fft_sample->tlv.length = __cpu_to_be16(length);
-++
-++	/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
-++	 * but the results/plots suggest that its actually 22/44/88 MHz.
-++	 */
-++	switch (phyerr->chan_width_mhz) {
-++	case 20:
-++		fft_sample->chan_width_mhz = 22;
-++		break;
-++	case 40:
-++		fft_sample->chan_width_mhz = 44;
-++		break;
-++	case 80:
-++		/* TODO: As experiments with an analogue sender and various
-++		 * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
-++		 * show, the particular configuration of 80 MHz/64 bins does
-++		 * not match with the other smaples at all. Until the reason
-++		 * for that is found, don't report these samples.
-++		 */
-++		if (bin_len == 64)
-++			return -EINVAL;
-++		fft_sample->chan_width_mhz = 88;
-++		break;
-++	default:
-++		fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
-++	}
-++
-++	fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
-++	fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
-++
-++	peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
-++	fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
-++	fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
-++	fft_sample->rssi = phyerr->rssi_combined;
-++
-++	total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
-++	base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
-++	fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
-++	fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
-++
-++	freq1 = __le16_to_cpu(phyerr->freq1);
-++	freq2 = __le16_to_cpu(phyerr->freq2);
-++	fft_sample->freq1 = __cpu_to_be16(freq1);
-++	fft_sample->freq2 = __cpu_to_be16(freq2);
-++
-++	chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
-++
-++	fft_sample->noise = __cpu_to_be16(
-++			__le16_to_cpu(phyerr->nf_chains[chain_idx]));
-++
-++	bins = (u8 *)fftr;
-++	bins += sizeof(*fftr);
-++
-++	fft_sample->tsf = __cpu_to_be64(tsf);
-++
-++	/* max_exp has been directly reported by previous hardware (ath9k),
-++	 * maybe its possible to get it by other means?
-++	 */
-++	fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
-++					  bin_len, bins);
-++
-++	memcpy(fft_sample->data, bins, bin_len);
-++
-++	/* DC value (value in the middle) is the blind spot of the spectral
-++	 * sample and invalid, interpolate it.
-++	 */
-++	dc_pos = bin_len / 2;
-++	fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
-++				    fft_sample->data[dc_pos - 1]) / 2;
-++
-++	send_fft_sample(ar, &fft_sample->tlv);
-++
-++	return 0;
-++}
-++
-++static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
-++{
-++	struct ath10k_vif *arvif;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	if (list_empty(&ar->arvifs))
-++		return NULL;
-++
-++	/* if there already is a vif doing spectral, return that. */
-++	list_for_each_entry(arvif, &ar->arvifs, list)
-++		if (arvif->spectral_enabled)
-++			return arvif;
-++
-++	/* otherwise, return the first vif. */
-++	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
-++}
-++
-++static int ath10k_spectral_scan_trigger(struct ath10k *ar)
-++{
-++	struct ath10k_vif *arvif;
-++	int res;
-++	int vdev_id;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	arvif = ath10k_get_spectral_vdev(ar);
-++	if (!arvif)
-++		return -ENODEV;
-++	vdev_id = arvif->vdev_id;
-++
-++	if (ar->spectral.mode == SPECTRAL_DISABLED)
-++		return 0;
-++
-++	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
-++					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
-++					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
-++	if (res < 0)
-++		return res;
-++
-++	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
-++					      WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
-++					      WMI_SPECTRAL_ENABLE_CMD_ENABLE);
-++	if (res < 0)
-++		return res;
-++
-++	return 0;
-++}
-++
-++static int ath10k_spectral_scan_config(struct ath10k *ar,
-++				       enum ath10k_spectral_mode mode)
-++{
-++	struct wmi_vdev_spectral_conf_arg arg;
-++	struct ath10k_vif *arvif;
-++	int vdev_id, count, res = 0;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	arvif = ath10k_get_spectral_vdev(ar);
-++	if (!arvif)
-++		return -ENODEV;
-++
-++	vdev_id = arvif->vdev_id;
-++
-++	arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
-++	ar->spectral.mode = mode;
-++
-++	res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
-++					      WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
-++					      WMI_SPECTRAL_ENABLE_CMD_DISABLE);
-++	if (res < 0) {
-++		ath10k_warn(ar, "failed to enable spectral scan: %d\n", res);
-++		return res;
-++	}
-++
-++	if (mode == SPECTRAL_DISABLED)
-++		return 0;
-++
-++	if (mode == SPECTRAL_BACKGROUND)
-++		count = WMI_SPECTRAL_COUNT_DEFAULT;
-++	else
-++		count = max_t(u8, 1, ar->spectral.config.count);
-++
-++	arg.vdev_id = vdev_id;
-++	arg.scan_count = count;
-++	arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
-++	arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
-++	arg.scan_fft_size = ar->spectral.config.fft_size;
-++	arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
-++	arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
-++	arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
-++	arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
-++	arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
-++	arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
-++	arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
-++	arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
-++	arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
-++	arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
-++	arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
-++	arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
-++	arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
-++	arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
-++
-++	res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
-++	if (res < 0) {
-++		ath10k_warn(ar, "failed to configure spectral scan: %d\n", res);
-++		return res;
-++	}
-++
-++	return 0;
-++}
-++
-++static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
-++				       size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	char *mode = "";
-++	unsigned int len;
-++	enum ath10k_spectral_mode spectral_mode;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	spectral_mode = ar->spectral.mode;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	switch (spectral_mode) {
-++	case SPECTRAL_DISABLED:
-++		mode = "disable";
-++		break;
-++	case SPECTRAL_BACKGROUND:
-++		mode = "background";
-++		break;
-++	case SPECTRAL_MANUAL:
-++		mode = "manual";
-++		break;
-++	}
-++
-++	len = strlen(mode);
-++	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
-++}
-++
-++static ssize_t write_file_spec_scan_ctl(struct file *file,
-++					const char __user *user_buf,
-++					size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	char buf[32];
-++	ssize_t len;
-++	int res;
-++
-++	len = min(count, sizeof(buf) - 1);
-++	if (copy_from_user(buf, user_buf, len))
-++		return -EFAULT;
-++
-++	buf[len] = '\0';
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (strncmp("trigger", buf, 7) == 0) {
-++		if (ar->spectral.mode == SPECTRAL_MANUAL ||
-++		    ar->spectral.mode == SPECTRAL_BACKGROUND) {
-++			/* reset the configuration to adopt possibly changed
-++			 * debugfs parameters
-++			 */
-++			res = ath10k_spectral_scan_config(ar,
-++							  ar->spectral.mode);
-++			if (res < 0) {
-++				ath10k_warn(ar, "failed to reconfigure spectral scan: %d\n",
-++					    res);
-++			}
-++			res = ath10k_spectral_scan_trigger(ar);
-++			if (res < 0) {
-++				ath10k_warn(ar, "failed to trigger spectral scan: %d\n",
-++					    res);
-++			}
-++		} else {
-++			res = -EINVAL;
-++		}
-++	} else if (strncmp("background", buf, 9) == 0) {
-++		res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
-++	} else if (strncmp("manual", buf, 6) == 0) {
-++		res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
-++	} else if (strncmp("disable", buf, 7) == 0) {
-++		res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
-++	} else {
-++		res = -EINVAL;
-++	}
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	if (res < 0)
-++		return res;
-++
-++	return count;
-++}
-++
-++static const struct file_operations fops_spec_scan_ctl = {
-++	.read = read_file_spec_scan_ctl,
-++	.write = write_file_spec_scan_ctl,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t read_file_spectral_count(struct file *file,
-++					char __user *user_buf,
-++					size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	char buf[32];
-++	unsigned int len;
-++	u8 spectral_count;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	spectral_count = ar->spectral.config.count;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	len = sprintf(buf, "%d\n", spectral_count);
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t write_file_spectral_count(struct file *file,
-++					 const char __user *user_buf,
-++					 size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	unsigned long val;
-++	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, &val))
-++		return -EINVAL;
-++
-++	if (val < 0 || val > 255)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	ar->spectral.config.count = val;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return count;
-++}
-++
-++static const struct file_operations fops_spectral_count = {
-++	.read = read_file_spectral_count,
-++	.write = write_file_spectral_count,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t read_file_spectral_bins(struct file *file,
-++				       char __user *user_buf,
-++				       size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	char buf[32];
-++	unsigned int len, bins, fft_size, bin_scale;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	fft_size = ar->spectral.config.fft_size;
-++	bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
-++	bins = 1 << (fft_size - bin_scale);
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	len = sprintf(buf, "%d\n", bins);
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t write_file_spectral_bins(struct file *file,
-++					const char __user *user_buf,
-++					size_t count, loff_t *ppos)
-++{
-++	struct ath10k *ar = file->private_data;
-++	unsigned long val;
-++	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, &val))
-++		return -EINVAL;
-++
-++	if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
-++		return -EINVAL;
-++
-++	if (!is_power_of_2(val))
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	ar->spectral.config.fft_size = ilog2(val);
-++	ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return count;
-++}
-++
-++static const struct file_operations fops_spectral_bins = {
-++	.read = read_file_spectral_bins,
-++	.write = write_file_spectral_bins,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static struct dentry *create_buf_file_handler(const char *filename,
-++					      struct dentry *parent,
-++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
-++					      umode_t mode,
-++#else
-++					      int mode,
-++#endif
-++					      struct rchan_buf *buf,
-++					      int *is_global)
-++{
-++	struct dentry *buf_file;
-++
-++	buf_file = debugfs_create_file(filename, mode, parent, buf,
-++				       &relay_file_operations);
-++	*is_global = 1;
-++	return buf_file;
-++}
-++
-++static int remove_buf_file_handler(struct dentry *dentry)
-++{
-++	debugfs_remove(dentry);
-++
-++	return 0;
-++}
-++
-++static struct rchan_callbacks rfs_spec_scan_cb = {
-++	.create_buf_file = create_buf_file_handler,
-++	.remove_buf_file = remove_buf_file_handler,
-++};
-++
-++int ath10k_spectral_start(struct ath10k *ar)
-++{
-++	struct ath10k_vif *arvif;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	list_for_each_entry(arvif, &ar->arvifs, list)
-++		arvif->spectral_enabled = 0;
-++
-++	ar->spectral.mode = SPECTRAL_DISABLED;
-++	ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
-++	ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
-++
-++	return 0;
-++}
-++
-++int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
-++{
-++	if (!arvif->spectral_enabled)
-++		return 0;
-++
-++	return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
-++}
-++
-++int ath10k_spectral_create(struct ath10k *ar)
-++{
-++	ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
-++						     ar->debug.debugfs_phy,
-++						     1024, 256,
-++						     &rfs_spec_scan_cb, NULL);
-++	debugfs_create_file("spectral_scan_ctl",
-++			    S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar,
-++			    &fops_spec_scan_ctl);
-++	debugfs_create_file("spectral_count",
-++			    S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar,
-++			    &fops_spectral_count);
-++	debugfs_create_file("spectral_bins",
-++			    S_IRUSR | S_IWUSR,
-++			    ar->debug.debugfs_phy, ar,
-++			    &fops_spectral_bins);
-++
-++	return 0;
-++}
-++
-++void ath10k_spectral_destroy(struct ath10k *ar)
-++{
-++	if (ar->spectral.rfs_chan_spec_scan) {
-++		relay_close(ar->spectral.rfs_chan_spec_scan);
-++		ar->spectral.rfs_chan_spec_scan = NULL;
-++	}
-++}
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/spectral.h
-+@@ -0,0 +1,90 @@
-++/*
-++ * Copyright (c) 2013 Qualcomm Atheros, Inc.
-++ *
-++ * 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 SPECTRAL_H
-++#define SPECTRAL_H
-++
-++#include "../spectral_common.h"
-++
-++/**
-++ * struct ath10k_spec_scan - parameters for Atheros spectral scan
-++ *
-++ * @count: number of scan results requested for manual mode
-++ * @fft_size: number of bins to be requested = 2^(fft_size - bin_scale)
-++ */
-++struct ath10k_spec_scan {
-++	u8 count;
-++	u8 fft_size;
-++};
-++
-++/* enum ath10k_spectral_mode:
-++ *
-++ * @SPECTRAL_DISABLED: spectral mode is disabled
-++ * @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
-++ *	something else.
-++ * @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
-++ *	is performed manually.
-++ */
-++enum ath10k_spectral_mode {
-++	SPECTRAL_DISABLED = 0,
-++	SPECTRAL_BACKGROUND,
-++	SPECTRAL_MANUAL,
-++};
-++
-++#ifdef CPTCFG_ATH10K_DEBUGFS
-++
-++int ath10k_spectral_process_fft(struct ath10k *ar,
-++				const struct wmi_phyerr *phyerr,
-++				const struct phyerr_fft_report *fftr,
-++				size_t bin_len, u64 tsf);
-++int ath10k_spectral_start(struct ath10k *ar);
-++int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
-++int ath10k_spectral_create(struct ath10k *ar);
-++void ath10k_spectral_destroy(struct ath10k *ar);
-++
-++#else
-++
-++static inline int
-++ath10k_spectral_process_fft(struct ath10k *ar,
-++			    const struct wmi_phyerr *phyerr,
-++			    const struct phyerr_fft_report *fftr,
-++			    size_t bin_len, u64 tsf)
-++{
-++	return 0;
-++}
-++
-++static inline int ath10k_spectral_start(struct ath10k *ar)
-++{
-++	return 0;
-++}
-++
-++static inline int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
-++{
-++	return 0;
-++}
-++
-++static inline int ath10k_spectral_create(struct ath10k *ar)
-++{
-++	return 0;
-++}
-++
-++static inline void ath10k_spectral_destroy(struct ath10k *ar)
-++{
-++}
-++
-++#endif /* CPTCFG_ATH10K_DEBUGFS */
-++
-++#endif /* SPECTRAL_H */
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/testmode.c
-+@@ -0,0 +1,385 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 "testmode.h"
-++
-++#include <net/netlink.h>
-++#include <linux/firmware.h>
-++
-++#include "debug.h"
-++#include "wmi.h"
-++#include "hif.h"
-++#include "hw.h"
-++
-++#include "testmode_i.h"
-++
-++static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
-++	[ATH10K_TM_ATTR_CMD]		= { .type = NLA_U32 },
-++	[ATH10K_TM_ATTR_DATA]		= { .type = NLA_BINARY,
-++					    .len = ATH10K_TM_DATA_MAX_LEN },
-++	[ATH10K_TM_ATTR_WMI_CMDID]	= { .type = NLA_U32 },
-++	[ATH10K_TM_ATTR_VERSION_MAJOR]	= { .type = NLA_U32 },
-++	[ATH10K_TM_ATTR_VERSION_MINOR]	= { .type = NLA_U32 },
-++};
-++
-++/* Returns true if callee consumes the skb and the skb should be discarded.
-++ * Returns false if skb is not used. Does not sleep.
-++ */
-++bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
-++{
-++	struct sk_buff *nl_skb;
-++	bool consumed;
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
-++		   "testmode event wmi cmd_id %d skb %p skb->len %d\n",
-++		   cmd_id, skb, skb->len);
-++
-++	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	if (!ar->testmode.utf_monitor) {
-++		consumed = false;
-++		goto out;
-++	}
-++
-++	/* Only testmode.c should be handling events from utf firmware,
-++	 * otherwise all sort of problems will arise as mac80211 operations
-++	 * are not initialised.
-++	 */
-++	consumed = true;
-++
-++	nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
-++						   2 * sizeof(u32) + skb->len,
-++						   GFP_ATOMIC);
-++	if (!nl_skb) {
-++		ath10k_warn(ar,
-++			    "failed to allocate skb for testmode wmi event\n");
-++		goto out;
-++	}
-++
-++	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
-++	if (ret) {
-++		ath10k_warn(ar,
-++			    "failed to to put testmode wmi event cmd attribute: %d\n",
-++			    ret);
-++		kfree_skb(nl_skb);
-++		goto out;
-++	}
-++
-++	ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
-++	if (ret) {
-++		ath10k_warn(ar,
-++			    "failed to to put testmode wmi even cmd_id: %d\n",
-++			    ret);
-++		kfree_skb(nl_skb);
-++		goto out;
-++	}
-++
-++	ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
-++	if (ret) {
-++		ath10k_warn(ar,
-++			    "failed to copy skb to testmode wmi event: %d\n",
-++			    ret);
-++		kfree_skb(nl_skb);
-++		goto out;
-++	}
-++
-++	cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
-++
-++out:
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	return consumed;
-++}
-++
-++static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
-++{
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
-++		   "testmode cmd get version_major %d version_minor %d\n",
-++		   ATH10K_TESTMODE_VERSION_MAJOR,
-++		   ATH10K_TESTMODE_VERSION_MINOR);
-++
-++	skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
-++						nla_total_size(sizeof(u32)));
-++	if (!skb)
-++		return -ENOMEM;
-++
-++	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
-++			  ATH10K_TESTMODE_VERSION_MAJOR);
-++	if (ret) {
-++		kfree_skb(skb);
-++		return ret;
-++	}
-++
-++	ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
-++			  ATH10K_TESTMODE_VERSION_MINOR);
-++	if (ret) {
-++		kfree_skb(skb);
-++		return ret;
-++	}
-++
-++	return cfg80211_testmode_reply(skb);
-++}
-++
-++static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
-++{
-++	char filename[100];
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state == ATH10K_STATE_UTF) {
-++		ret = -EALREADY;
-++		goto err;
-++	}
-++
-++	/* start utf only when the driver is not in use  */
-++	if (ar->state != ATH10K_STATE_OFF) {
-++		ret = -EBUSY;
-++		goto err;
-++	}
-++
-++	if (WARN_ON(ar->testmode.utf != NULL)) {
-++		/* utf image is already downloaded, it shouldn't be */
-++		ret = -EEXIST;
-++		goto err;
-++	}
-++
-++	snprintf(filename, sizeof(filename), "%s/%s",
-++		 ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
-++
-++	/* load utf firmware image */
-++	ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
-++			    filename, ret);
-++		goto err;
-++	}
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	ar->testmode.utf_monitor = true;
-++
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	BUILD_BUG_ON(sizeof(ar->fw_features) !=
-++		     sizeof(ar->testmode.orig_fw_features));
-++
-++	memcpy(ar->testmode.orig_fw_features, ar->fw_features,
-++	       sizeof(ar->fw_features));
-++	ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
-++
-++	/* utf.bin firmware image does not advertise firmware features. Do
-++	 * an ugly hack where we force the firmware features so that wmi.c
-++	 * will use the correct WMI interface.
-++	 */
-++	memset(ar->fw_features, 0, sizeof(ar->fw_features));
-++	ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
-++
-++	ret = ath10k_hif_power_up(ar);
-++	if (ret) {
-++		ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
-++		ar->state = ATH10K_STATE_OFF;
-++		goto err_fw_features;
-++	}
-++
-++	ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
-++	if (ret) {
-++		ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
-++		ar->state = ATH10K_STATE_OFF;
-++		goto err_power_down;
-++	}
-++
-++	ar->state = ATH10K_STATE_UTF;
-++
-++	ath10k_info(ar, "UTF firmware started\n");
-++
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return 0;
-++
-++err_power_down:
-++	ath10k_hif_power_down(ar);
-++
-++err_fw_features:
-++	/* return the original firmware features */
-++	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
-++	       sizeof(ar->fw_features));
-++	ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
-++
-++	release_firmware(ar->testmode.utf);
-++	ar->testmode.utf = NULL;
-++
-++err:
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return ret;
-++}
-++
-++static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
-++{
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	ath10k_core_stop(ar);
-++	ath10k_hif_power_down(ar);
-++
-++	spin_lock_bh(&ar->data_lock);
-++
-++	ar->testmode.utf_monitor = false;
-++
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	/* return the original firmware features */
-++	memcpy(ar->fw_features, ar->testmode.orig_fw_features,
-++	       sizeof(ar->fw_features));
-++	ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
-++
-++	release_firmware(ar->testmode.utf);
-++	ar->testmode.utf = NULL;
-++
-++	ar->state = ATH10K_STATE_OFF;
-++}
-++
-++static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
-++{
-++	int ret;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto out;
-++	}
-++
-++	__ath10k_tm_cmd_utf_stop(ar);
-++
-++	ret = 0;
-++
-++	ath10k_info(ar, "UTF firmware stopped\n");
-++
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
-++{
-++	struct sk_buff *skb;
-++	int ret, buf_len;
-++	u32 cmd_id;
-++	void *buf;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_UTF) {
-++		ret = -ENETDOWN;
-++		goto out;
-++	}
-++
-++	if (!tb[ATH10K_TM_ATTR_DATA]) {
-++		ret = -EINVAL;
-++		goto out;
-++	}
-++
-++	if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
-++		ret = -EINVAL;
-++		goto out;
-++	}
-++
-++	buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
-++	buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
-++	cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
-++		   "testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
-++		   cmd_id, buf, buf_len);
-++
-++	ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, buf_len);
-++	if (!skb) {
-++		ret = -ENOMEM;
-++		goto out;
-++	}
-++
-++	memcpy(skb->data, buf, buf_len);
-++
-++	ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
-++			    ret);
-++		goto out;
-++	}
-++
-++	ret = 0;
-++
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-++		  void *data, int len)
-++{
-++	struct ath10k *ar = hw->priv;
-++	struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
-++	int ret;
-++
-++	ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
-++			ath10k_tm_policy);
-++	if (ret)
-++		return ret;
-++
-++	if (!tb[ATH10K_TM_ATTR_CMD])
-++		return -EINVAL;
-++
-++	switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
-++	case ATH10K_TM_CMD_GET_VERSION:
-++		return ath10k_tm_cmd_get_version(ar, tb);
-++	case ATH10K_TM_CMD_UTF_START:
-++		return ath10k_tm_cmd_utf_start(ar, tb);
-++	case ATH10K_TM_CMD_UTF_STOP:
-++		return ath10k_tm_cmd_utf_stop(ar, tb);
-++	case ATH10K_TM_CMD_WMI:
-++		return ath10k_tm_cmd_wmi(ar, tb);
-++	default:
-++		return -EOPNOTSUPP;
-++	}
-++}
-++
-++void ath10k_testmode_destroy(struct ath10k *ar)
-++{
-++	mutex_lock(&ar->conf_mutex);
-++
-++	if (ar->state != ATH10K_STATE_UTF) {
-++		/* utf firmware is not running, nothing to do */
-++		goto out;
-++	}
-++
-++	__ath10k_tm_cmd_utf_stop(ar);
-++
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++}
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/testmode.h
-+@@ -0,0 +1,46 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 "core.h"
-++
-++#ifdef CPTCFG_NL80211_TESTMODE
-++
-++void ath10k_testmode_destroy(struct ath10k *ar);
-++
-++bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
-++int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-++		  void *data, int len);
-++
-++#else
-++
-++static inline void ath10k_testmode_destroy(struct ath10k *ar)
-++{
-++}
-++
-++static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
-++				       struct sk_buff *skb)
-++{
-++	return false;
-++}
-++
-++static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
-++				struct ieee80211_vif *vif,
-++				void *data, int len)
-++{
-++	return 0;
-++}
-++
-++#endif
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
-+@@ -0,0 +1,70 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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.
-++ */
-++
-++/* "API" level of the ath10k testmode interface. Bump it after every
-++ * incompatible interface change.
-++ */
-++#define ATH10K_TESTMODE_VERSION_MAJOR 1
-++
-++/* Bump this after every _compatible_ interface change, for example
-++ * addition of a new command or an attribute.
-++ */
-++#define ATH10K_TESTMODE_VERSION_MINOR 0
-++
-++#define ATH10K_TM_DATA_MAX_LEN		5000
-++
-++enum ath10k_tm_attr {
-++	__ATH10K_TM_ATTR_INVALID	= 0,
-++	ATH10K_TM_ATTR_CMD		= 1,
-++	ATH10K_TM_ATTR_DATA		= 2,
-++	ATH10K_TM_ATTR_WMI_CMDID	= 3,
-++	ATH10K_TM_ATTR_VERSION_MAJOR	= 4,
-++	ATH10K_TM_ATTR_VERSION_MINOR	= 5,
-++
-++	/* keep last */
-++	__ATH10K_TM_ATTR_AFTER_LAST,
-++	ATH10K_TM_ATTR_MAX		= __ATH10K_TM_ATTR_AFTER_LAST - 1,
-++};
-++
-++/* All ath10k testmode interface commands specified in
-++ * ATH10K_TM_ATTR_CMD
-++ */
-++enum ath10k_tm_cmd {
-++	/* Returns the supported ath10k testmode interface version in
-++	 * ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
-++	 * uses this to verify it's using the correct version of the
-++	 * testmode interface
-++	 */
-++	ATH10K_TM_CMD_GET_VERSION = 0,
-++
-++	/* Boots the UTF firmware, the netdev interface must be down at the
-++	 * time.
-++	 */
-++	ATH10K_TM_CMD_UTF_START = 1,
-++
-++	/* Shuts down the UTF firmware and puts the driver back into OFF
-++	 * state.
-++	 */
-++	ATH10K_TM_CMD_UTF_STOP = 2,
-++
-++	/* The command used to transmit a WMI command to the firmware and
-++	 * the event to receive WMI events from the firmware. Without
-++	 * struct wmi_cmd_hdr header, only the WMI payload. Command id is
-++	 * provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
-++	 * ATH10K_TM_ATTR_DATA.
-++	 */
-++	ATH10K_TM_CMD_WMI = 3,
-++};
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
-+@@ -0,0 +1,243 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 "core.h"
-++#include "wmi-ops.h"
-++#include "debug.h"
-++
-++static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
-++					     char __user *user_buf,
-++					     size_t count, loff_t *ppos)
-++{
-++	struct ieee80211_sta *sta = file->private_data;
-++	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-++	struct ath10k *ar = arsta->arvif->ar;
-++	char buf[32];
-++	int len = 0;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
-++			(arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
-++			"auto" : "manual");
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-++}
-++
-++static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
-++					      const char __user *user_buf,
-++					      size_t count, loff_t *ppos)
-++{
-++	struct ieee80211_sta *sta = file->private_data;
-++	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-++	struct ath10k *ar = arsta->arvif->ar;
-++	u32 aggr_mode;
-++	int ret;
-++
-++	if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
-++		return -EINVAL;
-++
-++	if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	if ((ar->state != ATH10K_STATE_ON) ||
-++	    (aggr_mode == arsta->aggr_mode)) {
-++		ret = count;
-++		goto out;
-++	}
-++
-++	ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
-++		goto out;
-++	}
-++
-++	arsta->aggr_mode = aggr_mode;
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static const struct file_operations fops_aggr_mode = {
-++	.read = ath10k_dbg_sta_read_aggr_mode,
-++	.write = ath10k_dbg_sta_write_aggr_mode,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
-++					  const char __user *user_buf,
-++					  size_t count, loff_t *ppos)
-++{
-++	struct ieee80211_sta *sta = file->private_data;
-++	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-++	struct ath10k *ar = arsta->arvif->ar;
-++	u32 tid, buf_size;
-++	int ret;
-++	char buf[64];
-++
-++	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
-++
-++	/* make sure that buf is null terminated */
-++	buf[sizeof(buf) - 1] = '\0';
-++
-++	ret = sscanf(buf, "%u %u", &tid, &buf_size);
-++	if (ret != 2)
-++		return -EINVAL;
-++
-++	/* Valid TID values are 0 through 15 */
-++	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	if ((ar->state != ATH10K_STATE_ON) ||
-++	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
-++		ret = count;
-++		goto out;
-++	}
-++
-++	ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
-++				    tid, buf_size);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
-++			    arsta->arvif->vdev_id, sta->addr, tid, buf_size);
-++	}
-++
-++	ret = count;
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static const struct file_operations fops_addba = {
-++	.write = ath10k_dbg_sta_write_addba,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
-++					       const char __user *user_buf,
-++					       size_t count, loff_t *ppos)
-++{
-++	struct ieee80211_sta *sta = file->private_data;
-++	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-++	struct ath10k *ar = arsta->arvif->ar;
-++	u32 tid, status;
-++	int ret;
-++	char buf[64];
-++
-++	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
-++
-++	/* make sure that buf is null terminated */
-++	buf[sizeof(buf) - 1] = '\0';
-++
-++	ret = sscanf(buf, "%u %u", &tid, &status);
-++	if (ret != 2)
-++		return -EINVAL;
-++
-++	/* Valid TID values are 0 through 15 */
-++	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	if ((ar->state != ATH10K_STATE_ON) ||
-++	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
-++		ret = count;
-++		goto out;
-++	}
-++
-++	ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
-++					tid, status);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
-++			    arsta->arvif->vdev_id, sta->addr, tid, status);
-++	}
-++	ret = count;
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static const struct file_operations fops_addba_resp = {
-++	.write = ath10k_dbg_sta_write_addba_resp,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
-++					  const char __user *user_buf,
-++					  size_t count, loff_t *ppos)
-++{
-++	struct ieee80211_sta *sta = file->private_data;
-++	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-++	struct ath10k *ar = arsta->arvif->ar;
-++	u32 tid, initiator, reason;
-++	int ret;
-++	char buf[64];
-++
-++	simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
-++
-++	/* make sure that buf is null terminated */
-++	buf[sizeof(buf) - 1] = '\0';
-++
-++	ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
-++	if (ret != 3)
-++		return -EINVAL;
-++
-++	/* Valid TID values are 0 through 15 */
-++	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
-++		return -EINVAL;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	if ((ar->state != ATH10K_STATE_ON) ||
-++	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
-++		ret = count;
-++		goto out;
-++	}
-++
-++	ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
-++				    tid, initiator, reason);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
-++			    arsta->arvif->vdev_id, sta->addr, tid, initiator,
-++			    reason);
-++	}
-++	ret = count;
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static const struct file_operations fops_delba = {
-++	.write = ath10k_dbg_sta_write_delba,
-++	.open = simple_open,
-++	.owner = THIS_MODULE,
-++	.llseek = default_llseek,
-++};
-++
-++void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-++			    struct ieee80211_sta *sta, struct dentry *dir)
-++{
-++	debugfs_create_file("aggr_mode", S_IRUGO | S_IWUSR, dir, sta,
-++			    &fops_aggr_mode);
-++	debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
-++	debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
-++	debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
-++}
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/hw.c
-+@@ -0,0 +1,58 @@
-++/*
-++ * Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
-++ *
-++ * 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/types.h>
-++#include "hw.h"
-++
-++const struct ath10k_hw_regs qca988x_regs = {
-++	.rtc_state_cold_reset_mask	= 0x00000400,
-++	.rtc_soc_base_address		= 0x00004000,
-++	.rtc_wmac_base_address		= 0x00005000,
-++	.soc_core_base_address		= 0x00009000,
-++	.ce_wrapper_base_address	= 0x00057000,
-++	.ce0_base_address		= 0x00057400,
-++	.ce1_base_address		= 0x00057800,
-++	.ce2_base_address		= 0x00057c00,
-++	.ce3_base_address		= 0x00058000,
-++	.ce4_base_address		= 0x00058400,
-++	.ce5_base_address		= 0x00058800,
-++	.ce6_base_address		= 0x00058c00,
-++	.ce7_base_address		= 0x00059000,
-++	.soc_reset_control_si0_rst_mask	= 0x00000001,
-++	.soc_reset_control_ce_rst_mask	= 0x00040000,
-++	.soc_chip_id_address		= 0x00ec,
-++	.scratch_3_address		= 0x0030,
-++};
-++
-++const struct ath10k_hw_regs qca6174_regs = {
-++	.rtc_state_cold_reset_mask		= 0x00002000,
-++	.rtc_soc_base_address			= 0x00000800,
-++	.rtc_wmac_base_address			= 0x00001000,
-++	.soc_core_base_address			= 0x0003a000,
-++	.ce_wrapper_base_address		= 0x00034000,
-++	.ce0_base_address			= 0x00034400,
-++	.ce1_base_address			= 0x00034800,
-++	.ce2_base_address			= 0x00034c00,
-++	.ce3_base_address			= 0x00035000,
-++	.ce4_base_address			= 0x00035400,
-++	.ce5_base_address			= 0x00035800,
-++	.ce6_base_address			= 0x00035c00,
-++	.ce7_base_address			= 0x00036000,
-++	.soc_reset_control_si0_rst_mask		= 0x00000000,
-++	.soc_reset_control_ce_rst_mask		= 0x00000001,
-++	.soc_chip_id_address			= 0x000f0,
-++	.scratch_3_address			= 0x0028,
-++};
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/thermal.c
-+@@ -0,0 +1,244 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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/device.h>
-++#include <linux/sysfs.h>
-++#include <linux/thermal.h>
-++#include <linux/hwmon.h>
-++#include <linux/hwmon-sysfs.h>
-++#include "core.h"
-++#include "debug.h"
-++#include "wmi-ops.h"
-++
-++static int ath10k_thermal_get_active_vifs(struct ath10k *ar,
-++					  enum wmi_vdev_type type)
-++{
-++	struct ath10k_vif *arvif;
-++	int count = 0;
-++
-++	lockdep_assert_held(&ar->conf_mutex);
-++
-++	list_for_each_entry(arvif, &ar->arvifs, list) {
-++		if (!arvif->is_started)
-++			continue;
-++
-++		if (!arvif->is_up)
-++			continue;
-++
-++		if (arvif->vdev_type != type)
-++			continue;
-++
-++		count++;
-++	}
-++	return count;
-++}
-++
-++static int ath10k_thermal_get_max_dutycycle(struct thermal_cooling_device *cdev,
-++					    unsigned long *state)
-++{
-++	*state = ATH10K_QUIET_DUTY_CYCLE_MAX;
-++
-++	return 0;
-++}
-++
-++static int ath10k_thermal_get_cur_dutycycle(struct thermal_cooling_device *cdev,
-++					    unsigned long *state)
-++{
-++	struct ath10k *ar = cdev->devdata;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	*state = ar->thermal.duty_cycle;
-++	mutex_unlock(&ar->conf_mutex);
-++
-++	return 0;
-++}
-++
-++static int ath10k_thermal_set_cur_dutycycle(struct thermal_cooling_device *cdev,
-++					    unsigned long duty_cycle)
-++{
-++	struct ath10k *ar = cdev->devdata;
-++	u32 period, duration, enabled;
-++	int num_bss, ret = 0;
-++
-++	mutex_lock(&ar->conf_mutex);
-++	if (ar->state != ATH10K_STATE_ON) {
-++		ret = -ENETDOWN;
-++		goto out;
-++	}
-++
-++	if (duty_cycle > ATH10K_QUIET_DUTY_CYCLE_MAX) {
-++		ath10k_warn(ar, "duty cycle %ld is exceeding the limit %d\n",
-++			    duty_cycle, ATH10K_QUIET_DUTY_CYCLE_MAX);
-++		ret = -EINVAL;
-++		goto out;
-++	}
-++	/* TODO: Right now, thermal mitigation is handled only for single/multi
-++	 * vif AP mode. Since quiet param is not validated in STA mode, it needs
-++	 * to be investigated further to handle multi STA and multi-vif (AP+STA)
-++	 * mode properly.
-++	 */
-++	num_bss = ath10k_thermal_get_active_vifs(ar, WMI_VDEV_TYPE_AP);
-++	if (!num_bss) {
-++		ath10k_warn(ar, "no active AP interfaces\n");
-++		ret = -ENETDOWN;
-++		goto out;
-++	}
-++	period = max(ATH10K_QUIET_PERIOD_MIN,
-++		     (ATH10K_QUIET_PERIOD_DEFAULT / num_bss));
-++	duration = (period * duty_cycle) / 100;
-++	enabled = duration ? 1 : 0;
-++
-++	ret = ath10k_wmi_pdev_set_quiet_mode(ar, period, duration,
-++					     ATH10K_QUIET_START_OFFSET,
-++					     enabled);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to set quiet mode period %u duarion %u enabled %u ret %d\n",
-++			    period, duration, enabled, ret);
-++		goto out;
-++	}
-++	ar->thermal.duty_cycle = duty_cycle;
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++static struct thermal_cooling_device_ops ath10k_thermal_ops = {
-++	.get_max_state = ath10k_thermal_get_max_dutycycle,
-++	.get_cur_state = ath10k_thermal_get_cur_dutycycle,
-++	.set_cur_state = ath10k_thermal_set_cur_dutycycle,
-++};
-++
-++static ssize_t ath10k_thermal_show_temp(struct device *dev,
-++					struct device_attribute *attr,
-++					char *buf)
-++{
-++	struct ath10k *ar = dev_get_drvdata(dev);
-++	int ret, temperature;
-++
-++	mutex_lock(&ar->conf_mutex);
-++
-++	/* Can't get temperature when the card is off */
-++	if (ar->state != ATH10K_STATE_ON) {
-++		ret = -ENETDOWN;
-++		goto out;
-++	}
-++
-++	reinit_completion(&ar->thermal.wmi_sync);
-++	ret = ath10k_wmi_pdev_get_temperature(ar);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to read temperature %d\n", ret);
-++		goto out;
-++	}
-++
-++	if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
-++		ret = -ESHUTDOWN;
-++		goto out;
-++	}
-++
-++	ret = wait_for_completion_timeout(&ar->thermal.wmi_sync,
-++					  ATH10K_THERMAL_SYNC_TIMEOUT_HZ);
-++	if (ret == 0) {
-++		ath10k_warn(ar, "failed to synchronize thermal read\n");
-++		ret = -ETIMEDOUT;
-++		goto out;
-++	}
-++
-++	spin_lock_bh(&ar->data_lock);
-++	temperature = ar->thermal.temperature;
-++	spin_unlock_bh(&ar->data_lock);
-++
-++	/* display in millidegree celcius */
-++	ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
-++out:
-++	mutex_unlock(&ar->conf_mutex);
-++	return ret;
-++}
-++
-++void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature)
-++{
-++	spin_lock_bh(&ar->data_lock);
-++	ar->thermal.temperature = temperature;
-++	spin_unlock_bh(&ar->data_lock);
-++	complete(&ar->thermal.wmi_sync);
-++}
-++
-++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ath10k_thermal_show_temp,
-++			  NULL, 0);
-++
-++static struct attribute *ath10k_hwmon_attrs[] = {
-++	&sensor_dev_attr_temp1_input.dev_attr.attr,
-++	NULL,
-++};
-++ATTRIBUTE_GROUPS(ath10k_hwmon);
-++
-++int ath10k_thermal_register(struct ath10k *ar)
-++{
-++	struct thermal_cooling_device *cdev;
-++	struct device *hwmon_dev;
-++	int ret;
-++
-++	cdev = thermal_cooling_device_register("ath10k_thermal", ar,
-++					       &ath10k_thermal_ops);
-++
-++	if (IS_ERR(cdev)) {
-++		ath10k_err(ar, "failed to setup thermal device result: %ld\n",
-++			   PTR_ERR(cdev));
-++		return -EINVAL;
-++	}
-++
-++	ret = sysfs_create_link(&ar->dev->kobj, &cdev->device.kobj,
-++				"cooling_device");
-++	if (ret) {
-++		ath10k_err(ar, "failed to create thermal symlink\n");
-++		goto err_cooling_destroy;
-++	}
-++
-++	ar->thermal.cdev = cdev;
-++
-++	/* Do not register hwmon device when temperature reading is not
-++	 * supported by firmware
-++	 */
-++	if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
-++		return 0;
-++
-++	/* Avoid linking error on devm_hwmon_device_register_with_groups, I
-++	 * guess linux/hwmon.h is missing proper stubs. */
-++	if (!config_enabled(CPTCFG_HWMON))
-++		return 0;
-++
-++	hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev,
-++							   "ath10k_hwmon", ar,
-++							   ath10k_hwmon_groups);
-++	if (IS_ERR(hwmon_dev)) {
-++		ath10k_err(ar, "failed to register hwmon device: %ld\n",
-++			   PTR_ERR(hwmon_dev));
-++		ret = -EINVAL;
-++		goto err_remove_link;
-++	}
-++	return 0;
-++
-++err_remove_link:
-++	sysfs_remove_link(&ar->dev->kobj, "thermal_sensor");
-++err_cooling_destroy:
-++	thermal_cooling_device_unregister(cdev);
-++	return ret;
-++}
-++
-++void ath10k_thermal_unregister(struct ath10k *ar)
-++{
-++	thermal_cooling_device_unregister(ar->thermal.cdev);
-++	sysfs_remove_link(&ar->dev->kobj, "cooling_device");
-++}
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/thermal.h
-+@@ -0,0 +1,58 @@
-++/*
-++ * Copyright (c) 2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 _THERMAL_
-++#define _THERMAL_
-++
-++#define ATH10K_QUIET_PERIOD_DEFAULT     100
-++#define ATH10K_QUIET_PERIOD_MIN         25
-++#define ATH10K_QUIET_START_OFFSET       10
-++#define ATH10K_QUIET_DUTY_CYCLE_MAX     70
-++#define ATH10K_HWMON_NAME_LEN           15
-++#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ)
-++
-++struct ath10k_thermal {
-++	struct thermal_cooling_device *cdev;
-++	struct completion wmi_sync;
-++
-++	/* protected by conf_mutex */
-++	u32 duty_cycle;
-++	/* temperature value in Celcius degree
-++	 * protected by data_lock
-++	 */
-++	int temperature;
-++};
-++
-++#ifdef CONFIG_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);
-++#else
-++static inline int ath10k_thermal_register(struct ath10k *ar)
-++{
-++	return 0;
-++}
-++
-++static inline void ath10k_thermal_unregister(struct ath10k *ar)
-++{
-++}
-++
-++static inline void ath10k_thermal_event_temperature(struct ath10k *ar,
-++						    int temperature)
-++{
-++}
-++
-++#endif
-++#endif /* _THERMAL_ */
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
-+@@ -0,0 +1,1063 @@
-++/*
-++ * Copyright (c) 2005-2011 Atheros Communications Inc.
-++ * Copyright (c) 2011-2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 _WMI_OPS_H_
-++#define _WMI_OPS_H_
-++
-++struct ath10k;
-++struct sk_buff;
-++
-++struct wmi_ops {
-++	void (*rx)(struct ath10k *ar, struct sk_buff *skb);
-++	void (*map_svc)(const __le32 *in, unsigned long *out, size_t len);
-++
-++	int (*pull_scan)(struct ath10k *ar, struct sk_buff *skb,
-++			 struct wmi_scan_ev_arg *arg);
-++	int (*pull_mgmt_rx)(struct ath10k *ar, struct sk_buff *skb,
-++			    struct wmi_mgmt_rx_ev_arg *arg);
-++	int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
-++			    struct wmi_ch_info_ev_arg *arg);
-++	int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
-++			       struct wmi_vdev_start_ev_arg *arg);
-++	int (*pull_peer_kick)(struct ath10k *ar, struct sk_buff *skb,
-++			      struct wmi_peer_kick_ev_arg *arg);
-++	int (*pull_swba)(struct ath10k *ar, struct sk_buff *skb,
-++			 struct wmi_swba_ev_arg *arg);
-++	int (*pull_phyerr)(struct ath10k *ar, struct sk_buff *skb,
-++			   struct wmi_phyerr_ev_arg *arg);
-++	int (*pull_svc_rdy)(struct ath10k *ar, struct sk_buff *skb,
-++			    struct wmi_svc_rdy_ev_arg *arg);
-++	int (*pull_rdy)(struct ath10k *ar, struct sk_buff *skb,
-++			struct wmi_rdy_ev_arg *arg);
-++	int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
-++			     struct ath10k_fw_stats *stats);
-++
-++	struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
-++	struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
-++	struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
-++					   u16 rd5g, u16 ctl2g, u16 ctl5g,
-++					   enum wmi_dfs_region dfs_reg);
-++	struct sk_buff *(*gen_pdev_set_param)(struct ath10k *ar, u32 id,
-++					      u32 value);
-++	struct sk_buff *(*gen_init)(struct ath10k *ar);
-++	struct sk_buff *(*gen_start_scan)(struct ath10k *ar,
-++					  const struct wmi_start_scan_arg *arg);
-++	struct sk_buff *(*gen_stop_scan)(struct ath10k *ar,
-++					 const struct wmi_stop_scan_arg *arg);
-++	struct sk_buff *(*gen_vdev_create)(struct ath10k *ar, u32 vdev_id,
-++					   enum wmi_vdev_type type,
-++					   enum wmi_vdev_subtype subtype,
-++					   const u8 macaddr[ETH_ALEN]);
-++	struct sk_buff *(*gen_vdev_delete)(struct ath10k *ar, u32 vdev_id);
-++	struct sk_buff *(*gen_vdev_start)(struct ath10k *ar,
-++					  const struct wmi_vdev_start_request_arg *arg,
-++					  bool restart);
-++	struct sk_buff *(*gen_vdev_stop)(struct ath10k *ar, u32 vdev_id);
-++	struct sk_buff *(*gen_vdev_up)(struct ath10k *ar, u32 vdev_id, u32 aid,
-++				       const u8 *bssid);
-++	struct sk_buff *(*gen_vdev_down)(struct ath10k *ar, u32 vdev_id);
-++	struct sk_buff *(*gen_vdev_set_param)(struct ath10k *ar, u32 vdev_id,
-++					      u32 param_id, u32 param_value);
-++	struct sk_buff *(*gen_vdev_install_key)(struct ath10k *ar,
-++						const struct wmi_vdev_install_key_arg *arg);
-++	struct sk_buff *(*gen_vdev_spectral_conf)(struct ath10k *ar,
-++						  const struct wmi_vdev_spectral_conf_arg *arg);
-++	struct sk_buff *(*gen_vdev_spectral_enable)(struct ath10k *ar, u32 vdev_id,
-++						    u32 trigger, u32 enable);
-++	struct sk_buff *(*gen_vdev_wmm_conf)(struct ath10k *ar, u32 vdev_id,
-++					     const struct wmi_wmm_params_all_arg *arg);
-++	struct sk_buff *(*gen_peer_create)(struct ath10k *ar, u32 vdev_id,
-++					   const u8 peer_addr[ETH_ALEN]);
-++	struct sk_buff *(*gen_peer_delete)(struct ath10k *ar, u32 vdev_id,
-++					   const u8 peer_addr[ETH_ALEN]);
-++	struct sk_buff *(*gen_peer_flush)(struct ath10k *ar, u32 vdev_id,
-++					  const u8 peer_addr[ETH_ALEN],
-++					  u32 tid_bitmap);
-++	struct sk_buff *(*gen_peer_set_param)(struct ath10k *ar, u32 vdev_id,
-++					      const u8 *peer_addr,
-++					      enum wmi_peer_param param_id,
-++					      u32 param_value);
-++	struct sk_buff *(*gen_peer_assoc)(struct ath10k *ar,
-++					  const struct wmi_peer_assoc_complete_arg *arg);
-++	struct sk_buff *(*gen_set_psmode)(struct ath10k *ar, u32 vdev_id,
-++					  enum wmi_sta_ps_mode psmode);
-++	struct sk_buff *(*gen_set_sta_ps)(struct ath10k *ar, u32 vdev_id,
-++					  enum wmi_sta_powersave_param param_id,
-++					  u32 value);
-++	struct sk_buff *(*gen_set_ap_ps)(struct ath10k *ar, u32 vdev_id,
-++					 const u8 *mac,
-++					 enum wmi_ap_ps_peer_param param_id,
-++					 u32 value);
-++	struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar,
-++					      const struct wmi_scan_chan_list_arg *arg);
-++	struct sk_buff *(*gen_beacon_dma)(struct ath10k *ar, u32 vdev_id,
-++					  const void *bcn, size_t bcn_len,
-++					  u32 bcn_paddr, bool dtim_zero,
-++					  bool deliver_cab);
-++	struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar,
-++					    const struct wmi_wmm_params_all_arg *arg);
-++	struct sk_buff *(*gen_request_stats)(struct ath10k *ar, u32 stats_mask);
-++	struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar,
-++					     enum wmi_force_fw_hang_type type,
-++					     u32 delay_ms);
-++	struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb);
-++	struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u32 module_enable,
-++					  u32 log_level);
-++	struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
-++	struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar);
-++	struct sk_buff *(*gen_pdev_set_quiet_mode)(struct ath10k *ar,
-++						   u32 period, u32 duration,
-++						   u32 next_offset,
-++						   u32 enabled);
-++	struct sk_buff *(*gen_pdev_get_temperature)(struct ath10k *ar);
-++	struct sk_buff *(*gen_addba_clear_resp)(struct ath10k *ar, u32 vdev_id,
-++						const u8 *mac);
-++	struct sk_buff *(*gen_addba_send)(struct ath10k *ar, u32 vdev_id,
-++					  const u8 *mac, u32 tid, u32 buf_size);
-++	struct sk_buff *(*gen_addba_set_resp)(struct ath10k *ar, u32 vdev_id,
-++					      const u8 *mac, u32 tid,
-++					      u32 status);
-++	struct sk_buff *(*gen_delba_send)(struct ath10k *ar, u32 vdev_id,
-++					  const u8 *mac, u32 tid, u32 initiator,
-++					  u32 reason);
-++	struct sk_buff *(*gen_bcn_tmpl)(struct ath10k *ar, u32 vdev_id,
-++					u32 tim_ie_offset, struct sk_buff *bcn,
-++					u32 prb_caps, u32 prb_erp,
-++					void *prb_ies, size_t prb_ies_len);
-++	struct sk_buff *(*gen_prb_tmpl)(struct ath10k *ar, u32 vdev_id,
-++					struct sk_buff *bcn);
-++	struct sk_buff *(*gen_p2p_go_bcn_ie)(struct ath10k *ar, u32 vdev_id,
-++					     const u8 *p2p_ie);
-++	struct sk_buff *(*gen_vdev_sta_uapsd)(struct ath10k *ar, u32 vdev_id,
-++					      const u8 peer_addr[ETH_ALEN],
-++					      const struct wmi_sta_uapsd_auto_trig_arg *args,
-++					      u32 num_ac);
-++	struct sk_buff *(*gen_sta_keepalive)(struct ath10k *ar,
-++					     const struct wmi_sta_keepalive_arg *arg);
-++};
-++
-++int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
-++
-++static inline int
-++ath10k_wmi_rx(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	if (WARN_ON_ONCE(!ar->wmi.ops->rx))
-++		return -EOPNOTSUPP;
-++
-++	ar->wmi.ops->rx(ar, skb);
-++	return 0;
-++}
-++
-++static inline int
-++ath10k_wmi_map_svc(struct ath10k *ar, const __le32 *in, unsigned long *out,
-++		   size_t len)
-++{
-++	if (!ar->wmi.ops->map_svc)
-++		return -EOPNOTSUPP;
-++
-++	ar->wmi.ops->map_svc(in, out, len);
-++	return 0;
-++}
-++
-++static inline int
-++ath10k_wmi_pull_scan(struct ath10k *ar, struct sk_buff *skb,
-++		     struct wmi_scan_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_scan)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_scan(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
-++			struct wmi_mgmt_rx_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_mgmt_rx)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_mgmt_rx(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_ch_info(struct ath10k *ar, struct sk_buff *skb,
-++			struct wmi_ch_info_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_ch_info)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_ch_info(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_vdev_start(struct ath10k *ar, struct sk_buff *skb,
-++			   struct wmi_vdev_start_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_vdev_start)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_vdev_start(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_peer_kick(struct ath10k *ar, struct sk_buff *skb,
-++			  struct wmi_peer_kick_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_peer_kick)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_peer_kick(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_swba(struct ath10k *ar, struct sk_buff *skb,
-++		     struct wmi_swba_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_swba)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_swba(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_phyerr(struct ath10k *ar, struct sk_buff *skb,
-++		       struct wmi_phyerr_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_phyerr)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_phyerr(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_svc_rdy(struct ath10k *ar, struct sk_buff *skb,
-++			struct wmi_svc_rdy_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_svc_rdy)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_svc_rdy(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_rdy(struct ath10k *ar, struct sk_buff *skb,
-++		    struct wmi_rdy_ev_arg *arg)
-++{
-++	if (!ar->wmi.ops->pull_rdy)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_rdy(ar, skb, arg);
-++}
-++
-++static inline int
-++ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
-++			 struct ath10k_fw_stats *stats)
-++{
-++	if (!ar->wmi.ops->pull_fw_stats)
-++		return -EOPNOTSUPP;
-++
-++	return ar->wmi.ops->pull_fw_stats(ar, skb, stats);
-++}
-++
-++static inline int
-++ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
-++{
-++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	if (!ar->wmi.ops->gen_mgmt_tx)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_mgmt_tx(ar, msdu);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	ret = ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->mgmt_tx_cmdid);
-++	if (ret)
-++		return ret;
-++
-++	/* FIXME There's no ACK event for Management Tx. This probably
-++	 * shouldn't be called here either. */
-++	info->flags |= IEEE80211_TX_STAT_ACK;
-++	ieee80211_tx_status_irqsafe(ar->hw, msdu);
-++
-++	return 0;
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
-++			      u16 ctl2g, u16 ctl5g,
-++			      enum wmi_dfs_region dfs_reg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_set_rd)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_set_rd(ar, rd, rd2g, rd5g, ctl2g, ctl5g,
-++					   dfs_reg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->pdev_set_regdomain_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_suspend)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_suspend(ar, suspend_opt);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_resume_target(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_resume)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_resume(ar);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_set_param)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_set_param(ar, id, value);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_cmd_init(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_init)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_init(ar);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->init_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_start_scan(struct ath10k *ar,
-++		      const struct wmi_start_scan_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_start_scan)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_start_scan(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_stop_scan)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_stop_scan(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
-++		       enum wmi_vdev_type type,
-++		       enum wmi_vdev_subtype subtype,
-++		       const u8 macaddr[ETH_ALEN])
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_create)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_create(ar, vdev_id, type, subtype, macaddr);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_delete)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_delete(ar, vdev_id);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_start(struct ath10k *ar,
-++		      const struct wmi_vdev_start_request_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_start)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_start(ar, arg, false);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->vdev_start_request_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_restart(struct ath10k *ar,
-++			const struct wmi_vdev_start_request_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_start)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_start(ar, arg, true);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->vdev_restart_request_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_stop)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_stop(ar, vdev_id);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_up)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_up(ar, vdev_id, aid, bssid);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_down)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_down(ar, vdev_id);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, u32 param_id,
-++			  u32 param_value)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_set_param)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_set_param(ar, vdev_id, param_id,
-++					      param_value);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_install_key(struct ath10k *ar,
-++			    const struct wmi_vdev_install_key_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_vdev_install_key)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_install_key(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->vdev_install_key_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
-++			      const struct wmi_vdev_spectral_conf_arg *arg)
-++{
-++	struct sk_buff *skb;
-++	u32 cmd_id;
-++
-++	skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	cmd_id = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
-++	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
-++				u32 enable)
-++{
-++	struct sk_buff *skb;
-++	u32 cmd_id;
-++
-++	skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
-++						    enable);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	cmd_id = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
-++	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
-++			  const u8 peer_addr[ETH_ALEN],
-++			  const struct wmi_sta_uapsd_auto_trig_arg *args,
-++			  u32 num_ac)
-++{
-++	struct sk_buff *skb;
-++	u32 cmd_id;
-++
-++	if (!ar->wmi.ops->gen_vdev_sta_uapsd)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_vdev_sta_uapsd(ar, vdev_id, peer_addr, args,
-++					      num_ac);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	cmd_id = ar->wmi.cmd->sta_uapsd_auto_trig_cmdid;
-++	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++}
-++
-++static inline int
-++ath10k_wmi_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
-++			 const struct wmi_wmm_params_all_arg *arg)
-++{
-++	struct sk_buff *skb;
-++	u32 cmd_id;
-++
-++	skb = ar->wmi.ops->gen_vdev_wmm_conf(ar, vdev_id, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	cmd_id = ar->wmi.cmd->vdev_set_wmm_params_cmdid;
-++	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++}
-++
-++static inline int
-++ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
-++		       const u8 peer_addr[ETH_ALEN])
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_peer_create)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_peer_create(ar, vdev_id, peer_addr);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
-++		       const u8 peer_addr[ETH_ALEN])
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_peer_delete)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_peer_delete(ar, vdev_id, peer_addr);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
-++		      const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_peer_flush)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_peer_flush(ar, vdev_id, peer_addr, tid_bitmap);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, const u8 *peer_addr,
-++			  enum wmi_peer_param param_id, u32 param_value)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_peer_set_param)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_peer_set_param(ar, vdev_id, peer_addr, param_id,
-++					      param_value);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
-++		      enum wmi_sta_ps_mode psmode)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_set_psmode)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_set_psmode(ar, vdev_id, psmode);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->sta_powersave_mode_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
-++			    enum wmi_sta_powersave_param param_id, u32 value)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_set_sta_ps)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_set_sta_ps(ar, vdev_id, param_id, value);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->sta_powersave_param_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++			   enum wmi_ap_ps_peer_param param_id, u32 value)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_set_ap_ps)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_set_ap_ps(ar, vdev_id, mac, param_id, value);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->ap_ps_peer_param_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_scan_chan_list(struct ath10k *ar,
-++			  const struct wmi_scan_chan_list_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_scan_chan_list)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_scan_chan_list(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_peer_assoc(struct ath10k *ar,
-++		      const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_peer_assoc)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_peer_assoc(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_beacon_send_ref_nowait(struct ath10k *ar, u32 vdev_id,
-++				  const void *bcn, size_t bcn_len,
-++				  u32 bcn_paddr, bool dtim_zero,
-++				  bool deliver_cab)
-++{
-++	struct sk_buff *skb;
-++	int ret;
-++
-++	if (!ar->wmi.ops->gen_beacon_dma)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_beacon_dma(ar, vdev_id, bcn, bcn_len, bcn_paddr,
-++					  dtim_zero, deliver_cab);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	ret = ath10k_wmi_cmd_send_nowait(ar, skb,
-++					 ar->wmi.cmd->pdev_send_bcn_cmdid);
-++	if (ret) {
-++		dev_kfree_skb(skb);
-++		return ret;
-++	}
-++
-++	return 0;
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
-++			       const struct wmi_wmm_params_all_arg *arg)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_set_wmm)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_set_wmm(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->pdev_set_wmm_params_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_request_stats(struct ath10k *ar, u32 stats_mask)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_request_stats)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_request_stats(ar, stats_mask);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_force_fw_hang(struct ath10k *ar,
-++			 enum wmi_force_fw_hang_type type, u32 delay_ms)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_force_fw_hang)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_force_fw_hang(ar, type, delay_ms);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable, u32 log_level)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_dbglog_cfg)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_dbglog_cfg(ar, module_enable, log_level);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 filter)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pktlog_enable)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pktlog_enable(ar, filter);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_pktlog_enable_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pktlog_disable)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pktlog_disable(ar);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->pdev_pktlog_disable_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_set_quiet_mode(struct ath10k *ar, u32 period, u32 duration,
-++			       u32 next_offset, u32 enabled)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_set_quiet_mode)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_set_quiet_mode(ar, period, duration,
-++						   next_offset, enabled);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->pdev_set_quiet_mode_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_pdev_get_temperature(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_pdev_get_temperature)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_pdev_get_temperature(ar);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->pdev_get_temperature_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_addba_clear_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_addba_clear_resp)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_addba_clear_resp(ar, vdev_id, mac);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->addba_clear_resp_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_addba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++		      u32 tid, u32 buf_size)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_addba_send)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_addba_send(ar, vdev_id, mac, tid, buf_size);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->addba_send_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_addba_set_resp(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++			  u32 tid, u32 status)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_addba_set_resp)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_addba_set_resp(ar, vdev_id, mac, tid, status);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->addba_set_resp_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++		      u32 tid, u32 initiator, u32 reason)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_delba_send)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_delba_send(ar, vdev_id, mac, tid, initiator,
-++					  reason);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb,
-++				   ar->wmi.cmd->delba_send_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_bcn_tmpl(struct ath10k *ar, u32 vdev_id, u32 tim_ie_offset,
-++		    struct sk_buff *bcn, u32 prb_caps, u32 prb_erp,
-++		    void *prb_ies, size_t prb_ies_len)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_bcn_tmpl)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_bcn_tmpl(ar, vdev_id, tim_ie_offset, bcn,
-++					prb_caps, prb_erp, prb_ies,
-++					prb_ies_len);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->bcn_tmpl_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_prb_tmpl(struct ath10k *ar, u32 vdev_id, struct sk_buff *prb)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_prb_tmpl)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_prb_tmpl(ar, vdev_id, prb);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->prb_tmpl_cmdid);
-++}
-++
-++static inline int
-++ath10k_wmi_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id, const u8 *p2p_ie)
-++{
-++	struct sk_buff *skb;
-++
-++	if (!ar->wmi.ops->gen_p2p_go_bcn_ie)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_p2p_go_bcn_ie(ar, vdev_id, p2p_ie);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->p2p_go_set_beacon_ie);
-++}
-++
-++static inline int
-++ath10k_wmi_sta_keepalive(struct ath10k *ar,
-++			 const struct wmi_sta_keepalive_arg *arg)
-++{
-++	struct sk_buff *skb;
-++	u32 cmd_id;
-++
-++	if (!ar->wmi.ops->gen_sta_keepalive)
-++		return -EOPNOTSUPP;
-++
-++	skb = ar->wmi.ops->gen_sta_keepalive(ar, arg);
-++	if (IS_ERR(skb))
-++		return PTR_ERR(skb);
-++
-++	cmd_id = ar->wmi.cmd->sta_keepalive_cmd;
-++	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
-++}
-++
-++#endif
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-+@@ -0,0 +1,2796 @@
-++/*
-++ * Copyright (c) 2005-2011 Atheros Communications Inc.
-++ * Copyright (c) 2011-2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 "core.h"
-++#include "debug.h"
-++#include "hw.h"
-++#include "wmi.h"
-++#include "wmi-ops.h"
-++#include "wmi-tlv.h"
-++
-++/***************/
-++/* TLV helpers */
-++/**************/
-++
-++struct wmi_tlv_policy {
-++	size_t min_len;
-++};
-++
-++static const struct wmi_tlv_policy wmi_tlv_policies[] = {
-++	[WMI_TLV_TAG_ARRAY_BYTE]
-++		= { .min_len = sizeof(u8) },
-++	[WMI_TLV_TAG_ARRAY_UINT32]
-++		= { .min_len = sizeof(u32) },
-++	[WMI_TLV_TAG_STRUCT_SCAN_EVENT]
-++		= { .min_len = sizeof(struct wmi_scan_event) },
-++	[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]
-++		= { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) },
-++	[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]
-++		= { .min_len = sizeof(struct wmi_chan_info_event) },
-++	[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]
-++		= { .min_len = sizeof(struct wmi_vdev_start_response_event) },
-++	[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]
-++		= { .min_len = sizeof(struct wmi_peer_sta_kickout_event) },
-++	[WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT]
-++		= { .min_len = sizeof(struct wmi_host_swba_event) },
-++	[WMI_TLV_TAG_STRUCT_TIM_INFO]
-++		= { .min_len = sizeof(struct wmi_tim_info) },
-++	[WMI_TLV_TAG_STRUCT_P2P_NOA_INFO]
-++		= { .min_len = sizeof(struct wmi_p2p_noa_info) },
-++	[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]
-++		= { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) },
-++	[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]
-++		= { .min_len = sizeof(struct hal_reg_capabilities) },
-++	[WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ]
-++		= { .min_len = sizeof(struct wlan_host_mem_req) },
-++	[WMI_TLV_TAG_STRUCT_READY_EVENT]
-++		= { .min_len = sizeof(struct wmi_tlv_rdy_ev) },
-++	[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]
-++		= { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) },
-++	[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]
-++		= { .min_len = sizeof(struct wmi_tlv_diag_data_ev) },
-++};
-++
-++static int
-++ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len,
-++		    int (*iter)(struct ath10k *ar, u16 tag, u16 len,
-++				const void *ptr, void *data),
-++		    void *data)
-++{
-++	const void *begin = ptr;
-++	const struct wmi_tlv *tlv;
-++	u16 tlv_tag, tlv_len;
-++	int ret;
-++
-++	while (len > 0) {
-++		if (len < sizeof(*tlv)) {
-++			ath10k_dbg(ar, ATH10K_DBG_WMI,
-++				   "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n",
-++				   ptr - begin, len, sizeof(*tlv));
-++			return -EINVAL;
-++		}
-++
-++		tlv = ptr;
-++		tlv_tag = __le16_to_cpu(tlv->tag);
-++		tlv_len = __le16_to_cpu(tlv->len);
-++		ptr += sizeof(*tlv);
-++		len -= sizeof(*tlv);
-++
-++		if (tlv_len > len) {
-++			ath10k_dbg(ar, ATH10K_DBG_WMI,
-++				   "wmi tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n",
-++				   tlv_tag, ptr - begin, len, tlv_len);
-++			return -EINVAL;
-++		}
-++
-++		if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) &&
-++		    wmi_tlv_policies[tlv_tag].min_len &&
-++		    wmi_tlv_policies[tlv_tag].min_len > tlv_len) {
-++			ath10k_dbg(ar, ATH10K_DBG_WMI,
-++				   "wmi tlv parse failure of tag %hhu at byte %zd (%hhu bytes is less than min length %zu)\n",
-++				   tlv_tag, ptr - begin, tlv_len,
-++				   wmi_tlv_policies[tlv_tag].min_len);
-++			return -EINVAL;
-++		}
-++
-++		ret = iter(ar, tlv_tag, tlv_len, ptr, data);
-++		if (ret)
-++			return ret;
-++
-++		ptr += tlv_len;
-++		len -= tlv_len;
-++	}
-++
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len,
-++				     const void *ptr, void *data)
-++{
-++	const void **tb = data;
-++
-++	if (tag < WMI_TLV_TAG_MAX)
-++		tb[tag] = ptr;
-++
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb,
-++				const void *ptr, size_t len)
-++{
-++	return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse,
-++				   (void *)tb);
-++}
-++
-++static const void **
-++ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
-++			   size_t len, gfp_t gfp)
-++{
-++	const void **tb;
-++	int ret;
-++
-++	tb = kzalloc(sizeof(*tb) * WMI_TLV_TAG_MAX, gfp);
-++	if (!tb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len);
-++	if (ret) {
-++		kfree(tb);
-++		return ERR_PTR(ret);
-++	}
-++
-++	return tb;
-++}
-++
-++static u16 ath10k_wmi_tlv_len(const void *ptr)
-++{
-++	return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len);
-++}
-++
-++/**************/
-++/* TLV events */
-++/**************/
-++static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar,
-++					      struct sk_buff *skb)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_bcn_tx_status_ev *ev;
-++	u32 vdev_id, tx_status;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	tx_status = __le32_to_cpu(ev->tx_status);
-++	vdev_id = __le32_to_cpu(ev->vdev_id);
-++
-++	switch (tx_status) {
-++	case WMI_TLV_BCN_TX_STATUS_OK:
-++		break;
-++	case WMI_TLV_BCN_TX_STATUS_XRETRY:
-++	case WMI_TLV_BCN_TX_STATUS_DROP:
-++	case WMI_TLV_BCN_TX_STATUS_FILTERED:
-++		/* FIXME: It's probably worth telling mac80211 to stop the
-++		 * interface as it is crippled.
-++		 */
-++		ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d",
-++			    vdev_id, tx_status);
-++		break;
-++	}
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar,
-++					  struct sk_buff *skb)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_diag_data_ev *ev;
-++	const struct wmi_tlv_diag_item *item;
-++	const void *data;
-++	int ret, num_items, len;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT];
-++	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
-++	if (!ev || !data) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	num_items = __le32_to_cpu(ev->num_items);
-++	len = ath10k_wmi_tlv_len(data);
-++
-++	while (num_items--) {
-++		if (len == 0)
-++			break;
-++		if (len < sizeof(*item)) {
-++			ath10k_warn(ar, "failed to parse diag data: can't fit item header\n");
-++			break;
-++		}
-++
-++		item = data;
-++
-++		if (len < sizeof(*item) + __le16_to_cpu(item->len)) {
-++			ath10k_warn(ar, "failed to parse diag data: item is too long\n");
-++			break;
-++		}
-++
-++		trace_ath10k_wmi_diag_container(ar,
-++						item->type,
-++						__le32_to_cpu(item->timestamp),
-++						__le32_to_cpu(item->code),
-++						__le16_to_cpu(item->len),
-++						item->payload);
-++
-++		len -= sizeof(*item);
-++		len -= roundup(__le16_to_cpu(item->len), 4);
-++
-++		data += sizeof(*item);
-++		data += roundup(__le16_to_cpu(item->len), 4);
-++	}
-++
-++	if (num_items != -1 || len != 0)
-++		ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n",
-++			    num_items, len);
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_event_diag(struct ath10k *ar,
-++				     struct sk_buff *skb)
-++{
-++	const void **tb;
-++	const void *data;
-++	int ret, len;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
-++	if (!data) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++	len = ath10k_wmi_tlv_len(data);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len);
-++	trace_ath10k_wmi_diag(ar, data, len);
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++/***********/
-++/* TLV ops */
-++/***********/
-++
-++static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
-++{
-++	struct wmi_cmd_hdr *cmd_hdr;
-++	enum wmi_tlv_event_id id;
-++
-++	cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
-++	id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
-++
-++	if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-++		return;
-++
-++	trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
-++
-++	switch (id) {
-++	case WMI_TLV_MGMT_RX_EVENTID:
-++		ath10k_wmi_event_mgmt_rx(ar, skb);
-++		/* mgmt_rx() owns the skb now! */
-++		return;
-++	case WMI_TLV_SCAN_EVENTID:
-++		ath10k_wmi_event_scan(ar, skb);
-++		break;
-++	case WMI_TLV_CHAN_INFO_EVENTID:
-++		ath10k_wmi_event_chan_info(ar, skb);
-++		break;
-++	case WMI_TLV_ECHO_EVENTID:
-++		ath10k_wmi_event_echo(ar, skb);
-++		break;
-++	case WMI_TLV_DEBUG_MESG_EVENTID:
-++		ath10k_wmi_event_debug_mesg(ar, skb);
-++		break;
-++	case WMI_TLV_UPDATE_STATS_EVENTID:
-++		ath10k_wmi_event_update_stats(ar, skb);
-++		break;
-++	case WMI_TLV_VDEV_START_RESP_EVENTID:
-++		ath10k_wmi_event_vdev_start_resp(ar, skb);
-++		break;
-++	case WMI_TLV_VDEV_STOPPED_EVENTID:
-++		ath10k_wmi_event_vdev_stopped(ar, skb);
-++		break;
-++	case WMI_TLV_PEER_STA_KICKOUT_EVENTID:
-++		ath10k_wmi_event_peer_sta_kickout(ar, skb);
-++		break;
-++	case WMI_TLV_HOST_SWBA_EVENTID:
-++		ath10k_wmi_event_host_swba(ar, skb);
-++		break;
-++	case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID:
-++		ath10k_wmi_event_tbttoffset_update(ar, skb);
-++		break;
-++	case WMI_TLV_PHYERR_EVENTID:
-++		ath10k_wmi_event_phyerr(ar, skb);
-++		break;
-++	case WMI_TLV_ROAM_EVENTID:
-++		ath10k_wmi_event_roam(ar, skb);
-++		break;
-++	case WMI_TLV_PROFILE_MATCH:
-++		ath10k_wmi_event_profile_match(ar, skb);
-++		break;
-++	case WMI_TLV_DEBUG_PRINT_EVENTID:
-++		ath10k_wmi_event_debug_print(ar, skb);
-++		break;
-++	case WMI_TLV_PDEV_QVIT_EVENTID:
-++		ath10k_wmi_event_pdev_qvit(ar, skb);
-++		break;
-++	case WMI_TLV_WLAN_PROFILE_DATA_EVENTID:
-++		ath10k_wmi_event_wlan_profile_data(ar, skb);
-++		break;
-++	case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID:
-++		ath10k_wmi_event_rtt_measurement_report(ar, skb);
-++		break;
-++	case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID:
-++		ath10k_wmi_event_tsf_measurement_report(ar, skb);
-++		break;
-++	case WMI_TLV_RTT_ERROR_REPORT_EVENTID:
-++		ath10k_wmi_event_rtt_error_report(ar, skb);
-++		break;
-++	case WMI_TLV_WOW_WAKEUP_HOST_EVENTID:
-++		ath10k_wmi_event_wow_wakeup_host(ar, skb);
-++		break;
-++	case WMI_TLV_DCS_INTERFERENCE_EVENTID:
-++		ath10k_wmi_event_dcs_interference(ar, skb);
-++		break;
-++	case WMI_TLV_PDEV_TPC_CONFIG_EVENTID:
-++		ath10k_wmi_event_pdev_tpc_config(ar, skb);
-++		break;
-++	case WMI_TLV_PDEV_FTM_INTG_EVENTID:
-++		ath10k_wmi_event_pdev_ftm_intg(ar, skb);
-++		break;
-++	case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID:
-++		ath10k_wmi_event_gtk_offload_status(ar, skb);
-++		break;
-++	case WMI_TLV_GTK_REKEY_FAIL_EVENTID:
-++		ath10k_wmi_event_gtk_rekey_fail(ar, skb);
-++		break;
-++	case WMI_TLV_TX_DELBA_COMPLETE_EVENTID:
-++		ath10k_wmi_event_delba_complete(ar, skb);
-++		break;
-++	case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID:
-++		ath10k_wmi_event_addba_complete(ar, skb);
-++		break;
-++	case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID:
-++		ath10k_wmi_event_vdev_install_key_complete(ar, skb);
-++		break;
-++	case WMI_TLV_SERVICE_READY_EVENTID:
-++		ath10k_wmi_event_service_ready(ar, skb);
-++		break;
-++	case WMI_TLV_READY_EVENTID:
-++		ath10k_wmi_event_ready(ar, skb);
-++		break;
-++	case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID:
-++		ath10k_wmi_tlv_event_bcn_tx_status(ar, skb);
-++		break;
-++	case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID:
-++		ath10k_wmi_tlv_event_diag_data(ar, skb);
-++		break;
-++	case WMI_TLV_DIAG_EVENTID:
-++		ath10k_wmi_tlv_event_diag(ar, skb);
-++		break;
-++	default:
-++		ath10k_warn(ar, "Unknown eventid: %d\n", id);
-++		break;
-++	}
-++
-++	dev_kfree_skb(skb);
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
-++					  struct sk_buff *skb,
-++					  struct wmi_scan_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_scan_event *ev;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->event_type = ev->event_type;
-++	arg->reason = ev->reason;
-++	arg->channel_freq = ev->channel_freq;
-++	arg->scan_req_id = ev->scan_req_id;
-++	arg->scan_id = ev->scan_id;
-++	arg->vdev_id = ev->vdev_id;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
-++					     struct sk_buff *skb,
-++					     struct wmi_mgmt_rx_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_mgmt_rx_ev *ev;
-++	const u8 *frame;
-++	u32 msdu_len;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR];
-++	frame = tb[WMI_TLV_TAG_ARRAY_BYTE];
-++
-++	if (!ev || !frame) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->channel = ev->channel;
-++	arg->buf_len = ev->buf_len;
-++	arg->status = ev->status;
-++	arg->snr = ev->snr;
-++	arg->phy_mode = ev->phy_mode;
-++	arg->rate = ev->rate;
-++
-++	msdu_len = __le32_to_cpu(arg->buf_len);
-++
-++	if (skb->len < (frame - skb->data) + msdu_len) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	/* shift the sk_buff to point to `frame` */
-++	skb_trim(skb, 0);
-++	skb_put(skb, frame - skb->data);
-++	skb_pull(skb, frame - skb->data);
-++	skb_put(skb, msdu_len);
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar,
-++					     struct sk_buff *skb,
-++					     struct wmi_ch_info_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_chan_info_event *ev;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->err_code = ev->err_code;
-++	arg->freq = ev->freq;
-++	arg->cmd_flags = ev->cmd_flags;
-++	arg->noise_floor = ev->noise_floor;
-++	arg->rx_clear_count = ev->rx_clear_count;
-++	arg->cycle_count = ev->cycle_count;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int
-++ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb,
-++				     struct wmi_vdev_start_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_vdev_start_response_event *ev;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	skb_pull(skb, sizeof(*ev));
-++	arg->vdev_id = ev->vdev_id;
-++	arg->req_id = ev->req_id;
-++	arg->resp_type = ev->resp_type;
-++	arg->status = ev->status;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar,
-++					       struct sk_buff *skb,
-++					       struct wmi_peer_kick_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_peer_sta_kickout_event *ev;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->mac_addr = ev->peer_macaddr.addr;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++struct wmi_tlv_swba_parse {
-++	const struct wmi_host_swba_event *ev;
-++	bool tim_done;
-++	bool noa_done;
-++	size_t n_tim;
-++	size_t n_noa;
-++	struct wmi_swba_ev_arg *arg;
-++};
-++
-++static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
-++					 const void *ptr, void *data)
-++{
-++	struct wmi_tlv_swba_parse *swba = data;
-++
-++	if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
-++		return -EPROTO;
-++
-++	if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
-++		return -ENOBUFS;
-++
-++	swba->arg->tim_info[swba->n_tim++] = ptr;
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len,
-++					 const void *ptr, void *data)
-++{
-++	struct wmi_tlv_swba_parse *swba = data;
-++
-++	if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO)
-++		return -EPROTO;
-++
-++	if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info))
-++		return -ENOBUFS;
-++
-++	swba->arg->noa_info[swba->n_noa++] = ptr;
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len,
-++				     const void *ptr, void *data)
-++{
-++	struct wmi_tlv_swba_parse *swba = data;
-++	int ret;
-++
-++	switch (tag) {
-++	case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT:
-++		swba->ev = ptr;
-++		break;
-++	case WMI_TLV_TAG_ARRAY_STRUCT:
-++		if (!swba->tim_done) {
-++			swba->tim_done = true;
-++			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
-++						  ath10k_wmi_tlv_swba_tim_parse,
-++						  swba);
-++			if (ret)
-++				return ret;
-++		} else if (!swba->noa_done) {
-++			swba->noa_done = true;
-++			ret = ath10k_wmi_tlv_iter(ar, ptr, len,
-++						  ath10k_wmi_tlv_swba_noa_parse,
-++						  swba);
-++			if (ret)
-++				return ret;
-++		}
-++		break;
-++	default:
-++		break;
-++	}
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar,
-++					  struct sk_buff *skb,
-++					  struct wmi_swba_ev_arg *arg)
-++{
-++	struct wmi_tlv_swba_parse swba = { .arg = arg };
-++	u32 map;
-++	size_t n_vdevs;
-++	int ret;
-++
-++	ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
-++				  ath10k_wmi_tlv_swba_parse, &swba);
-++	if (ret) {
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	if (!swba.ev)
-++		return -EPROTO;
-++
-++	arg->vdev_map = swba.ev->vdev_map;
-++
-++	for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1)
-++		if (map & BIT(0))
-++			n_vdevs++;
-++
-++	if (n_vdevs != swba.n_tim ||
-++	    n_vdevs != swba.n_noa)
-++		return -EPROTO;
-++
-++	return 0;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar,
-++					    struct sk_buff *skb,
-++					    struct wmi_phyerr_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_phyerr_ev *ev;
-++	const void *phyerrs;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR];
-++	phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE];
-++
-++	if (!ev || !phyerrs) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->num_phyerrs  = ev->num_phyerrs;
-++	arg->tsf_l32 = ev->tsf_l32;
-++	arg->tsf_u32 = ev->tsf_u32;
-++	arg->buf_len = ev->buf_len;
-++	arg->phyerrs = phyerrs;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++#define WMI_TLV_ABI_VER_NS0 0x5F414351
-++#define WMI_TLV_ABI_VER_NS1 0x00004C4D
-++#define WMI_TLV_ABI_VER_NS2 0x00000000
-++#define WMI_TLV_ABI_VER_NS3 0x00000000
-++
-++#define WMI_TLV_ABI_VER0_MAJOR 1
-++#define WMI_TLV_ABI_VER0_MINOR 0
-++#define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \
-++			  (((WMI_TLV_ABI_VER0_MINOR) <<  0) & 0x00FFFFFF))
-++#define WMI_TLV_ABI_VER1 53
-++
-++static int
-++ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len,
-++			      const void *ptr, void *data)
-++{
-++	struct wmi_svc_rdy_ev_arg *arg = data;
-++	int i;
-++
-++	if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ)
-++		return -EPROTO;
-++
-++	for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) {
-++		if (!arg->mem_reqs[i]) {
-++			arg->mem_reqs[i] = ptr;
-++			return 0;
-++		}
-++	}
-++
-++	return -ENOMEM;
-++}
-++
-++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;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		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];
-++
-++	if (!ev || !reg || !svc_bmap || !mem_reqs) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	/* This is an internal ABI compatibility check for WMI TLV so check it
-++	 * here instead of the generic WMI code.
-++	 */
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n",
-++		   __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0,
-++		   __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0,
-++		   __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);
-++
-++	if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 ||
-++	    __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 ||
-++	    __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;
-++	}
-++
-++	arg->min_tx_power = ev->hw_min_tx_power;
-++	arg->max_tx_power = ev->hw_max_tx_power;
-++	arg->ht_cap = ev->ht_cap_info;
-++	arg->vht_cap = ev->vht_cap_info;
-++	arg->sw_ver0 = ev->abi.abi_ver0;
-++	arg->sw_ver1 = ev->abi.abi_ver1;
-++	arg->fw_build = ev->fw_build_vers;
-++	arg->phy_capab = ev->phy_capability;
-++	arg->num_rf_chains = ev->num_rf_chains;
-++	arg->eeprom_rd = reg->eeprom_rd;
-++	arg->num_mem_reqs = ev->num_mem_reqs;
-++	arg->service_map = svc_bmap;
-++	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
-++
-++	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;
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar,
-++					 struct sk_buff *skb,
-++					 struct wmi_rdy_ev_arg *arg)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_rdy_ev *ev;
-++	int ret;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT];
-++	if (!ev) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	arg->sw_version = ev->abi.abi_ver0;
-++	arg->abi_version = ev->abi.abi_ver1;
-++	arg->status = ev->status;
-++	arg->mac_addr = ev->mac_addr.addr;
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static void ath10k_wmi_tlv_pull_vdev_stats(const struct wmi_tlv_vdev_stats *src,
-++					   struct ath10k_fw_stats_vdev *dst)
-++{
-++	int i;
-++
-++	dst->vdev_id = __le32_to_cpu(src->vdev_id);
-++	dst->beacon_snr = __le32_to_cpu(src->beacon_snr);
-++	dst->data_snr = __le32_to_cpu(src->data_snr);
-++	dst->num_rx_frames = __le32_to_cpu(src->num_rx_frames);
-++	dst->num_rts_fail = __le32_to_cpu(src->num_rts_fail);
-++	dst->num_rts_success = __le32_to_cpu(src->num_rts_success);
-++	dst->num_rx_err = __le32_to_cpu(src->num_rx_err);
-++	dst->num_rx_discard = __le32_to_cpu(src->num_rx_discard);
-++	dst->num_tx_not_acked = __le32_to_cpu(src->num_tx_not_acked);
-++
-++	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames); i++)
-++		dst->num_tx_frames[i] =
-++			__le32_to_cpu(src->num_tx_frames[i]);
-++
-++	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_retries); i++)
-++		dst->num_tx_frames_retries[i] =
-++			__le32_to_cpu(src->num_tx_frames_retries[i]);
-++
-++	for (i = 0; i < ARRAY_SIZE(src->num_tx_frames_failures); i++)
-++		dst->num_tx_frames_failures[i] =
-++			__le32_to_cpu(src->num_tx_frames_failures[i]);
-++
-++	for (i = 0; i < ARRAY_SIZE(src->tx_rate_history); i++)
-++		dst->tx_rate_history[i] =
-++			__le32_to_cpu(src->tx_rate_history[i]);
-++
-++	for (i = 0; i < ARRAY_SIZE(src->beacon_rssi_history); i++)
-++		dst->beacon_rssi_history[i] =
-++			__le32_to_cpu(src->beacon_rssi_history[i]);
-++}
-++
-++static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
-++					   struct sk_buff *skb,
-++					   struct ath10k_fw_stats *stats)
-++{
-++	const void **tb;
-++	const struct wmi_tlv_stats_ev *ev;
-++	const void *data;
-++	u32 num_pdev_stats;
-++	u32 num_vdev_stats;
-++	u32 num_peer_stats;
-++	u32 num_bcnflt_stats;
-++	u32 num_chan_stats;
-++	size_t data_len;
-++	int ret;
-++	int i;
-++
-++	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-++	if (IS_ERR(tb)) {
-++		ret = PTR_ERR(tb);
-++		ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
-++		return ret;
-++	}
-++
-++	ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT];
-++	data = tb[WMI_TLV_TAG_ARRAY_BYTE];
-++
-++	if (!ev || !data) {
-++		kfree(tb);
-++		return -EPROTO;
-++	}
-++
-++	data_len = ath10k_wmi_tlv_len(data);
-++	num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
-++	num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
-++	num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-++	num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
-++	num_chan_stats = __le32_to_cpu(ev->num_chan_stats);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n",
-++		   num_pdev_stats, num_vdev_stats, num_peer_stats,
-++		   num_bcnflt_stats, num_chan_stats);
-++
-++	for (i = 0; i < num_pdev_stats; i++) {
-++		const struct wmi_pdev_stats *src;
-++		struct ath10k_fw_stats_pdev *dst;
-++
-++		src = data;
-++		if (data_len < sizeof(*src))
-++			return -EPROTO;
-++
-++		data += sizeof(*src);
-++		data_len -= sizeof(*src);
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
-++		ath10k_wmi_pull_pdev_stats_tx(&src->tx, dst);
-++		ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
-++		list_add_tail(&dst->list, &stats->pdevs);
-++	}
-++
-++	for (i = 0; i < num_vdev_stats; i++) {
-++		const struct wmi_tlv_vdev_stats *src;
-++		struct ath10k_fw_stats_vdev *dst;
-++
-++		src = data;
-++		if (data_len < sizeof(*src))
-++			return -EPROTO;
-++
-++		data += sizeof(*src);
-++		data_len -= sizeof(*src);
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_tlv_pull_vdev_stats(src, dst);
-++		list_add_tail(&dst->list, &stats->vdevs);
-++	}
-++
-++	for (i = 0; i < num_peer_stats; i++) {
-++		const struct wmi_10x_peer_stats *src;
-++		struct ath10k_fw_stats_peer *dst;
-++
-++		src = data;
-++		if (data_len < sizeof(*src))
-++			return -EPROTO;
-++
-++		data += sizeof(*src);
-++		data_len -= sizeof(*src);
-++
-++		dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
-++		if (!dst)
-++			continue;
-++
-++		ath10k_wmi_pull_peer_stats(&src->old, dst);
-++		dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
-++		list_add_tail(&dst->list, &stats->peers);
-++	}
-++
-++	kfree(tb);
-++	return 0;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt)
-++{
-++	struct wmi_tlv_pdev_suspend *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->opt = __cpu_to_le32(opt);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar)
-++{
-++	struct wmi_tlv_resume_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->reserved = __cpu_to_le32(0);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
-++				  u16 rd, u16 rd2g, u16 rd5g,
-++				  u16 ctl2g, u16 ctl5g,
-++				  enum wmi_dfs_region dfs_reg)
-++{
-++	struct wmi_tlv_pdev_set_rd_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->regd = __cpu_to_le32(rd);
-++	cmd->regd_2ghz = __cpu_to_le32(rd2g);
-++	cmd->regd_5ghz = __cpu_to_le32(rd5g);
-++	cmd->conform_limit_2ghz = __cpu_to_le32(rd2g);
-++	cmd->conform_limit_5ghz = __cpu_to_le32(rd5g);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
-++				     u32 param_value)
-++{
-++	struct wmi_tlv_pdev_set_param_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->param_id = __cpu_to_le32(param_id);
-++	cmd->param_value = __cpu_to_le32(param_value);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
-++{
-++	struct sk_buff *skb;
-++	struct wmi_tlv *tlv;
-++	struct wmi_tlv_init_cmd *cmd;
-++	struct wmi_tlv_resource_config *cfg;
-++	struct wmi_host_mem_chunks *chunks;
-++	size_t len, chunks_len;
-++	void *ptr;
-++
-++	chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk);
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (sizeof(*tlv) + sizeof(*cfg)) +
-++	      (sizeof(*tlv) + chunks_len);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = skb->data;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG);
-++	tlv->len = __cpu_to_le16(sizeof(*cfg));
-++	cfg = (void *)tlv->value;
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cfg);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
-++	tlv->len = __cpu_to_le16(chunks_len);
-++	chunks = (void *)tlv->value;
-++
-++	ptr += sizeof(*tlv);
-++	ptr += chunks_len;
-++
-++	cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0);
-++	cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1);
-++	cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0);
-++	cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1);
-++	cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2);
-++	cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3);
-++	cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
-++
-++	cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
-++	cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
-++
-++	if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
-++		cfg->num_offload_peers = __cpu_to_le32(3);
-++		cfg->num_offload_reorder_bufs = __cpu_to_le32(3);
-++	} else {
-++		cfg->num_offload_peers = __cpu_to_le32(0);
-++		cfg->num_offload_reorder_bufs = __cpu_to_le32(0);
-++	}
-++
-++	cfg->num_peer_keys = __cpu_to_le32(2);
-++	cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
-++	cfg->ast_skid_limit = __cpu_to_le32(0x10);
-++	cfg->tx_chain_mask = __cpu_to_le32(0x7);
-++	cfg->rx_chain_mask = __cpu_to_le32(0x7);
-++	cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
-++	cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
-++	cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
-++	cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
-++	cfg->rx_decap_mode = __cpu_to_le32(1);
-++	cfg->scan_max_pending_reqs = __cpu_to_le32(4);
-++	cfg->bmiss_offload_max_vdev = __cpu_to_le32(3);
-++	cfg->roam_offload_max_vdev = __cpu_to_le32(3);
-++	cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8);
-++	cfg->num_mcast_groups = __cpu_to_le32(0);
-++	cfg->num_mcast_table_elems = __cpu_to_le32(0);
-++	cfg->mcast2ucast_mode = __cpu_to_le32(0);
-++	cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
-++	cfg->num_wds_entries = __cpu_to_le32(0x20);
-++	cfg->dma_burst_size = __cpu_to_le32(0);
-++	cfg->mac_aggr_delim = __cpu_to_le32(0);
-++	cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
-++	cfg->vow_config = __cpu_to_le32(0);
-++	cfg->gtk_offload_max_vdev = __cpu_to_le32(2);
-++	cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC);
-++	cfg->max_frag_entries = __cpu_to_le32(2);
-++	cfg->num_tdls_vdevs = __cpu_to_le32(1);
-++	cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20);
-++	cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2);
-++	cfg->num_multicast_filter_entries = __cpu_to_le32(5);
-++	cfg->num_wow_filters = __cpu_to_le32(0x16);
-++	cfg->num_keep_alive_pattern = __cpu_to_le32(6);
-++	cfg->keep_alive_pattern_size = __cpu_to_le32(0);
-++	cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1);
-++	cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1);
-++
-++	ath10k_wmi_put_host_mem_chunks(ar, chunks);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar,
-++				 const struct wmi_start_scan_arg *arg)
-++{
-++	struct wmi_tlv_start_scan_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len, chan_len, ssid_len, bssid_len, ie_len;
-++	__le32 *chans;
-++	struct wmi_ssid *ssids;
-++	struct wmi_mac_addr *addrs;
-++	void *ptr;
-++	int i, ret;
-++
-++	ret = ath10k_wmi_start_scan_verify(arg);
-++	if (ret)
-++		return ERR_PTR(ret);
-++
-++	chan_len = arg->n_channels * sizeof(__le32);
-++	ssid_len = arg->n_ssids * sizeof(struct wmi_ssid);
-++	bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr);
-++	ie_len = roundup(arg->ie_len, 4);
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (arg->n_channels ? sizeof(*tlv) + chan_len : 0) +
-++	      (arg->n_ssids ? sizeof(*tlv) + ssid_len : 0) +
-++	      (arg->n_bssids ? sizeof(*tlv) + bssid_len : 0) +
-++	      (arg->ie_len ? sizeof(*tlv) + ie_len : 0);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++
-++	ath10k_wmi_put_start_scan_common(&cmd->common, arg);
-++	cmd->burst_duration_ms = __cpu_to_le32(0);
-++	cmd->num_channels = __cpu_to_le32(arg->n_channels);
-++	cmd->num_ssids = __cpu_to_le32(arg->n_ssids);
-++	cmd->num_bssids = __cpu_to_le32(arg->n_bssids);
-++	cmd->ie_len = __cpu_to_le32(arg->ie_len);
-++	cmd->num_probes = __cpu_to_le32(3);
-++
-++	/* FIXME: There are some scan flag inconsistencies across firmwares,
-++	 * e.g. WMI-TLV inverts the logic behind the following flag.
-++	 */
-++	cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
-++	tlv->len = __cpu_to_le16(chan_len);
-++	chans = (void *)tlv->value;
-++	for (i = 0; i < arg->n_channels; i++)
-++		chans[i] = __cpu_to_le32(arg->channels[i]);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += chan_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
-++	tlv->len = __cpu_to_le16(ssid_len);
-++	ssids = (void *)tlv->value;
-++	for (i = 0; i < arg->n_ssids; i++) {
-++		ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len);
-++		memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len);
-++	}
-++
-++	ptr += sizeof(*tlv);
-++	ptr += ssid_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT);
-++	tlv->len = __cpu_to_le16(bssid_len);
-++	addrs = (void *)tlv->value;
-++	for (i = 0; i < arg->n_bssids; i++)
-++		ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += bssid_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(ie_len);
-++	memcpy(tlv->value, arg->ie, arg->ie_len);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += ie_len;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar,
-++				const struct wmi_stop_scan_arg *arg)
-++{
-++	struct wmi_stop_scan_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	u32 scan_id;
-++	u32 req_id;
-++
-++	if (arg->req_id > 0xFFF)
-++		return ERR_PTR(-EINVAL);
-++	if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	scan_id = arg->u.scan_id;
-++	scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX;
-++
-++	req_id = arg->req_id;
-++	req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->req_type = __cpu_to_le32(arg->req_type);
-++	cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id);
-++	cmd->scan_id = __cpu_to_le32(scan_id);
-++	cmd->scan_req_id = __cpu_to_le32(req_id);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar,
-++				  u32 vdev_id,
-++				  enum wmi_vdev_type vdev_type,
-++				  enum wmi_vdev_subtype vdev_subtype,
-++				  const u8 mac_addr[ETH_ALEN])
-++{
-++	struct wmi_vdev_create_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->vdev_type = __cpu_to_le32(vdev_type);
-++	cmd->vdev_subtype = __cpu_to_le32(vdev_subtype);
-++	ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct wmi_vdev_delete_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar,
-++				 const struct wmi_vdev_start_request_arg *arg,
-++				 bool restart)
-++{
-++	struct wmi_tlv_vdev_start_cmd *cmd;
-++	struct wmi_channel *ch;
-++	struct wmi_p2p_noa_descriptor *noa;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len;
-++	void *ptr;
-++	u32 flags = 0;
-++
-++	if (WARN_ON(arg->ssid && arg->ssid_len == 0))
-++		return ERR_PTR(-EINVAL);
-++	if (WARN_ON(arg->hidden_ssid && !arg->ssid))
-++		return ERR_PTR(-EINVAL);
-++	if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
-++		return ERR_PTR(-EINVAL);
-++
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (sizeof(*tlv) + sizeof(*ch)) +
-++	      (sizeof(*tlv) + 0);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	if (arg->hidden_ssid)
-++		flags |= WMI_VDEV_START_HIDDEN_SSID;
-++	if (arg->pmf_enabled)
-++		flags |= WMI_VDEV_START_PMF_ENABLED;
-++
-++	ptr = (void *)skb->data;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
-++	cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval);
-++	cmd->dtim_period = __cpu_to_le32(arg->dtim_period);
-++	cmd->flags = __cpu_to_le32(flags);
-++	cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate);
-++	cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power);
-++	cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack);
-++
-++	if (arg->ssid) {
-++		cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len);
-++		memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
-++	}
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
-++	tlv->len = __cpu_to_le16(sizeof(*ch));
-++	ch = (void *)tlv->value;
-++	ath10k_wmi_put_wmi_channel(ch, &arg->channel);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*ch);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
-++	tlv->len = 0;
-++	noa = (void *)tlv->value;
-++
-++	/* Note: This is a nested TLV containing:
-++	 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv]..
-++	 */
-++
-++	ptr += sizeof(*tlv);
-++	ptr += 0;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct wmi_vdev_stop_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
-++			      const u8 *bssid)
-++
-++{
-++	struct wmi_vdev_up_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->vdev_assoc_id = __cpu_to_le32(aid);
-++	ether_addr_copy(cmd->vdev_bssid.addr, bssid);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id)
-++{
-++	struct wmi_vdev_down_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id,
-++				     u32 param_id, u32 param_value)
-++{
-++	struct wmi_vdev_set_param_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->param_id = __cpu_to_le32(param_id);
-++	cmd->param_value = __cpu_to_le32(param_value);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar,
-++				       const struct wmi_vdev_install_key_arg *arg)
-++{
-++	struct wmi_vdev_install_key_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len;
-++	void *ptr;
-++
-++	if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL)
-++		return ERR_PTR(-EINVAL);
-++	if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL)
-++		return ERR_PTR(-EINVAL);
-++
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32));
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
-++	cmd->key_idx = __cpu_to_le32(arg->key_idx);
-++	cmd->key_flags = __cpu_to_le32(arg->key_flags);
-++	cmd->key_cipher = __cpu_to_le32(arg->key_cipher);
-++	cmd->key_len = __cpu_to_le32(arg->key_len);
-++	cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len);
-++	cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
-++
-++	if (arg->macaddr)
-++		ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32)));
-++	if (arg->key_data)
-++		memcpy(tlv->value, arg->key_data, arg->key_len);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += roundup(arg->key_len, sizeof(__le32));
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n");
-++	return skb;
-++}
-++
-++static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr,
-++					 const struct wmi_sta_uapsd_auto_trig_arg *arg)
-++{
-++	struct wmi_sta_uapsd_auto_trig_param *ac;
-++	struct wmi_tlv *tlv;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM);
-++	tlv->len = __cpu_to_le16(sizeof(*ac));
-++	ac = (void *)tlv->value;
-++
-++	ac->wmm_ac = __cpu_to_le32(arg->wmm_ac);
-++	ac->user_priority = __cpu_to_le32(arg->user_priority);
-++	ac->service_interval = __cpu_to_le32(arg->service_interval);
-++	ac->suspend_interval = __cpu_to_le32(arg->suspend_interval);
-++	ac->delay_interval = __cpu_to_le32(arg->delay_interval);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI,
-++		   "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n",
-++		   ac->wmm_ac, ac->user_priority, ac->service_interval,
-++		   ac->suspend_interval, ac->delay_interval);
-++
-++	return ptr + sizeof(*tlv) + sizeof(*ac);
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id,
-++				     const u8 peer_addr[ETH_ALEN],
-++				     const struct wmi_sta_uapsd_auto_trig_arg *args,
-++				     u32 num_ac)
-++{
-++	struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
-++	struct wmi_sta_uapsd_auto_trig_param *ac;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len;
-++	size_t ac_tlv_len;
-++	void *ptr;
-++	int i;
-++
-++	ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac));
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + ac_tlv_len;
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->num_ac = __cpu_to_le32(num_ac);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
-++	tlv->len = __cpu_to_le16(ac_tlv_len);
-++	ac = (void *)tlv->value;
-++
-++	ptr += sizeof(*tlv);
-++	for (i = 0; i < num_ac; i++)
-++		ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n");
-++	return skb;
-++}
-++
-++static void *ath10k_wmi_tlv_put_wmm(void *ptr,
-++				    const struct wmi_wmm_params_arg *arg)
-++{
-++	struct wmi_wmm_params *wmm;
-++	struct wmi_tlv *tlv;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS);
-++	tlv->len = __cpu_to_le16(sizeof(*wmm));
-++	wmm = (void *)tlv->value;
-++	ath10k_wmi_set_wmm_param(wmm, arg);
-++
-++	return ptr + sizeof(*tlv) + sizeof(*wmm);
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id,
-++				    const struct wmi_wmm_params_all_arg *arg)
-++{
-++	struct wmi_tlv_vdev_set_wmm_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len;
-++	void *ptr;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++
-++	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[0].params, &arg->ac_be);
-++	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[1].params, &arg->ac_bk);
-++	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[2].params, &arg->ac_vi);
-++	ath10k_wmi_set_wmm_param(&cmd->vdev_wmm_params[3].params, &arg->ac_vo);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar,
-++				    const struct wmi_sta_keepalive_arg *arg)
-++{
-++	struct wmi_tlv_sta_keepalive_cmd *cmd;
-++	struct wmi_sta_keepalive_arp_resp *arp;
-++	struct sk_buff *skb;
-++	struct wmi_tlv *tlv;
-++	void *ptr;
-++	size_t len;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + sizeof(*arp);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
-++	cmd->enabled = __cpu_to_le32(arg->enabled);
-++	cmd->method = __cpu_to_le32(arg->method);
-++	cmd->interval = __cpu_to_le32(arg->interval);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE);
-++	tlv->len = __cpu_to_le16(sizeof(*arp));
-++	arp = (void *)tlv->value;
-++
-++	arp->src_ip4_addr = arg->src_ip4_addr;
-++	arp->dest_ip4_addr = arg->dest_ip4_addr;
-++	ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n",
-++		   arg->vdev_id, arg->enabled, arg->method, arg->interval);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id,
-++				  const u8 peer_addr[ETH_ALEN])
-++{
-++	struct wmi_tlv_peer_create_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->peer_type = __cpu_to_le32(WMI_TLV_PEER_TYPE_DEFAULT); /* FIXME */
-++	ether_addr_copy(cmd->peer_addr.addr, peer_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id,
-++				  const u8 peer_addr[ETH_ALEN])
-++{
-++	struct wmi_peer_delete_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id,
-++				 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
-++{
-++	struct wmi_peer_flush_tids_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id,
-++				     const u8 *peer_addr,
-++				     enum wmi_peer_param param_id,
-++				     u32 param_value)
-++{
-++	struct wmi_peer_set_param_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->param_id = __cpu_to_le32(param_id);
-++	cmd->param_value = __cpu_to_le32(param_value);
-++	ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar,
-++				 const struct wmi_peer_assoc_complete_arg *arg)
-++{
-++	struct wmi_tlv_peer_assoc_cmd *cmd;
-++	struct wmi_vht_rate_set *vht_rate;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len, legacy_rate_len, ht_rate_len;
-++	void *ptr;
-++
-++	if (arg->peer_mpdu_density > 16)
-++		return ERR_PTR(-EINVAL);
-++	if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES)
-++		return ERR_PTR(-EINVAL);
-++	if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES)
-++		return ERR_PTR(-EINVAL);
-++
-++	legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates,
-++				  sizeof(__le32));
-++	ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32));
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (sizeof(*tlv) + legacy_rate_len) +
-++	      (sizeof(*tlv) + ht_rate_len) +
-++	      (sizeof(*tlv) + sizeof(*vht_rate));
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++
-++	cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
-++	cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1);
-++	cmd->assoc_id = __cpu_to_le32(arg->peer_aid);
-++	cmd->flags = __cpu_to_le32(arg->peer_flags);
-++	cmd->caps = __cpu_to_le32(arg->peer_caps);
-++	cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval);
-++	cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps);
-++	cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu);
-++	cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density);
-++	cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps);
-++	cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams);
-++	cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps);
-++	cmd->phy_mode = __cpu_to_le32(arg->peer_phymode);
-++	cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates);
-++	cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates);
-++	ether_addr_copy(cmd->mac_addr.addr, arg->addr);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(legacy_rate_len);
-++	memcpy(tlv->value, arg->peer_legacy_rates.rates,
-++	       arg->peer_legacy_rates.num_rates);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += legacy_rate_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(ht_rate_len);
-++	memcpy(tlv->value, arg->peer_ht_rates.rates,
-++	       arg->peer_ht_rates.num_rates);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += ht_rate_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET);
-++	tlv->len = __cpu_to_le16(sizeof(*vht_rate));
-++	vht_rate = (void *)tlv->value;
-++
-++	vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate);
-++	vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set);
-++	vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate);
-++	vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*vht_rate);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
-++				 enum wmi_sta_ps_mode psmode)
-++{
-++	struct wmi_sta_powersave_mode_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->sta_ps_mode = __cpu_to_le32(psmode);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id,
-++				 enum wmi_sta_powersave_param param_id,
-++				 u32 param_value)
-++{
-++	struct wmi_sta_powersave_param_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->param_id = __cpu_to_le32(param_id);
-++	cmd->param_value = __cpu_to_le32(param_value);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac,
-++				enum wmi_ap_ps_peer_param param_id, u32 value)
-++{
-++	struct wmi_ap_ps_peer_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	if (!mac)
-++		return ERR_PTR(-EINVAL);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->param_id = __cpu_to_le32(param_id);
-++	cmd->param_value = __cpu_to_le32(value);
-++	ether_addr_copy(cmd->peer_macaddr.addr, mac);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar,
-++				     const struct wmi_scan_chan_list_arg *arg)
-++{
-++	struct wmi_tlv_scan_chan_list_cmd *cmd;
-++	struct wmi_channel *ci;
-++	struct wmi_channel_arg *ch;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t chans_len, len;
-++	int i;
-++	void *ptr, *chans;
-++
-++	chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci));
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (sizeof(*tlv) + chans_len);
-++
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
-++	tlv->len = __cpu_to_le16(chans_len);
-++	chans = (void *)tlv->value;
-++
-++	for (i = 0; i < arg->n_channels; i++) {
-++		ch = &arg->channels[i];
-++
-++		tlv = chans;
-++		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL);
-++		tlv->len = __cpu_to_le16(sizeof(*ci));
-++		ci = (void *)tlv->value;
-++
-++		ath10k_wmi_put_wmi_channel(ci, ch);
-++
-++		chans += sizeof(*tlv);
-++		chans += sizeof(*ci);
-++	}
-++
-++	ptr += sizeof(*tlv);
-++	ptr += chans_len;
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id,
-++				 const void *bcn, size_t bcn_len,
-++				 u32 bcn_paddr, bool dtim_zero,
-++				 bool deliver_cab)
-++
-++{
-++	struct wmi_bcn_tx_ref_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	struct ieee80211_hdr *hdr;
-++	u16 fc;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	hdr = (struct ieee80211_hdr *)bcn;
-++	fc = le16_to_cpu(hdr->frame_control);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->data_len = __cpu_to_le32(bcn_len);
-++	cmd->data_ptr = __cpu_to_le32(bcn_paddr);
-++	cmd->msdu_id = 0;
-++	cmd->frame_control = __cpu_to_le32(fc);
-++	cmd->flags = 0;
-++
-++	if (dtim_zero)
-++		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO);
-++
-++	if (deliver_cab)
-++		cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar,
-++				   const struct wmi_wmm_params_all_arg *arg)
-++{
-++	struct wmi_tlv_pdev_set_wmm_cmd *cmd;
-++	struct wmi_wmm_params *wmm;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len;
-++	void *ptr;
-++
-++	len = (sizeof(*tlv) + sizeof(*cmd)) +
-++	      (4 * (sizeof(*tlv) + sizeof(*wmm)));
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++
-++	/* nothing to set here */
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be);
-++	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk);
-++	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi);
-++	ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
-++{
-++	struct wmi_request_stats_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->stats_id = __cpu_to_le32(stats_mask);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar,
-++				    enum wmi_force_fw_hang_type type,
-++				    u32 delay_ms)
-++{
-++	struct wmi_force_fw_hang_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++
-++	skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd));
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	tlv = (void *)skb->data;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->type = __cpu_to_le32(type);
-++	cmd->delay_ms = __cpu_to_le32(delay_ms);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable,
-++				 u32 log_level) {
-++	struct wmi_tlv_dbglog_cmd *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	size_t len, bmap_len;
-++	u32 value;
-++	void *ptr;
-++
-++	if (module_enable) {
-++		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
-++				module_enable,
-++				WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE);
-++	} else {
-++		value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(
-++				WMI_TLV_DBGLOG_ALL_MODULES,
-++				WMI_TLV_DBGLOG_LOG_LEVEL_WARN);
-++	}
-++
-++	bmap_len = 0;
-++	len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len;
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL);
-++	cmd->value = __cpu_to_le32(value);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
-++	tlv->len = __cpu_to_le16(bmap_len);
-++
-++	/* nothing to do here */
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(bmap_len);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter)
-++{
-++	struct wmi_tlv_pktlog_enable *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	void *ptr;
-++	size_t len;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->filter = __cpu_to_le32(filter);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n",
-++		   filter);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar)
-++{
-++	struct wmi_tlv_pktlog_disable *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	void *ptr;
-++	size_t len;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n");
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id,
-++			       u32 tim_ie_offset, struct sk_buff *bcn,
-++			       u32 prb_caps, u32 prb_erp, void *prb_ies,
-++			       size_t prb_ies_len)
-++{
-++	struct wmi_tlv_bcn_tmpl_cmd *cmd;
-++	struct wmi_tlv_bcn_prb_info *info;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	void *ptr;
-++	size_t len;
-++
-++	if (WARN_ON(prb_ies_len > 0 && !prb_ies))
-++		return ERR_PTR(-EINVAL);
-++
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + sizeof(*info) + prb_ies_len +
-++	      sizeof(*tlv) + roundup(bcn->len, 4);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset);
-++	cmd->buf_len = __cpu_to_le32(bcn->len);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	/* FIXME: prb_ies_len should be probably aligned to 4byte boundary but
-++	 * then it is then impossible to pass original ie len.
-++	 * This chunk is not used yet so if setting probe resp template yields
-++	 * problems with beaconing or crashes firmware look here.
-++	 */
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
-++	tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len);
-++	info = (void *)tlv->value;
-++	info->caps = __cpu_to_le32(prb_caps);
-++	info->erp = __cpu_to_le32(prb_erp);
-++	memcpy(info->ies, prb_ies, prb_ies_len);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*info);
-++	ptr += prb_ies_len;
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(roundup(bcn->len, 4));
-++	memcpy(tlv->value, bcn->data, bcn->len);
-++
-++	/* FIXME: Adjust TSF? */
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n",
-++		   vdev_id);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id,
-++			       struct sk_buff *prb)
-++{
-++	struct wmi_tlv_prb_tmpl_cmd *cmd;
-++	struct wmi_tlv_bcn_prb_info *info;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	void *ptr;
-++	size_t len;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + sizeof(*info) +
-++	      sizeof(*tlv) + roundup(prb->len, 4);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->buf_len = __cpu_to_le32(prb->len);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO);
-++	tlv->len = __cpu_to_le16(sizeof(*info));
-++	info = (void *)tlv->value;
-++	info->caps = 0;
-++	info->erp = 0;
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*info);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(roundup(prb->len, 4));
-++	memcpy(tlv->value, prb->data, prb->len);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n",
-++		   vdev_id);
-++	return skb;
-++}
-++
-++static struct sk_buff *
-++ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id,
-++				    const u8 *p2p_ie)
-++{
-++	struct wmi_tlv_p2p_go_bcn_ie *cmd;
-++	struct wmi_tlv *tlv;
-++	struct sk_buff *skb;
-++	void *ptr;
-++	size_t len;
-++
-++	len = sizeof(*tlv) + sizeof(*cmd) +
-++	      sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4);
-++	skb = ath10k_wmi_alloc_skb(ar, len);
-++	if (!skb)
-++		return ERR_PTR(-ENOMEM);
-++
-++	ptr = (void *)skb->data;
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE);
-++	tlv->len = __cpu_to_le16(sizeof(*cmd));
-++	cmd = (void *)tlv->value;
-++	cmd->vdev_id = __cpu_to_le32(vdev_id);
-++	cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += sizeof(*cmd);
-++
-++	tlv = ptr;
-++	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
-++	tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4));
-++	memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2);
-++
-++	ptr += sizeof(*tlv);
-++	ptr += roundup(p2p_ie[1] + 2, 4);
-++
-++	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n",
-++		   vdev_id);
-++	return skb;
-++}
-++
-++/****************/
-++/* TLV mappings */
-++/****************/
-++
-++static struct wmi_cmd_map wmi_tlv_cmd_map = {
-++	.init_cmdid = WMI_TLV_INIT_CMDID,
-++	.start_scan_cmdid = WMI_TLV_START_SCAN_CMDID,
-++	.stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID,
-++	.scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID,
-++	.scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
-++	.pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID,
-++	.pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID,
-++	.pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID,
-++	.pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
-++	.pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
-++	.pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
-++	.pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
-++	.pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
-++	.pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
-++	.pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
-++	.pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
-++	.pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
-++	.pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
-++	.vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID,
-++	.vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID,
-++	.vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID,
-++	.vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
-++	.vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID,
-++	.vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID,
-++	.vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID,
-++	.vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID,
-++	.vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID,
-++	.peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID,
-++	.peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID,
-++	.peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID,
-++	.peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID,
-++	.peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID,
-++	.peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
-++	.peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
-++	.peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID,
-++	.bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID,
-++	.pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID,
-++	.bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID,
-++	.bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID,
-++	.prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
-++	.mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID,
-++	.prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID,
-++	.addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID,
-++	.addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID,
-++	.addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID,
-++	.delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID,
-++	.addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID,
-++	.send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID,
-++	.sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID,
-++	.sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
-++	.sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID,
-++	.pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID,
-++	.pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID,
-++	.roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE,
-++	.roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
-++	.roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD,
-++	.roam_scan_rssi_change_threshold =
-++				WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	.roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
-++	.ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE,
-++	.ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
-++	.ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD,
-++	.p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO,
-++	.p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
-++	.p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE,
-++	.p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
-++	.p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
-++	.ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID,
-++	.ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
-++	.peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID,
-++	.wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID,
-++	.wlan_profile_set_hist_intvl_cmdid =
-++				WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
-++	.wlan_profile_get_profile_data_cmdid =
-++				WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
-++	.wlan_profile_enable_profile_id_cmdid =
-++				WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
-++	.wlan_profile_list_profile_id_cmdid =
-++				WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
-++	.pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID,
-++	.pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID,
-++	.add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID,
-++	.rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID,
-++	.wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID,
-++	.wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
-++	.wow_enable_disable_wake_event_cmdid =
-++				WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
-++	.wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID,
-++	.wow_hostwakeup_from_sleep_cmdid =
-++				WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
-++	.rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID,
-++	.rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID,
-++	.vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID,
-++	.vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
-++	.request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID,
-++	.set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID,
-++	.network_list_offload_config_cmdid =
-++				WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID,
-++	.gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID,
-++	.csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID,
-++	.csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
-++	.chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID,
-++	.peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID,
-++	.peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID,
-++	.sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
-++	.sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
-++	.sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID,
-++	.echo_cmdid = WMI_TLV_ECHO_CMDID,
-++	.pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID,
-++	.dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID,
-++	.pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID,
-++	.pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID,
-++	.vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
-++	.vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
-++	.force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID,
-++	.gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID,
-++	.gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID,
-++	.pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED,
-++	.vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
-++};
-++
-++static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
-++	.tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK,
-++	.rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
-++	.txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
-++	.txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
-++	.txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
-++	.beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
-++	.beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
-++	.resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
-++	.protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
-++	.dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
-++	.non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
-++	.agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
-++	.sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
-++	.ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
-++	.ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE,
-++	.ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
-++	.ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
-++	.ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
-++	.ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
-++	.ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
-++	.ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
-++	.ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
-++	.ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
-++	.l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
-++	.dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
-++	.pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
-++	.pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
-++	.pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
-++	.pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
-++	.pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
-++	.vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
-++	.peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
-++	.bcnflt_stats_update_period =
-++				WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
-++	.pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS,
-++	.arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
-++	.dcs = WMI_TLV_PDEV_PARAM_DCS,
-++	.ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE,
-++	.ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
-++	.ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
-++	.ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
-++	.ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
-++	.dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
-++	.proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA,
-++	.idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
-++	.power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
-++	.fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED,
-++	.burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
-++	.burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
-++	.cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
-++};
-++
-++static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
-++	.rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD,
-++	.fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
-++	.beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
-++	.listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
-++	.multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
-++	.mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
-++	.slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME,
-++	.preamble = WMI_TLV_VDEV_PARAM_PREAMBLE,
-++	.swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME,
-++	.wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
-++	.wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
-++	.wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
-++	.dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
-++	.wmi_vdev_oc_scheduler_air_time_limit =
-++				WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
-++	.wds = WMI_TLV_VDEV_PARAM_WDS,
-++	.atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
-++	.bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
-++	.bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
-++	.bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
-++	.feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM,
-++	.chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH,
-++	.chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
-++	.disable_htprotection =	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
-++	.sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
-++	.mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE,
-++	.protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
-++	.fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE,
-++	.sgi = WMI_TLV_VDEV_PARAM_SGI,
-++	.ldpc = WMI_TLV_VDEV_PARAM_LDPC,
-++	.tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC,
-++	.rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC,
-++	.intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
-++	.def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID,
-++	.nss = WMI_TLV_VDEV_PARAM_NSS,
-++	.bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
-++	.mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
-++	.mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
-++	.dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
-++	.unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
-++	.ap_keepalive_min_idle_inactive_time_secs =
-++		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
-++	.ap_keepalive_max_idle_inactive_time_secs =
-++		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
-++	.ap_keepalive_max_unresponsive_time_secs =
-++		WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
-++	.ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
-++	.mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED,
-++	.enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
-++	.txbf = WMI_TLV_VDEV_PARAM_TXBF,
-++	.packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
-++	.drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
-++	.tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
-++	.ap_detect_out_of_sync_sleeping_sta_time_secs =
-++					WMI_TLV_VDEV_PARAM_UNSUPPORTED,
-++};
-++
-++static const struct wmi_ops wmi_tlv_ops = {
-++	.rx = ath10k_wmi_tlv_op_rx,
-++	.map_svc = wmi_tlv_svc_map,
-++
-++	.pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
-++	.pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
-++	.pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
-++	.pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
-++	.pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
-++	.pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
-++	.pull_phyerr = ath10k_wmi_tlv_op_pull_phyerr_ev,
-++	.pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
-++	.pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
-++	.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
-++
-++	.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
-++	.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
-++	.gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
-++	.gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
-++	.gen_init = ath10k_wmi_tlv_op_gen_init,
-++	.gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
-++	.gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
-++	.gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
-++	.gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
-++	.gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
-++	.gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
-++	.gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
-++	.gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
-++	.gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
-++	.gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
-++	.gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
-++	.gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
-++	.gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
-++	.gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
-++	.gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
-++	.gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
-++	.gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
-++	.gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
-++	.gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
-++	.gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
-++	.gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
-++	.gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
-++	.gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
-++	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
-++	/* .gen_mgmt_tx = not implemented; HTT is used */
-++	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
-++	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
-++	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
-++	/* .gen_pdev_set_quiet_mode not implemented */
-++	/* .gen_pdev_get_temperature not implemented */
-++	/* .gen_addba_clear_resp not implemented */
-++	/* .gen_addba_send not implemented */
-++	/* .gen_addba_set_resp not implemented */
-++	/* .gen_delba_send not implemented */
-++	.gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
-++	.gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
-++	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
-++	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
-++	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
-++};
-++
-++/************/
-++/* TLV init */
-++/************/
-++
-++void ath10k_wmi_tlv_attach(struct ath10k *ar)
-++{
-++	ar->wmi.cmd = &wmi_tlv_cmd_map;
-++	ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
-++	ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
-++	ar->wmi.ops = &wmi_tlv_ops;
-++}
-+--- /dev/null
-++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
-+@@ -0,0 +1,1459 @@
-++/*
-++ * Copyright (c) 2005-2011 Atheros Communications Inc.
-++ * Copyright (c) 2011-2014 Qualcomm Atheros, Inc.
-++ *
-++ * 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 _WMI_TLV_H
-++#define _WMI_TLV_H
-++
-++#define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
-++#define WMI_TLV_EV(grp_id) (((grp_id) << 12) | 0x1)
-++#define WMI_TLV_CMD_UNSUPPORTED 0
-++#define WMI_TLV_PDEV_PARAM_UNSUPPORTED 0
-++#define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
-++
-++enum wmi_tlv_grp_id {
-++	WMI_TLV_GRP_START = 0x3,
-++	WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START,
-++	WMI_TLV_GRP_PDEV,
-++	WMI_TLV_GRP_VDEV,
-++	WMI_TLV_GRP_PEER,
-++	WMI_TLV_GRP_MGMT,
-++	WMI_TLV_GRP_BA_NEG,
-++	WMI_TLV_GRP_STA_PS,
-++	WMI_TLV_GRP_DFS,
-++	WMI_TLV_GRP_ROAM,
-++	WMI_TLV_GRP_OFL_SCAN,
-++	WMI_TLV_GRP_P2P,
-++	WMI_TLV_GRP_AP_PS,
-++	WMI_TLV_GRP_RATECTL,
-++	WMI_TLV_GRP_PROFILE,
-++	WMI_TLV_GRP_SUSPEND,
-++	WMI_TLV_GRP_BCN_FILTER,
-++	WMI_TLV_GRP_WOW,
-++	WMI_TLV_GRP_RTT,
-++	WMI_TLV_GRP_SPECTRAL,
-++	WMI_TLV_GRP_STATS,
-++	WMI_TLV_GRP_ARP_NS_OFL,
-++	WMI_TLV_GRP_NLO_OFL,
-++	WMI_TLV_GRP_GTK_OFL,
-++	WMI_TLV_GRP_CSA_OFL,
-++	WMI_TLV_GRP_CHATTER,
-++	WMI_TLV_GRP_TID_ADDBA,
-++	WMI_TLV_GRP_MISC,
-++	WMI_TLV_GRP_GPIO,
-++	WMI_TLV_GRP_FWTEST,
-++	WMI_TLV_GRP_TDLS,
-++	WMI_TLV_GRP_RESMGR,
-++	WMI_TLV_GRP_STA_SMPS,
-++	WMI_TLV_GRP_WLAN_HB,
-++	WMI_TLV_GRP_RMC,
-++	WMI_TLV_GRP_MHF_OFL,
-++	WMI_TLV_GRP_LOCATION_SCAN,
-++	WMI_TLV_GRP_OEM,
-++	WMI_TLV_GRP_NAN,
-++	WMI_TLV_GRP_COEX,
-++	WMI_TLV_GRP_OBSS_OFL,
-++	WMI_TLV_GRP_LPI,
-++	WMI_TLV_GRP_EXTSCAN,
-++	WMI_TLV_GRP_DHCP_OFL,
-++	WMI_TLV_GRP_IPA,
-++	WMI_TLV_GRP_MDNS_OFL,
-++	WMI_TLV_GRP_SAP_OFL,
-++};
-++
-++enum wmi_tlv_cmd_id {
-++	WMI_TLV_INIT_CMDID = 0x1,
-++	WMI_TLV_START_SCAN_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_SCAN),
-++	WMI_TLV_STOP_SCAN_CMDID,
-++	WMI_TLV_SCAN_CHAN_LIST_CMDID,
-++	WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID,
-++	WMI_TLV_SCAN_UPDATE_REQUEST_CMDID,
-++	WMI_TLV_SCAN_PROB_REQ_OUI_CMDID,
-++	WMI_TLV_PDEV_SET_REGDOMAIN_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_PDEV),
-++	WMI_TLV_PDEV_SET_CHANNEL_CMDID,
-++	WMI_TLV_PDEV_SET_PARAM_CMDID,
-++	WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID,
-++	WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID,
-++	WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID,
-++	WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID,
-++	WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID,
-++	WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID,
-++	WMI_TLV_PDEV_SET_QUIET_MODE_CMDID,
-++	WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID,
-++	WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID,
-++	WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID,
-++	WMI_TLV_PDEV_DUMP_CMDID,
-++	WMI_TLV_PDEV_SET_LED_CONFIG_CMDID,
-++	WMI_TLV_PDEV_GET_TEMPERATURE_CMDID,
-++	WMI_TLV_PDEV_SET_LED_FLASHING_CMDID,
-++	WMI_TLV_VDEV_CREATE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_VDEV),
-++	WMI_TLV_VDEV_DELETE_CMDID,
-++	WMI_TLV_VDEV_START_REQUEST_CMDID,
-++	WMI_TLV_VDEV_RESTART_REQUEST_CMDID,
-++	WMI_TLV_VDEV_UP_CMDID,
-++	WMI_TLV_VDEV_STOP_CMDID,
-++	WMI_TLV_VDEV_DOWN_CMDID,
-++	WMI_TLV_VDEV_SET_PARAM_CMDID,
-++	WMI_TLV_VDEV_INSTALL_KEY_CMDID,
-++	WMI_TLV_VDEV_WNM_SLEEPMODE_CMDID,
-++	WMI_TLV_VDEV_WMM_ADDTS_CMDID,
-++	WMI_TLV_VDEV_WMM_DELTS_CMDID,
-++	WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID,
-++	WMI_TLV_VDEV_SET_GTX_PARAMS_CMDID,
-++	WMI_TLV_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMDID,
-++	WMI_TLV_VDEV_PLMREQ_START_CMDID,
-++	WMI_TLV_VDEV_PLMREQ_STOP_CMDID,
-++	WMI_TLV_PEER_CREATE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_PEER),
-++	WMI_TLV_PEER_DELETE_CMDID,
-++	WMI_TLV_PEER_FLUSH_TIDS_CMDID,
-++	WMI_TLV_PEER_SET_PARAM_CMDID,
-++	WMI_TLV_PEER_ASSOC_CMDID,
-++	WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID,
-++	WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID,
-++	WMI_TLV_PEER_MCAST_GROUP_CMDID,
-++	WMI_TLV_PEER_INFO_REQ_CMDID,
-++	WMI_TLV_PEER_GET_ESTIMATED_LINKSPEED_CMDID,
-++	WMI_TLV_BCN_TX_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_MGMT),
-++	WMI_TLV_PDEV_SEND_BCN_CMDID,
-++	WMI_TLV_BCN_TMPL_CMDID,
-++	WMI_TLV_BCN_FILTER_RX_CMDID,
-++	WMI_TLV_PRB_REQ_FILTER_RX_CMDID,
-++	WMI_TLV_MGMT_TX_CMDID,
-++	WMI_TLV_PRB_TMPL_CMDID,
-++	WMI_TLV_ADDBA_CLEAR_RESP_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_BA_NEG),
-++	WMI_TLV_ADDBA_SEND_CMDID,
-++	WMI_TLV_ADDBA_STATUS_CMDID,
-++	WMI_TLV_DELBA_SEND_CMDID,
-++	WMI_TLV_ADDBA_SET_RESP_CMDID,
-++	WMI_TLV_SEND_SINGLEAMSDU_CMDID,
-++	WMI_TLV_STA_POWERSAVE_MODE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_STA_PS),
-++	WMI_TLV_STA_POWERSAVE_PARAM_CMDID,
-++	WMI_TLV_STA_MIMO_PS_MODE_CMDID,
-++	WMI_TLV_PDEV_DFS_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_DFS),
-++	WMI_TLV_PDEV_DFS_DISABLE_CMDID,
-++	WMI_TLV_DFS_PHYERR_FILTER_ENA_CMDID,
-++	WMI_TLV_DFS_PHYERR_FILTER_DIS_CMDID,
-++	WMI_TLV_ROAM_SCAN_MODE = WMI_TLV_CMD(WMI_TLV_GRP_ROAM),
-++	WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD,
-++	WMI_TLV_ROAM_SCAN_PERIOD,
-++	WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	WMI_TLV_ROAM_AP_PROFILE,
-++	WMI_TLV_ROAM_CHAN_LIST,
-++	WMI_TLV_ROAM_SCAN_CMD,
-++	WMI_TLV_ROAM_SYNCH_COMPLETE,
-++	WMI_TLV_ROAM_SET_RIC_REQUEST_CMDID,
-++	WMI_TLV_ROAM_INVOKE_CMDID,
-++	WMI_TLV_OFL_SCAN_ADD_AP_PROFILE = WMI_TLV_CMD(WMI_TLV_GRP_OFL_SCAN),
-++	WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE,
-++	WMI_TLV_OFL_SCAN_PERIOD,
-++	WMI_TLV_P2P_DEV_SET_DEVICE_INFO = WMI_TLV_CMD(WMI_TLV_GRP_P2P),
-++	WMI_TLV_P2P_DEV_SET_DISCOVERABILITY,
-++	WMI_TLV_P2P_GO_SET_BEACON_IE,
-++	WMI_TLV_P2P_GO_SET_PROBE_RESP_IE,
-++	WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID,
-++	WMI_TLV_P2P_DISC_OFFLOAD_CONFIG_CMDID,
-++	WMI_TLV_P2P_DISC_OFFLOAD_APPIE_CMDID,
-++	WMI_TLV_P2P_DISC_OFFLOAD_PATTERN_CMDID,
-++	WMI_TLV_P2P_SET_OPPPS_PARAM_CMDID,
-++	WMI_TLV_AP_PS_PEER_PARAM_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_AP_PS),
-++	WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID,
-++	WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_RATECTL),
-++	WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_PROFILE),
-++	WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
-++	WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
-++	WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
-++	WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
-++	WMI_TLV_PDEV_SUSPEND_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_SUSPEND),
-++	WMI_TLV_PDEV_RESUME_CMDID,
-++	WMI_TLV_ADD_BCN_FILTER_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_BCN_FILTER),
-++	WMI_TLV_RMV_BCN_FILTER_CMDID,
-++	WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_WOW),
-++	WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID,
-++	WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
-++	WMI_TLV_WOW_ENABLE_CMDID,
-++	WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
-++	WMI_TLV_WOW_ACER_IOAC_ADD_KEEPALIVE_CMDID,
-++	WMI_TLV_WOW_ACER_IOAC_DEL_KEEPALIVE_CMDID,
-++	WMI_TLV_WOW_ACER_IOAC_ADD_WAKE_PATTERN_CMDID,
-++	WMI_TLV_WOW_ACER_IOAC_DEL_WAKE_PATTERN_CMDID,
-++	WMI_TLV_D0_WOW_ENABLE_DISABLE_CMDID,
-++	WMI_TLV_EXTWOW_ENABLE_CMDID,
-++	WMI_TLV_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID,
-++	WMI_TLV_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID,
-++	WMI_TLV_RTT_MEASREQ_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_RTT),
-++	WMI_TLV_RTT_TSF_CMDID,
-++	WMI_TLV_SPECTRAL_SCAN_CONF_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_SPECTRAL),
-++	WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID,
-++	WMI_TLV_REQUEST_STATS_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_STATS),
-++	WMI_TLV_MCC_SCHED_TRAFFIC_STATS_CMDID,
-++	WMI_TLV_REQUEST_STATS_EXT_CMDID,
-++	WMI_TLV_REQUEST_LINK_STATS_CMDID,
-++	WMI_TLV_START_LINK_STATS_CMDID,
-++	WMI_TLV_CLEAR_LINK_STATS_CMDID,
-++	WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_ARP_NS_OFL),
-++	WMI_TLV_ADD_PROACTIVE_ARP_RSP_PATTERN_CMDID,
-++	WMI_TLV_DEL_PROACTIVE_ARP_RSP_PATTERN_CMDID,
-++	WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID =
-++			WMI_TLV_CMD(WMI_TLV_GRP_NLO_OFL),
-++	WMI_TLV_APFIND_CMDID,
-++	WMI_TLV_GTK_OFFLOAD_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_GTK_OFL),
-++	WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_CSA_OFL),
-++	WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID,
-++	WMI_TLV_CHATTER_SET_MODE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_CHATTER),
-++	WMI_TLV_CHATTER_ADD_COALESCING_FILTER_CMDID,
-++	WMI_TLV_CHATTER_DELETE_COALESCING_FILTER_CMDID,
-++	WMI_TLV_CHATTER_COALESCING_QUERY_CMDID,
-++	WMI_TLV_PEER_TID_ADDBA_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_TID_ADDBA),
-++	WMI_TLV_PEER_TID_DELBA_CMDID,
-++	WMI_TLV_STA_DTIM_PS_METHOD_CMDID,
-++	WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID,
-++	WMI_TLV_STA_KEEPALIVE_CMDID,
-++	WMI_TLV_BA_REQ_SSN_CMDID,
-++	WMI_TLV_ECHO_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_MISC),
-++	WMI_TLV_PDEV_UTF_CMDID,
-++	WMI_TLV_DBGLOG_CFG_CMDID,
-++	WMI_TLV_PDEV_QVIT_CMDID,
-++	WMI_TLV_PDEV_FTM_INTG_CMDID,
-++	WMI_TLV_VDEV_SET_KEEPALIVE_CMDID,
-++	WMI_TLV_VDEV_GET_KEEPALIVE_CMDID,
-++	WMI_TLV_FORCE_FW_HANG_CMDID,
-++	WMI_TLV_SET_MCASTBCAST_FILTER_CMDID,
-++	WMI_TLV_THERMAL_MGMT_CMDID,
-++	WMI_TLV_HOST_AUTO_SHUTDOWN_CFG_CMDID,
-++	WMI_TLV_TPC_CHAINMASK_CONFIG_CMDID,
-++	WMI_TLV_SET_ANTENNA_DIVERSITY_CMDID,
-++	WMI_TLV_GPIO_CONFIG_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_GPIO),
-++	WMI_TLV_GPIO_OUTPUT_CMDID,
-++	WMI_TLV_TXBF_CMDID,
-++	WMI_TLV_FWTEST_VDEV_MCC_SET_TBTT_MODE_CMDID =
-++			WMI_TLV_CMD(WMI_TLV_GRP_FWTEST),
-++	WMI_TLV_FWTEST_P2P_SET_NOA_PARAM_CMDID,
-++	WMI_TLV_UNIT_TEST_CMDID,
-++	WMI_TLV_TDLS_SET_STATE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_TDLS),
-++	WMI_TLV_TDLS_PEER_UPDATE_CMDID,
-++	WMI_TLV_TDLS_SET_OFFCHAN_MODE_CMDID,
-++	WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_RESMGR),
-++	WMI_TLV_RESMGR_SET_CHAN_TIME_QUOTA_CMDID,
-++	WMI_TLV_RESMGR_SET_CHAN_LATENCY_CMDID,
-++	WMI_TLV_STA_SMPS_FORCE_MODE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_STA_SMPS),
-++	WMI_TLV_STA_SMPS_PARAM_CMDID,
-++	WMI_TLV_HB_SET_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_WLAN_HB),
-++	WMI_TLV_HB_SET_TCP_PARAMS_CMDID,
-++	WMI_TLV_HB_SET_TCP_PKT_FILTER_CMDID,
-++	WMI_TLV_HB_SET_UDP_PARAMS_CMDID,
-++	WMI_TLV_HB_SET_UDP_PKT_FILTER_CMDID,
-++	WMI_TLV_RMC_SET_MODE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_RMC),
-++	WMI_TLV_RMC_SET_ACTION_PERIOD_CMDID,
-++	WMI_TLV_RMC_CONFIG_CMDID,
-++	WMI_TLV_MHF_OFFLOAD_SET_MODE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_MHF_OFL),
-++	WMI_TLV_MHF_OFFLOAD_PLUMB_ROUTING_TBL_CMDID,
-++	WMI_TLV_BATCH_SCAN_ENABLE_CMDID =
-++			WMI_TLV_CMD(WMI_TLV_GRP_LOCATION_SCAN),
-++	WMI_TLV_BATCH_SCAN_DISABLE_CMDID,
-++	WMI_TLV_BATCH_SCAN_TRIGGER_RESULT_CMDID,
-++	WMI_TLV_OEM_REQ_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_OEM),
-++	WMI_TLV_NAN_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_NAN),
-++	WMI_TLV_MODEM_POWER_STATE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_COEX),
-++	WMI_TLV_CHAN_AVOID_UPDATE_CMDID,
-++	WMI_TLV_OBSS_SCAN_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_OBSS_OFL),
-++	WMI_TLV_OBSS_SCAN_DISABLE_CMDID,
-++	WMI_TLV_LPI_MGMT_SNOOPING_CONFIG_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_LPI),
-++	WMI_TLV_LPI_START_SCAN_CMDID,
-++	WMI_TLV_LPI_STOP_SCAN_CMDID,
-++	WMI_TLV_EXTSCAN_START_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_EXTSCAN),
-++	WMI_TLV_EXTSCAN_STOP_CMDID,
-++	WMI_TLV_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID,
-++	WMI_TLV_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID,
-++	WMI_TLV_EXTSCAN_GET_CACHED_RESULTS_CMDID,
-++	WMI_TLV_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMDID,
-++	WMI_TLV_EXTSCAN_SET_CAPABILITIES_CMDID,
-++	WMI_TLV_EXTSCAN_GET_CAPABILITIES_CMDID,
-++	WMI_TLV_SET_DHCP_SERVER_OFFLOAD_CMDID =
-++			WMI_TLV_CMD(WMI_TLV_GRP_DHCP_OFL),
-++	WMI_TLV_IPA_OFFLOAD_ENABLE_DISABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_IPA),
-++	WMI_TLV_MDNS_OFFLOAD_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_MDNS_OFL),
-++	WMI_TLV_MDNS_SET_FQDN_CMDID,
-++	WMI_TLV_MDNS_SET_RESPONSE_CMDID,
-++	WMI_TLV_MDNS_GET_STATS_CMDID,
-++	WMI_TLV_SAP_OFL_ENABLE_CMDID = WMI_TLV_CMD(WMI_TLV_GRP_SAP_OFL),
-++};
-++
-++enum wmi_tlv_event_id {
-++	WMI_TLV_SERVICE_READY_EVENTID = 0x1,
-++	WMI_TLV_READY_EVENTID,
-++	WMI_TLV_SCAN_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_SCAN),
-++	WMI_TLV_PDEV_TPC_CONFIG_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PDEV),
-++	WMI_TLV_CHAN_INFO_EVENTID,
-++	WMI_TLV_PHYERR_EVENTID,
-++	WMI_TLV_PDEV_DUMP_EVENTID,
-++	WMI_TLV_TX_PAUSE_EVENTID,
-++	WMI_TLV_DFS_RADAR_EVENTID,
-++	WMI_TLV_PDEV_L1SS_TRACK_EVENTID,
-++	WMI_TLV_PDEV_TEMPERATURE_EVENTID,
-++	WMI_TLV_VDEV_START_RESP_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_VDEV),
-++	WMI_TLV_VDEV_STOPPED_EVENTID,
-++	WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID,
-++	WMI_TLV_VDEV_MCC_BCN_INTERVAL_CHANGE_REQ_EVENTID,
-++	WMI_TLV_PEER_STA_KICKOUT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_PEER),
-++	WMI_TLV_PEER_INFO_EVENTID,
-++	WMI_TLV_PEER_TX_FAIL_CNT_THR_EVENTID,
-++	WMI_TLV_PEER_ESTIMATED_LINKSPEED_EVENTID,
-++	WMI_TLV_PEER_STATE_EVENTID,
-++	WMI_TLV_MGMT_RX_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MGMT),
-++	WMI_TLV_HOST_SWBA_EVENTID,
-++	WMI_TLV_TBTTOFFSET_UPDATE_EVENTID,
-++	WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID,
-++	WMI_TLV_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID,
-++	WMI_TLV_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_BA_NEG),
-++	WMI_TLV_TX_ADDBA_COMPLETE_EVENTID,
-++	WMI_TLV_BA_RSP_SSN_EVENTID,
-++	WMI_TLV_AGGR_STATE_TRIG_EVENTID,
-++	WMI_TLV_ROAM_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_ROAM),
-++	WMI_TLV_PROFILE_MATCH,
-++	WMI_TLV_ROAM_SYNCH_EVENTID,
-++	WMI_TLV_P2P_DISC_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_P2P),
-++	WMI_TLV_P2P_NOA_EVENTID,
-++	WMI_TLV_PDEV_RESUME_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_SUSPEND),
-++	WMI_TLV_WOW_WAKEUP_HOST_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_WOW),
-++	WMI_TLV_D0_WOW_DISABLE_ACK_EVENTID,
-++	WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_RTT),
-++	WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID,
-++	WMI_TLV_RTT_ERROR_REPORT_EVENTID,
-++	WMI_TLV_STATS_EXT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_STATS),
-++	WMI_TLV_IFACE_LINK_STATS_EVENTID,
-++	WMI_TLV_PEER_LINK_STATS_EVENTID,
-++	WMI_TLV_RADIO_LINK_STATS_EVENTID,
-++	WMI_TLV_NLO_MATCH_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_NLO_OFL),
-++	WMI_TLV_NLO_SCAN_COMPLETE_EVENTID,
-++	WMI_TLV_APFIND_EVENTID,
-++	WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_GTK_OFL),
-++	WMI_TLV_GTK_REKEY_FAIL_EVENTID,
-++	WMI_TLV_CSA_HANDLING_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_CSA_OFL),
-++	WMI_TLV_CHATTER_PC_QUERY_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_CHATTER),
-++	WMI_TLV_ECHO_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MISC),
-++	WMI_TLV_PDEV_UTF_EVENTID,
-++	WMI_TLV_DEBUG_MESG_EVENTID,
-++	WMI_TLV_UPDATE_STATS_EVENTID,
-++	WMI_TLV_DEBUG_PRINT_EVENTID,
-++	WMI_TLV_DCS_INTERFERENCE_EVENTID,
-++	WMI_TLV_PDEV_QVIT_EVENTID,
-++	WMI_TLV_WLAN_PROFILE_DATA_EVENTID,
-++	WMI_TLV_PDEV_FTM_INTG_EVENTID,
-++	WMI_TLV_WLAN_FREQ_AVOID_EVENTID,
-++	WMI_TLV_VDEV_GET_KEEPALIVE_EVENTID,
-++	WMI_TLV_THERMAL_MGMT_EVENTID,
-++	WMI_TLV_DIAG_DATA_CONTAINER_EVENTID,
-++	WMI_TLV_HOST_AUTO_SHUTDOWN_EVENTID,
-++	WMI_TLV_UPDATE_WHAL_MIB_STATS_EVENTID,
-++	WMI_TLV_UPDATE_VDEV_RATE_STATS_EVENTID,
-++	WMI_TLV_DIAG_EVENTID,
-++	WMI_TLV_GPIO_INPUT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_GPIO),
-++	WMI_TLV_UPLOADH_EVENTID,
-++	WMI_TLV_CAPTUREH_EVENTID,
-++	WMI_TLV_RFKILL_STATE_CHANGE_EVENTID,
-++	WMI_TLV_TDLS_PEER_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_TDLS),
-++	WMI_TLV_BATCH_SCAN_ENABLED_EVENTID =
-++			WMI_TLV_EV(WMI_TLV_GRP_LOCATION_SCAN),
-++	WMI_TLV_BATCH_SCAN_RESULT_EVENTID,
-++	WMI_TLV_OEM_CAPABILITY_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_OEM),
-++	WMI_TLV_OEM_MEASUREMENT_REPORT_EVENTID,
-++	WMI_TLV_OEM_ERROR_REPORT_EVENTID,
-++	WMI_TLV_NAN_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_NAN),
-++	WMI_TLV_LPI_RESULT_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_LPI),
-++	WMI_TLV_LPI_STATUS_EVENTID,
-++	WMI_TLV_LPI_HANDOFF_EVENTID,
-++	WMI_TLV_EXTSCAN_START_STOP_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_EXTSCAN),
-++	WMI_TLV_EXTSCAN_OPERATION_EVENTID,
-++	WMI_TLV_EXTSCAN_TABLE_USAGE_EVENTID,
-++	WMI_TLV_EXTSCAN_CACHED_RESULTS_EVENTID,
-++	WMI_TLV_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID,
-++	WMI_TLV_EXTSCAN_HOTLIST_MATCH_EVENTID,
-++	WMI_TLV_EXTSCAN_CAPABILITIES_EVENTID,
-++	WMI_TLV_MDNS_STATS_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_MDNS_OFL),
-++	WMI_TLV_SAP_OFL_ADD_STA_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_SAP_OFL),
-++	WMI_TLV_SAP_OFL_DEL_STA_EVENTID,
-++};
-++
-++enum wmi_tlv_pdev_param {
-++	WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK = 0x1,
-++	WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_SCALE,
-++	WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE,
-++	WMI_TLV_PDEV_PARAM_BEACON_TX_MODE,
-++	WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
-++	WMI_TLV_PDEV_PARAM_PROTECTION_MODE,
-++	WMI_TLV_PDEV_PARAM_DYNAMIC_BW,
-++	WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
-++	WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH,
-++	WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH,
-++	WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING,
-++	WMI_TLV_PDEV_PARAM_LTR_ENABLE,
-++	WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE,
-++	WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK,
-++	WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI,
-++	WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO,
-++	WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
-++	WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
-++	WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE,
-++	WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
-++	WMI_TLV_PDEV_PARAM_L1SS_ENABLE,
-++	WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE,
-++	WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
-++	WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_WATERMARK,
-++	WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
-++	WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
-++	WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
-++	WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
-++	WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
-++	WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
-++	WMI_TLV_PDEV_PARAM_PMF_QOS,
-++	WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE,
-++	WMI_TLV_PDEV_PARAM_DCS,
-++	WMI_TLV_PDEV_PARAM_ANI_ENABLE,
-++	WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD,
-++	WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD,
-++	WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL,
-++	WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL,
-++	WMI_TLV_PDEV_PARAM_DYNTXCHAIN,
-++	WMI_TLV_PDEV_PARAM_PROXY_STA,
-++	WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG,
-++	WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP,
-++	WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
-++	WMI_TLV_PDEV_PARAM_BURST_DUR,
-++	WMI_TLV_PDEV_PARAM_BURST_ENABLE,
-++	WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
-++	WMI_TLV_PDEV_PARAM_LOW_POWER_RF_ENABLE,
-++	WMI_TLV_PDEV_PARAM_L1SS_TRACK,
-++	WMI_TLV_PDEV_PARAM_HYST_EN,
-++	WMI_TLV_PDEV_PARAM_POWER_COLLAPSE_ENABLE,
-++	WMI_TLV_PDEV_PARAM_LED_SYS_STATE,
-++	WMI_TLV_PDEV_PARAM_LED_ENABLE,
-++	WMI_TLV_PDEV_PARAM_AUDIO_OVER_WLAN_LATENCY,
-++	WMI_TLV_PDEV_PARAM_AUDIO_OVER_WLAN_ENABLE,
-++	WMI_TLV_PDEV_PARAM_WHAL_MIB_STATS_UPDATE_ENABLE,
-++	WMI_TLV_PDEV_PARAM_VDEV_RATE_STATS_UPDATE_PERIOD,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_REASON_NONE,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_REASON_SAR,
-++	WMI_TLV_PDEV_PARAM_TXPOWER_REASON_MAX,
-++};
-++
-++enum wmi_tlv_vdev_param {
-++	WMI_TLV_VDEV_PARAM_RTS_THRESHOLD = 0x1,
-++	WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
-++	WMI_TLV_VDEV_PARAM_BEACON_INTERVAL,
-++	WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL,
-++	WMI_TLV_VDEV_PARAM_MULTICAST_RATE,
-++	WMI_TLV_VDEV_PARAM_MGMT_TX_RATE,
-++	WMI_TLV_VDEV_PARAM_SLOT_TIME,
-++	WMI_TLV_VDEV_PARAM_PREAMBLE,
-++	WMI_TLV_VDEV_PARAM_SWBA_TIME,
-++	WMI_TLV_VDEV_STATS_UPDATE_PERIOD,
-++	WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME,
-++	WMI_TLV_VDEV_HOST_SWBA_INTERVAL,
-++	WMI_TLV_VDEV_PARAM_DTIM_PERIOD,
-++	WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
-++	WMI_TLV_VDEV_PARAM_WDS,
-++	WMI_TLV_VDEV_PARAM_ATIM_WINDOW,
-++	WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX,
-++	WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT,
-++	WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT,
-++	WMI_TLV_VDEV_PARAM_FEATURE_WMM,
-++	WMI_TLV_VDEV_PARAM_CHWIDTH,
-++	WMI_TLV_VDEV_PARAM_CHEXTOFFSET,
-++	WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION,
-++	WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT,
-++	WMI_TLV_VDEV_PARAM_MGMT_RATE,
-++	WMI_TLV_VDEV_PARAM_PROTECTION_MODE,
-++	WMI_TLV_VDEV_PARAM_FIXED_RATE,
-++	WMI_TLV_VDEV_PARAM_SGI,
-++	WMI_TLV_VDEV_PARAM_LDPC,
-++	WMI_TLV_VDEV_PARAM_TX_STBC,
-++	WMI_TLV_VDEV_PARAM_RX_STBC,
-++	WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD,
-++	WMI_TLV_VDEV_PARAM_DEF_KEYID,
-++	WMI_TLV_VDEV_PARAM_NSS,
-++	WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE,
-++	WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE,
-++	WMI_TLV_VDEV_PARAM_MCAST_INDICATE,
-++	WMI_TLV_VDEV_PARAM_DHCP_INDICATE,
-++	WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
-++	WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
-++	WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
-++	WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
-++	WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS,
-++	WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS,
-++	WMI_TLV_VDEV_PARAM_TXBF,
-++	WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE,
-++	WMI_TLV_VDEV_PARAM_DROP_UNENCRY,
-++	WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
-++	WMI_TLV_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_SLOP_STEP,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_INIT_SLOP,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE,
-++	WMI_TLV_VDEV_PARAM_TX_PWRLIMIT,
-++	WMI_TLV_VDEV_PARAM_SNR_NUM_FOR_CAL,
-++	WMI_TLV_VDEV_PARAM_ROAM_FW_OFFLOAD,
-++	WMI_TLV_VDEV_PARAM_ENABLE_RMC,
-++	WMI_TLV_VDEV_PARAM_IBSS_MAX_BCN_LOST_MS,
-++	WMI_TLV_VDEV_PARAM_MAX_RATE,
-++	WMI_TLV_VDEV_PARAM_EARLY_RX_DRIFT_SAMPLE,
-++	WMI_TLV_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
-++	WMI_TLV_VDEV_PARAM_EBT_RESYNC_TIMEOUT,
-++	WMI_TLV_VDEV_PARAM_AGGR_TRIG_EVENT_ENABLE,
-++	WMI_TLV_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED,
-++	WMI_TLV_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED,
-++	WMI_TLV_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED,
-++	WMI_TLV_VDEV_PARAM_INACTIVITY_CNT,
-++	WMI_TLV_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS,
-++	WMI_TLV_VDEV_PARAM_DTIM_POLICY,
-++	WMI_TLV_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS,
-++	WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
-++};
-++
-++enum wmi_tlv_tag {
-++	WMI_TLV_TAG_LAST_RESERVED = 15,
-++
-++	WMI_TLV_TAG_FIRST_ARRAY_ENUM,
-++	WMI_TLV_TAG_ARRAY_UINT32 = WMI_TLV_TAG_FIRST_ARRAY_ENUM,
-++	WMI_TLV_TAG_ARRAY_BYTE,
-++	WMI_TLV_TAG_ARRAY_STRUCT,
-++	WMI_TLV_TAG_ARRAY_FIXED_STRUCT,
-++	WMI_TLV_TAG_LAST_ARRAY_ENUM = 31,
-++
-++	WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT,
-++	WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES,
-++	WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ,
-++	WMI_TLV_TAG_STRUCT_READY_EVENT,
-++	WMI_TLV_TAG_STRUCT_SCAN_EVENT,
-++	WMI_TLV_TAG_STRUCT_PDEV_TPC_CONFIG_EVENT,
-++	WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT,
-++	WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR,
-++	WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_STOPPED_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_COMPLETE_EVENT,
-++	WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT,
-++	WMI_TLV_TAG_STRUCT_MGMT_RX_HDR,
-++	WMI_TLV_TAG_STRUCT_TBTT_OFFSET_EVENT,
-++	WMI_TLV_TAG_STRUCT_TX_DELBA_COMPLETE_EVENT,
-++	WMI_TLV_TAG_STRUCT_TX_ADDBA_COMPLETE_EVENT,
-++	WMI_TLV_TAG_STRUCT_ROAM_EVENT,
-++	WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO,
-++	WMI_TLV_TAG_STRUCT_WOW_EVENT_INFO_SECTION_BITMAP,
-++	WMI_TLV_TAG_STRUCT_RTT_EVENT_HEADER,
-++	WMI_TLV_TAG_STRUCT_RTT_ERROR_REPORT_EVENT,
-++	WMI_TLV_TAG_STRUCT_RTT_MEAS_EVENT,
-++	WMI_TLV_TAG_STRUCT_ECHO_EVENT,
-++	WMI_TLV_TAG_STRUCT_FTM_INTG_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_GET_KEEPALIVE_EVENT,
-++	WMI_TLV_TAG_STRUCT_GPIO_INPUT_EVENT,
-++	WMI_TLV_TAG_STRUCT_CSA_EVENT,
-++	WMI_TLV_TAG_STRUCT_GTK_OFFLOAD_STATUS_EVENT,
-++	WMI_TLV_TAG_STRUCT_IGTK_INFO,
-++	WMI_TLV_TAG_STRUCT_DCS_INTERFERENCE_EVENT,
-++	WMI_TLV_TAG_STRUCT_ATH_DCS_CW_INT,
-++	WMI_TLV_TAG_STRUCT_ATH_DCS_WLAN_INT_STAT,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_CTX_T,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_T,
-++	WMI_TLV_TAG_STRUCT_PDEV_QVIT_EVENT,
-++	WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT,
-++	WMI_TLV_TAG_STRUCT_TIM_INFO,
-++	WMI_TLV_TAG_STRUCT_P2P_NOA_INFO,
-++	WMI_TLV_TAG_STRUCT_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_AVOID_FREQ_RANGES_EVENT,
-++	WMI_TLV_TAG_STRUCT_AVOID_FREQ_RANGE_DESC,
-++	WMI_TLV_TAG_STRUCT_GTK_REKEY_FAIL_EVENT,
-++	WMI_TLV_TAG_STRUCT_INIT_CMD,
-++	WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG,
-++	WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK,
-++	WMI_TLV_TAG_STRUCT_START_SCAN_CMD,
-++	WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD,
-++	WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD,
-++	WMI_TLV_TAG_STRUCT_CHANNEL,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_WMM_PARAMS,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD,
-++	WMI_TLV_TAG_STRUCT_P2P_NOA_DESCRIPTOR,
-++	WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE,
-++	WMI_TLV_TAG_STRUCT_GTK_OFFLOAD_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_UP_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD,
-++	WMI_TLV_TAG_STRUCT_VHT_RATE_SET,
-++	WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD,
-++	WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD,
-++	WMI_TLV_TAG_STRUCT_BCN_PRB_INFO,
-++	WMI_TLV_TAG_STRUCT_PEER_TID_ADDBA_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_TID_DELBA_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_DTIM_PS_METHOD_CMD,
-++	WMI_TLV_TAG_STRUCT_ROAM_SCAN_MODE,
-++	WMI_TLV_TAG_STRUCT_ROAM_SCAN_RSSI_THRESHOLD,
-++	WMI_TLV_TAG_STRUCT_ROAM_SCAN_PERIOD,
-++	WMI_TLV_TAG_STRUCT_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD,
-++	WMI_TLV_TAG_STRUCT_ADD_BCN_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_RMV_BCN_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_HOSTWAKEUP_FROM_SLEEP_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM,
-++	WMI_TLV_TAG_STRUCT_SET_ARP_NS_OFFLOAD_CMD,
-++	WMI_TLV_TAG_STRUCT_ARP_OFFLOAD_TUPLE,
-++	WMI_TLV_TAG_STRUCT_NS_OFFLOAD_TUPLE,
-++	WMI_TLV_TAG_STRUCT_FTM_INTG_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD,
-++	WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE,
-++	WMI_TLV_TAG_STRUCT_P2P_SET_VENDOR_IE_DATA_CMD,
-++	WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_RATE_RETRY_SCHED_CMD,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_TRIGGER_CMD,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_SET_HIST_INTVL_CMD,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_GET_PROF_DATA_CMD,
-++	WMI_TLV_TAG_STRUCT_WLAN_PROFILE_ENABLE_PROFILE_ID_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_DEL_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_ADD_DEL_EVT_CMD,
-++	WMI_TLV_TAG_STRUCT_RTT_MEASREQ_HEAD,
-++	WMI_TLV_TAG_STRUCT_RTT_MEASREQ_BODY,
-++	WMI_TLV_TAG_STRUCT_RTT_TSF_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_CONFIGURE_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SPECTRAL_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_NLO_CONFIGURED_PARAMETERS,
-++	WMI_TLV_TAG_STRUCT_CSA_OFFLOAD_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_CSA_OFFLOAD_CHANSWITCH_CMD,
-++	WMI_TLV_TAG_STRUCT_CHATTER_SET_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_ECHO_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SET_KEEPALIVE_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_GET_KEEPALIVE_CMD,
-++	WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD,
-++	WMI_TLV_TAG_STRUCT_GPIO_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_GPIO_OUTPUT_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_ADD_WDS_ENTRY_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_REMOVE_WDS_ENTRY_CMD,
-++	WMI_TLV_TAG_STRUCT_BCN_TX_HDR,
-++	WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD,
-++	WMI_TLV_TAG_STRUCT_MGMT_TX_HDR,
-++	WMI_TLV_TAG_STRUCT_ADDBA_CLEAR_RESP_CMD,
-++	WMI_TLV_TAG_STRUCT_ADDBA_SEND_CMD,
-++	WMI_TLV_TAG_STRUCT_DELBA_SEND_CMD,
-++	WMI_TLV_TAG_STRUCT_ADDBA_SETRESPONSE_CMD,
-++	WMI_TLV_TAG_STRUCT_SEND_SINGLEAMSDU_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_HT_IE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_VHT_IE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_DSCP_TID_MAP_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_GREEN_AP_PS_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_GET_TPC_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_MCAST_GROUP_CMD,
-++	WMI_TLV_TAG_STRUCT_ROAM_AP_PROFILE,
-++	WMI_TLV_TAG_STRUCT_AP_PROFILE,
-++	WMI_TLV_TAG_STRUCT_SCAN_SCH_PRIORITY_TABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_DFS_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_DFS_DISABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_ADD_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_BITMAP_PATTERN_T,
-++	WMI_TLV_TAG_STRUCT_WOW_IPV4_SYNC_PATTERN_T,
-++	WMI_TLV_TAG_STRUCT_WOW_IPV6_SYNC_PATTERN_T,
-++	WMI_TLV_TAG_STRUCT_WOW_MAGIC_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_SCAN_UPDATE_REQUEST_CMD,
-++	WMI_TLV_TAG_STRUCT_CHATTER_PKT_COALESCING_FILTER,
-++	WMI_TLV_TAG_STRUCT_CHATTER_COALESCING_ADD_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_CHATTER_COALESCING_DELETE_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_CHATTER_COALESCING_QUERY_CMD,
-++	WMI_TLV_TAG_STRUCT_TXBF_CMD,
-++	WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_NLO_EVENT,
-++	WMI_TLV_TAG_STRUCT_CHATTER_QUERY_REPLY_EVENT,
-++	WMI_TLV_TAG_STRUCT_UPLOAD_H_HDR,
-++	WMI_TLV_TAG_STRUCT_CAPTURE_H_EVENT_HDR,
-++	WMI_TLV_TAG_STRUCT_VDEV_WNM_SLEEPMODE_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_IPSEC_NATKEEPALIVE_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_WMM_ADDTS_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_WMM_DELTS_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_TDLS_SET_STATE_CMD,
-++	WMI_TLV_TAG_STRUCT_TDLS_PEER_UPDATE_CMD,
-++	WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT,
-++	WMI_TLV_TAG_STRUCT_TDLS_PEER_CAPABILITIES,
-++	WMI_TLV_TAG_STRUCT_VDEV_MCC_SET_TBTT_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_ROAM_CHAN_LIST,
-++	WMI_TLV_TAG_STRUCT_VDEV_MCC_BCN_INTVL_CHANGE_EVENT,
-++	WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD,
-++	WMI_TLV_TAG_STRUCT_RESMGR_SET_CHAN_TIME_QUOTA_CMD,
-++	WMI_TLV_TAG_STRUCT_RESMGR_SET_CHAN_LATENCY_CMD,
-++	WMI_TLV_TAG_STRUCT_BA_REQ_SSN_CMD,
-++	WMI_TLV_TAG_STRUCT_BA_RSP_SSN_EVENT,
-++	WMI_TLV_TAG_STRUCT_STA_SMPS_FORCE_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_SET_MCASTBCAST_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_P2P_SET_OPPPS_CMD,
-++	WMI_TLV_TAG_STRUCT_P2P_SET_NOA_CMD,
-++	WMI_TLV_TAG_STRUCT_BA_REQ_SSN_CMD_SUB_STRUCT_PARAM,
-++	WMI_TLV_TAG_STRUCT_BA_REQ_SSN_EVENT_SUB_STRUCT_PARAM,
-++	WMI_TLV_TAG_STRUCT_STA_SMPS_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_SET_GTX_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_MCC_SCHED_TRAFFIC_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_MCC_SCHED_STA_TRAFFIC_STATS,
-++	WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT,
-++	WMI_TLV_TAG_STRUCT_P2P_NOA_EVENT,
-++	WMI_TLV_TAG_STRUCT_HB_SET_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_HB_SET_TCP_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_HB_SET_TCP_PKT_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_HB_SET_UDP_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_HB_SET_UDP_PKT_FILTER_CMD,
-++	WMI_TLV_TAG_STRUCT_HB_IND_EVENT,
-++	WMI_TLV_TAG_STRUCT_TX_PAUSE_EVENT,
-++	WMI_TLV_TAG_STRUCT_RFKILL_EVENT,
-++	WMI_TLV_TAG_STRUCT_DFS_RADAR_EVENT,
-++	WMI_TLV_TAG_STRUCT_DFS_PHYERR_FILTER_ENA_CMD,
-++	WMI_TLV_TAG_STRUCT_DFS_PHYERR_FILTER_DIS_CMD,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_RESULT_SCAN_LIST,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_RESULT_NETWORK_INFO,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_DISABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_TRIGGER_RESULT_CMD,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_ENABLED_EVENT,
-++	WMI_TLV_TAG_STRUCT_BATCH_SCAN_RESULT_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_PLMREQ_START_CMD,
-++	WMI_TLV_TAG_STRUCT_VDEV_PLMREQ_STOP_CMD,
-++	WMI_TLV_TAG_STRUCT_THERMAL_MGMT_CMD,
-++	WMI_TLV_TAG_STRUCT_THERMAL_MGMT_EVENT,
-++	WMI_TLV_TAG_STRUCT_PEER_INFO_REQ_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_INFO_EVENT,
-++	WMI_TLV_TAG_STRUCT_PEER_INFO,
-++	WMI_TLV_TAG_STRUCT_PEER_TX_FAIL_CNT_THR_EVENT,
-++	WMI_TLV_TAG_STRUCT_RMC_SET_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_RMC_SET_ACTION_PERIOD_CMD,
-++	WMI_TLV_TAG_STRUCT_RMC_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_MHF_OFFLOAD_SET_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_MHF_OFFLOAD_PLUMB_ROUTING_TABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_ADD_PROACTIVE_ARP_RSP_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_DEL_PROACTIVE_ARP_RSP_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_NAN_CMD_PARAM,
-++	WMI_TLV_TAG_STRUCT_NAN_EVENT_HDR,
-++	WMI_TLV_TAG_STRUCT_PDEV_L1SS_TRACK_EVENT,
-++	WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT,
-++	WMI_TLV_TAG_STRUCT_MODEM_POWER_STATE_CMD_PARAM,
-++	WMI_TLV_TAG_STRUCT_PEER_GET_ESTIMATED_LINKSPEED_CMD,
-++	WMI_TLV_TAG_STRUCT_PEER_ESTIMATED_LINKSPEED_EVENT,
-++	WMI_TLV_TAG_STRUCT_AGGR_STATE_TRIG_EVENT,
-++	WMI_TLV_TAG_STRUCT_MHF_OFFLOAD_ROUTING_TABLE_ENTRY,
-++	WMI_TLV_TAG_STRUCT_ROAM_SCAN_CMD,
-++	WMI_TLV_TAG_STRUCT_REQ_STATS_EXT_CMD,
-++	WMI_TLV_TAG_STRUCT_STATS_EXT_EVENT,
-++	WMI_TLV_TAG_STRUCT_OBSS_SCAN_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_OBSS_SCAN_DISABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_OFFLOAD_PRB_RSP_TX_STATUS_EVENT,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_LED_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_HOST_AUTO_SHUTDOWN_CFG_CMD,
-++	WMI_TLV_TAG_STRUCT_HOST_AUTO_SHUTDOWN_EVENT,
-++	WMI_TLV_TAG_STRUCT_UPDATE_WHAL_MIB_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_CHAN_AVOID_UPDATE_CMD_PARAM,
-++	WMI_TLV_TAG_STRUCT_WOW_ACER_IOAC_PKT_PATTERN_T,
-++	WMI_TLV_TAG_STRUCT_WOW_ACER_IOAC_TMR_PATTERN_T,
-++	WMI_TLV_TAG_STRUCT_WOW_IOAC_ADD_KEEPALIVE_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_IOAC_DEL_KEEPALIVE_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_IOAC_KEEPALIVE_T,
-++	WMI_TLV_TAG_STRUCT_WOW_ACER_IOAC_ADD_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_WOW_ACER_IOAC_DEL_PATTERN_CMD,
-++	WMI_TLV_TAG_STRUCT_START_LINK_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_CLEAR_LINK_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_REQUEST_LINK_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_IFACE_LINK_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_RADIO_LINK_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_PEER_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_CHANNEL_STATS,
-++	WMI_TLV_TAG_STRUCT_RADIO_LINK_STATS,
-++	WMI_TLV_TAG_STRUCT_RATE_STATS,
-++	WMI_TLV_TAG_STRUCT_PEER_LINK_STATS,
-++	WMI_TLV_TAG_STRUCT_WMM_AC_STATS,
-++	WMI_TLV_TAG_STRUCT_IFACE_LINK_STATS,
-++	WMI_TLV_TAG_STRUCT_LPI_MGMT_SNOOPING_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_LPI_START_SCAN_CMD,
-++	WMI_TLV_TAG_STRUCT_LPI_STOP_SCAN_CMD,
-++	WMI_TLV_TAG_STRUCT_LPI_RESULT_EVENT,
-++	WMI_TLV_TAG_STRUCT_PEER_STATE_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_BUCKET_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_BUCKET_CHANNEL_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_START_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_STOP_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_WLAN_CHANGE_BSSID_PARAM_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_GET_CACHED_RESULTS_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_GET_WLAN_CHANGE_RESULTS_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_SET_CAPABILITIES_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_GET_CAPABILITIES_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_OPERATION_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_START_STOP_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_TABLE_USAGE_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_WLAN_DESCRIPTOR_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_RSSI_INFO_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_CACHED_RESULTS_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_WLAN_CHANGE_RESULTS_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_WLAN_CHANGE_RESULT_BSSID_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_HOTLIST_MATCH_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_CAPABILITIES_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_CACHE_CAPABILITIES_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_WLAN_CHANGE_MONITOR_CAPABILITIES_EVENT,
-++	WMI_TLV_TAG_STRUCT_EXTSCAN_HOTLIST_MONITOR_CAPABILITIES_EVENT,
-++	WMI_TLV_TAG_STRUCT_D0_WOW_ENABLE_DISABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_D0_WOW_DISABLE_ACK_EVENT,
-++	WMI_TLV_TAG_STRUCT_UNIT_TEST_CMD,
-++	WMI_TLV_TAG_STRUCT_ROAM_OFFLOAD_TLV_PARAM,
-++	WMI_TLV_TAG_STRUCT_ROAM_11I_OFFLOAD_TLV_PARAM,
-++	WMI_TLV_TAG_STRUCT_ROAM_11R_OFFLOAD_TLV_PARAM,
-++	WMI_TLV_TAG_STRUCT_ROAM_ESE_OFFLOAD_TLV_PARAM,
-++	WMI_TLV_TAG_STRUCT_ROAM_SYNCH_EVENT,
-++	WMI_TLV_TAG_STRUCT_ROAM_SYNCH_COMPLETE,
-++	WMI_TLV_TAG_STRUCT_EXTWOW_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTWOW_SET_APP_TYPE1_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_EXTWOW_SET_APP_TYPE2_PARAMS_CMD,
-++	WMI_TLV_TAG_STRUCT_LPI_STATUS_EVENT,
-++	WMI_TLV_TAG_STRUCT_LPI_HANDOFF_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_RATE_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_VDEV_RATE_HT_INFO,
-++	WMI_TLV_TAG_STRUCT_RIC_REQUEST,
-++	WMI_TLV_TAG_STRUCT_PDEV_GET_TEMPERATURE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_TEMPERATURE_EVENT,
-++	WMI_TLV_TAG_STRUCT_SET_DHCP_SERVER_OFFLOAD_CMD,
-++	WMI_TLV_TAG_STRUCT_TPC_CHAINMASK_CONFIG_CMD,
-++	WMI_TLV_TAG_STRUCT_RIC_TSPEC,
-++	WMI_TLV_TAG_STRUCT_TPC_CHAINMASK_CONFIG,
-++	WMI_TLV_TAG_STRUCT_IPA_OFFLOAD_CMD,
-++	WMI_TLV_TAG_STRUCT_SCAN_PROB_REQ_OUI_CMD,
-++	WMI_TLV_TAG_STRUCT_KEY_MATERIAL,
-++	WMI_TLV_TAG_STRUCT_TDLS_SET_OFFCHAN_MODE_CMD,
-++	WMI_TLV_TAG_STRUCT_SET_LED_FLASHING_CMD,
-++	WMI_TLV_TAG_STRUCT_MDNS_OFFLOAD_CMD,
-++	WMI_TLV_TAG_STRUCT_MDNS_SET_FQDN_CMD,
-++	WMI_TLV_TAG_STRUCT_MDNS_SET_RESP_CMD,
-++	WMI_TLV_TAG_STRUCT_MDNS_GET_STATS_CMD,
-++	WMI_TLV_TAG_STRUCT_MDNS_STATS_EVENT,
-++	WMI_TLV_TAG_STRUCT_ROAM_INVOKE_CMD,
-++	WMI_TLV_TAG_STRUCT_PDEV_RESUME_EVENT,
-++	WMI_TLV_TAG_STRUCT_PDEV_SET_ANTENNA_DIVERSITY_CMD,
-++	WMI_TLV_TAG_STRUCT_SAP_OFL_ENABLE_CMD,
-++	WMI_TLV_TAG_STRUCT_SAP_OFL_ADD_STA_EVENT,
-++	WMI_TLV_TAG_STRUCT_SAP_OFL_DEL_STA_EVENT,
-++	WMI_TLV_TAG_STRUCT_APFIND_CMD_PARAM,
-++	WMI_TLV_TAG_STRUCT_APFIND_EVENT_HDR,
-++
-++	WMI_TLV_TAG_MAX
-++};
-++
-++enum wmi_tlv_service {
-++	WMI_TLV_SERVICE_BEACON_OFFLOAD = 0,
-++	WMI_TLV_SERVICE_SCAN_OFFLOAD,
-++	WMI_TLV_SERVICE_ROAM_SCAN_OFFLOAD,
-++	WMI_TLV_SERVICE_BCN_MISS_OFFLOAD,
-++	WMI_TLV_SERVICE_STA_PWRSAVE,
-++	WMI_TLV_SERVICE_STA_ADVANCED_PWRSAVE,
-++	WMI_TLV_SERVICE_AP_UAPSD,
-++	WMI_TLV_SERVICE_AP_DFS,
-++	WMI_TLV_SERVICE_11AC,
-++	WMI_TLV_SERVICE_BLOCKACK,
-++	WMI_TLV_SERVICE_PHYERR,
-++	WMI_TLV_SERVICE_BCN_FILTER,
-++	WMI_TLV_SERVICE_RTT,
-++	WMI_TLV_SERVICE_WOW,
-++	WMI_TLV_SERVICE_RATECTRL_CACHE,
-++	WMI_TLV_SERVICE_IRAM_TIDS,
-++	WMI_TLV_SERVICE_ARPNS_OFFLOAD,
-++	WMI_TLV_SERVICE_NLO,
-++	WMI_TLV_SERVICE_GTK_OFFLOAD,
-++	WMI_TLV_SERVICE_SCAN_SCH,
-++	WMI_TLV_SERVICE_CSA_OFFLOAD,
-++	WMI_TLV_SERVICE_CHATTER,
-++	WMI_TLV_SERVICE_COEX_FREQAVOID,
-++	WMI_TLV_SERVICE_PACKET_POWER_SAVE,
-++	WMI_TLV_SERVICE_FORCE_FW_HANG,
-++	WMI_TLV_SERVICE_GPIO,
-++	WMI_TLV_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-++	WMI_TLV_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-++	WMI_TLV_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-++	WMI_TLV_SERVICE_STA_KEEP_ALIVE,
-++	WMI_TLV_SERVICE_TX_ENCAP,
-++	WMI_TLV_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
-++	WMI_TLV_SERVICE_EARLY_RX,
-++	WMI_TLV_SERVICE_STA_SMPS,
-++	WMI_TLV_SERVICE_FWTEST,
-++	WMI_TLV_SERVICE_STA_WMMAC,
-++	WMI_TLV_SERVICE_TDLS,
-++	WMI_TLV_SERVICE_BURST,
-++	WMI_TLV_SERVICE_MCC_BCN_INTERVAL_CHANGE,
-++	WMI_TLV_SERVICE_ADAPTIVE_OCS,
-++	WMI_TLV_SERVICE_BA_SSN_SUPPORT,
-++	WMI_TLV_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
-++	WMI_TLV_SERVICE_WLAN_HB,
-++	WMI_TLV_SERVICE_LTE_ANT_SHARE_SUPPORT,
-++	WMI_TLV_SERVICE_BATCH_SCAN,
-++	WMI_TLV_SERVICE_QPOWER,
-++	WMI_TLV_SERVICE_PLMREQ,
-++	WMI_TLV_SERVICE_THERMAL_MGMT,
-++	WMI_TLV_SERVICE_RMC,
-++	WMI_TLV_SERVICE_MHF_OFFLOAD,
-++	WMI_TLV_SERVICE_COEX_SAR,
-++	WMI_TLV_SERVICE_BCN_TXRATE_OVERRIDE,
-++	WMI_TLV_SERVICE_NAN,
-++	WMI_TLV_SERVICE_L1SS_STAT,
-++	WMI_TLV_SERVICE_ESTIMATE_LINKSPEED,
-++	WMI_TLV_SERVICE_OBSS_SCAN,
-++	WMI_TLV_SERVICE_TDLS_OFFCHAN,
-++	WMI_TLV_SERVICE_TDLS_UAPSD_BUFFER_STA,
-++	WMI_TLV_SERVICE_TDLS_UAPSD_SLEEP_STA,
-++	WMI_TLV_SERVICE_IBSS_PWRSAVE,
-++	WMI_TLV_SERVICE_LPASS,
-++	WMI_TLV_SERVICE_EXTSCAN,
-++	WMI_TLV_SERVICE_D0WOW,
-++	WMI_TLV_SERVICE_HSOFFLOAD,
-++	WMI_TLV_SERVICE_ROAM_HO_OFFLOAD,
-++	WMI_TLV_SERVICE_RX_FULL_REORDER,
-++	WMI_TLV_SERVICE_DHCP_OFFLOAD,
-++	WMI_TLV_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
-++	WMI_TLV_SERVICE_MDNS_OFFLOAD,
-++	WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
-++};
-++
-++#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
-++	((svc_id) < (len) && \
-++	 __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
-++	 BIT((svc_id)%(sizeof(u32))))
-++
-++#define SVCMAP(x, y, len) \
-++	do { \
-++		if (WMI_SERVICE_IS_ENABLED((in), (x), (len))) \
-++			__set_bit(y, out); \
-++	} while (0)
-++
-++static inline void
-++wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
-++{
-++	SVCMAP(WMI_TLV_SERVICE_BEACON_OFFLOAD,
-++	       WMI_SERVICE_BEACON_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_SCAN_OFFLOAD,
-++	       WMI_SERVICE_SCAN_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_ROAM_SCAN_OFFLOAD,
-++	       WMI_SERVICE_ROAM_SCAN_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_BCN_MISS_OFFLOAD,
-++	       WMI_SERVICE_BCN_MISS_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_PWRSAVE,
-++	       WMI_SERVICE_STA_PWRSAVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_ADVANCED_PWRSAVE,
-++	       WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_AP_UAPSD,
-++	       WMI_SERVICE_AP_UAPSD, len);
-++	SVCMAP(WMI_TLV_SERVICE_AP_DFS,
-++	       WMI_SERVICE_AP_DFS, len);
-++	SVCMAP(WMI_TLV_SERVICE_11AC,
-++	       WMI_SERVICE_11AC, len);
-++	SVCMAP(WMI_TLV_SERVICE_BLOCKACK,
-++	       WMI_SERVICE_BLOCKACK, len);
-++	SVCMAP(WMI_TLV_SERVICE_PHYERR,
-++	       WMI_SERVICE_PHYERR, len);
-++	SVCMAP(WMI_TLV_SERVICE_BCN_FILTER,
-++	       WMI_SERVICE_BCN_FILTER, len);
-++	SVCMAP(WMI_TLV_SERVICE_RTT,
-++	       WMI_SERVICE_RTT, len);
-++	SVCMAP(WMI_TLV_SERVICE_WOW,
-++	       WMI_SERVICE_WOW, len);
-++	SVCMAP(WMI_TLV_SERVICE_RATECTRL_CACHE,
-++	       WMI_SERVICE_RATECTRL_CACHE, len);
-++	SVCMAP(WMI_TLV_SERVICE_IRAM_TIDS,
-++	       WMI_SERVICE_IRAM_TIDS, len);
-++	SVCMAP(WMI_TLV_SERVICE_ARPNS_OFFLOAD,
-++	       WMI_SERVICE_ARPNS_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_NLO,
-++	       WMI_SERVICE_NLO, len);
-++	SVCMAP(WMI_TLV_SERVICE_GTK_OFFLOAD,
-++	       WMI_SERVICE_GTK_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_SCAN_SCH,
-++	       WMI_SERVICE_SCAN_SCH, len);
-++	SVCMAP(WMI_TLV_SERVICE_CSA_OFFLOAD,
-++	       WMI_SERVICE_CSA_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_CHATTER,
-++	       WMI_SERVICE_CHATTER, len);
-++	SVCMAP(WMI_TLV_SERVICE_COEX_FREQAVOID,
-++	       WMI_SERVICE_COEX_FREQAVOID, len);
-++	SVCMAP(WMI_TLV_SERVICE_PACKET_POWER_SAVE,
-++	       WMI_SERVICE_PACKET_POWER_SAVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_FORCE_FW_HANG,
-++	       WMI_SERVICE_FORCE_FW_HANG, len);
-++	SVCMAP(WMI_TLV_SERVICE_GPIO,
-++	       WMI_SERVICE_GPIO, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
-++	       WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
-++	       WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
-++	       WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_KEEP_ALIVE,
-++	       WMI_SERVICE_STA_KEEP_ALIVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_TX_ENCAP,
-++	       WMI_SERVICE_TX_ENCAP, len);
-++	SVCMAP(WMI_TLV_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
-++	       WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC, len);
-++	SVCMAP(WMI_TLV_SERVICE_EARLY_RX,
-++	       WMI_SERVICE_EARLY_RX, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_SMPS,
-++	       WMI_SERVICE_STA_SMPS, len);
-++	SVCMAP(WMI_TLV_SERVICE_FWTEST,
-++	       WMI_SERVICE_FWTEST, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_WMMAC,
-++	       WMI_SERVICE_STA_WMMAC, len);
-++	SVCMAP(WMI_TLV_SERVICE_TDLS,
-++	       WMI_SERVICE_TDLS, len);
-++	SVCMAP(WMI_TLV_SERVICE_BURST,
-++	       WMI_SERVICE_BURST, len);
-++	SVCMAP(WMI_TLV_SERVICE_MCC_BCN_INTERVAL_CHANGE,
-++	       WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE, len);
-++	SVCMAP(WMI_TLV_SERVICE_ADAPTIVE_OCS,
-++	       WMI_SERVICE_ADAPTIVE_OCS, len);
-++	SVCMAP(WMI_TLV_SERVICE_BA_SSN_SUPPORT,
-++	       WMI_SERVICE_BA_SSN_SUPPORT, len);
-++	SVCMAP(WMI_TLV_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
-++	       WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_WLAN_HB,
-++	       WMI_SERVICE_WLAN_HB, len);
-++	SVCMAP(WMI_TLV_SERVICE_LTE_ANT_SHARE_SUPPORT,
-++	       WMI_SERVICE_LTE_ANT_SHARE_SUPPORT, len);
-++	SVCMAP(WMI_TLV_SERVICE_BATCH_SCAN,
-++	       WMI_SERVICE_BATCH_SCAN, len);
-++	SVCMAP(WMI_TLV_SERVICE_QPOWER,
-++	       WMI_SERVICE_QPOWER, len);
-++	SVCMAP(WMI_TLV_SERVICE_PLMREQ,
-++	       WMI_SERVICE_PLMREQ, len);
-++	SVCMAP(WMI_TLV_SERVICE_THERMAL_MGMT,
-++	       WMI_SERVICE_THERMAL_MGMT, len);
-++	SVCMAP(WMI_TLV_SERVICE_RMC,
-++	       WMI_SERVICE_RMC, len);
-++	SVCMAP(WMI_TLV_SERVICE_MHF_OFFLOAD,
-++	       WMI_SERVICE_MHF_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_COEX_SAR,
-++	       WMI_SERVICE_COEX_SAR, len);
-++	SVCMAP(WMI_TLV_SERVICE_BCN_TXRATE_OVERRIDE,
-++	       WMI_SERVICE_BCN_TXRATE_OVERRIDE, len);
-++	SVCMAP(WMI_TLV_SERVICE_NAN,
-++	       WMI_SERVICE_NAN, len);
-++	SVCMAP(WMI_TLV_SERVICE_L1SS_STAT,
-++	       WMI_SERVICE_L1SS_STAT, len);
-++	SVCMAP(WMI_TLV_SERVICE_ESTIMATE_LINKSPEED,
-++	       WMI_SERVICE_ESTIMATE_LINKSPEED, len);
-++	SVCMAP(WMI_TLV_SERVICE_OBSS_SCAN,
-++	       WMI_SERVICE_OBSS_SCAN, len);
-++	SVCMAP(WMI_TLV_SERVICE_TDLS_OFFCHAN,
-++	       WMI_SERVICE_TDLS_OFFCHAN, len);
-++	SVCMAP(WMI_TLV_SERVICE_TDLS_UAPSD_BUFFER_STA,
-++	       WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, len);
-++	SVCMAP(WMI_TLV_SERVICE_TDLS_UAPSD_SLEEP_STA,
-++	       WMI_SERVICE_TDLS_UAPSD_SLEEP_STA, len);
-++	SVCMAP(WMI_TLV_SERVICE_IBSS_PWRSAVE,
-++	       WMI_SERVICE_IBSS_PWRSAVE, len);
-++	SVCMAP(WMI_TLV_SERVICE_LPASS,
-++	       WMI_SERVICE_LPASS, len);
-++	SVCMAP(WMI_TLV_SERVICE_EXTSCAN,
-++	       WMI_SERVICE_EXTSCAN, len);
-++	SVCMAP(WMI_TLV_SERVICE_D0WOW,
-++	       WMI_SERVICE_D0WOW, len);
-++	SVCMAP(WMI_TLV_SERVICE_HSOFFLOAD,
-++	       WMI_SERVICE_HSOFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_ROAM_HO_OFFLOAD,
-++	       WMI_SERVICE_ROAM_HO_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_RX_FULL_REORDER,
-++	       WMI_SERVICE_RX_FULL_REORDER, len);
-++	SVCMAP(WMI_TLV_SERVICE_DHCP_OFFLOAD,
-++	       WMI_SERVICE_DHCP_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
-++	       WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT, len);
-++	SVCMAP(WMI_TLV_SERVICE_MDNS_OFFLOAD,
-++	       WMI_SERVICE_MDNS_OFFLOAD, len);
-++	SVCMAP(WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
-++	       WMI_SERVICE_SAP_AUTH_OFFLOAD, len);
-++}
-++
-++#undef SVCMAP
-++
-++struct wmi_tlv {
-++	__le16 len;
-++	__le16 tag;
-++	u8 value[0];
-++} __packed;
-++
-++#define WMI_TLV_MGMT_RX_NUM_RSSI 4
-++
-++struct wmi_tlv_mgmt_rx_ev {
-++	__le32 channel;
-++	__le32 snr;
-++	__le32 rate;
-++	__le32 phy_mode;
-++	__le32 buf_len;
-++	__le32 status;
-++	__le32 rssi[WMI_TLV_MGMT_RX_NUM_RSSI];
-++} __packed;
-++
-++struct wmi_tlv_abi_version {
-++	__le32 abi_ver0;
-++	__le32 abi_ver1;
-++	__le32 abi_ver_ns0;
-++	__le32 abi_ver_ns1;
-++	__le32 abi_ver_ns2;
-++	__le32 abi_ver_ns3;
-++} __packed;
-++
-++enum wmi_tlv_hw_bd_id {
-++	WMI_TLV_HW_BD_LEGACY = 0,
-++	WMI_TLV_HW_BD_QCA6174 = 1,
-++	WMI_TLV_HW_BD_QCA2582 = 2,
-++};
-++
-++struct wmi_tlv_hw_bd_info {
-++	u8 rev;
-++	u8 project_id;
-++	u8 custom_id;
-++	u8 reference_design_id;
-++} __packed;
-++
-++struct wmi_tlv_svc_rdy_ev {
-++	__le32 fw_build_vers;
-++	struct wmi_tlv_abi_version abi;
-++	__le32 phy_capability;
-++	__le32 max_frag_entry;
-++	__le32 num_rf_chains;
-++	__le32 ht_cap_info;
-++	__le32 vht_cap_info;
-++	__le32 vht_supp_mcs;
-++	__le32 hw_min_tx_power;
-++	__le32 hw_max_tx_power;
-++	__le32 sys_cap_info;
-++	__le32 min_pkt_size_enable;
-++	__le32 max_bcn_ie_size;
-++	__le32 num_mem_reqs;
-++	__le32 max_num_scan_chans;
-++	__le32 hw_bd_id; /* 0 means hw_bd_info is invalid */
-++	struct wmi_tlv_hw_bd_info hw_bd_info[5];
-++} __packed;
-++
-++struct wmi_tlv_rdy_ev {
-++	struct wmi_tlv_abi_version abi;
-++	struct wmi_mac_addr mac_addr;
-++	__le32 status;
-++} __packed;
-++
-++struct wmi_tlv_resource_config {
-++	__le32 num_vdevs;
-++	__le32 num_peers;
-++	__le32 num_offload_peers;
-++	__le32 num_offload_reorder_bufs;
-++	__le32 num_peer_keys;
-++	__le32 num_tids;
-++	__le32 ast_skid_limit;
-++	__le32 tx_chain_mask;
-++	__le32 rx_chain_mask;
-++	__le32 rx_timeout_pri[4];
-++	__le32 rx_decap_mode;
-++	__le32 scan_max_pending_reqs;
-++	__le32 bmiss_offload_max_vdev;
-++	__le32 roam_offload_max_vdev;
-++	__le32 roam_offload_max_ap_profiles;
-++	__le32 num_mcast_groups;
-++	__le32 num_mcast_table_elems;
-++	__le32 mcast2ucast_mode;
-++	__le32 tx_dbg_log_size;
-++	__le32 num_wds_entries;
-++	__le32 dma_burst_size;
-++	__le32 mac_aggr_delim;
-++	__le32 rx_skip_defrag_timeout_dup_detection_check;
-++	__le32 vow_config;
-++	__le32 gtk_offload_max_vdev;
-++	__le32 num_msdu_desc;
-++	__le32 max_frag_entries;
-++	__le32 num_tdls_vdevs;
-++	__le32 num_tdls_conn_table_entries;
-++	__le32 beacon_tx_offload_max_vdev;
-++	__le32 num_multicast_filter_entries;
-++	__le32 num_wow_filters;
-++	__le32 num_keep_alive_pattern;
-++	__le32 keep_alive_pattern_size;
-++	__le32 max_tdls_concurrent_sleep_sta;
-++	__le32 max_tdls_concurrent_buffer_sta;
-++} __packed;
-++
-++struct wmi_tlv_init_cmd {
-++	struct wmi_tlv_abi_version abi;
-++	__le32 num_host_mem_chunks;
-++} __packed;
-++
-++struct wmi_tlv_pdev_set_param_cmd {
-++	__le32 pdev_id; /* not used yet */
-++	__le32 param_id;
-++	__le32 param_value;
-++} __packed;
-++
-++struct wmi_tlv_pdev_set_rd_cmd {
-++	__le32 pdev_id; /* not used yet */
-++	__le32 regd;
-++	__le32 regd_2ghz;
-++	__le32 regd_5ghz;
-++	__le32 conform_limit_2ghz;
-++	__le32 conform_limit_5ghz;
-++} __packed;
-++
-++struct wmi_tlv_scan_chan_list_cmd {
-++	__le32 num_scan_chans;
-++} __packed;
-++
-++struct wmi_tlv_start_scan_cmd {
-++	struct wmi_start_scan_common common;
-++	__le32 burst_duration_ms;
-++	__le32 num_channels;
-++	__le32 num_bssids;
-++	__le32 num_ssids;
-++	__le32 ie_len;
-++	__le32 num_probes;
-++} __packed;
-++
-++struct wmi_tlv_vdev_start_cmd {
-++	__le32 vdev_id;
-++	__le32 requestor_id;
-++	__le32 bcn_intval;
-++	__le32 dtim_period;
-++	__le32 flags;
-++	struct wmi_ssid ssid;
-++	__le32 bcn_tx_rate;
-++	__le32 bcn_tx_power;
-++	__le32 num_noa_descr;
-++	__le32 disable_hw_ack;
-++} __packed;
-++
-++enum {
-++	WMI_TLV_PEER_TYPE_DEFAULT = 0, /* generic / non-BSS / self-peer */
-++	WMI_TLV_PEER_TYPE_BSS = 1,
-++	WMI_TLV_PEER_TYPE_TDLS = 2,
-++	WMI_TLV_PEER_TYPE_HOST_MAX = 127,
-++	WMI_TLV_PEER_TYPE_ROAMOFFLOAD_TMP = 128,
-++};
-++
-++struct wmi_tlv_peer_create_cmd {
-++	__le32 vdev_id;
-++	struct wmi_mac_addr peer_addr;
-++	__le32 peer_type;
-++} __packed;
-++
-++struct wmi_tlv_peer_assoc_cmd {
-++	struct wmi_mac_addr mac_addr;
-++	__le32 vdev_id;
-++	__le32 new_assoc;
-++	__le32 assoc_id;
-++	__le32 flags;
-++	__le32 caps;
-++	__le32 listen_intval;
-++	__le32 ht_caps;
-++	__le32 max_mpdu;
-++	__le32 mpdu_density;
-++	__le32 rate_caps;
-++	__le32 nss;
-++	__le32 vht_caps;
-++	__le32 phy_mode;
-++	__le32 ht_info[2];
-++	__le32 num_legacy_rates;
-++	__le32 num_ht_rates;
-++} __packed;
-++
-++struct wmi_tlv_pdev_suspend {
-++	__le32 pdev_id; /* not used yet */
-++	__le32 opt;
-++} __packed;
-++
-++struct wmi_tlv_pdev_set_wmm_cmd {
-++	__le32 pdev_id; /* not used yet */
-++	__le32 dg_type; /* no idea.. */
-++} __packed;
-++
-++struct wmi_tlv_vdev_wmm_params {
-++	__le32 dummy;
-++	struct wmi_wmm_params params;
-++} __packed;
-++
-++struct wmi_tlv_vdev_set_wmm_cmd {
-++	__le32 vdev_id;
-++	struct wmi_tlv_vdev_wmm_params vdev_wmm_params[4];
-++} __packed;
-++
-++struct wmi_tlv_phyerr_ev {
-++	__le32 num_phyerrs;
-++	__le32 tsf_l32;
-++	__le32 tsf_u32;
-++	__le32 buf_len;
-++} __packed;
-++
-++enum wmi_tlv_dbglog_param {
-++	WMI_TLV_DBGLOG_PARAM_LOG_LEVEL = 1,
-++	WMI_TLV_DBGLOG_PARAM_VDEV_ENABLE,
-++	WMI_TLV_DBGLOG_PARAM_VDEV_DISABLE,
-++	WMI_TLV_DBGLOG_PARAM_VDEV_ENABLE_BITMAP,
-++	WMI_TLV_DBGLOG_PARAM_VDEV_DISABLE_BITMAP,
-++};
-++
-++enum wmi_tlv_dbglog_log_level {
-++	WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE = 0,
-++	WMI_TLV_DBGLOG_LOG_LEVEL_INFO,
-++	WMI_TLV_DBGLOG_LOG_LEVEL_INFO_LVL_1,
-++	WMI_TLV_DBGLOG_LOG_LEVEL_INFO_LVL_2,
-++	WMI_TLV_DBGLOG_LOG_LEVEL_WARN,
-++	WMI_TLV_DBGLOG_LOG_LEVEL_ERR,
-++};
-++
-++#define WMI_TLV_DBGLOG_BITMAP_MAX_IDS 512
-++#define WMI_TLV_DBGLOG_BITMAP_MAX_WORDS (WMI_TLV_DBGLOG_BITMAP_MAX_IDS / \
-++					 sizeof(__le32))
-++#define WMI_TLV_DBGLOG_ALL_MODULES 0xffff
-++#define WMI_TLV_DBGLOG_LOG_LEVEL_VALUE(module_id, log_level) \
-++		(((module_id << 16) & 0xffff0000) | \
-++		 ((log_level <<  0) & 0x000000ff))
-++
-++struct wmi_tlv_dbglog_cmd {
-++	__le32 param;
-++	__le32 value;
-++} __packed;
-++
-++struct wmi_tlv_resume_cmd {
-++	__le32 reserved;
-++} __packed;
-++
-++struct wmi_tlv_req_stats_cmd {
-++	__le32 stats_id; /* wmi_stats_id */
-++	__le32 vdev_id;
-++	struct wmi_mac_addr peer_macaddr;
-++} __packed;
-++
-++struct wmi_tlv_vdev_stats {
-++	__le32 vdev_id;
-++	__le32 beacon_snr;
-++	__le32 data_snr;
-++	__le32 num_tx_frames[4]; /* per-AC */
-++	__le32 num_rx_frames;
-++	__le32 num_tx_frames_retries[4];
-++	__le32 num_tx_frames_failures[4];
-++	__le32 num_rts_fail;
-++	__le32 num_rts_success;
-++	__le32 num_rx_err;
-++	__le32 num_rx_discard;
-++	__le32 num_tx_not_acked;
-++	__le32 tx_rate_history[10];
-++	__le32 beacon_rssi_history[10];
-++} __packed;
-++
-++struct wmi_tlv_pktlog_enable {
-++	__le32 reserved;
-++	__le32 filter;
-++} __packed;
-++
-++struct wmi_tlv_pktlog_disable {
-++	__le32 reserved;
-++} __packed;
-++
-++enum wmi_tlv_bcn_tx_status {
-++	WMI_TLV_BCN_TX_STATUS_OK,
-++	WMI_TLV_BCN_TX_STATUS_XRETRY,
-++	WMI_TLV_BCN_TX_STATUS_DROP,
-++	WMI_TLV_BCN_TX_STATUS_FILTERED,
-++};
-++
-++struct wmi_tlv_bcn_tx_status_ev {
-++	__le32 vdev_id;
-++	__le32 tx_status;
-++} __packed;
-++
-++struct wmi_tlv_bcn_prb_info {
-++	__le32 caps;
-++	__le32 erp;
-++	u8 ies[0];
-++} __packed;
-++
-++struct wmi_tlv_bcn_tmpl_cmd {
-++	__le32 vdev_id;
-++	__le32 tim_ie_offset;
-++	__le32 buf_len;
-++} __packed;
-++
-++struct wmi_tlv_prb_tmpl_cmd {
-++	__le32 vdev_id;
-++	__le32 buf_len;
-++} __packed;
-++
-++struct wmi_tlv_p2p_go_bcn_ie {
-++	__le32 vdev_id;
-++	__le32 ie_len;
-++} __packed;
-++
-++enum wmi_tlv_diag_item_type {
-++	WMI_TLV_DIAG_ITEM_TYPE_FW_EVENT,
-++	WMI_TLV_DIAG_ITEM_TYPE_FW_LOG,
-++	WMI_TLV_DIAG_ITEM_TYPE_FW_DEBUG_MSG,
-++};
-++
-++struct wmi_tlv_diag_item {
-++	u8 type;
-++	u8 reserved;
-++	__le16 len;
-++	__le32 timestamp;
-++	__le32 code;
-++	u8 payload[0];
-++} __packed;
-++
-++struct wmi_tlv_diag_data_ev {
-++	__le32 num_items;
-++} __packed;
-++
-++struct wmi_tlv_sta_keepalive_cmd {
-++	__le32 vdev_id;
-++	__le32 enabled;
-++	__le32 method; /* WMI_STA_KEEPALIVE_METHOD_ */
-++	__le32 interval; /* in seconds */
-++} __packed;
-++
-++struct wmi_tlv_stats_ev {
-++	__le32 stats_id; /* WMI_STAT_ */
-++	__le32 num_pdev_stats;
-++	__le32 num_vdev_stats;
-++	__le32 num_peer_stats;
-++	__le32 num_bcnflt_stats;
-++	__le32 num_chan_stats;
-++} __packed;
-++
-++void ath10k_wmi_tlv_attach(struct ath10k *ar);
-++
-++#endif
-+--- a/backport-include/linux/etherdevice.h
-++++ b/backport-include/linux/etherdevice.h
-+@@ -148,6 +148,29 @@ static inline bool ether_addr_equal_unal
-+ 	return memcmp(addr1, addr2, ETH_ALEN) == 0;
-+ #endif
-+ }
-++
-++/**
-++ * ether_addr_copy - Copy an Ethernet address
-++ * @dst: Pointer to a six-byte array Ethernet address destination
-++ * @src: Pointer to a six-byte array Ethernet address source
-++ *
-++ * Please note: dst & src must both be aligned to u16.
-++ */
-++#define ether_addr_copy LINUX_BACKPORT(ether_addr_copy)
-++static inline void ether_addr_copy(u8 *dst, const u8 *src)
-++{
-++#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-++	*(u32 *)dst = *(const u32 *)src;
-++	*(u16 *)(dst + 4) = *(const u16 *)(src + 4);
-++#else
-++	u16 *a = (u16 *)dst;
-++	const u16 *b = (const u16 *)src;
-++
-++	a[0] = b[0];
-++	a[1] = b[1];
-++	a[2] = b[2];
-++#endif
-++}
-+ #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) */
-+ 
-+ #endif /* _BACKPORT_LINUX_ETHERDEVICE_H */
-+--- a/drivers/net/wireless/ath/spectral_common.h
-++++ b/drivers/net/wireless/ath/spectral_common.h
-+@@ -20,6 +20,11 @@
-+ #define SPECTRAL_HT20_NUM_BINS		56
-+ #define SPECTRAL_HT20_40_NUM_BINS		128
-+ 
-++/* TODO: could possibly be 512, but no samples this large
-++ * could be acquired so far.
-++ */
-++#define SPECTRAL_ATH10K_MAX_NUM_BINS		256
-++
-+ /* FFT sample format given to userspace via debugfs.
-+  *
-+  * Please keep the type/length at the front position and change
-+@@ -31,6 +36,7 @@
-+ enum ath_fft_sample_type {
-+ 	ATH_FFT_SAMPLE_HT20 = 1,
-+ 	ATH_FFT_SAMPLE_HT20_40,
-++	ATH_FFT_SAMPLE_ATH10K,
-+ };
-+ 
-+ struct fft_sample_tlv {
-+@@ -85,4 +91,23 @@ struct fft_sample_ht20_40 {
-+ 	u8 data[SPECTRAL_HT20_40_NUM_BINS];
-+ } __packed;
-+ 
-++struct fft_sample_ath10k {
-++	struct fft_sample_tlv tlv;
-++	u8 chan_width_mhz;
-++	__be16 freq1;
-++	__be16 freq2;
-++	__be16 noise;
-++	__be16 max_magnitude;
-++	__be16 total_gain_db;
-++	__be16 base_pwr_db;
-++	__be64 tsf;
-++	s8 max_index;
-++	u8 rssi;
-++	u8 relpwr_db;
-++	u8 avgpwr_db;
-++	u8 max_exp;
-++
-++	u8 data[0];
-++} __packed;
-++
-+ #endif /* SPECTRAL_COMMON_H */
-+--- a/compat/backport-3.13.c
-++++ b/compat/backport-3.13.c
-+@@ -12,6 +12,10 @@
-+ #include <linux/version.h>
-+ #include <linux/kernel.h>
-+ #include <net/genetlink.h>
-++#include <linux/delay.h>
-++#include <linux/pci.h>
-++#include <linux/device.h>
-++#include <linux/hwmon.h>
-+ 
-+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
-+ #ifdef CPTCFG_REGULATOR
-+@@ -200,3 +204,103 @@ bool __net_get_random_once(void *buf, in
-+ }
-+ EXPORT_SYMBOL_GPL(__net_get_random_once);
-+ #endif /* __BACKPORT_NET_GET_RANDOM_ONCE */
-++
-++#ifdef CPTCFG_PCI
-++#define pci_bus_read_dev_vendor_id LINUX_BACKPORT(pci_bus_read_dev_vendor_id)
-++static bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
-++				int crs_timeout)
-++{
-++	int delay = 1;
-++
-++	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
-++		return false;
-++
-++	/* some broken boards return 0 or ~0 if a slot is empty: */
-++	if (*l == 0xffffffff || *l == 0x00000000 ||
-++	    *l == 0x0000ffff || *l == 0xffff0000)
-++		return false;
-++
-++	/*
-++	 * Configuration Request Retry Status.  Some root ports return the
-++	 * actual device ID instead of the synthetic ID (0xFFFF) required
-++	 * by the PCIe spec.  Ignore the device ID and only check for
-++	 * (vendor id == 1).
-++	 */
-++	while ((*l & 0xffff) == 0x0001) {
-++		if (!crs_timeout)
-++			return false;
-++
-++		msleep(delay);
-++		delay *= 2;
-++		if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
-++			return false;
-++		/* Card hasn't responded in 60 seconds?  Must be stuck. */
-++		if (delay > crs_timeout) {
-++			printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not responding\n",
-++			       pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
-++			       PCI_FUNC(devfn));
-++			return false;
-++		}
-++	}
-++
-++	return true;
-++}
-++
-++bool pci_device_is_present(struct pci_dev *pdev)
-++{
-++	u32 v;
-++
-++	return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
-++}
-++EXPORT_SYMBOL_GPL(pci_device_is_present);
-++#endif /* CPTCFG_PCI */
-++
-++#ifdef CPTCFG_HWMON
-++struct device*
-++hwmon_device_register_with_groups(struct device *dev, const char *name,
-++				  void *drvdata,
-++				  const struct attribute_group **groups)
-++{
-++	struct device *hwdev;
-++
-++	hwdev = hwmon_device_register(dev);
-++	hwdev->groups = groups;
-++	dev_set_drvdata(hwdev, drvdata);
-++	return hwdev;
-++}
-++
-++static void devm_hwmon_release(struct device *dev, void *res)
-++{
-++	struct device *hwdev = *(struct device **)res;
-++
-++	hwmon_device_unregister(hwdev);
-++}
-++
-++struct device *
-++devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
-++				       void *drvdata,
-++				       const struct attribute_group **groups)
-++{
-++	struct device **ptr, *hwdev;
-++
-++	if (!dev)
-++		return ERR_PTR(-EINVAL);
-++
-++	ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
-++	if (!ptr)
-++		return ERR_PTR(-ENOMEM);
-++
-++	hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
-++	if (IS_ERR(hwdev))
-++		goto error;
-++
-++	*ptr = hwdev;
-++	devres_add(dev, ptr);
-++	return hwdev;
-++
-++error:
-++	devres_free(ptr);
-++	return hwdev;
-++}
-++EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
-++#endif
-+--- /dev/null
-++++ b/backport-include/linux/hwmon.h
-+@@ -0,0 +1,34 @@
-++#ifndef __BACKPORT_LINUX_HWMON_H
-++#define __BACKPORT_LINUX_HWMON_H
-++#include_next <linux/hwmon.h>
-++#include <linux/version.h>
-++
-++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
-++/*
-++ * Backports
-++ *
-++ * commit bab2243ce1897865e31ea6d59b0478391f51812b
-++ * Author: Guenter Roeck <linux@roeck-us.net>
-++ * Date:   Sat Jul 6 13:57:23 2013 -0700
-++ *
-++ *     hwmon: Introduce hwmon_device_register_with_groups
-++ *
-++ *     hwmon_device_register_with_groups() lets callers register a hwmon device
-++ *     together with all sysfs attributes in a single call.
-++ *
-++ *     When using hwmon_device_register_with_groups(), hwmon attributes are attached
-++ *     to the hwmon device directly and no longer with its parent device.
-++ *
-++ * Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-++ */
-++struct device *
-++hwmon_device_register_with_groups(struct device *dev, const char *name,
-++				  void *drvdata,
-++				  const struct attribute_group **groups);
-++struct device *
-++devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
-++				       void *drvdata,
-++				       const struct attribute_group **groups);
-++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) */
-++
-++#endif /* __BACKPORT_LINUX_HWMON_H */
-diff --git a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch b/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch
-index 6a5c766..6a3d2a4 100644
---- a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch
-+++ b/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch
-@@ -1,14 +1,14 @@
- --- a/drivers/net/wireless/ath/ath10k/core.c
- +++ b/drivers/net/wireless/ath/ath10k/core.c
--@@ -277,7 +277,10 @@ static int ath10k_download_and_run_otp(s
-+@@ -387,7 +387,10 @@ static int ath10k_download_and_run_otp(s
-  
-- 	ath10k_dbg(ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-+ 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-  
---	if (result != 0) {
-+-	if (!skip_otp && result != 0) {
- +	if (result == 2) {
--+		ath10k_warn("otp stream is empty, using board.bin contents");
-++		ath10k_warn(ar, "otp stream is empty, using board.bin contents");
- +		return 0;
--+	} else if (result != 0) {
-- 		ath10k_err("otp calibration failed: %d", result);
-++	} else if (!skip_otp && result != 0) {
-+ 		ath10k_err(ar, "otp calibration failed: %d", result);
-  		return -EINVAL;
-  	}
-diff --git a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
-new file mode 100644
-index 0000000..c664faa
---- /dev/null
-+++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
-@@ -0,0 +1,33 @@
-+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
-+@@ -1321,6 +1321,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);
-diff --git a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch
-new file mode 100644
-index 0000000..54174b1
---- /dev/null
-+++ b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch
-@@ -0,0 +1,37 @@
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -5405,6 +5405,21 @@ struct ath10k_vif *ath10k_get_arvif(stru
-+ 	return arvif_iter.arvif;
-+ }
-+ 
-++#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)
-+ {
-+ 	struct ieee80211_supported_band *band;
-+@@ -5567,6 +5582,12 @@ int ath10k_mac_register(struct ath10k *a
-+ 		goto err_free;
-+ 	}
-+ 
-++#if 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);
-diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
-new file mode 100644
-index 0000000..0011b5d
---- /dev/null
-+++ b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch
-@@ -0,0 +1,32 @@
-+--- a/drivers/net/wireless/ath/ath10k/mac.c
-++++ b/drivers/net/wireless/ath/ath10k/mac.c
-+@@ -5253,6 +5253,10 @@ static const struct ieee80211_iface_limi
-+ 	.max	= 7,
-+ 	.types	= BIT(NL80211_IFTYPE_AP)
-+ 	},
-++	{
-++	.max	= 1,
-++	.types	= BIT(NL80211_IFTYPE_ADHOC)
-++	},
-+ };
-+ 
-+ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
-+@@ -5260,6 +5264,10 @@ static const struct ieee80211_iface_limi
-+ 	.max	= 8,
-+ 	.types	= BIT(NL80211_IFTYPE_AP)
-+ 	},
-++	{
-++	.max	= 1,
-++	.types	= BIT(NL80211_IFTYPE_ADHOC)
-++	},
-+ };
-+ 
-+ static const struct ieee80211_iface_combination ath10k_if_comb[] = {
-+@@ -5555,6 +5563,7 @@ int ath10k_mac_register(struct ath10k *a
-+ 		ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
-+ 		ar->hw->wiphy->n_iface_combinations =
-+ 			ARRAY_SIZE(ath10k_10x_if_comb);
-++		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
-+ 		break;
-+ 	case ATH10K_FW_WMI_OP_VERSION_UNSET:
-+ 	case ATH10K_FW_WMI_OP_VERSION_MAX:

+ 0 - 41
patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch

@@ -1,41 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 10 Mar 2015 13:17:06 +0100
-Subject: ath10k: update firmware to the latest version
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
-index b96e782..629692d 100644
---- a/package/kernel/mac80211/Makefile
-+++ b/package/kernel/mac80211/Makefile
-@@ -129,7 +129,7 @@ endef
- $(eval $(call Download,linux-firmware))
- 
- PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
--PKG_ATH10K_LINUX_FIRMWARE_VERSION:=38eeda3ae6f90fde5546bdd48ee4ff3090f238c0
-+PKG_ATH10K_LINUX_FIRMWARE_VERSION:=232b419e71dab27b52b96e80ea7649ed67bdac77
- PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
- PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git
- PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git
-@@ -1821,18 +1821,17 @@ endef
- 
- define KernelPackage/ath10k/install
- 	$(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0
--ifeq ($(CONFIG_ATH10K_STA_FW),y)
- 	$(INSTALL_DATA) \
- 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
- 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
-+ifeq ($(CONFIG_ATH10K_STA_FW),y)
- 	$(INSTALL_DATA) \
- 		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \
- 		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
- else
- 	$(INSTALL_DATA) \
--		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
--		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/firmware-2.bin \
--		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
-+		$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2/firmware-3.bin_10.2-00082-4-2 \
-+		$(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-3.bin
- endif
- endef
- 

+ 0 - 20
patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch

@@ -1,20 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 10 Mar 2015 13:17:23 +0100
-Subject: at71xx: TP-LINK Archer: add 5GHz led entry
-
-Add 5GHz led entry after r44033.
-
-Signed-off-by: Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
-
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index a74b8f4..36fe028 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -326,6 +326,7 @@ tl-wdr4900-v2)
- 	ucidef_set_led_usbdev "usb1" "USB1" "tp-link:green:usb1" "1-1"
- 	ucidef_set_led_usbdev "usb2" "USB2" "tp-link:green:usb2" "2-1"
- 	ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy0tpt"
-+	ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:blue:wlan5g" "phy1tpt"
- 	;;
- 
- tl-wr741nd)

+ 0 - 34
patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch

@@ -1,34 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 10 Mar 2015 14:06:01 +0100
-Subject: ar71xx: fix switched WLAN LEDs on TP-LINK Archer C5/C7
-
-ath10k is loaded before ath9k, so the 5GHz adapter becomes phy0.
-
-diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-index 36fe028..315a9fd 100755
---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds
-@@ -320,8 +320,6 @@ tl-wdr4300)
- 	ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy0tpt"
- 	;;
- 
--archer-c5|\
--archer-c7|\
- tl-wdr4900-v2)
- 	ucidef_set_led_usbdev "usb1" "USB1" "tp-link:green:usb1" "1-1"
- 	ucidef_set_led_usbdev "usb2" "USB2" "tp-link:green:usb2" "2-1"
-@@ -329,6 +327,14 @@ tl-wdr4900-v2)
- 	ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:blue:wlan5g" "phy1tpt"
- 	;;
- 
-+archer-c5|\
-+archer-c7)
-+	ucidef_set_led_usbdev "usb1" "USB1" "tp-link:green:usb1" "1-1"
-+	ucidef_set_led_usbdev "usb2" "USB2" "tp-link:green:usb2" "2-1"
-+	ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy1tpt"
-+	ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:blue:wlan5g" "phy0tpt"
-+	;;
-+
- tl-wr741nd)
- 	ucidef_set_led_netdev "wan" "WAN" "tp-link:green:wan" "eth1"
- 	ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x02"

+ 0 - 24
patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch

@@ -1,24 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 11 Mar 2015 18:30:54 +0100
-Subject: uClibc: fix syscall() for syscalls with 6 arguments on PowerPC
-
-Patch from the uClibc master.
-
-Fixes the package fastd on PowerPC.
-
-diff --git a/toolchain/uClibc/patches-0.9.33.2/470-powerpc_syscall6.patch b/toolchain/uClibc/patches-0.9.33.2/470-powerpc_syscall6.patch
-new file mode 100644
-index 0000000..9511dcc
---- /dev/null
-+++ b/toolchain/uClibc/patches-0.9.33.2/470-powerpc_syscall6.patch
-@@ -0,0 +1,10 @@
-+--- a/libc/sysdeps/linux/powerpc/syscall.S
-++++ b/libc/sysdeps/linux/powerpc/syscall.S
-+@@ -30,6 +30,7 @@ syscall:
-+ 	mr 5,6
-+ 	mr 6,7
-+ 	mr 7,8
-++	mr 8,9
-+ 	sc
-+ 	bnslr;
-+ 

+ 0 - 35
patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch

@@ -1,35 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 12 Mar 2015 16:57:32 +0100
-Subject: ar71xx: Add build profile for the gl-inet 6416A and 6408A
-
-Patch to add the buildprofile for the GL-Init-6408A-v1 and the GL-Inet-6416A-v1
-Both devices are identical, only difference is one comes with 8MB flash and
-the other with 16MB flash
-
-Official website: http://www.gl-inet.com/w/?page_id=241&lang=en
-Comprehensive list of specs: https://revspace.nl/GL-Inet
-
-Signed-off-by: Martijn Zilverschoon <martijn@friedzombie.com>
-
-diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile
-index 8505ac4..fc59c33 100644
---- a/target/linux/ar71xx/image/Makefile
-+++ b/target/linux/ar71xx/image/Makefile
-@@ -1216,7 +1216,8 @@ $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,ARCHERC7V1,archer-c7-v1,ARCHER-C7
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,ARCHERC7V2,archer-c7-v2,ARCHER-C7,ttyS0,115200,0xc7000002,1,16Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,ELM150,el-m150,EL-M150,ttyATH0,115200,0x01500101,1,8Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,ELMINI,el-mini,EL-MINI,ttyATH0,115200,0x01530001,1,8Mlzma))
--$(eval $(call SingleProfile,TPLINK-LZMA,64kraw,GLINET,gl-inet-v1,GL-INET,ttyATH0,115200,0x08000001,1,8Mlzma))
-+$(eval $(call SingleProfile,TPLINK-LZMA,64kraw,GLINET6408A,gl-inet-6408A-v1,GL-INET,ttyATH0,115200,0x08000001,1,8Mlzma))
-+$(eval $(call SingleProfile,TPLINK-LZMA,64kraw,GLINET6416A,gl-inet-6416A-v1,GL-INET,ttyATH0,115200,0x08000001,1,16Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLMR10U,tl-mr10u-v1,TL-MR10U,ttyATH0,115200,0x00100101,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLMR11UV1,tl-mr11u-v1,TL-MR11U,ttyATH0,115200,0x00110101,1,4Mlzma))
- $(eval $(call SingleProfile,TPLINK-LZMA,64kraw,TLMR11UV2,tl-mr11u-v2,TL-MR11U,ttyATH0,115200,0x00110102,1,4Mlzma))
-@@ -1304,6 +1305,7 @@ $(eval $(call MultiProfile,AP136,AP136_010 AP136_020))
- $(eval $(call MultiProfile,ARCHERC7, ARCHERC5 ARCHERC7V1 ARCHERC7V2))
- $(eval $(call MultiProfile,EWDORIN, EWDORINAP EWDORINRT EWDORIN16M))
- $(eval $(call MultiProfile,OPENMESH,OM2P OM5P MR600))
-+$(eval $(call MultiProfile,GLINET,GLINET6408A GLINET6416A))
- $(eval $(call MultiProfile,TEW652BRP,TEW652BRP_FW TEW652BRP_RECOVERY))
- $(eval $(call MultiProfile,TLMR11U,TLMR11UV1 TLMR11UV2))
- $(eval $(call MultiProfile,TLMR3040,TLMR3040V1 TLMR3040V2))

+ 0 - 39
patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch

@@ -1,39 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Fri, 13 Mar 2015 11:59:58 +0100
-Subject: ar71xx: detect GL.iNet model
-
-There are two versions of the GL.iNet, the 6408A and the 6416A. The only
-difference is the flash size.
-
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index 61a7936..a698ce5 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -262,6 +262,19 @@ tplink_pharos_board_detect() {
- 	[ -n "$model" ] && AR71XX_MODEL="$model v$2"
- }
- 
-+gl_inet_board_detect() {
-+	local size="$(mtd_get_part_size 'firmware')"
-+
-+	case "$size" in
-+	8192000)
-+		AR71XX_MODEL='GL-iNet 6408A v1'
-+		;;
-+	16580608)
-+		AR71XX_MODEL='GL-iNet 6416A v1'
-+		;;
-+	esac
-+}
-+
- ar71xx_board_detect() {
- 	local machine
- 	local name
-@@ -380,6 +393,7 @@ ar71xx_board_detect() {
- 		;;
- 	*"GL-CONNECT INET v1")
- 		name="gl-inet"
-+		gl_inet_board_detect
- 		;;
- 	*"EnGenius ESR1750")
- 		name="esr1750"

+ 0 - 70
patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch

@@ -1,70 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sun, 15 Mar 2015 18:06:49 +0100
-Subject: firmware-utils: allow passing a specific MBR signature to ptgen
-
-Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-
-diff --git a/tools/firmware-utils/src/ptgen.c b/tools/firmware-utils/src/ptgen.c
-index 0247fd0..6379ed7 100644
---- a/tools/firmware-utils/src/ptgen.c
-+++ b/tools/firmware-utils/src/ptgen.c
-@@ -28,6 +28,7 @@
- #include <stdio.h>
- #include <ctype.h>
- #include <fcntl.h>
-+#include <stdint.h>
- 
- #if __BYTE_ORDER == __BIG_ENDIAN
- #define cpu_to_le16(x) bswap_16(x)
-@@ -124,7 +125,7 @@ static inline unsigned long round_to_kb(long sect) {
- }
- 
- /* check the partition sizes and write the partition table */
--static int gen_ptable(int nr)
-+static int gen_ptable(uint32_t signature, int nr)
- {
- 	struct pte pte[4];
- 	unsigned long sect = 0; 
-@@ -159,6 +160,12 @@ static int gen_ptable(int nr)
- 		return -1;
- 	}
- 
-+	lseek(fd, 440, SEEK_SET);
-+	if (write(fd, &signature, sizeof(signature)) != sizeof(signature)) {
-+		fprintf(stderr, "write failed.\n");
-+		goto fail;
-+	}
-+
- 	lseek(fd, 446, SEEK_SET);
- 	if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) {
- 		fprintf(stderr, "write failed.\n");
-@@ -187,8 +194,9 @@ int main (int argc, char **argv)
- 	char type = 0x83;
- 	int ch;
- 	int part = 0;
-+	uint32_t signature = 0x5452574F; /* 'OWRT' */
- 
--	while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vl:")) != -1) {
-+	while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vl:S:")) != -1) {
- 		switch (ch) {
- 		case 'o':
- 			filename = optarg;
-@@ -221,6 +229,9 @@ int main (int argc, char **argv)
- 		case 'l':
- 			kb_align = (int) strtoul(optarg, NULL, 0) * 2;
- 			break;
-+		case 'S':
-+			signature = strtoul(optarg, NULL, 0);
-+			break;
- 		case '?':
- 		default:
- 			usage(argv[0]);
-@@ -229,6 +240,6 @@ int main (int argc, char **argv)
- 	argc -= optind;
- 	if (argc || (heads <= 0) || (sectors <= 0) || !filename) 
- 		usage(argv[0]);
--	
--	return gen_ptable(part);
-+
-+	return gen_ptable(signature, part);
- }

+ 0 - 180
patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch

@@ -1,180 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Mon, 23 Mar 2015 21:11:41 +0100
-Subject: x86: use PARTUUID instead explicitly specifying the device by default
-
-This changes the x86 image generation to match x86_64, using the PARTUUID for
-the rootfs instead of explicitly configuring the device.
-
-It unbreaks KVM with VirtIO, which uses /dev/vda2 instead of /dev/sda2.
-
-Tested in QEMU/KVM with VirtIO, VirtualBox and VMware.
-
-diff --git a/config/Config-images.in b/config/Config-images.in
-index 39e51e4..f44ec73 100644
---- a/config/Config-images.in
-+++ b/config/Config-images.in
-@@ -267,8 +267,6 @@ menu "Target Images"
- 	config TARGET_ROOTFS_PARTNAME
- 		string "Root partition on target device"
- 		depends on OLPC_BOOTSCRIPT_IMAGES || GRUB_IMAGES
--		default "/dev/xvda2" if TARGET_x86_xen_domu
--		default "/dev/sda2" if ! TARGET_x86_xen_domu
- 		help
- 		  The root partition on the final device.  If you don't know,
- 		  you probably want the default (/dev/sda2).
-diff --git a/target/linux/x86/base-files/lib/preinit/79_move_config b/target/linux/x86/base-files/lib/preinit/79_move_config
-index 0bffbab..1d4873d 100644
---- a/target/linux/x86/base-files/lib/preinit/79_move_config
-+++ b/target/linux/x86/base-files/lib/preinit/79_move_config
-@@ -1,21 +1,14 @@
- #!/bin/sh
--# Copyright (C) 2012 OpenWrt.org
-+# Copyright (C) 2012-2015 OpenWrt.org
- 
- move_config() {
--	local rootfsdev
--	local rootfstype
--	
--	rootfstype="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "rootfstype") { print $2 }' < /proc/cmdline)"
--	case "$rootfstype" in
--		squashfs|jffs2)
--			rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "block2mtd.block2mtd") { print substr($2,1,index($2, ",")-1) }' < /proc/cmdline)";;
--		ext4)
--			rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "root") { print $2 }' < /proc/cmdline)";;
--	esac
-+	. /lib/upgrade/platform.sh
- 
--	mount -t ext4 -o rw,noatime "${rootfsdev%[0-9]}1" /mnt
--	mv -f /mnt/sysupgrade.tgz /
--	umount /mnt
-+	if platform_export_bootpart; then
-+		mount -t ext4 -o rw,noatime "$BOOTPART" /mnt
-+		mv -f /mnt/sysupgrade.tgz /
-+		umount /mnt
-+	fi
- }
- 
- boot_hook_add preinit_mount_root move_config
-diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh
-index a2dd20a..73ab5ef 100644
---- a/target/linux/x86/base-files/lib/upgrade/platform.sh
-+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh
-@@ -1,16 +1,38 @@
--x86_get_rootfs() {
--	local rootfsdev
--	local rootfstype
--	
--	rootfstype="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "rootfstype") { print $2 }' < /proc/cmdline)"
--	case "$rootfstype" in
--		squashfs|jffs2)
--			rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "block2mtd.block2mtd") { print substr($2,1,index($2, ",")-1) }' < /proc/cmdline)";;
--		ext4)
--			rootfsdev="$(awk 'BEGIN { RS=" "; FS="="; } ($1 == "root") { print $2 }' < /proc/cmdline)";;
--	esac
--		
--	echo "$rootfstype:$rootfsdev"
-+platform_export_bootpart() {
-+	local cmdline uuid disk
-+
-+	if read cmdline < /proc/cmdline; then
-+		case "$cmdline" in
-+			*block2mtd=*)
-+				disk="${cmdline##*block2mtd=}"
-+				disk="${disk%%,*}"
-+			;;
-+			*root=*)
-+				disk="${cmdline##*root=}"
-+				disk="${disk%% *}"
-+			;;
-+		esac
-+
-+		case "$disk" in
-+			PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-02)
-+				uuid="${disk#PARTUUID=}"
-+				uuid="${uuid%-02}"
-+				for disk in /dev/[hsv]d[a-z]; do
-+					set -- $(dd if=$disk bs=1 skip=440 count=4 2>/dev/null | hexdump -v -e '4/1 "%02x "')
-+					if [ "$4$3$2$1" = "$uuid" ]; then
-+						export BOOTPART="${disk}1"
-+						return 0
-+					fi
-+				done
-+			;;
-+			/dev/*)
-+				export BOOTPART="${disk%[0-9]}1"
-+				return 0
-+			;;
-+		esac
-+	fi
-+
-+	return 1
- }
- 
- platform_check_image() {
-@@ -26,19 +48,19 @@ platform_check_image() {
- }
- 
- platform_copy_config() {
--	local rootfs="$(x86_get_rootfs)"
--	local rootfsdev="${rootfs##*:}"
--	
--	mount -t ext4 -o rw,noatime "${rootfsdev%[0-9]}1" /mnt
--	cp -af "$CONF_TAR" /mnt/
--	umount /mnt
-+	if [ -b "$BOOTPART" ]; then
-+		mount -t ext4 -o rw,noatime "$BOOTPART" /mnt
-+		cp -af "$CONF_TAR" /mnt/
-+		umount /mnt
-+	fi
- }
- 
- platform_do_upgrade() {
--	local rootfs="$(x86_get_rootfs)"
--	local rootfsdev="${rootfs##*:}"
-+	platform_export_bootpart
- 
--	sync
--	[ -b ${rootfsdev%[0-9]} ] && get_image "$@" | dd of=${rootfsdev%[0-9]} bs=4096 conv=fsync
--	sleep 1
-+	if [ -b "${BOOTPART%[0-9]}" ]; then
-+		sync
-+		get_image "$@" | dd of="${BOOTPART%[0-9]}" bs=4096 conv=fsync
-+		sleep 1
-+	fi
- }
-diff --git a/target/linux/x86/image/Makefile b/target/linux/x86/image/Makefile
-index 5983718..1f91b9f 100644
---- a/target/linux/x86/image/Makefile
-+++ b/target/linux/x86/image/Makefile
-@@ -40,7 +40,9 @@ ifneq ($(GRUB_TERMINALS),)
-   GRUB_TERMINAL_CONFIG := terminal_input $(GRUB_TERMINALS); terminal_output $(GRUB_TERMINALS)
- endif
- 
-+SIGNATURE:=$(shell dd if=/dev/urandom bs=4 count=1 2>/dev/null | hexdump -v -e '"%08x"')
- ROOTPART:=$(call qstrip,$(CONFIG_TARGET_ROOTFS_PARTNAME))
-+ROOTPART:=$(if $(ROOTPART),$(ROOTPART),PARTUUID=$(SIGNATURE)-02)
- 
- GRUB_TIMEOUT:=$(call qstrip,$(CONFIG_GRUB_TIMEOUT))
- 
-@@ -82,7 +84,7 @@ ifneq ($(CONFIG_GRUB_IMAGES),)
- 		-e 's#@CMDLINE@#$(strip $(call Image/cmdline/$(1)) $(BOOTOPTS) $(GRUB_CONSOLE_CMDLINE))#g' \
- 		-e 's#@TIMEOUT@#$(GRUB_TIMEOUT)#g' \
- 		./grub.cfg > $(KDIR)/root.grub/boot/grub/grub.cfg
--	PADDING="$(CONFIG_TARGET_IMAGES_PAD)" PATH="$(TARGET_PATH)" ./gen_image_generic.sh \
-+	PADDING="$(CONFIG_TARGET_IMAGES_PAD)" SIGNATURE="$(SIGNATURE)" PATH="$(TARGET_PATH)" ./gen_image_generic.sh \
- 		$(BIN_DIR)/$(IMG_PREFIX)-combined-$(1).img \
- 		$(CONFIG_TARGET_KERNEL_PARTSIZE) $(KDIR)/root.grub \
- 		$(CONFIG_TARGET_ROOTFS_PARTSIZE) $(KDIR)/root.$(1) \
-diff --git a/target/linux/x86/image/gen_image_generic.sh b/target/linux/x86/image/gen_image_generic.sh
-index 9d11efb..3fb31f6 100755
---- a/target/linux/x86/image/gen_image_generic.sh
-+++ b/target/linux/x86/image/gen_image_generic.sh
-@@ -20,7 +20,7 @@ sect=63
- cyl=$(( ($KERNELSIZE + $ROOTFSSIZE) * 1024 * 1024 / ($head * $sect * 512)))
- 
- # create partition table
--set `ptgen -o "$OUTPUT" -h $head -s $sect -p ${KERNELSIZE}m -p ${ROOTFSSIZE}m ${ALIGN:+-l $ALIGN}`
-+set `ptgen -o "$OUTPUT" -h $head -s $sect -p ${KERNELSIZE}m -p ${ROOTFSSIZE}m ${ALIGN:+-l $ALIGN} ${SIGNATURE:+-S 0x$SIGNATURE}`
- 
- KERNELOFFSET="$(($1 / 512))"
- KERNELSIZE="$(($2 / 512))"

+ 0 - 65
patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch

@@ -1,65 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sun, 29 Mar 2015 13:23:26 +0200
-Subject: ar71xx: fix model string detection on NETGEAR WNDR3700/3800/WNDRMAC
-
-There were a few issues with the existing code to detect the model string:
-* Always using the string starting with byte 56 would cut off the W of WNDR when
-  the ID starts with 29763654+16+64 instead of 29763654+16+128
-* The string contained garbage after the zero byte instead of cutting it off
-  after the zero (which wasn't always visible using busybox tools, but could
-  confuse other scripts)
-
-Tested on a WNDR3700v1 and a WNDR3700v2 using the new 29763654+16+64 ID in the
-ART. Furthermore, tested against ART dumps of a WNDR3700v2 using the old
-$'\xff...' value and a WNDR3800.
-
-The [ -z "$model" ] check was dropped as there is no way to actually hit this
-unless no ART partition is found at all.
-
-The awk command was carefully crafted to work both with gawk and the (horribly
-broken) busybox awk.
-
-Fixes #18992.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-index a698ce5..1838cb4 100755
---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh
-+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh
-@@ -37,16 +37,26 @@ wndr3700_board_detect() {
- 		machine="NETGEAR WNDR3700"
- 		;;
- 	"33373031")
--		local model
--		model=$(ar71xx_get_mtd_offset_size_format art 56 10 %c)
--		if [ -z "$model" ] || [ "$model" = $'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' ]; then
--			machine="NETGEAR WNDR3700v2"
--		elif [ -z "$model" ] || [ "$model" = $'\xff\xff\xff\xff\xff\xff\xff\xff\xffN' ]; then
--			machine="NETGEAR WNDRMAC"
--		else
-+		# Use awk to remove everything after the first zero byte
-+		model="$(ar71xx_get_mtd_offset_size_format art 41 32 %c | awk 'BEGIN{FS="[[:cntrl:]]"} {print $1; exit}')"
-+		case $model in
-+		$'\xff'*)
-+			if [ "${model:24:1}" = 'N' ]; then
-+				machine="NETGEAR WNDRMAC"
-+			else
-+				machine="NETGEAR WNDR3700v2"
-+			fi
-+			;;
-+		'29763654+16+64'*)
-+			machine="NETGEAR ${model:14}"
-+			;;
-+		'29763654+16+128'*)
-+			machine="NETGEAR ${model:15}"
-+			;;
-+		*)
-+			# Unknown ID
- 			machine="NETGEAR $model"
--		fi
--		;;
-+		esac
- 	esac
- 
- 	AR71XX_BOARD_NAME="$name"

+ 0 - 22
patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch

@@ -1,22 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sun, 15 Mar 2015 21:03:25 +0100
-Subject: ar71xx: fix TP-LINK TL-WDR3600/4300 RFKILL switch positions
-
-While the switch positions aren't explicitly labeled as on and off, we've heard
-complaints about them being wrong. This patch changes the handling to match the
-stock firmware.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-
-diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c
-index 99ae80d..3afc714 100644
---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c
-+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wdr4300.c
-@@ -103,6 +103,7 @@ static struct gpio_keys_button wdr4300_gpio_keys[] __initdata = {
- 		.code		= KEY_RFKILL,
- 		.debounce_interval = WDR4300_KEYS_DEBOUNCE_INTERVAL,
- 		.gpio		= WDR4300_GPIO_BTN_RFKILL,
-+		.active_low	= 1,
- 	},
- };
- 

+ 0 - 57
patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch

@@ -1,57 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Mon, 16 Mar 2015 13:23:34 +0100
-Subject: buildroot: make it easier to build all kmods
-
-Split out kmods from ALL to make it easier to create local builds that
-are compatible kmod-wise with releases.
-
-Signed-off-by: Jonas Gorski <jogo@openwrt.org>
-
-diff --git a/config/Config-build.in b/config/Config-build.in
-index 371ae76..8b0ebbf 100644
---- a/config/Config-build.in
-+++ b/config/Config-build.in
-@@ -6,8 +6,12 @@
- 
- menu "Global build settings"
- 
-+	config ALL_KMODS
-+		bool "Select all kernel module packages by default"
-+		default ALL
-+
- 	config ALL
--		bool "Select all packages by default"
-+		bool "Select all userspace packages by default"
- 		default n
- 
- 	comment "General build options"
-diff --git a/include/version.mk b/include/version.mk
-index 2fd605f..f6c0fe2 100644
---- a/include/version.mk
-+++ b/include/version.mk
-@@ -50,7 +50,7 @@ $(lastword $(subst :, ,$(1)))
- endef
- 
- VERSION_TAINT_SPECS := \
--	-ALL:no-all \
-+	-ALL_KMODS:no-all \
- 	-IPV6:no-ipv6 \
- 	+USE_EGLIBC:eglibc \
- 	+USE_MKLIBS:mklibs \
-diff --git a/scripts/metadata.pl b/scripts/metadata.pl
-index 79f930c..4eecb0c 100755
---- a/scripts/metadata.pl
-+++ b/scripts/metadata.pl
-@@ -574,7 +574,11 @@ sub print_package_config_category($) {
- 			print "\t\t".($pkg->{tristate} ? 'tristate' : 'bool')." $title\n";
- 			print "\t\tdefault y if DEFAULT_".$pkg->{name}."\n";
- 			unless ($pkg->{hidden}) {
--				$pkg->{default} ||= "m if ALL";
-+				if ($pkg->{name} =~ /^kmod-/) {
-+					$pkg->{default} ||= "m if ALL_KMODS";
-+				} else {
-+					$pkg->{default} ||= "m if ALL";
-+				}
- 			}
- 			if ($pkg->{default}) {
- 				foreach my $default (split /\s*,\s*/, $pkg->{default}) {

+ 0 - 26
patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch

@@ -1,26 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 18 Mar 2015 20:07:22 +0100
-Subject: build: define STAMP_CONFIGURED recursively
-
-Defining STAMP_CONFIGURED statically caused it not to reflect changes to
-PKG_CONFIG_DEPENDS made after including package.mk, like the additional options
-added by feeds.mk for all packages.
-
-Furthermore, as STAMP_CONFIGURED_WILDCARD was already defined recursively, the
-patsubst in its definition would never match, and in consequence, the stamps
-were never removed. This caused packages not to be rebuilt when they should have
-been.
-
-diff --git a/include/package.mk b/include/package.mk
-index 53ca6de..402fb1a 100644
---- a/include/package.mk
-+++ b/include/package.mk
-@@ -60,7 +60,7 @@ ifneq ($(PREV_STAMP_PREPARED),)
- else
-   STAMP_PREPARED=$(PKG_BUILD_DIR)/.prepared$(if $(QUILT)$(DUMP),,_$(shell $(call find_md5,${CURDIR} $(PKG_FILE_DEPENDS),))$(call confvar,$(PKG_PREPARED_DEPENDS)))
- endif
--STAMP_CONFIGURED:=$(PKG_BUILD_DIR)/.configured$(if $(DUMP),,_$(call confvar,$(PKG_CONFIG_DEPENDS)))
-+STAMP_CONFIGURED=$(PKG_BUILD_DIR)/.configured$(if $(DUMP),,_$(call confvar,$(PKG_CONFIG_DEPENDS)))
- STAMP_CONFIGURED_WILDCARD=$(patsubst %_$(call confvar,$(PKG_CONFIG_DEPENDS)),%_*,$(STAMP_CONFIGURED))
- STAMP_BUILT:=$(PKG_BUILD_DIR)/.built
- STAMP_INSTALLED:=$(STAGING_DIR)/stamp/.$(PKG_NAME)_installed

+ 0 - 1111
patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch

@@ -1,1111 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 30 Apr 2015 03:21:01 +0200
-Subject: mpc85xx: move newly created files from patch files to files directory
-
-This will make these files much more maintainable.
-
-diff --git a/target/linux/mpc85xx/files/arch/powerpc/boot/cuboot-tl-wdr4900-v1.c b/target/linux/mpc85xx/files/arch/powerpc/boot/cuboot-tl-wdr4900-v1.c
-new file mode 100644
-index 0000000..17459ef
---- /dev/null
-+++ b/target/linux/mpc85xx/files/arch/powerpc/boot/cuboot-tl-wdr4900-v1.c
-@@ -0,0 +1,168 @@
-+/*
-+ * U-Boot compatibility wrapper for the TP-Link TL-WDR4900 v1 board
-+ *
-+ * Copyright (c) 2013 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * Based on:
-+ *  cuboot-85xx.c
-+ *     Author: Scott Wood <scottwood@freescale.com>
-+ *     Copyright (c) 2007 Freescale Semiconductor, Inc.
-+ *
-+ *  simpleboot.c
-+ *     Authors: Scott Wood <scottwood@freescale.com>
-+ *              Grant Likely <grant.likely@secretlab.ca>
-+ *     Copyright (c) 2007 Freescale Semiconductor, Inc.
-+ *     Copyright (c) 2008 Secret Lab Technologies Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+
-+#include "ops.h"
-+#include "types.h"
-+#include "io.h"
-+#include "stdio.h"
-+#include <libfdt.h>
-+
-+BSS_STACK(4*1024);
-+
-+static unsigned long bus_freq;
-+static unsigned long int_freq;
-+static u64 mem_size;
-+static unsigned char enetaddr[6];
-+
-+static void process_boot_dtb(void *boot_dtb)
-+{
-+	const u32 *na, *ns, *reg, *val32;
-+	const char *path;
-+	u64 memsize64;
-+	int node, size, i;
-+
-+	/* Make sure FDT blob is sane */
-+	if (fdt_check_header(boot_dtb) != 0)
-+		fatal("Invalid device tree blob\n");
-+
-+	/* Find the #address-cells and #size-cells properties */
-+	node = fdt_path_offset(boot_dtb, "/");
-+	if (node < 0)
-+		fatal("Cannot find root node\n");
-+	na = fdt_getprop(boot_dtb, node, "#address-cells", &size);
-+	if (!na || (size != 4))
-+		fatal("Cannot find #address-cells property");
-+
-+	ns = fdt_getprop(boot_dtb, node, "#size-cells", &size);
-+	if (!ns || (size != 4))
-+		fatal("Cannot find #size-cells property");
-+
-+	/* Find the memory range */
-+	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
-+					     "memory", sizeof("memory"));
-+	if (node < 0)
-+		fatal("Cannot find memory node\n");
-+	reg = fdt_getprop(boot_dtb, node, "reg", &size);
-+	if (size < (*na+*ns) * sizeof(u32))
-+		fatal("cannot get memory range\n");
-+
-+	/* Only interested in memory based at 0 */
-+	for (i = 0; i < *na; i++)
-+		if (*reg++ != 0)
-+			fatal("Memory range is not based at address 0\n");
-+
-+	/* get the memsize and trucate it to under 4G on 32 bit machines */
-+	memsize64 = 0;
-+	for (i = 0; i < *ns; i++)
-+		memsize64 = (memsize64 << 32) | *reg++;
-+	if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
-+		memsize64 = 0xffffffff;
-+
-+	mem_size = memsize64;
-+
-+	/* get clock frequencies */
-+	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
-+					     "cpu", sizeof("cpu"));
-+	if (!node)
-+		fatal("Cannot find cpu node\n");
-+
-+	val32 = fdt_getprop(boot_dtb, node, "clock-frequency", &size);
-+	if (!val32 || (size != 4))
-+		fatal("Cannot get clock frequency");
-+
-+	int_freq = *val32;
-+
-+	val32 = fdt_getprop(boot_dtb, node, "bus-frequency", &size);
-+	if (!val32 || (size != 4))
-+		fatal("Cannot get bus frequency");
-+
-+	bus_freq = *val32;
-+
-+	path = fdt_get_alias(boot_dtb, "ethernet0");
-+	if (path) {
-+		const void *p;
-+
-+		node = fdt_path_offset(boot_dtb, path);
-+		if (node < 0)
-+			fatal("Cannot find ethernet0 node");
-+
-+		p = fdt_getprop(boot_dtb, node, "mac-address", &size);
-+		if (!p || (size < 6)) {
-+			printf("no mac-address property, finding local\n\r");
-+			p = fdt_getprop(boot_dtb, node, "local-mac-address", &size);
-+		}
-+
-+		if (!p || (size < 6))
-+			fatal("cannot get MAC addres");
-+
-+		memcpy(enetaddr, p, sizeof(enetaddr));
-+	}
-+}
-+
-+static void platform_fixups(void)
-+{
-+	void *soc, *mpic;
-+
-+	dt_fixup_memory(0, mem_size);
-+
-+	dt_fixup_mac_address_by_alias("ethernet0", enetaddr);
-+	dt_fixup_cpu_clocks(int_freq, bus_freq / 8, bus_freq);
-+
-+	/* Unfortunately, the specific model number is encoded in the
-+	 * soc node name in existing dts files -- once that is fixed,
-+	 * this can do a simple path lookup.
-+	 */
-+	soc = find_node_by_devtype(NULL, "soc");
-+	if (soc) {
-+		void *serial = NULL;
-+
-+		setprop(soc, "bus-frequency", &bus_freq, sizeof(bus_freq));
-+
-+		while ((serial = find_node_by_devtype(serial, "serial"))) {
-+			if (get_parent(serial) != soc)
-+				continue;
-+
-+			setprop(serial, "clock-frequency", &bus_freq,
-+				sizeof(bus_freq));
-+		}
-+	}
-+
-+	mpic = find_node_by_compatible(NULL, "fsl,mpic");
-+	if (mpic)
-+		setprop(mpic, "clock-frequency", &bus_freq, sizeof(bus_freq));
-+}
-+
-+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-+                   unsigned long r6, unsigned long r7)
-+{
-+	mem_size = 64 * 1024 * 1024;
-+
-+	simple_alloc_init(_end, mem_size - (u32)_end - 1024*1024, 32, 64);
-+
-+	fdt_init(_dtb_start);
-+	serial_console_init();
-+
-+	printf("\n\r-- TL-WDR4900 v1 boot wrapper --\n\r");
-+
-+	process_boot_dtb((void *) r3);
-+
-+	platform_ops.fixups = platform_fixups;
-+}
-diff --git a/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-new file mode 100644
-index 0000000..49e516c
---- /dev/null
-+++ b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-@@ -0,0 +1,212 @@
-+/*
-+ * TP-Link TL-WDR4900 v1 Device Tree Source
-+ *
-+ * Copyright 2013 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 as published by the
-+ * Free Software Foundation;  either version 2 of the  License, or (at your
-+ * option) any later version.
-+ */
-+
-+/include/ "fsl/p1010si-pre.dtsi"
-+
-+/ {
-+	model = "TP-Link TL-WDR4900 v1";
-+	compatible = "tp-link,TL-WDR4900v1";
-+
-+	chosen {
-+		bootargs = "console=ttyS0,115200";
-+/*
-+		linux,stdout-path = "/soc@ffe00000/serial@4500";
-+*/
-+	};
-+
-+	aliases {
-+		spi0 = &spi0;
-+	};
-+
-+	memory {
-+		device_type = "memory";
-+	};
-+
-+	soc: soc@ffe00000 {
-+		ranges = <0x0 0x0 0xffe00000 0x100000>;
-+
-+		spi0: spi@7000 {
-+			flash@0 {
-+				#address-cells = <1>;
-+				#size-cells = <1>;
-+				compatible = "spansion,s25fl129p1";
-+				reg = <0>;
-+				spi-max-frequency = <25000000>;
-+
-+				u-boot@0 {
-+					reg = <0x0 0x0050000>;
-+					label = "u-boot";
-+					read-only;
-+				};
-+
-+				dtb@50000 {
-+					reg = <0x00050000 0x00010000>;
-+					label = "dtb";
-+					read-only;
-+				};
-+
-+				kernel@60000 {
-+					reg = <0x00060000 0x002a0000>;
-+					label = "kernel";
-+				};
-+
-+				rootfs@300000 {
-+					reg = <0x00300000 0x00ce0000>;
-+					label = "rootfs";
-+				};
-+
-+				config@fe0000 {
-+					reg = <0x00fe0000 0x00010000>;
-+					label = "config";
-+					read-only;
-+				};
-+
-+				caldata@ff0000 {
-+					reg = <0x00ff0000 0x00010000>;
-+					label = "caldata";
-+					read-only;
-+				};
-+
-+				firmware@60000 {
-+					reg = <0x00060000 0x00f80000>;
-+					label = "firmware";
-+				};
-+			};
-+		};
-+
-+		gpio0: gpio-controller@f000 {
-+		};
-+
-+		usb@22000 {
-+			phy_type = "utmi";
-+			dr_mode = "host";
-+		};
-+
-+		mdio@24000 {
-+			phy0: ethernet-phy@0 {
-+				reg = <0x0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x07600000 /* PAD0_MODE */
-+					0x00008 0x00000000 /* PAD5_MODE */
-+					0x0000c 0x01000000 /* PAD6_MODE */
-+					0x00010 0x40000000 /* POWER_ON_STRIP */
-+					0x00050 0xcf35cf35 /* LED_CTRL0 */
-+					0x00054 0xcf35cf35 /* LED_CTRL1 */
-+					0x00058 0xcf35cf35 /* LED_CTRL2 */
-+					0x0005c 0x03ffff00 /* LED_CTRL3 */
-+					0x0007c 0x0000007e /* PORT0_STATUS */
-+				>;
-+			};
-+		};
-+
-+		mdio@25000 {
-+			status = "disabled";
-+		};
-+
-+		mdio@26000 {
-+			status = "disabled";
-+		};
-+
-+		enet0: ethernet@b0000 {
-+			phy-handle = <&phy0>;
-+			phy-connection-type = "rgmii-id";
-+		};
-+
-+		enet1: ethernet@b1000 {
-+			status = "disabled";
-+		};
-+
-+		enet2: ethernet@b2000 {
-+			status = "disabled";
-+		};
-+
-+		sdhc@2e000 {
-+			status = "disabled";
-+		};
-+
-+		serial1: serial@4600 {
-+			status = "disabled";
-+		};
-+
-+		can0: can@1c000 {
-+			status = "disabled";
-+		};
-+
-+		can1: can@1d000 {
-+			status = "disabled";
-+		};
-+	};
-+
-+	pci0: pcie@ffe09000 {
-+		reg = <0 0xffe09000 0 0x1000>;
-+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
-+		pcie@0 {
-+			ranges = <0x2000000 0x0 0xa0000000
-+				  0x2000000 0x0 0xa0000000
-+				  0x0 0x20000000
-+
-+				  0x1000000 0x0 0x0
-+				  0x1000000 0x0 0x0
-+				  0x0 0x100000>;
-+		};
-+	};
-+
-+	pci1: pcie@ffe0a000 {
-+		reg = <0 0xffe0a000 0 0x1000>;
-+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
-+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
-+		pcie@0 {
-+			ranges = <0x2000000 0x0 0x80000000
-+				  0x2000000 0x0 0x80000000
-+				  0x0 0x20000000
-+
-+				  0x1000000 0x0 0x0
-+				  0x1000000 0x0 0x0
-+				  0x0 0x100000>;
-+		};
-+	};
-+
-+	ifc: ifc@ffe1e000 {
-+		status = "disabled";
-+	};
-+
-+	leds {
-+		compatible = "gpio-leds";
-+
-+		system {
-+			gpios = <&gpio0 2 1>; /* active low */
-+			label = "tp-link:blue:system";
-+		};
-+
-+		usb1 {
-+			gpios = <&gpio0 3 1>; /* active low */
-+			label = "tp-link:green:usb1";
-+		};
-+
-+		usb2 {
-+			gpios = <&gpio0 4 1>; /* active low */
-+			label = "tp-link:green:usb2";
-+		};
-+	};
-+
-+	buttons {
-+		compatible = "gpio-keys";
-+
-+		reset {
-+			label = "Reset button";
-+			gpios = <&gpio0 5 1>; /* active low */
-+			linux,code = <0x198>; /* KEY_RESTART */
-+		};
-+	};
-+};
-+
-+/include/ "fsl/p1010si-post.dtsi"
-diff --git a/target/linux/mpc85xx/files/arch/powerpc/platforms/85xx/tl_wdr4900_v1.c b/target/linux/mpc85xx/files/arch/powerpc/platforms/85xx/tl_wdr4900_v1.c
-new file mode 100644
-index 0000000..95afa4d
---- /dev/null
-+++ b/target/linux/mpc85xx/files/arch/powerpc/platforms/85xx/tl_wdr4900_v1.c
-@@ -0,0 +1,145 @@
-+/*
-+ * TL-WDR4900 v1 board setup
-+ *
-+ * Copyright (c) 2013 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * Based on:
-+ *   p1010rdb.c:
-+ *      P1010RDB Board Setup
-+ *      Copyright 2011 Freescale Semiconductor Inc.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/stddef.h>
-+#include <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/of_platform.h>
-+#include <linux/ath9k_platform.h>
-+#include <linux/leds.h>
-+
-+#include <asm/time.h>
-+#include <asm/machdep.h>
-+#include <asm/pci-bridge.h>
-+#include <mm/mmu_decl.h>
-+#include <asm/prom.h>
-+#include <asm/udbg.h>
-+#include <asm/mpic.h>
-+
-+#include <sysdev/fsl_soc.h>
-+#include <sysdev/fsl_pci.h>
-+
-+#include "mpc85xx.h"
-+
-+void __init tl_wdr4900_v1_pic_init(void)
-+{
-+	struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
-+	  MPIC_SINGLE_DEST_CPU,
-+	  0, 256, " OpenPIC  ");
-+
-+	BUG_ON(mpic == NULL);
-+
-+	mpic_init(mpic);
-+}
-+
-+#ifdef CONFIG_PCI
-+static struct gpio_led tl_wdr4900_v1_wmac_leds_gpio[] = {
-+	{
-+		.name		= "tp-link:blue:wps",
-+		.gpio		= 1,
-+		.active_low	= 1,
-+	},
-+};
-+
-+static struct ath9k_platform_data tl_wdr4900_v1_wmac0_data = {
-+	.led_pin = 0,
-+	.eeprom_name = "pci_wmac0.eeprom",
-+	.leds = tl_wdr4900_v1_wmac_leds_gpio,
-+	.num_leds = ARRAY_SIZE(tl_wdr4900_v1_wmac_leds_gpio),
-+};
-+
-+static struct ath9k_platform_data tl_wdr4900_v1_wmac1_data = {
-+	.led_pin = 0,
-+	.eeprom_name = "pci_wmac1.eeprom",
-+};
-+
-+static void tl_wdr4900_v1_pci_wmac_fixup(struct pci_dev *dev)
-+{
-+	if (!machine_is(tl_wdr4900_v1))
-+		return;
-+
-+	if (dev->bus->number == 1 &&
-+	    PCI_SLOT(dev->devfn) == 0) {
-+		dev->dev.platform_data = &tl_wdr4900_v1_wmac0_data;
-+		return;
-+	}
-+
-+	if (dev->bus->number == 3 &&
-+	    PCI_SLOT(dev->devfn) == 0 &&
-+	    dev->device == 0xabcd) {
-+		dev->dev.platform_data = &tl_wdr4900_v1_wmac1_data;
-+
-+		/*
-+		 * The PCI header of the AR9381 chip is not programmed
-+		 * correctly by the bootloader and the device uses wrong
-+		 * data due to that. Replace the broken values with the
-+		 * correct ones.
-+		 */
-+		dev->device = 0x30;
-+		dev->class = 0x028000;
-+
-+		pr_info("pci %s: AR9381 fixup applied\n", pci_name(dev));
-+	}
-+}
-+
-+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID,
-+			tl_wdr4900_v1_pci_wmac_fixup);
-+#endif /* CONFIG_PCI */
-+
-+/*
-+ * Setup the architecture
-+ */
-+static void __init tl_wdr4900_v1_setup_arch(void)
-+{
-+	if (ppc_md.progress)
-+		ppc_md.progress("tl_wdr4900_v1_setup_arch()", 0);
-+
-+	fsl_pci_assign_primary();
-+
-+	printk(KERN_INFO "TL-WDR4900 v1 board from TP-Link\n");
-+}
-+
-+machine_arch_initcall(tl_wdr4900_v1, mpc85xx_common_publish_devices);
-+machine_arch_initcall(tl_wdr4900_v1, swiotlb_setup_bus_notifier);
-+
-+/*
-+ * Called very early, device-tree isn't unflattened
-+ */
-+static int __init tl_wdr4900_v1_probe(void)
-+{
-+	unsigned long root = of_get_flat_dt_root();
-+
-+	if (of_flat_dt_is_compatible(root, "tp-link,TL-WDR4900v1"))
-+		return 1;
-+
-+	return 0;
-+}
-+
-+define_machine(tl_wdr4900_v1) {
-+	.name			= "Freescale P1014",
-+	.probe			= tl_wdr4900_v1_probe,
-+	.setup_arch		= tl_wdr4900_v1_setup_arch,
-+	.init_IRQ		= tl_wdr4900_v1_pic_init,
-+#ifdef CONFIG_PCI
-+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-+#endif
-+	.get_irq		= mpic_get_irq,
-+	.restart		= fsl_rstcr_restart,
-+	.calibrate_decr		= generic_calibrate_decr,
-+	.progress		= udbg_progress,
-+};
-diff --git a/target/linux/mpc85xx/patches-3.10/140-powerpc-85xx-tl-wdr4900-v1-support.patch b/target/linux/mpc85xx/patches-3.10/140-powerpc-85xx-tl-wdr4900-v1-support.patch
-index 8407176..dae2305 100644
---- a/target/linux/mpc85xx/patches-3.10/140-powerpc-85xx-tl-wdr4900-v1-support.patch
-+++ b/target/linux/mpc85xx/patches-3.10/140-powerpc-85xx-tl-wdr4900-v1-support.patch
-@@ -11,16 +11,9 @@ the Freescale P1014 SoC.
- Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
- ---
-  arch/powerpc/boot/Makefile                  |    3 +
-- arch/powerpc/boot/cuboot-tl-wdr4900-v1.c    |  164 ++++++++++++++++++++++++++
-- arch/powerpc/boot/dts/tl-wdr4900-v1.dts     |  166 +++++++++++++++++++++++++++
-  arch/powerpc/boot/wrapper                   |    4 +
-  arch/powerpc/platforms/85xx/Kconfig         |   11 ++
-  arch/powerpc/platforms/85xx/Makefile        |    1 +
-- arch/powerpc/platforms/85xx/tl_wdr4900_v1.c |  145 +++++++++++++++++++++++
-- 7 files changed, 494 insertions(+)
-- create mode 100644 arch/powerpc/boot/cuboot-tl-wdr4900-v1.c
-- create mode 100644 arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-- create mode 100644 arch/powerpc/platforms/85xx/tl_wdr4900_v1.c
- 
- --- a/arch/powerpc/boot/Makefile
- +++ b/arch/powerpc/boot/Makefile
-@@ -41,388 +34,6 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
-  
-  # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
-  image-$(CONFIG_STORCENTER)		+= cuImage.storcenter
----- /dev/null
--+++ b/arch/powerpc/boot/cuboot-tl-wdr4900-v1.c
--@@ -0,0 +1,164 @@
--+/*
--+ * U-Boot compatibility wrapper for the TP-Link TL-WDR4900 v1 board
--+ *
--+ * Copyright (c) 2013 Gabor Juhos <juhosg@openwrt.org>
--+ *
--+ * Based on:
--+ *  cuboot-85xx.c
--+ *     Author: Scott Wood <scottwood@freescale.com>
--+ *     Copyright (c) 2007 Freescale Semiconductor, Inc.
--+ *
--+ *  simpleboot.c
--+ *     Authors: Scott Wood <scottwood@freescale.com>
--+ *              Grant Likely <grant.likely@secretlab.ca>
--+ *     Copyright (c) 2007 Freescale Semiconductor, Inc.
--+ *     Copyright (c) 2008 Secret Lab Technologies Ltd.
--+ *
--+ * This program is free software; you can redistribute it and/or modify it
--+ * under the terms of the GNU General Public License version 2 as published
--+ * by the Free Software Foundation.
--+ */
--+
--+#include "ops.h"
--+#include "types.h"
--+#include "io.h"
--+#include "stdio.h"
--+#include <libfdt.h>
--+
--+BSS_STACK(4*1024);
--+
--+static unsigned long bus_freq;
--+static unsigned long int_freq;
--+static u64 mem_size;
--+static unsigned char enetaddr[6];
--+
--+static void process_boot_dtb(void *boot_dtb)
--+{
--+	const u32 *na, *ns, *reg, *val32;
--+	const char *path;
--+	u64 memsize64;
--+	int node, size, i;
--+
--+	/* Make sure FDT blob is sane */
--+	if (fdt_check_header(boot_dtb) != 0)
--+		fatal("Invalid device tree blob\n");
--+
--+	/* Find the #address-cells and #size-cells properties */
--+	node = fdt_path_offset(boot_dtb, "/");
--+	if (node < 0)
--+		fatal("Cannot find root node\n");
--+	na = fdt_getprop(boot_dtb, node, "#address-cells", &size);
--+	if (!na || (size != 4))
--+		fatal("Cannot find #address-cells property");
--+
--+	ns = fdt_getprop(boot_dtb, node, "#size-cells", &size);
--+	if (!ns || (size != 4))
--+		fatal("Cannot find #size-cells property");
--+
--+	/* Find the memory range */
--+	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
--+					     "memory", sizeof("memory"));
--+	if (node < 0)
--+		fatal("Cannot find memory node\n");
--+	reg = fdt_getprop(boot_dtb, node, "reg", &size);
--+	if (size < (*na+*ns) * sizeof(u32))
--+		fatal("cannot get memory range\n");
--+
--+	/* Only interested in memory based at 0 */
--+	for (i = 0; i < *na; i++)
--+		if (*reg++ != 0)
--+			fatal("Memory range is not based at address 0\n");
--+
--+	/* get the memsize and trucate it to under 4G on 32 bit machines */
--+	memsize64 = 0;
--+	for (i = 0; i < *ns; i++)
--+		memsize64 = (memsize64 << 32) | *reg++;
--+	if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL)
--+		memsize64 = 0xffffffff;
--+
--+	mem_size = memsize64;
--+
--+	/* get clock frequencies */
--+	node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type",
--+					     "cpu", sizeof("cpu"));
--+	if (!node)
--+		fatal("Cannot find cpu node\n");
--+
--+	val32 = fdt_getprop(boot_dtb, node, "clock-frequency", &size);
--+	if (!val32 || (size != 4))
--+		fatal("Cannot get clock frequency");
--+
--+	int_freq = *val32;
--+
--+	val32 = fdt_getprop(boot_dtb, node, "bus-frequency", &size);
--+	if (!val32 || (size != 4))
--+		fatal("Cannot get bus frequency");
--+
--+	bus_freq = *val32;
--+
--+	path = fdt_get_alias(boot_dtb, "ethernet0");
--+	if (path) {
--+		const void *p;
--+
--+		node = fdt_path_offset(boot_dtb, path);
--+		if (node < 0)
--+			fatal("Cannot find ethernet0 node");
--+
--+		p = fdt_getprop(boot_dtb, node, "mac-address", &size);
--+		if (!p || (size < 6)) {
--+			printf("no mac-address property, finding local\n\r");
--+			p = fdt_getprop(boot_dtb, node, "local-mac-address", &size);
--+		}
--+
--+		if (!p || (size < 6))
--+			fatal("cannot get MAC addres");
--+
--+		memcpy(enetaddr, p, sizeof(enetaddr));
--+	}
--+}
--+
--+static void platform_fixups(void)
--+{
--+	void *soc;
--+
--+	dt_fixup_memory(0, mem_size);
--+
--+	dt_fixup_mac_address_by_alias("ethernet0", enetaddr);
--+	dt_fixup_cpu_clocks(int_freq, bus_freq / 8, bus_freq);
--+
--+	/* Unfortunately, the specific model number is encoded in the
--+	 * soc node name in existing dts files -- once that is fixed,
--+	 * this can do a simple path lookup.
--+	 */
--+	soc = find_node_by_devtype(NULL, "soc");
--+	if (soc) {
--+		void *serial = NULL;
--+
--+		setprop(soc, "bus-frequency", &bus_freq, sizeof(bus_freq));
--+
--+		while ((serial = find_node_by_devtype(serial, "serial"))) {
--+			if (get_parent(serial) != soc)
--+				continue;
--+
--+			setprop(serial, "clock-frequency", &bus_freq,
--+				sizeof(bus_freq));
--+		}
--+	}
--+}
--+
--+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
--+                   unsigned long r6, unsigned long r7)
--+{
--+	mem_size = 64 * 1024 * 1024;
--+
--+	simple_alloc_init(_end, mem_size - (u32)_end - 1024*1024, 32, 64);
--+
--+	fdt_init(_dtb_start);
--+	serial_console_init();
--+
--+	printf("\n\r-- TL-WDR4900 v1 boot wrapper --\n\r");
--+
--+	process_boot_dtb((void *) r3);
--+
--+	platform_ops.fixups = platform_fixups;
--+}
----- /dev/null
--+++ b/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
--@@ -0,0 +1,212 @@
--+/*
--+ * TP-Link TL-WDR4900 v1 Device Tree Source
--+ *
--+ * Copyright 2013 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 as published by the
--+ * Free Software Foundation;  either version 2 of the  License, or (at your
--+ * option) any later version.
--+ */
--+
--+/include/ "fsl/p1010si-pre.dtsi"
--+
--+/ {
--+	model = "TP-Link TL-WDR4900 v1";
--+	compatible = "tp-link,TL-WDR4900v1";
--+
--+	chosen {
--+		bootargs = "console=ttyS0,115200";
--+/*
--+		linux,stdout-path = "/soc@ffe00000/serial@4500";
--+*/
--+	};
--+
--+	aliases {
--+		spi0 = &spi0;
--+	};
--+
--+	memory {
--+		device_type = "memory";
--+	};
--+
--+	soc: soc@ffe00000 {
--+		ranges = <0x0 0x0 0xffe00000 0x100000>;
--+
--+		spi0: spi@7000 {
--+			flash@0 {
--+				#address-cells = <1>;
--+				#size-cells = <1>;
--+				compatible = "spansion,s25fl129p1";
--+				reg = <0>;
--+				spi-max-frequency = <25000000>;
--+
--+				u-boot@0 {
--+					reg = <0x0 0x0050000>;
--+					label = "u-boot";
--+					read-only;
--+				};
--+
--+				dtb@50000 {
--+					reg = <0x00050000 0x00010000>;
--+					label = "dtb";
--+					read-only;
--+				};
--+
--+				kernel@60000 {
--+					reg = <0x00060000 0x002a0000>;
--+					label = "kernel";
--+				};
--+
--+				rootfs@300000 {
--+					reg = <0x00300000 0x00ce0000>;
--+					label = "rootfs";
--+				};
--+
--+				config@fe0000 {
--+					reg = <0x00fe0000 0x00010000>;
--+					label = "config";
--+					read-only;
--+				};
--+
--+				caldata@ff0000 {
--+					reg = <0x00ff0000 0x00010000>;
--+					label = "caldata";
--+					read-only;
--+				};
--+
--+				firmware@60000 {
--+					reg = <0x00060000 0x00f80000>;
--+					label = "firmware";
--+				};
--+			};
--+		};
--+
--+		gpio0: gpio-controller@f000 {
--+		};
--+
--+		usb@22000 {
--+			phy_type = "utmi";
--+			dr_mode = "host";
--+		};
--+
--+		mdio@24000 {
--+			phy0: ethernet-phy@0 {
--+				reg = <0x0>;
--+				qca,ar8327-initvals = <
--+					0x00004 0x07600000 /* PAD0_MODE */
--+					0x00008 0x00000000 /* PAD5_MODE */
--+					0x0000c 0x01000000 /* PAD6_MODE */
--+					0x00010 0x40000000 /* POWER_ON_STRIP */
--+					0x00050 0xcf35cf35 /* LED_CTRL0 */
--+					0x00054 0xcf35cf35 /* LED_CTRL1 */
--+					0x00058 0xcf35cf35 /* LED_CTRL2 */
--+					0x0005c 0x03ffff00 /* LED_CTRL3 */
--+					0x0007c 0x0000007e /* PORT0_STATUS */
--+				>;
--+			};
--+		};
--+
--+		mdio@25000 {
--+			status = "disabled";
--+		};
--+
--+		mdio@26000 {
--+			status = "disabled";
--+		};
--+
--+		enet0: ethernet@b0000 {
--+			phy-handle = <&phy0>;
--+			phy-connection-type = "rgmii-id";
--+		};
--+
--+		enet1: ethernet@b1000 {
--+			status = "disabled";
--+		};
--+
--+		enet2: ethernet@b2000 {
--+			status = "disabled";
--+		};
--+
--+		sdhc@2e000 {
--+			status = "disabled";
--+		};
--+
--+		serial1: serial@4600 {
--+			status = "disabled";
--+		};
--+
--+		can0: can@1c000 {
--+			status = "disabled";
--+		};
--+
--+		can1: can@1d000 {
--+			status = "disabled";
--+		};
--+	};
--+
--+	pci0: pcie@ffe09000 {
--+		reg = <0 0xffe09000 0 0x1000>;
--+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
--+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
--+		pcie@0 {
--+			ranges = <0x2000000 0x0 0xa0000000
--+				  0x2000000 0x0 0xa0000000
--+				  0x0 0x20000000
--+
--+				  0x1000000 0x0 0x0
--+				  0x1000000 0x0 0x0
--+				  0x0 0x100000>;
--+		};
--+	};
--+
--+	pci1: pcie@ffe0a000 {
--+		reg = <0 0xffe0a000 0 0x1000>;
--+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
--+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
--+		pcie@0 {
--+			ranges = <0x2000000 0x0 0x80000000
--+				  0x2000000 0x0 0x80000000
--+				  0x0 0x20000000
--+
--+				  0x1000000 0x0 0x0
--+				  0x1000000 0x0 0x0
--+				  0x0 0x100000>;
--+		};
--+	};
--+
--+	ifc: ifc@ffe1e000 {
--+		status = "disabled";
--+	};
--+
--+	leds {
--+		compatible = "gpio-leds";
--+
--+		system {
--+			gpios = <&gpio0 2 1>; /* active low */
--+			label = "tp-link:blue:system";
--+		};
--+
--+		usb1 {
--+			gpios = <&gpio0 3 1>; /* active low */
--+			label = "tp-link:green:usb1";
--+		};
--+
--+		usb2 {
--+			gpios = <&gpio0 4 1>; /* active low */
--+			label = "tp-link:green:usb2";
--+		};
--+	};
--+
--+	buttons {
--+		compatible = "gpio-keys";
--+
--+		reset {
--+			label = "Reset button";
--+			gpios = <&gpio0 5 1>; /* active low */
--+			linux,code = <0x198>; /* KEY_RESTART */
--+		};
--+	};
--+};
--+
--+/include/ "fsl/p1010si-post.dtsi"
- --- a/arch/powerpc/boot/wrapper
- +++ b/arch/powerpc/boot/wrapper
- @@ -197,6 +197,10 @@ cuboot*)
-@@ -466,151 +77,3 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
-  obj-$(CONFIG_SBC8548)     += sbc8548.o
-  obj-$(CONFIG_PPA8548)     += ppa8548.o
-  obj-$(CONFIG_SOCRATES)    += socrates.o socrates_fpga_pic.o
----- /dev/null
--+++ b/arch/powerpc/platforms/85xx/tl_wdr4900_v1.c
--@@ -0,0 +1,145 @@
--+/*
--+ * TL-WDR4900 v1 board setup
--+ *
--+ * Copyright (c) 2013 Gabor Juhos <juhosg@openwrt.org>
--+ *
--+ * Based on:
--+ *   p1010rdb.c:
--+ *      P1010RDB Board Setup
--+ *      Copyright 2011 Freescale Semiconductor Inc.
--+ *
--+ * 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.
--+ */
--+
--+#include <linux/stddef.h>
--+#include <linux/kernel.h>
--+#include <linux/pci.h>
--+#include <linux/delay.h>
--+#include <linux/interrupt.h>
--+#include <linux/of_platform.h>
--+#include <linux/ath9k_platform.h>
--+#include <linux/leds.h>
--+
--+#include <asm/time.h>
--+#include <asm/machdep.h>
--+#include <asm/pci-bridge.h>
--+#include <mm/mmu_decl.h>
--+#include <asm/prom.h>
--+#include <asm/udbg.h>
--+#include <asm/mpic.h>
--+
--+#include <sysdev/fsl_soc.h>
--+#include <sysdev/fsl_pci.h>
--+
--+#include "mpc85xx.h"
--+
--+void __init tl_wdr4900_v1_pic_init(void)
--+{
--+	struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
--+	  MPIC_SINGLE_DEST_CPU,
--+	  0, 256, " OpenPIC  ");
--+
--+	BUG_ON(mpic == NULL);
--+
--+	mpic_init(mpic);
--+}
--+
--+#ifdef CONFIG_PCI
--+static struct gpio_led tl_wdr4900_v1_wmac_leds_gpio[] = {
--+	{
--+		.name		= "tp-link:blue:wps",
--+		.gpio		= 1,
--+		.active_low	= 1,
--+	},
--+};
--+
--+static struct ath9k_platform_data tl_wdr4900_v1_wmac0_data = {
--+	.led_pin = 0,
--+	.eeprom_name = "pci_wmac0.eeprom",
--+	.leds = tl_wdr4900_v1_wmac_leds_gpio,
--+	.num_leds = ARRAY_SIZE(tl_wdr4900_v1_wmac_leds_gpio),
--+};
--+
--+static struct ath9k_platform_data tl_wdr4900_v1_wmac1_data = {
--+	.led_pin = 0,
--+	.eeprom_name = "pci_wmac1.eeprom",
--+};
--+
--+static void tl_wdr4900_v1_pci_wmac_fixup(struct pci_dev *dev)
--+{
--+	if (!machine_is(tl_wdr4900_v1))
--+		return;
--+
--+	if (dev->bus->number == 1 &&
--+	    PCI_SLOT(dev->devfn) == 0) {
--+		dev->dev.platform_data = &tl_wdr4900_v1_wmac0_data;
--+		return;
--+	}
--+
--+	if (dev->bus->number == 3 &&
--+	    PCI_SLOT(dev->devfn) == 0 &&
--+	    dev->device == 0xabcd) {
--+		dev->dev.platform_data = &tl_wdr4900_v1_wmac1_data;
--+
--+		/*
--+		 * The PCI header of the AR9381 chip is not programmed
--+		 * correctly by the bootloader and the device uses wrong
--+		 * data due to that. Replace the broken values with the
--+		 * correct ones.
--+		 */
--+		dev->device = 0x30;
--+		dev->class = 0x028000;
--+
--+		pr_info("pci %s: AR9381 fixup applied\n", pci_name(dev));
--+	}
--+}
--+
--+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID,
--+			tl_wdr4900_v1_pci_wmac_fixup);
--+#endif /* CONFIG_PCI */
--+
--+/*
--+ * Setup the architecture
--+ */
--+static void __init tl_wdr4900_v1_setup_arch(void)
--+{
--+	if (ppc_md.progress)
--+		ppc_md.progress("tl_wdr4900_v1_setup_arch()", 0);
--+
--+	fsl_pci_assign_primary();
--+
--+	printk(KERN_INFO "TL-WDR4900 v1 board from TP-Link\n");
--+}
--+
--+machine_arch_initcall(tl_wdr4900_v1, mpc85xx_common_publish_devices);
--+machine_arch_initcall(tl_wdr4900_v1, swiotlb_setup_bus_notifier);
--+
--+/*
--+ * Called very early, device-tree isn't unflattened
--+ */
--+static int __init tl_wdr4900_v1_probe(void)
--+{
--+	unsigned long root = of_get_flat_dt_root();
--+
--+	if (of_flat_dt_is_compatible(root, "tp-link,TL-WDR4900v1"))
--+		return 1;
--+
--+	return 0;
--+}
--+
--+define_machine(tl_wdr4900_v1) {
--+	.name			= "Freescale P1014",
--+	.probe			= tl_wdr4900_v1_probe,
--+	.setup_arch		= tl_wdr4900_v1_setup_arch,
--+	.init_IRQ		= tl_wdr4900_v1_pic_init,
--+#ifdef CONFIG_PCI
--+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
--+#endif
--+	.get_irq		= mpic_get_irq,
--+	.restart		= fsl_rstcr_restart,
--+	.calibrate_decr		= generic_calibrate_decr,
--+	.progress		= udbg_progress,
--+};

+ 0 - 168
patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch

@@ -1,168 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 30 Apr 2015 02:10:54 +0200
-Subject: mpc85xx: gianfar: add add mtd-mac-address support
-
-diff --git a/target/linux/mpc85xx/patches-3.10/101-NET-add-of_get_mac_address_mtd.patch b/target/linux/mpc85xx/patches-3.10/101-NET-add-of_get_mac_address_mtd.patch
-new file mode 100644
-index 0000000..cd88d2b
---- /dev/null
-+++ b/target/linux/mpc85xx/patches-3.10/101-NET-add-of_get_mac_address_mtd.patch
-@@ -0,0 +1,76 @@
-+From 92f38460229a8816404408f036f0a374f1013d0e Mon Sep 17 00:00:00 2001
-+From: John Crispin <blogic@openwrt.org>
-+Date: Sun, 27 Jul 2014 09:40:01 +0100
-+Subject: NET: add of_get_mac_address_mtd()
-+
-+Many embedded devices have information such as mac addresses stored inside mtd
-+devices. This patch allows us to add a property inside a node describing a
-+network interface. The new property points at a mtd partition with an offset
-+where the mac address can be found.
-+
-+Signed-off-by: John Crispin <blogic@openwrt.org>
-+---
-+ drivers/of/of_net.c    |   37 +++++++++++++++++++++++++++++++++++++
-+ include/linux/of_net.h |    1 +
-+ 2 files changed, 38 insertions(+)
-+
-+--- a/drivers/of/of_net.c
-++++ b/drivers/of/of_net.c
-+@@ -10,6 +10,7 @@
-+ #include <linux/of_net.h>
-+ #include <linux/phy.h>
-+ #include <linux/export.h>
-++#include <linux/mtd/mtd.h>
-+ 
-+ /**
-+  * It maps 'enum phy_interface_t' found in include/linux/phy.h
-+@@ -92,3 +93,39 @@ const void *of_get_mac_address(struct de
-+ 	return NULL;
-+ }
-+ EXPORT_SYMBOL(of_get_mac_address);
-++
-++int of_get_mac_address_mtd(struct device_node *np, void *mac)
-++{
-++	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-mac-address", &size);
-++	if (!list || (size != (2 * sizeof(*list))))
-++		return -ENOENT;
-++
-++	phandle = be32_to_cpup(list++);
-++	if (phandle)
-++		mtd_np = of_find_node_by_phandle(phandle);
-++
-++	if (!mtd_np)
-++		return -ENOENT;
-++
-++	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 PTR_ERR(mtd);
-++
-++	ret = mtd_read(mtd, be32_to_cpup(list), 6, &retlen, (u_char *) mac);
-++	put_mtd_device(mtd);
-++
-++	return ret;
-++}
-++EXPORT_SYMBOL_GPL(of_get_mac_address_mtd);
-+--- a/include/linux/of_net.h
-++++ b/include/linux/of_net.h
-+@@ -11,6 +11,7 @@
-+ #include <linux/of.h>
-+ extern const int of_get_phy_mode(struct device_node *np);
-+ extern const void *of_get_mac_address(struct device_node *np);
-++extern int of_get_mac_address_mtd(struct device_node *np, void *mac);
-+ #else
-+ static inline const int of_get_phy_mode(struct device_node *np)
-+ {
-diff --git a/target/linux/mpc85xx/patches-3.10/201-net-gianfar-use-mtd-mac-address.patch b/target/linux/mpc85xx/patches-3.10/201-net-gianfar-use-mtd-mac-address.patch
-new file mode 100644
-index 0000000..1de4418
---- /dev/null
-+++ b/target/linux/mpc85xx/patches-3.10/201-net-gianfar-use-mtd-mac-address.patch
-@@ -0,0 +1,19 @@
-+--- a/drivers/net/ethernet/freescale/gianfar.c
-++++ b/drivers/net/ethernet/freescale/gianfar.c
-+@@ -741,10 +741,13 @@ static int gfar_of_init(struct platform_
-+ 	if (stash_len || stash_idx)
-+ 		priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;
-+ 
-+-	mac_addr = of_get_mac_address(np);
-++	err = of_get_mac_address_mtd(np, dev->dev_addr);
-++	if (err) {
-++		mac_addr = of_get_mac_address(np);
-+ 
-+-	if (mac_addr)
-+-		memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
-++		if (mac_addr)
-++			memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
-++	}
-+ 
-+ 	if (model && !strcasecmp(model, "TSEC"))
-+ 		priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
-diff --git a/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch b/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch
-index d0380ff..0d510bc 100644
---- a/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch
-+++ b/target/linux/mpc85xx/patches-3.10/220-fix_gianfar_reported_number_of_sent_bytes_to_BQL.patch
-@@ -1,6 +1,6 @@
- --- a/drivers/net/ethernet/freescale/gianfar.c
- +++ b/drivers/net/ethernet/freescale/gianfar.c
--@@ -2064,7 +2064,7 @@ static int gfar_start_xmit(struct sk_buf
-+@@ -2067,7 +2067,7 @@ static int gfar_start_xmit(struct sk_buf
-  	int i, rq = 0, do_tstamp = 0;
-  	u32 bufaddr;
-  	unsigned long flags;
-@@ -9,7 +9,7 @@
-  
-  	/* TOE=1 frames larger than 2500 bytes may see excess delays
-  	 * before start of transmission.
--@@ -2130,7 +2130,10 @@ static int gfar_start_xmit(struct sk_buf
-+@@ -2133,7 +2133,10 @@ static int gfar_start_xmit(struct sk_buf
-  	}
-  
-  	/* Update transmit stats */
-@@ -21,7 +21,7 @@
-  	tx_queue->stats.tx_packets++;
-  
-  	txbdp = txbdp_start = tx_queue->cur_tx;
--@@ -2150,12 +2153,13 @@ static int gfar_start_xmit(struct sk_buf
-+@@ -2153,12 +2156,13 @@ static int gfar_start_xmit(struct sk_buf
-  	} else {
-  		/* Place the fragment addresses and lengths into the TxBDs */
-  		for (i = 0; i < nr_frags; i++) {
-@@ -37,7 +37,7 @@
-  				  BD_LFLAG(TXBD_READY);
-  
-  			/* Handle the last BD specially */
--@@ -2165,7 +2169,7 @@ static int gfar_start_xmit(struct sk_buf
-+@@ -2168,7 +2172,7 @@ static int gfar_start_xmit(struct sk_buf
-  			bufaddr = skb_frag_dma_map(priv->dev,
-  						   &skb_shinfo(skb)->frags[i],
-  						   0,
-@@ -46,7 +46,7 @@
-  						   DMA_TO_DEVICE);
-  
-  			/* set the TxBD length and buffer pointer */
--@@ -2231,7 +2235,7 @@ static int gfar_start_xmit(struct sk_buf
-+@@ -2234,7 +2238,7 @@ static int gfar_start_xmit(struct sk_buf
-  		lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
-  	}
-  
-@@ -55,7 +55,7 @@
-  
-  	/* We can work in parallel with gfar_clean_tx_ring(), except
-  	 * when modifying num_txbdfree. Note that we didn't grab the lock
--@@ -2551,7 +2555,7 @@ static void gfar_clean_tx_ring(struct gf
-+@@ -2554,7 +2558,7 @@ static void gfar_clean_tx_ring(struct gf
-  			bdp = next_txbd(bdp, base, tx_ring_size);
-  		}
-  

+ 0 - 41
patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch

@@ -1,41 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 30 Apr 2015 02:12:18 +0200
-Subject: mpc85xx: replace WDR4900 uci-defaults ethernet MAC address hack with DTS entry
-
-This also changes the MAC address to one of the adresses actually used by the
-stock firmware on one of the ethernet interfaces.
-
-diff --git a/target/linux/mpc85xx/base-files/etc/uci-defaults/02_network b/target/linux/mpc85xx/base-files/etc/uci-defaults/02_network
-index e4e3566..525a552 100755
---- a/target/linux/mpc85xx/base-files/etc/uci-defaults/02_network
-+++ b/target/linux/mpc85xx/base-files/etc/uci-defaults/02_network
-@@ -20,8 +20,6 @@ tl-wdr4900-v1)
- 	ucidef_add_switch "switch0" "1" "1"
- 	ucidef_add_switch_vlan "switch0" "1" "0t 2 3 4 5"
- 	ucidef_add_switch_vlan "switch0" "2" "0t 1"
--	ucidef_set_interface_macaddr lan "$(mtd_get_mac_binary config 338)"
--	ucidef_set_interface_macaddr wan "$(mtd_get_mac_binary config 344)"
- 	;;
- *)
- 	ucidef_set_interfaces_lan_wan "eth0" "eth1"
-diff --git a/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-index 49e516c..7e48e23 100644
---- a/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-+++ b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts
-@@ -63,7 +63,7 @@
- 					label = "rootfs";
- 				};
- 
--				config@fe0000 {
-+				config: config@fe0000 {
- 					reg = <0x00fe0000 0x00010000>;
- 					label = "config";
- 					read-only;
-@@ -118,6 +118,7 @@
- 		enet0: ethernet@b0000 {
- 			phy-handle = <&phy0>;
- 			phy-connection-type = "rgmii-id";
-+			mtd-mac-address = <&config 0x14c>;
- 		};
- 
- 		enet1: ethernet@b1000 {

+ 0 - 20
patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch

@@ -1,20 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Mon, 4 May 2015 20:38:37 +0200
-Subject: iwinfo: update NanoStation (Loco) txpower offsets
-
-diff --git a/package/network/utils/iwinfo/src/hardware.txt b/package/network/utils/iwinfo/src/hardware.txt
-index 153ffeb..b8dfc51 100644
---- a/package/network/utils/iwinfo/src/hardware.txt
-+++ b/package/network/utils/iwinfo/src/hardware.txt
-@@ -42,8 +42,9 @@
- 0x168c 0x0027 0x0777 0x4082    7      0  "Ubiquiti" "SR71"
- 0x168c 0x0029 0x0777 0x4005    7      0  "Ubiquiti" "SR71-15"
- 0x168c 0x002a 0x0777 0xe302   12      0  "Ubiquiti" "PicoStation M2" /* ToDo: confirm offset */
--0x168c 0x002a 0x0777 0xe012   12      0  "Ubiquiti" "NanoStation M2" /* ToDo: confirm offset */
--0x168c 0x002a 0x0777 0xe005    5      0  "Ubiquiti" "NanoStation M5" /* ToDo: confirm offset */
-+0x168c 0x002a 0x0777 0xe012   11      0  "Ubiquiti" "NanoStation M2"
-+0x168c 0x002e 0x0777 0xe0a2    8      0  "Ubiquiti" "NanoStation Loco M2"
-+0x168c 0x002a 0x0777 0xe005   16      0  "Ubiquiti" "NanoStation M5"
- 0x168c 0x002a 0x0777 0xe202   12      0  "Ubiquiti" "Bullet M2"
- 0x168c 0x002a 0x0777 0xe805    5      0  "Ubiquiti" "Bullet M5"
- 0x168c 0x002a 0x0777 0xe345    0      0  "Ubiquiti" "WispStation M5" /* ToDo: confirm offset */

+ 3 - 3
patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch

@@ -2,10 +2,10 @@ From: Nils Schneider <nils@nilsschneider.net>
 Date: Sat, 9 Aug 2014 09:33:21 +0200
 Subject: fvalue.html: add label that can be styled
 
-diff --git a/modules/base/luasrc/view/cbi/fvalue.htm b/modules/base/luasrc/view/cbi/fvalue.htm
+diff --git a/modules/luci-base/luasrc/view/cbi/fvalue.htm b/modules/luci-base/luasrc/view/cbi/fvalue.htm
 index a1e0808..a324ab2 100644
---- a/modules/base/luasrc/view/cbi/fvalue.htm
-+++ b/modules/base/luasrc/view/cbi/fvalue.htm
+--- a/modules/luci-base/luasrc/view/cbi/fvalue.htm
++++ b/modules/luci-base/luasrc/view/cbi/fvalue.htm
 @@ -6,4 +6,5 @@
  		attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) ..
  		ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked")

+ 6 - 6
patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch

@@ -2,11 +2,11 @@ From: Matthias Schiffer <mschiffer@universe-factory.net>
 Date: Thu, 19 Mar 2015 18:44:52 +0100
 Subject: modules/base: dispatcher: set default language if none provided by the browser matches
 
-diff --git a/modules/base/luasrc/dispatcher.lua b/modules/base/luasrc/dispatcher.lua
-index f7e16e7..479ac54 100644
---- a/modules/base/luasrc/dispatcher.lua
-+++ b/modules/base/luasrc/dispatcher.lua
-@@ -211,6 +211,7 @@ function dispatch(request)
+diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua
+index 8b8d1fa..27f9a15 100644
+--- a/modules/luci-base/luasrc/dispatcher.lua
++++ b/modules/luci-base/luasrc/dispatcher.lua
+@@ -182,6 +182,7 @@ function dispatch(request)
  	assert(conf.main,
  		"/etc/config/luci seems to be corrupt, unable to find section 'main'")
  
@@ -14,7 +14,7 @@ index f7e16e7..479ac54 100644
  	local lang = conf.main.lang or "auto"
  	if lang == "auto" then
  		local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or ""
-@@ -222,7 +223,10 @@ function dispatch(request)
+@@ -193,7 +194,10 @@ function dispatch(request)
  			end
  		end
  	end

+ 17 - 0
patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch

@@ -0,0 +1,17 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Thu, 21 May 2015 02:34:01 +0200
+Subject: luci-base: depend on libubus-lua
+
+diff --git a/modules/luci-base/Makefile b/modules/luci-base/Makefile
+index 80bbda1..55c21eb 100644
+--- a/modules/luci-base/Makefile
++++ b/modules/luci-base/Makefile
+@@ -12,7 +12,7 @@ LUCI_TYPE:=mod
+ LUCI_BASENAME:=base
+ 
+ LUCI_TITLE:=LuCI core libraries
+-LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd
++LUCI_DEPENDS:=+lua +libuci-lua +libubus-lua +luci-lib-nixio +luci-lib-ip +rpcd
+ 
+ PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2
+ PKG_SOURCE_URL:=https://luasrcdiet.googlecode.com/files

+ 0 - 33
patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch

@@ -1,33 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Sat, 26 Jul 2014 18:06:07 +0200
-Subject: haveged: start directly after initial setup and disable tests
-
-diff --git a/utils/haveged/Makefile b/utils/haveged/Makefile
-index aff998d..94c8c34 100644
---- a/utils/haveged/Makefile
-+++ b/utils/haveged/Makefile
-@@ -42,8 +42,9 @@ define Package/libhavege
- endef
- 
- CONFIGURE_ARGS+= \
--      --enable-daemon=yes
--      --enable-threads=no
-+      --enable-daemon=yes \
-+      --enable-threads=no \
-+      --enable-olt=no
- 
- define Build/InstallDev
- 	$(INSTALL_DIR) $(1)/usr/include
-diff --git a/utils/haveged/files/haveged.init b/utils/haveged/files/haveged.init
-index ce28e61..113d64f 100644
---- a/utils/haveged/files/haveged.init
-+++ b/utils/haveged/files/haveged.init
-@@ -1,7 +1,7 @@
- #!/bin/sh /etc/rc.common
- # Copyright (C) 2012 OpenWrt.org
- 
--START=98
-+START=13
- 
- HAVEGED_THRESHOLD=1024
- HAVEGED_DCACHE=32

+ 0 - 35
patches/packages/openwrt/0002-libuecc-update-to-v5.patch

@@ -1,35 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 29 Jan 2015 07:46:26 +0100
-Subject: libuecc: update to v5
-
-diff --git a/libs/libuecc/Makefile b/libs/libuecc/Makefile
-index 0fe4833..63b6ebe 100644
---- a/libs/libuecc/Makefile
-+++ b/libs/libuecc/Makefile
-@@ -1,5 +1,5 @@
- #
--# Copyright (C) 2012-2014 OpenWrt.org
-+# Copyright (C) 2012-2015 OpenWrt.org
- #
- # This is free software, licensed under the GNU General Public License v2.
- # See /LICENSE for more information.
-@@ -8,13 +8,16 @@
- include $(TOPDIR)/rules.mk
- 
- PKG_NAME:=libuecc
--PKG_VERSION:=4
-+PKG_VERSION:=5
- PKG_RELEASE:=1
- 
- PKG_MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
- PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
--PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/71
--PKG_MD5SUM:=7f44df5dc69cb8686947562e2a11eea9
-+PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/80
-+PKG_MD5SUM:=cd03c947931c2f4b0eea0bf45654bd34
-+
-+PKG_LICENSE:=BSD-2-Clause
-+PKG_LICENSE_FILES:=COPYRIGHT
- 
- include $(INCLUDE_DIR)/package.mk
- include $(INCLUDE_DIR)/cmake.mk

+ 0 - 213
patches/packages/openwrt/0003-fastd-update-to-v17.patch

@@ -1,213 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Thu, 29 Jan 2015 07:48:03 +0100
-Subject: fastd: update to v17
-
-diff --git a/net/fastd/Config.in b/net/fastd/Config.in
-index ca4045c..5820b97 100644
---- a/net/fastd/Config.in
-+++ b/net/fastd/Config.in
-@@ -11,6 +11,11 @@ config FASTD_ENABLE_METHOD_COMPOSED_GMAC
- 	depends on PACKAGE_fastd
- 	default y
- 
-+config FASTD_ENABLE_METHOD_COMPOSED_UMAC
-+	bool "Enable composed-umac method provider"
-+	depends on PACKAGE_fastd
-+	default y
-+
- config FASTD_ENABLE_METHOD_GENERIC_GMAC
- 	bool "Enable generic-gmac method provider"
- 	depends on PACKAGE_fastd
-@@ -21,6 +26,11 @@ config FASTD_ENABLE_METHOD_GENERIC_POLY1305
- 	depends on PACKAGE_fastd
- 	default n
- 
-+config FASTD_ENABLE_METHOD_GENERIC_UMAC
-+	bool "Enable generic-umac method provider"
-+	depends on PACKAGE_fastd
-+	default y
-+
- config FASTD_ENABLE_METHOD_NULL
- 	bool "Enable null method"
- 	depends on PACKAGE_fastd
-@@ -58,6 +68,11 @@ config FASTD_ENABLE_MAC_GHASH
- 	depends on PACKAGE_fastd
- 	default y
- 
-+config FASTD_ENABLE_MAC_UHASH
-+	bool "Enable the UHASH message authentication code"
-+	depends on PACKAGE_fastd
-+	default y
-+
- 
- config FASTD_WITH_CMDLINE_USER
- 	bool "Include support for setting user/group related options on the command line"
-@@ -79,9 +94,15 @@ config FASTD_WITH_CMDLINE_COMMANDS
- 	depends on PACKAGE_fastd
- 	default n
- 
--config FASTD_WITH_VERIFY
--        bool "Include support for on-verify handlers"
--        depends on PACKAGE_fastd
--        default n
-+config FASTD_WITH_DYNAMIC_PEERS
-+	bool "Include support for on-verify handlers"
-+	depends on PACKAGE_fastd
-+	default n
-+
-+config FASTD_WITH_STATUS_SOCKET
-+	bool "Include support for status sockets"
-+	depends on PACKAGE_fastd
-+	default y
-+
- 
- endmenu
-diff --git a/net/fastd/Makefile b/net/fastd/Makefile
-index 0629cd7..027f549 100644
---- a/net/fastd/Makefile
-+++ b/net/fastd/Makefile
-@@ -1,5 +1,5 @@
- #
--# Copyright (C) 2012-2014 OpenWrt.org
-+# Copyright (C) 2012-2015 OpenWrt.org
- #
- # This is free software, licensed under the GNU General Public License v2.
- # See /LICENSE for more information.
-@@ -8,19 +8,24 @@
- include $(TOPDIR)/rules.mk
- 
- PKG_NAME:=fastd
--PKG_VERSION:=14
-+PKG_VERSION:=17
- PKG_RELEASE:=1
- 
- PKG_MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
- PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
--PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/75
--PKG_MD5SUM:=34f6bdebd0410a1fba7c8fd06fff7a05
-+PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/81
-+PKG_MD5SUM:=bad4f1948702f418b799578f83a0edb8
-+
-+PKG_LICENSE:=BSD-2-Clause
-+PKG_LICENSE_FILES:=COPYRIGHT
- 
- PKG_CONFIG_DEPENDS:=\
- 	CONFIG_FASTD_ENABLE_METHOD_CIPHER_TEST \
- 	CONFIG_FASTD_ENABLE_METHOD_COMPOSED_GMAC \
-+	CONFIG_FASTD_ENABLE_METHOD_COMPOSED_UMAC \
- 	CONFIG_FASTD_ENABLE_METHOD_GENERIC_GMAC \
- 	CONFIG_FASTD_ENABLE_METHOD_GENERIC_POLY1305 \
-+	CONFIG_FASTD_ENABLE_METHOD_GENERIC_UMAC \
- 	CONFIG_FASTD_ENABLE_METHOD_NULL \
- 	CONFIG_FASTD_ENABLE_METHOD_XSALSA20_POLY1305 \
- 	CONFIG_FASTD_ENABLE_CIPHER_AES128_CTR \
-@@ -28,11 +33,13 @@ PKG_CONFIG_DEPENDS:=\
- 	CONFIG_FASTD_ENABLE_CIPHER_SALSA20 \
- 	CONFIG_FASTD_ENABLE_CIPHER_SALSA2012 \
- 	CONFIG_FASTD_ENABLE_MAC_GHASH \
-+	CONFIG_FASTD_ENABLE_MAC_UHASH \
- 	CONFIG_FASTD_WITH_CMDLINE_USER \
- 	CONFIG_FASTD_WITH_CMDLINE_LOGGING \
- 	CONFIG_FASTD_WITH_CMDLINE_OPERATION \
- 	CONFIG_FASTD_WITH_CMDLINE_COMMANDS \
--	CONFIG_FASTD_WITH_VERIFY
-+	CONFIG_FASTD_WITH_DYNAMIC_PEERS \
-+	CONFIG_FASTD_WITH_STATUS_SOCKET
- 
- 
- PKG_BUILD_DEPENDS:=nacl libuecc
-@@ -43,7 +50,7 @@ include $(INCLUDE_DIR)/cmake.mk
- define Package/fastd
-   SECTION:=net
-   CATEGORY:=Network
--  DEPENDS:=+kmod-tun +librt +libpthread
-+  DEPENDS:=+kmod-tun +librt +libpthread +FASTD_WITH_STATUS_SOCKET:libjson-c
-   TITLE:=Fast and Secure Tunneling Daemon
-   URL:=https://projects.universe-factory.net/projects/fastd
-   SUBMENU:=VPN
-@@ -60,8 +67,10 @@ CMAKE_OPTIONS += \
- 	-DCMAKE_BUILD_TYPE:STRING=MINSIZEREL \
- 	-DWITH_METHOD_CIPHER_TEST:BOOL=FALSE \
- 	-DWITH_METHOD_COMPOSED_GMAC:BOOL=FALSE \
-+	-DWITH_METHOD_COMPOSED_UMAC:BOOL=FALSE \
- 	-DWITH_METHOD_GENERIC_GMAC:BOOL=FALSE \
- 	-DWITH_METHOD_GENERIC_POLY1305:BOOL=FALSE \
-+	-DWITH_METHOD_GENERIC_UMAC:BOOL=FALSE \
- 	-DWITH_METHOD_NULL:BOOL=FALSE \
- 	-DWITH_METHOD_XSALSA20_POLY1305:BOOL=FALSE \
- 	-DWITH_CIPHER_AES128_CTR:BOOL=FALSE \
-@@ -69,11 +78,13 @@ CMAKE_OPTIONS += \
- 	-DWITH_CIPHER_SALSA20:BOOL=FALSE \
- 	-DWITH_CIPHER_SALSA2012:BOOL=FALSE \
- 	-DWITH_MAC_GHASH:BOOL=FALSE \
-+	-DWITH_MAC_UHASH:BOOL=FALSE \
- 	-DWITH_CMDLINE_USER:BOOL=FALSE \
- 	-DWITH_CMDLINE_LOGGING:BOOL=FALSE \
- 	-DWITH_CMDLINE_OPERATION:BOOL=FALSE \
- 	-DWITH_CMDLINE_COMMANDS:BOOL=FALSE \
--	-DWITH_VERIFY:BOOL=FALSE \
-+	-DWITH_DYNAMIC_PEERS:BOOL=FALSE \
-+	-DWITH_STATUS_SOCKET:BOOL=FALSE \
- 	-DWITH_CAPABILITIES:BOOL=FALSE \
- 	-DENABLE_SYSTEMD:BOOL=FALSE \
- 	-DENABLE_LIBSODIUM:BOOL=FALSE \
-@@ -88,6 +99,10 @@ ifeq ($(CONFIG_FASTD_ENABLE_METHOD_COMPOSED_GMAC),y)
- CMAKE_OPTIONS += -DWITH_METHOD_COMPOSED_GMAC:BOOL=TRUE
- endif
- 
-+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_COMPOSED_UMAC),y)
-+CMAKE_OPTIONS += -DWITH_METHOD_COMPOSED_UMAC:BOOL=TRUE
-+endif
-+
- ifeq ($(CONFIG_FASTD_ENABLE_METHOD_GENERIC_GMAC),y)
- CMAKE_OPTIONS += -DWITH_METHOD_GENERIC_GMAC:BOOL=TRUE
- endif
-@@ -96,6 +111,10 @@ ifeq ($(CONFIG_FASTD_ENABLE_METHOD_GENERIC_POLY1305),y)
- CMAKE_OPTIONS += -DWITH_METHOD_GENERIC_POLY1305:BOOL=TRUE
- endif
- 
-+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_GENERIC_UMAC),y)
-+CMAKE_OPTIONS += -DWITH_METHOD_GENERIC_UMAC:BOOL=TRUE
-+endif
-+
- ifeq ($(CONFIG_FASTD_ENABLE_METHOD_NULL),y)
- CMAKE_OPTIONS += -DWITH_METHOD_NULL:BOOL=TRUE
- endif
-@@ -126,6 +145,10 @@ ifeq ($(CONFIG_FASTD_ENABLE_MAC_GHASH),y)
- CMAKE_OPTIONS += -DWITH_MAC_GHASH:BOOL=TRUE
- endif
- 
-+ifeq ($(CONFIG_FASTD_ENABLE_MAC_UHASH),y)
-+CMAKE_OPTIONS += -DWITH_MAC_UHASH:BOOL=TRUE
-+endif
-+
- 
- ifeq ($(CONFIG_FASTD_WITH_CMDLINE_USER),y)
- CMAKE_OPTIONS += -DWITH_CMDLINE_USER:BOOL=TRUE
-@@ -143,8 +166,12 @@ ifeq ($(CONFIG_FASTD_WITH_CMDLINE_COMMANDS),y)
- CMAKE_OPTIONS += -DWITH_CMDLINE_COMMANDS:BOOL=TRUE
- endif
- 
--ifeq ($(CONFIG_FASTD_WITH_VERIFY),y)
--CMAKE_OPTIONS += -DWITH_VERIFY:BOOL=TRUE
-+ifeq ($(CONFIG_FASTD_WITH_DYNAMIC_PEERS),y)
-+CMAKE_OPTIONS += -DWITH_DYNAMIC_PEERS:BOOL=TRUE
-+endif
-+
-+ifeq ($(CONFIG_FASTD_WITH_STATUS_SOCKET),y)
-+CMAKE_OPTIONS += -DWITH_STATUS_SOCKET:BOOL=TRUE
- endif
- 
- 
-@@ -161,9 +188,9 @@ define Package/fastd/install
- 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fastd $(1)/usr/bin/
- 
- 	$(INSTALL_DIR) $(1)/etc/init.d/
--	$(INSTALL_BIN) files/fastd.init $(1)/etc/init.d/fastd
-+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/doc/examples/openwrt/fastd.init $(1)/etc/init.d/fastd
- 	$(INSTALL_DIR) $(1)/etc/config
--	$(INSTALL_CONF) files/fastd.config $(1)/etc/config/fastd
-+	$(INSTALL_CONF) $(PKG_BUILD_DIR)/doc/examples/openwrt/fastd.config $(1)/etc/config/fastd
- 	$(INSTALL_DIR) $(1)/etc/fastd
- 	$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
- 	$(INSTALL_DATA) files/fastd.upgrade $(1)/lib/upgrade/keep.d/fastd

+ 0 - 52
patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch

@@ -1,52 +0,0 @@
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Wed, 7 Jan 2015 16:40:43 +0100
-Subject: Update batman-adv and alfred to v2014.4
-
-diff --git a/alfred/Makefile b/alfred/Makefile
-index 648a5ef..0a5fcac 100644
---- a/alfred/Makefile
-+++ b/alfred/Makefile
-@@ -11,9 +11,9 @@ include $(TOPDIR)/rules.mk
- # The latest alfred git hash in PKG_REV can be obtained from http://git.open-mesh.org/alfred.git
- #
- PKG_NAME:=alfred
--PKG_VERSION:=2014.3.0
-+PKG_VERSION:=2014.4.0
- PKG_RELEASE:=0
--PKG_MD5SUM:=b8ab5677ed73d817b02b0e4fae10357a
-+PKG_MD5SUM:=053cb5d9e7ca9384598e82944343dea2
- 
- PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
- PKG_SOURCE_URL:=http://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
-diff --git a/batctl/Makefile b/batctl/Makefile
-index ae22286..1009b03 100644
---- a/batctl/Makefile
-+++ b/batctl/Makefile
-@@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk
- 
- PKG_NAME:=batctl
- 
--PKG_VERSION:=2014.2.0
-+PKG_VERSION:=2014.4.0
- PKG_RELEASE:=1
--PKG_MD5SUM:=c196cf95b7324d9123b701a56b06b31d
-+PKG_MD5SUM:=f3a14565699313258ee6ba3de783eb0a
- 
- PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
- PKG_SOURCE_URL:=http://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)
-diff --git a/batman-adv/Makefile b/batman-adv/Makefile
-index 889dea7..0d5ed33 100644
---- a/batman-adv/Makefile
-+++ b/batman-adv/Makefile
-@@ -10,9 +10,9 @@ include $(TOPDIR)/rules.mk
- 
- PKG_NAME:=batman-adv
- 
--PKG_VERSION:=2014.2.0
-+PKG_VERSION:=2014.4.0
- PKG_RELEASE:=1
--PKG_MD5SUM:=1243029b3a3e2f4fa721d1a59c2faaf5
-+PKG_MD5SUM:=b1518e84ce530883d224c6ca4c673ce8
- 
- PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
- PKG_SOURCE_URL:=http://downloads.open-mesh.org/batman/releases/batman-adv-$(PKG_VERSION)

+ 0 - 0
patches/packages/routing/0002-alfred-adjust-intervals.patch → patches/packages/routing/0001-alfred-adjust-intervals.patch


+ 0 - 0
patches/packages/routing/0003-batman-adv-introduce-no_rebroadcast-option.patch → patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch


+ 7 - 4
targets/ar71xx-generic/profiles.mk

@@ -112,10 +112,13 @@ $(eval $(call GluonProfile,TLMR3040))
 $(eval $(call GluonModel,TLMR3040,tl-mr3040-v1,tp-link-tl-mr3040-v1))
 $(eval $(call GluonModel,TLMR3040,tl-mr3040-v2,tp-link-tl-mr3040-v2))
 
-# TL-MR3220 v1, v2
-$(eval $(call GluonProfile,TLMR3220))
-$(eval $(call GluonModel,TLMR3220,tl-mr3220-v1,tp-link-tl-mr3220-v1))
-$(eval $(call GluonModel,TLMR3220,tl-mr3220-v2,tp-link-tl-mr3220-v2))
+# TL-MR3220 v1
+$(eval $(call GluonProfile,TLMR3220V1))
+$(eval $(call GluonModel,TLMR3220V1,tl-mr3220-v1,tp-link-tl-mr3220-v1))
+
+# TL-MR3220 v2
+$(eval $(call GluonProfile,TLMR3220V2))
+$(eval $(call GluonModel,TLMR3220V2,tl-mr3220-v2,tp-link-tl-mr3220-v2))
 
 # TL-MR3420 v1, v2
 $(eval $(call GluonProfile,TLMR3420))

+ 1 - 1
targets/ar71xx-generic/vermagic

@@ -1 +1 @@
-0114c71ed85677c9c1e4911437af4743
+c9110281555cccc9dd13e092c2acaeaf

+ 1 - 1
targets/ar71xx-nand/vermagic

@@ -1 +1 @@
-41123e63bc43f61af09d064504300966
+689cae9c23d40bdba3f46c59a12ca179

+ 1 - 1
targets/mpc85xx-generic/vermagic

@@ -1 +1 @@
-c1a44dd429e530bed2958b8e6cb54a52
+18b3b28a5f70d5040f741bd44916dc57

+ 1 - 1
targets/ramips-rt305x/vermagic

@@ -1 +1 @@
-194d0e9ee3ca8df976c737e78e8b2194
+4d806b94ed2b1e50df33a69891888e4a

+ 1 - 1
targets/x86-generic/vermagic

@@ -1 +1 @@
-3051dee8f07064b727e9d57fbfeb05ec
+6581cdee9837e0761056ab3c80d05a2e

+ 1 - 1
targets/x86-kvm_guest/vermagic

@@ -1 +1 @@
-5e81ad3c25d4a4f02e749f398f1868c5
+23b9575454f0084518a8c2f51423207c