From ab10be9f50077e32d6ae0cba5d761a3da9188dc5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 22 May 2015 01:09:19 +0200 Subject: [PATCH] We're on Chaos Calmer now --- Makefile | 15 +- docs/dev/i18n.rst | 6 +- include/Makefile.image | 7 - include/Makefile.target | 3 +- include/config | 2 +- include/gluon.mk | 4 +- include/package.mk | 33 +- modules | 15 +- .../files/usr/lib/lua/gluon/announce.lua | 6 +- .../controller/gluon-config-mode/index.lua | 5 +- .../model/cbi/gluon-config-mode/wizard.lua | 5 +- package/gluon-core/Makefile | 16 +- .../files/lib/gluon/upgrade/001-upgrade | 4 +- .../files/lib/gluon/upgrade/010-primary-mac | 2 +- .../files/lib/gluon/upgrade/999-version | 2 +- .../usr/lib/lua/luci/view/admin/info.htm | 2 +- .../lib/lua/luci/view/themes/gluon/header.htm | 1 - package/gluon-mesh-batman-adv-core/Makefile | 2 +- package/gluon-site/Makefile | 2 +- .../lib/gluon/status-page/www/cgi-bin/status | 2 +- ...le-fix-host-tools-build-dependencies.patch | 32 +- ...revision-on-TP-Link-Archer-C5-and-C7.patch | 31 - ...ndent-of-the-default-router-lifetime.patch | 31 + ...-really-empty-not-when-it-is-locked.patch} | 0 ...ndent-of-the-default-router-lifetime.patch | 26 - ...ty-firmware-as-an-additional-choice.patch} | 16 +- ...NK-Pharos-devices-CPE210-220-510-520.patch | 570 - ...pport-for-TP-LINK-CPE210-220-510-520.patch | 471 - ...files-disable-reset-button-handling.patch} | 0 ...-ar71xx-refactor-ubnt-xw-board-setup.patch | 72 - ...-ncurses-fix-host-build-with-GCC-5.1.patch | 21 + ...add-board-support-for-ubnt-loco-m-xw.patch | 161 - ...11-ath10k-allow-simultaneous-AP-IBSS.patch | 42 + ...ate-NanoStation-Loco-txpower-offsets.patch | 24 + ...ency-on-error.h-in-tplink-safeloader.patch | 43 - ...uild-explicitly-unexport-CONFIG_SITE.patch | 28 - ...ard-detection-for-TP-LINK-TL-WA860RE.patch | 20 - ...iguration-for-D-Link-DIR-615-rev.-C1.patch | 25 - ...ink-DIR-615-rev.-C1-WLAN-MAC-address.patch | 42 - ...upport-for-the-TP-LINK-TL-WR941ND-v5.patch | 229 - ...upport-for-the-UniFi-AP-Outdoor-Plus.patch | 177 - ...ath10k-to-compat-wireless-2015-03-05.patch | 33655 ---------------- ...pdate-firmware-to-the-latest-version.patch | 41 - ...xx-TP-LINK-Archer-add-5GHz-led-entry.patch | 20 - ...ed-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch | 34 - ...syscalls-with-6-arguments-on-PowerPC.patch | 24 - ...file-for-the-gl-inet-6416A-and-6408A.patch | 35 - .../0024-ar71xx-detect-GL.iNet-model.patch | 39 - ...ng-a-specific-MBR-signature-to-ptgen.patch | 70 - ...tly-specifying-the-device-by-default.patch | 180 - ...ion-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch | 65 - ...WDR3600-4300-RFKILL-switch-positions.patch | 22 - ...ot-make-it-easier-to-build-all-kmods.patch | 57 - ...-define-STAMP_CONFIGURED-recursively.patch | 26 - ...-from-patch-files-to-files-directory.patch | 1111 - ...nfar-add-add-mtd-mac-address-support.patch | 168 - ...rnet-MAC-address-hack-with-DTS-entry.patch | 41 - ...ate-NanoStation-Loco-txpower-offsets.patch | 20 - ...ue.html-add-label-that-can-be-styled.patch | 6 +- ...none-provided-by-the-browser-matches.patch | 12 +- ...0003-luci-base-depend-on-libubus-lua.patch | 17 + ...fter-initial-setup-and-disable-tests.patch | 33 - .../openwrt/0002-libuecc-update-to-v5.patch | 35 - .../openwrt/0003-fastd-update-to-v17.patch | 213 - ...ate-batman-adv-and-alfred-to-v2014.4.patch | 52 - ...tch => 0001-alfred-adjust-intervals.patch} | 0 ...adv-introduce-no_rebroadcast-option.patch} | 0 targets/ar71xx-generic/profiles.mk | 11 +- targets/ar71xx-generic/vermagic | 2 +- targets/ar71xx-nand/vermagic | 2 +- targets/mpc85xx-generic/vermagic | 2 +- targets/ramips-rt305x/vermagic | 2 +- targets/x86-generic/vermagic | 2 +- targets/x86-kvm_guest/vermagic | 2 +- 74 files changed, 220 insertions(+), 37974 deletions(-) delete mode 100644 include/Makefile.image delete mode 100644 patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch create mode 100644 patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch rename patches/openwrt/{0009-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch => 0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch} (100%) delete mode 100644 patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch rename patches/openwrt/{0019-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch => 0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch} (82%) delete mode 100644 patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch delete mode 100644 patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch rename patches/openwrt/{0031-base-files-disable-reset-button-handling.patch => 0006-base-files-disable-reset-button-handling.patch} (100%) delete mode 100644 patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch create mode 100644 patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch delete mode 100644 patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch create mode 100644 patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch create mode 100644 patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch delete mode 100644 patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch delete mode 100644 patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch delete mode 100644 patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch delete mode 100644 patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch delete mode 100644 patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch delete mode 100644 patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch delete mode 100644 patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch delete mode 100644 patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch delete mode 100644 patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch delete mode 100644 patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch delete mode 100644 patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch delete mode 100644 patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch delete mode 100644 patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch delete mode 100644 patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch delete mode 100644 patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch delete mode 100644 patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch delete mode 100644 patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch delete mode 100644 patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch delete mode 100644 patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch delete mode 100644 patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch delete mode 100644 patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch delete mode 100644 patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch delete mode 100644 patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch delete mode 100644 patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch create mode 100644 patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch delete mode 100644 patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch delete mode 100644 patches/packages/openwrt/0002-libuecc-update-to-v5.patch delete mode 100644 patches/packages/openwrt/0003-fastd-update-to-v17.patch delete mode 100644 patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch rename patches/packages/routing/{0002-alfred-adjust-intervals.patch => 0001-alfred-adjust-intervals.patch} (100%) rename patches/packages/routing/{0003-batman-adv-introduce-no_rebroadcast-option.patch => 0002-batman-adv-introduce-no_rebroadcast-option.patch} (100%) diff --git a/Makefile b/Makefile index 7f5fd437..a4fe82b8 100644 --- a/Makefile +++ b/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 diff --git a/docs/dev/i18n.rst b/docs/dev/i18n.rst index 536baf1a..b51bfdee 100644 --- a/docs/dev/i18n.rst +++ b/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. diff --git a/include/Makefile.image b/include/Makefile.image deleted file mode 100644 index d6a627c6..00000000 --- a/include/Makefile.image +++ /dev/null @@ -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 diff --git a/include/Makefile.target b/include/Makefile.target index 19370e52..a78a4044 100644 --- a/include/Makefile.target +++ b/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 diff --git a/include/config b/include/config index faab30c8..ac1a4f8d 100644 --- a/include/config +++ b/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 diff --git a/include/gluon.mk b/include/gluon.mk index 88db6f42..fdccef20 100644 --- a/include/gluon.mk +++ b/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 := diff --git a/include/package.mk b/include/package.mk index 271d1de0..76e109e2 100644 --- a/include/package.mk +++ b/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),+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_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_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 diff --git a/modules b/modules index 4776b64f..8c31b718 100644 --- a/modules +++ b/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 diff --git a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua b/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua index 7f3f62e2..17109785 100644 --- a/package/gluon-announce/files/usr/lib/lua/gluon/announce.lua +++ b/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 diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua b/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua index c3ab070d..39ba00a9 100644 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua +++ b/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) diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua b/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua index 101a02e3..dda5e58c 100644 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua +++ b/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) diff --git a/package/gluon-core/Makefile b/package/gluon-core/Makefile index 2c632a00..bf9768e2 100644 --- a/package/gluon-core/Makefile +++ b/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 diff --git a/package/gluon-core/files/lib/gluon/upgrade/001-upgrade b/package/gluon-core/files/lib/gluon/upgrade/001-upgrade index 6caba148..5d53398c 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/001-upgrade +++ b/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 diff --git a/package/gluon-core/files/lib/gluon/upgrade/010-primary-mac b/package/gluon-core/files/lib/gluon/upgrade/010-primary-mac index 70aee39d..d7c6e968 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/010-primary-mac +++ b/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' diff --git a/package/gluon-core/files/lib/gluon/upgrade/999-version b/package/gluon-core/files/lib/gluon/upgrade/999-version index 62f08206..9731692e 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/999-version +++ b/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' diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm b/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm index a04a834d..da403c1b 100644 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm +++ b/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' diff --git a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm b/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm index 730647bc..2fe1004b 100644 --- a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm +++ b/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 diff --git a/package/gluon-mesh-batman-adv-core/Makefile b/package/gluon-mesh-batman-adv-core/Makefile index fc4bc224..8358089c 100644 --- a/package/gluon-mesh-batman-adv-core/Makefile +++ b/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 diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index fc9f58ce..7816c9d3 100644 --- a/package/gluon-site/Makefile +++ b/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) diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/status b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/status index 771bdaba..b31e2f73 100755 --- a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/status +++ b/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") diff --git a/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch b/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch index 1a39c7bd..e400f28b 100644 --- a/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch +++ b/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 diff --git a/patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch b/patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch deleted file mode 100644 index 7b85d1e7..00000000 --- a/patches/openwrt/0003-ar71xx-correctly-detect-hardware-revision-on-TP-Link-Archer-C5-and-C7.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Matthias Schiffer -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 diff --git a/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch b/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch new file mode 100644 index 00000000..82de5300 --- /dev/null +++ b/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch @@ -0,0 +1,31 @@ +From: Matthias Schiffer +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) diff --git a/patches/openwrt/0009-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch b/patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch similarity index 100% rename from patches/openwrt/0009-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch rename to patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch diff --git a/patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch b/patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch deleted file mode 100644 index 21c81918..00000000 --- a/patches/openwrt/0004-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Matthias Schiffer -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) diff --git a/patches/openwrt/0019-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch b/patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch similarity index 82% rename from patches/openwrt/0019-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch rename to patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch index 0fa623f4..e662cbe5 100644 --- a/patches/openwrt/0019-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch +++ b/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 diff --git a/patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch b/patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch deleted file mode 100644 index 9cc72b6b..00000000 --- a/patches/openwrt/0005-firmware-utils-add-new-tool-tplink-safeloader-for-the-new-TP-LINK-Pharos-devices-CPE210-220-510-520.patch +++ /dev/null @@ -1,570 +0,0 @@ -From: Matthias Schiffer -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 - -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 -+ 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#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 create image for the board specified with \n" -+ " -k read kernel image from the file \n" -+ " -r read rootfs image from the file \n" -+ " -o write output to the file \n" -+ " -V sets the revision number to \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; -+} diff --git a/patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch b/patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch deleted file mode 100644 index 8e109662..00000000 --- a/patches/openwrt/0006-ar71xx-add-support-for-TP-LINK-CPE210-220-510-520.patch +++ /dev/null @@ -1,471 +0,0 @@ -From: Matthias Schiffer -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 - -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 -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+ -+#include "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 diff --git a/patches/openwrt/0031-base-files-disable-reset-button-handling.patch b/patches/openwrt/0006-base-files-disable-reset-button-handling.patch similarity index 100% rename from patches/openwrt/0031-base-files-disable-reset-button-handling.patch rename to patches/openwrt/0006-base-files-disable-reset-button-handling.patch diff --git a/patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch b/patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch deleted file mode 100644 index 208e1766..00000000 --- a/patches/openwrt/0007-ar71xx-refactor-ubnt-xw-board-setup.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 26 Nov 2014 23:20:33 +0100 -Subject: ar71xx: refactor ubnt xw board setup - -Signed-off-by: Alexander Couzens - -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 */ diff --git a/patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch b/patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch new file mode 100644 index 00000000..366039ff --- /dev/null +++ b/patches/openwrt/0007-ncurses-fix-host-build-with-GCC-5.1.patch @@ -0,0 +1,21 @@ +From: Matthias Schiffer +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 += diff --git a/patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch b/patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch deleted file mode 100644 index f3e496d1..00000000 --- a/patches/openwrt/0008-ar71xx-add-board-support-for-ubnt-loco-m-xw.patch +++ /dev/null @@ -1,161 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 26 Nov 2014 23:20:46 +0100 -Subject: ar71xx: add board support for ubnt loco m xw - -Signed-off-by: Alexander Couzens - -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 */ diff --git a/patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch b/patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch new file mode 100644 index 00000000..7586d3a2 --- /dev/null +++ b/patches/openwrt/0008-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch @@ -0,0 +1,42 @@ +From: Matthias Schiffer +Date: Wed, 20 May 2015 23:10:36 +0200 +Subject: mac80211: ath10k: allow simultaneous AP+IBSS + +diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch +new file mode 100644 +index 0000000..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: diff --git a/patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch b/patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch new file mode 100644 index 00000000..b45cf4e7 --- /dev/null +++ b/patches/openwrt/0009-iwinfo-update-NanoStation-Loco-txpower-offsets.patch @@ -0,0 +1,24 @@ +From: Matthias Schiffer +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 */ diff --git a/patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch b/patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch deleted file mode 100644 index c9c3b05b..00000000 --- a/patches/openwrt/0010-firmware-utils-remove-dependency-on-error.h-in-tplink-safeloader.patch +++ /dev/null @@ -1,43 +0,0 @@ -From: Matthias Schiffer -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 - -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 - #include --#include - #include - #include - #include -@@ -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"); - diff --git a/patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch b/patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch deleted file mode 100644 index c40d6b5d..00000000 --- a/patches/openwrt/0011-build-explicitly-unexport-CONFIG_SITE.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Matthias Schiffer -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 - -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)),) diff --git a/patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch b/patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch deleted file mode 100644 index 31c4304c..00000000 --- a/patches/openwrt/0012-ar71xx-fix-board-detection-for-TP-LINK-TL-WA860RE.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 16 Jan 2015 19:56:39 +0100 -Subject: ar71xx: fix board detection for TP-LINK TL-WA860RE - -Signed-off-by: Matthias Schiffer - -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" - ;; diff --git a/patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch b/patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch deleted file mode 100644 index e283375d..00000000 --- a/patches/openwrt/0013-ar71xx-add-default-LED-configuration-for-D-Link-DIR-615-rev.-C1.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Matthias Schiffer -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 - -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" - ;; diff --git a/patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch b/patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch deleted file mode 100644 index 964e3b71..00000000 --- a/patches/openwrt/0014-ar71xx-fix-D-Link-DIR-615-rev.-C1-WLAN-MAC-address.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Matthias Schiffer -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 - -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; diff --git a/patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch b/patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch deleted file mode 100644 index 48079fc6..00000000 --- a/patches/openwrt/0015-Add-support-for-the-TP-LINK-TL-WR941ND-v5.patch +++ /dev/null @@ -1,229 +0,0 @@ -From: Matthias Schiffer -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 - -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 diff --git a/patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch b/patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch deleted file mode 100644 index c5d18bf6..00000000 --- a/patches/openwrt/0016-ar71xx-add-support-for-the-UniFi-AP-Outdoor-Plus.patch +++ /dev/null @@ -1,177 +0,0 @@ -From: blogic -Date: Thu, 22 Jan 2015 09:35:46 +0000 -Subject: ar71xx: add support for the UniFi AP Outdoor Plus - -Signed-off-by: Matthias Schiffer - -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 */ diff --git a/patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch b/patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch deleted file mode 100644 index 387ea9cf..00000000 --- a/patches/openwrt/0017-mac80211-update-ath10k-to-compat-wireless-2015-03-05.patch +++ /dev/null @@ -1,33655 +0,0 @@ -From: Matthias Schiffer -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 -+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 -+ [fix endian bug] -+ Signed-off-by: Johannes Berg -+ -+--- 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 -+ #include -++#include -+ -+ #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, ¶m_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--.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 -+ #include -+ #include -++#include -++#include -+ -+ #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 -+ #include -++#include -++#include -+ -+ #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, ®_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, ®_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, &du); -++ -++ 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 -+ #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 -+ #include -+ #include -++#include -+ #include -+ -+ #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 -+ -+-/* 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 -+ #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, -+- ®_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, -+- ®_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, ®_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 -++#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 -++#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 -++#include -++ -++#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 -++#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 -++#include -++#include -++#include -++#include -++#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 -+ #include -+ #include -++#include -++#include -++#include -++#include -+ -+ #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 -++#include -++ -++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -++/* -++ * Backports -++ * -++ * commit bab2243ce1897865e31ea6d59b0478391f51812b -++ * Author: Guenter Roeck -++ * 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 -++ */ -++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 -+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 -+--- -+ -+--- 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: diff --git a/patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch b/patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch deleted file mode 100644 index 56ddc5ea..00000000 --- a/patches/openwrt/0018-ath10k-update-firmware-to-the-latest-version.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Matthias Schiffer -Date: Tue, 10 Mar 2015 13:17:06 +0100 -Subject: ath10k: update firmware to the latest version - -Signed-off-by: Felix Fietkau - -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 - diff --git a/patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch b/patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch deleted file mode 100644 index 406fa13d..00000000 --- a/patches/openwrt/0020-at71xx-TP-LINK-Archer-add-5GHz-led-entry.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Matthias Schiffer -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 - -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) diff --git a/patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch b/patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch deleted file mode 100644 index 846a4734..00000000 --- a/patches/openwrt/0021-ar71xx-fix-switched-WLAN-LEDs-on-TP-LINK-Archer-C5-C7.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Matthias Schiffer -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" diff --git a/patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch b/patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch deleted file mode 100644 index 50332a2b..00000000 --- a/patches/openwrt/0022-uClibc-fix-syscall-for-syscalls-with-6-arguments-on-PowerPC.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Matthias Schiffer -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; -+ diff --git a/patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch b/patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch deleted file mode 100644 index ce78a490..00000000 --- a/patches/openwrt/0023-ar71xx-Add-build-profile-for-the-gl-inet-6416A-and-6408A.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Matthias Schiffer -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 - -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)) diff --git a/patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch b/patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch deleted file mode 100644 index 9996872a..00000000 --- a/patches/openwrt/0024-ar71xx-detect-GL.iNet-model.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Matthias Schiffer -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" diff --git a/patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch b/patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch deleted file mode 100644 index f7635d30..00000000 --- a/patches/openwrt/0025-firmware-utils-allow-passing-a-specific-MBR-signature-to-ptgen.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Matthias Schiffer -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 - -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 - #include - #include -+#include - - #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); - } diff --git a/patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch b/patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch deleted file mode 100644 index a2e7e7d9..00000000 --- a/patches/openwrt/0026-x86-use-PARTUUID-instead-explicitly-specifying-the-device-by-default.patch +++ /dev/null @@ -1,180 +0,0 @@ -From: Matthias Schiffer -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))" diff --git a/patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch b/patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch deleted file mode 100644 index f4051a2d..00000000 --- a/patches/openwrt/0027-ar71xx-fix-model-string-detection-on-NETGEAR-WNDR3700-3800-WNDRMAC.patch +++ /dev/null @@ -1,65 +0,0 @@ -From: Matthias Schiffer -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 - -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" diff --git a/patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch b/patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch deleted file mode 100644 index 6eb7100e..00000000 --- a/patches/openwrt/0028-ar71xx-fix-TP-LINK-TL-WDR3600-4300-RFKILL-switch-positions.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Matthias Schiffer -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 - -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, - }, - }; - diff --git a/patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch b/patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch deleted file mode 100644 index 3dfce311..00000000 --- a/patches/openwrt/0029-buildroot-make-it-easier-to-build-all-kmods.patch +++ /dev/null @@ -1,57 +0,0 @@ -From: Matthias Schiffer -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 - -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}) { diff --git a/patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch b/patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch deleted file mode 100644 index 5e68ad4c..00000000 --- a/patches/openwrt/0030-build-define-STAMP_CONFIGURED-recursively.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Matthias Schiffer -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 diff --git a/patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch b/patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch deleted file mode 100644 index 656ffc27..00000000 --- a/patches/openwrt/0032-mpc85xx-move-newly-created-files-from-patch-files-to-files-directory.patch +++ /dev/null @@ -1,1111 +0,0 @@ -From: Matthias Schiffer -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 -+ * -+ * Based on: -+ * cuboot-85xx.c -+ * Author: Scott Wood -+ * Copyright (c) 2007 Freescale Semiconductor, Inc. -+ * -+ * simpleboot.c -+ * Authors: Scott Wood -+ * Grant Likely -+ * 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 -+ -+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 -+ * -+ * 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 -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#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 - --- - 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 - - # 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 --+ * --+ * Based on: --+ * cuboot-85xx.c --+ * Author: Scott Wood --+ * Copyright (c) 2007 Freescale Semiconductor, Inc. --+ * --+ * simpleboot.c --+ * Authors: Scott Wood --+ * Grant Likely --+ * 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 --+ --+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 --+ * --+ * 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 - 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 --+ * --+ * 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 --+#include --+#include --+#include --+#include --+#include --+#include --+#include --+ --+#include --+#include --+#include --+#include --+#include --+#include --+#include --+ --+#include --+#include --+ --+#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/patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch b/patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch deleted file mode 100644 index 461e7479..00000000 --- a/patches/openwrt/0033-mpc85xx-gianfar-add-add-mtd-mac-address-support.patch +++ /dev/null @@ -1,168 +0,0 @@ -From: Matthias Schiffer -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 -+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 -+--- -+ 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 -+ #include -+ #include -++#include -+ -+ /** -+ * 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 -+ 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); - } - diff --git a/patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch b/patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch deleted file mode 100644 index d27b0f0d..00000000 --- a/patches/openwrt/0034-mpc85xx-replace-WDR4900-uci-defaults-ethernet-MAC-address-hack-with-DTS-entry.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Matthias Schiffer -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 { diff --git a/patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch b/patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch deleted file mode 100644 index 0b5e1861..00000000 --- a/patches/openwrt/0035-iwinfo-update-NanoStation-Loco-txpower-offsets.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Matthias Schiffer -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 */ diff --git a/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch b/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch index 8a1e00a2..8a01351f 100644 --- a/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch +++ b/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch @@ -2,10 +2,10 @@ From: Nils Schneider 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") diff --git a/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch b/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch index 2e1da79c..745e6cef 100644 --- a/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch +++ b/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 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 diff --git a/patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch b/patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch new file mode 100644 index 00000000..eb8f8aa2 --- /dev/null +++ b/patches/packages/luci/0003-luci-base-depend-on-libubus-lua.patch @@ -0,0 +1,17 @@ +From: Matthias Schiffer +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 diff --git a/patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch b/patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch deleted file mode 100644 index 985b7c69..00000000 --- a/patches/packages/openwrt/0001-haveged-start-directly-after-initial-setup-and-disable-tests.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Matthias Schiffer -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 diff --git a/patches/packages/openwrt/0002-libuecc-update-to-v5.patch b/patches/packages/openwrt/0002-libuecc-update-to-v5.patch deleted file mode 100644 index 979961e0..00000000 --- a/patches/packages/openwrt/0002-libuecc-update-to-v5.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Matthias Schiffer -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 - 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 diff --git a/patches/packages/openwrt/0003-fastd-update-to-v17.patch b/patches/packages/openwrt/0003-fastd-update-to-v17.patch deleted file mode 100644 index 33cc08bf..00000000 --- a/patches/packages/openwrt/0003-fastd-update-to-v17.patch +++ /dev/null @@ -1,213 +0,0 @@ -From: Matthias Schiffer -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 - 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 diff --git a/patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch b/patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch deleted file mode 100644 index e46c8c2c..00000000 --- a/patches/packages/routing/0001-Update-batman-adv-and-alfred-to-v2014.4.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: Matthias Schiffer -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) diff --git a/patches/packages/routing/0002-alfred-adjust-intervals.patch b/patches/packages/routing/0001-alfred-adjust-intervals.patch similarity index 100% rename from patches/packages/routing/0002-alfred-adjust-intervals.patch rename to patches/packages/routing/0001-alfred-adjust-intervals.patch diff --git a/patches/packages/routing/0003-batman-adv-introduce-no_rebroadcast-option.patch b/patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch similarity index 100% rename from patches/packages/routing/0003-batman-adv-introduce-no_rebroadcast-option.patch rename to patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch diff --git a/targets/ar71xx-generic/profiles.mk b/targets/ar71xx-generic/profiles.mk index 27ebf827..e22fe62c 100644 --- a/targets/ar71xx-generic/profiles.mk +++ b/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)) diff --git a/targets/ar71xx-generic/vermagic b/targets/ar71xx-generic/vermagic index 7a493135..ab5f8c55 100644 --- a/targets/ar71xx-generic/vermagic +++ b/targets/ar71xx-generic/vermagic @@ -1 +1 @@ -0114c71ed85677c9c1e4911437af4743 +c9110281555cccc9dd13e092c2acaeaf diff --git a/targets/ar71xx-nand/vermagic b/targets/ar71xx-nand/vermagic index 1e8c75b0..e3613a7a 100644 --- a/targets/ar71xx-nand/vermagic +++ b/targets/ar71xx-nand/vermagic @@ -1 +1 @@ -41123e63bc43f61af09d064504300966 +689cae9c23d40bdba3f46c59a12ca179 diff --git a/targets/mpc85xx-generic/vermagic b/targets/mpc85xx-generic/vermagic index bf824cec..9f75ad13 100644 --- a/targets/mpc85xx-generic/vermagic +++ b/targets/mpc85xx-generic/vermagic @@ -1 +1 @@ -c1a44dd429e530bed2958b8e6cb54a52 +18b3b28a5f70d5040f741bd44916dc57 diff --git a/targets/ramips-rt305x/vermagic b/targets/ramips-rt305x/vermagic index 6b3ea89d..c6652242 100644 --- a/targets/ramips-rt305x/vermagic +++ b/targets/ramips-rt305x/vermagic @@ -1 +1 @@ -194d0e9ee3ca8df976c737e78e8b2194 +4d806b94ed2b1e50df33a69891888e4a diff --git a/targets/x86-generic/vermagic b/targets/x86-generic/vermagic index f3bb33e2..457dc764 100644 --- a/targets/x86-generic/vermagic +++ b/targets/x86-generic/vermagic @@ -1 +1 @@ -3051dee8f07064b727e9d57fbfeb05ec +6581cdee9837e0761056ab3c80d05a2e diff --git a/targets/x86-kvm_guest/vermagic b/targets/x86-kvm_guest/vermagic index 47c31ca4..89969699 100644 --- a/targets/x86-kvm_guest/vermagic +++ b/targets/x86-kvm_guest/vermagic @@ -1 +1 @@ -5e81ad3c25d4a4f02e749f398f1868c5 +23b9575454f0084518a8c2f51423207c