aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211')
-rw-r--r--package/kernel/mac80211/Makefile2154
-rw-r--r--package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh748
-rw-r--r--package/kernel/mac80211/files/lib/wifi/mac80211.sh131
-rw-r--r--package/kernel/mac80211/files/regdb.txt1262
-rw-r--r--package/kernel/mac80211/patches/000-fix_kconfig.patch14
-rw-r--r--package/kernel/mac80211/patches/001-fix_build.patch167
-rw-r--r--package/kernel/mac80211/patches/002-change_allconfig.patch64
-rw-r--r--package/kernel/mac80211/patches/003-remove_bogus_modparams.patch34
-rw-r--r--package/kernel/mac80211/patches/010-disable_rfkill.patch13
-rw-r--r--package/kernel/mac80211/patches/030-rt2x00_options.patch47
-rw-r--r--package/kernel/mac80211/patches/040-brcmutil_option.patch9
-rw-r--r--package/kernel/mac80211/patches/050-lib80211_option.patch30
-rw-r--r--package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch130
-rw-r--r--package/kernel/mac80211/patches/070-ath_common_config.patch10
-rw-r--r--package/kernel/mac80211/patches/080-disable_clk_backport.patch20
-rw-r--r--package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch376
-rw-r--r--package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch12
-rw-r--r--package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch43
-rw-r--r--package/kernel/mac80211/patches/150-disable_addr_notifier.patch67
-rw-r--r--package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch38
-rw-r--r--package/kernel/mac80211/patches/210-ap_scan.patch11
-rw-r--r--package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch31
-rw-r--r--package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch121
-rw-r--r--package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch108
-rw-r--r--package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch239
-rw-r--r--package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch331
-rw-r--r--package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch468
-rw-r--r--package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch60
-rw-r--r--package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch49
-rw-r--r--package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch165
-rw-r--r--package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch90
-rw-r--r--package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch77
-rw-r--r--package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch37
-rw-r--r--package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch314
-rw-r--r--package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch42
-rw-r--r--package/kernel/mac80211/patches/400-ath_move_debug_code.patch30
-rw-r--r--package/kernel/mac80211/patches/401-ath9k_blink_default.patch11
-rw-r--r--package/kernel/mac80211/patches/402-ath_regd_optional.patch69
-rw-r--r--package/kernel/mac80211/patches/403-world_regd_fixup.patch84
-rw-r--r--package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch19
-rw-r--r--package/kernel/mac80211/patches/405-ath_regd_us.patch26
-rw-r--r--package/kernel/mac80211/patches/406-ath_relax_default_regd.patch47
-rw-r--r--package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch10
-rw-r--r--package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch46
-rw-r--r--package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch18
-rw-r--r--package/kernel/mac80211/patches/430-add_ath5k_platform.patch33
-rw-r--r--package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch56
-rw-r--r--package/kernel/mac80211/patches/432-ath5k_add_pciids.patch11
-rw-r--r--package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch143
-rw-r--r--package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch65
-rw-r--r--package/kernel/mac80211/patches/501-ath9k_ahb_init.patch32
-rw-r--r--package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch18
-rw-r--r--package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch11
-rw-r--r--package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch125
-rw-r--r--package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch30
-rw-r--r--package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch160
-rw-r--r--package/kernel/mac80211/patches/530-ath9k_extra_leds.patch251
-rw-r--r--package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch71
-rw-r--r--package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch11
-rw-r--r--package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch28
-rw-r--r--package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch139
-rw-r--r--package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch186
-rw-r--r--package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch79
-rw-r--r--package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch155
-rw-r--r--package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch66
-rw-r--r--package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch80
-rw-r--r--package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch531
-rw-r--r--package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch131
-rw-r--r--package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch62
-rw-r--r--package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch67
-rw-r--r--package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch24
-rw-r--r--package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch30
-rw-r--r--package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch20
-rw-r--r--package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch112
-rw-r--r--package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch28
-rw-r--r--package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch235
-rw-r--r--package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch20
-rw-r--r--package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch77
-rw-r--r--package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch30
-rw-r--r--package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch71
-rw-r--r--package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch178
-rw-r--r--package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch21
-rw-r--r--package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch136
-rw-r--r--package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch30
-rw-r--r--package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch23
-rw-r--r--package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch33
-rw-r--r--package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch20
-rw-r--r--package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch32
-rw-r--r--package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch44
-rw-r--r--package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch42
-rw-r--r--package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch23
-rw-r--r--package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch22
-rw-r--r--package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch136
-rw-r--r--package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch13
-rw-r--r--package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch32
-rw-r--r--package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch301
-rw-r--r--package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch33
-rw-r--r--package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch101
-rw-r--r--package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch47
-rw-r--r--package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch63
-rw-r--r--package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch27
-rw-r--r--package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch211
-rw-r--r--package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch106
-rw-r--r--package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch33
-rw-r--r--package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch29
-rw-r--r--package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch276
-rw-r--r--package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch40
-rw-r--r--package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch11
-rw-r--r--package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch15
-rw-r--r--package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch29
-rw-r--r--package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch10
-rw-r--r--package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch21
-rw-r--r--package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch11
-rw-r--r--package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch37
-rw-r--r--package/kernel/mac80211/patches/810-b43_no_pio.patch86
-rw-r--r--package/kernel/mac80211/patches/820-b43-add-antenna-control.patch131
-rw-r--r--package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch11
-rw-r--r--package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch17
-rw-r--r--package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch11
-rw-r--r--package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch27
-rw-r--r--package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch97
-rw-r--r--package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch50
-rw-r--r--package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch20
-rw-r--r--package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch1202
-rw-r--r--package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch33
-rw-r--r--package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch37
-rw-r--r--package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch20
-rwxr-xr-xpackage/kernel/mac80211/scripts/import-backports.sh109
133 files changed, 15207 insertions, 0 deletions
diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
new file mode 100644
index 0000000..580b2c3
--- /dev/null
+++ b/package/kernel/mac80211/Makefile
@@ -0,0 +1,2154 @@
+#
+# Copyright (C) 2007-2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=mac80211
+
+PKG_VERSION:=2015-10-26
+PKG_RELEASE:=1
+PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
+PKG_BACKPORT_VERSION:=
+PKG_MD5SUM:=3b07569065a18c6a69a340ea50235b7d
+
+PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
+PKG_BUILD_PARALLEL:=1
+
+PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+
+PKG_DRIVERS = \
+ adm8211 \
+ ath ath5k ath9k ath9k-common ath9k-htc ath10k \
+ b43 b43legacy \
+ carl9170 \
+ hermes hermes-pci hermes-pcmcia hermes-plx\
+ iwl-legacy iwl3945 iwl4965 iwlwifi \
+ lib80211 \
+ libipw ipw2100 ipw2200 \
+ libertas-sdio libertas-usb \
+ mac80211-hwsim \
+ mt7601u \
+ mwl8k mwifiex-pcie \
+ p54-common p54-pci p54-spi p54-usb \
+ rt2x00-lib rt2x00-pci rt2x00-usb \
+ rt2400-pci rt2500-pci rt2500-usb \
+ rt2800-lib rt2800-mmio rt2800-pci rt2800-soc rt2800-usb \
+ rt61-pci rt73-usb \
+ rtl8180 rtl8187 \
+ rtlwifi rtlwifi-pci rtlwifi-usb rtl8192c-common rtl8192ce rtl8192se \
+ rtl8192de rtl8192cu \
+ wlcore wl12xx wl18xx \
+ zd1211rw
+
+PKG_CONFIG_DEPENDS:= \
+ CONFIG_PACKAGE_kmod-mac80211 \
+ $(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS)) \
+ CONFIG_PACKAGE_MAC80211_DEBUGFS \
+ CONFIG_PACKAGE_MAC80211_MESH \
+ CONFIG_PACKAGE_ATH_DEBUG \
+ CONFIG_PACKAGE_ATH_DFS \
+ CONFIG_PACKAGE_B43_DEBUG \
+ CONFIG_PACKAGE_B43_PIO \
+ CONFIG_PACKAGE_B43_PHY_G \
+ CONFIG_PACKAGE_B43_PHY_N \
+ CONFIG_PACKAGE_B43_PHY_LP \
+ CONFIG_PACKAGE_B43_PHY_HT \
+ CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB \
+ CONFIG_PACKAGE_B43_BUSES_BCMA \
+ CONFIG_PACKAGE_B43_BUSES_SSB \
+ CONFIG_PACKAGE_RTLWIFI_DEBUG \
+ CONFIG_ATH_USER_REGD \
+
+include $(INCLUDE_DIR)/package.mk
+
+WMENU:=Wireless Drivers
+
+define KernelPackage/mac80211/Default
+ SUBMENU:=$(WMENU)
+ URL:=https://wireless.wiki.kernel.org/
+ MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+endef
+
+define KernelPackage/cfg80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=cfg80211 - wireless configuration API
+ DEPENDS+= +iw
+ FILES:= \
+ $(PKG_BUILD_DIR)/compat/compat.ko \
+ $(PKG_BUILD_DIR)/net/wireless/cfg80211.ko
+endef
+
+define KernelPackage/cfg80211/description
+cfg80211 is the Linux wireless LAN (802.11) configuration API.
+endef
+
+define KernelPackage/mac80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Linux 802.11 Wireless Networking Stack
+ DEPENDS+= +kmod-cfg80211 +hostapd-common
+ KCONFIG:=\
+ CONFIG_AVERAGE=y
+ FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
+ MENU:=1
+endef
+
+define KernelPackage/mac80211/config
+ if PACKAGE_kmod-mac80211
+
+ config PACKAGE_MAC80211_DEBUGFS
+ bool "Export mac80211 internals in DebugFS"
+ select KERNEL_DEBUG_FS
+ default y
+ help
+ Select this to see extensive information about
+ the internal state of mac80211 in debugfs.
+
+ config PACKAGE_MAC80211_MESH
+ bool "Enable 802.11s mesh support"
+ default y
+
+ endif
+endef
+
+define KernelPackage/mac80211/description
+Generic IEEE 802.11 Networking Stack (mac80211)
+endef
+
+PKG_LINUX_FIRMWARE_NAME:=linux-firmware
+PKG_LINUX_FIRMWARE_VERSION:=6ebf5d57d9f6d0cf05558baef1af2b90a3fe98ed
+PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-2015-09-03-$(PKG_LINUX_FIRMWARE_VERSION).tar.xz
+PKG_LINUX_FIRMWARE_PROTO:=git
+PKG_LINUX_FIRMWARE_SOURCE_URL:=https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
+PKG_LINUX_FIRMWARE_SUBDIR:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION)
+#PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=e219333f01835c6e556875a9e0deb3f9
+
+define Download/linux-firmware
+ FILE:=$(PKG_LINUX_FIRMWARE_SOURCE)
+ URL:=$(PKG_LINUX_FIRMWARE_SOURCE_URL)
+ MD5SUM:=$(PKG_LINUX_FIRMWARE_MD5SUM)
+ PROTO:=$(PKG_LINUX_FIRMWARE_PROTO)
+ VERSION:=$(PKG_LINUX_FIRMWARE_VERSION)
+ SUBDIR:=$(PKG_LINUX_FIRMWARE_SUBDIR)
+ MIRROR_MD5SUM:=$(PKG_LINUX_FIRMWARE_MIRROR_MD5SUM)
+endef
+$(eval $(call Download,linux-firmware))
+
+
+define KernelPackage/adm8211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=ADMTek 8211 support
+ DEPENDS+=@PCI_SUPPORT +kmod-mac80211 +kmod-eeprom-93cx6
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/adm8211.ko
+ AUTOLOAD:=$(call AutoProbe,adm8211)
+endef
+
+define KernelPackage/ath/config
+ if PACKAGE_kmod-ath
+ config ATH_USER_REGD
+ bool "Force Atheros drivers to respect the user's regdomain settings"
+ help
+ Atheros' idea of regulatory handling is that the EEPROM of the card defines
+ the regulatory limits and the user is only allowed to restrict the settings
+ even further, even if the country allows frequencies or power levels that
+ are forbidden by the EEPROM settings.
+
+ Select this option if you want the driver to respect the user's decision about
+ regulatory settings.
+
+ config PACKAGE_ATH_DEBUG
+ bool "Atheros wireless debugging"
+ help
+ Say Y, if you want to debug atheros wireless drivers.
+ Only ath9k & ath10k make use of this.
+
+ config PACKAGE_ATH_DFS
+ bool "Enable DFS support"
+ default y
+ help
+ Dynamic frequency selection (DFS) is required for most of the 5 GHz band
+ channels in Europe, US, and Japan.
+
+ Select this option if you want to use such channels.
+
+ endif
+endef
+
+define KernelPackage/ath
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros common driver part
+ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx||TARGET_ath25 +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath.ko
+ MENU:=1
+endef
+
+define KernelPackage/ath/description
+ This module contains some common parts needed by Atheros Wireless drivers.
+endef
+
+define KernelPackage/ath5k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 5xxx wireless cards support
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath5k
+ DEPENDS+= @PCI_SUPPORT||@TARGET_ath25 +kmod-ath
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath5k/ath5k.ko
+ AUTOLOAD:=$(call AutoProbe,ath5k)
+endef
+
+define KernelPackage/ath5k/description
+ This module adds support for wireless adapters based on
+ Atheros 5xxx chipset.
+endef
+
+define KernelPackage/ath9k-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc)
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
+ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +@KERNEL_RELAY
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
+endef
+
+define KernelPackage/ath9k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n PCI wireless cards support
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
+ DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath9k-common
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k.ko
+ AUTOLOAD:=$(call AutoProbe,ath9k)
+endef
+
+define KernelPackage/ath9k/description
+This module adds support for wireless adapters based on
+Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
+endef
+
+define KernelPackage/ath9k/config
+
+ config ATH9K_SUPPORT_PCOEM
+ bool "Support chips used in PC OEM cards"
+ depends on PACKAGE_kmod-ath9k
+
+endef
+
+define KernelPackage/ath9k-htc
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11n USB device support
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k
+ DEPENDS+= @USB_SUPPORT +kmod-ath9k-common +kmod-usb-core
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
+ AUTOLOAD:=$(call AutoProbe,ath9k_htc)
+endef
+
+define KernelPackage/ath9k-htc/description
+This module adds support for wireless adapters based on
+Atheros USB AR9271 and AR7010 family of chipsets.
+endef
+
+define KernelPackage/ath10k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Atheros 802.11ac wireless cards support
+ URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
+ DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
+ AUTOLOAD:=$(call AutoLoad,55,ath10k_core ath10k_pci)
+endef
+
+define KernelPackage/ath10k/description
+This module adds support for wireless adapters based on
+Atheros IEEE 802.11ac family of chipsets. For now only
+PCI is supported.
+endef
+
+#Broadcom firmware
+ifneq ($(CONFIG_B43_FW_6_30),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=6.30.163.46
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).wl_apsta.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+ PKG_B43_FWV4_MD5SUM:=6fe97e9368d25342a1ab943d3cf3496d
+else
+ifneq ($(CONFIG_B43_FW_5_10),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.10.56.27.3
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta/wl_prebuilt.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)_mipsel.tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=3363e3a6b3d9d73c49dea870c7834eac
+else
+ifneq ($(CONFIG_B43_FW_4_178),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=4.178.10.4
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=14477e8cbbb91b11896affac9b219fdb
+else
+ifneq ($(CONFIG_B43_FW_5_100_138),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.100.138
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+ PKG_B43_FWV4_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
+else
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=4.150.10.5
+ PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/driver/wl_apsta_mimo.o
+ PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+ PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
+ PKG_B43_FWV4_MD5SUM:=0c6ba9687114c6b598e8019e262d9a60
+endif
+endif
+endif
+endif
+ifneq ($(CONFIG_B43_OPENFIRMWARE),)
+ PKG_B43_FWV4_NAME:=broadcom-wl
+ PKG_B43_FWV4_VERSION:=5.2
+ PKG_B43_FWV4_OBJECT:=openfwwf-$(PKG_B43_FWV4_VERSION)
+ PKG_B43_FWV4_SOURCE:=openfwwf-$(PKG_B43_FWV4_VERSION).tar.gz
+ PKG_B43_FWV4_SOURCE_URL:=http://www.ing.unibs.it/openfwwf/firmware/
+ PKG_B43_FWV4_MD5SUM:=e045a135453274e439ae183f8498b0fa
+endif
+
+
+PKG_B43_FWV3_NAME:=wl_apsta
+PKG_B43_FWV3_VERSION:=3.130.20.0
+PKG_B43_FWV3_SOURCE:=$(PKG_B43_FWV3_NAME)-$(PKG_B43_FWV3_VERSION).o
+PKG_B43_FWV3_SOURCE_URL:=http://downloads.openwrt.org/sources/
+PKG_B43_FWV3_MD5SUM:=e08665c5c5b66beb9c3b2dd54aa80cb3
+
+define Download/b43
+ FILE:=$(PKG_B43_FWV4_SOURCE)
+ URL:=$(PKG_B43_FWV4_SOURCE_URL)
+ MD5SUM:=$(PKG_B43_FWV4_MD5SUM)
+endef
+$(eval $(call Download,b43))
+
+define Download/b43legacy
+ FILE:=$(PKG_B43_FWV3_SOURCE)
+ URL:=$(PKG_B43_FWV3_SOURCE_URL)
+ MD5SUM:=$(PKG_B43_FWV3_MD5SUM)
+endef
+$(eval $(call Download,b43legacy))
+
+
+define KernelPackage/b43
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom 43xx wireless support
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
+ KCONFIG:= \
+ CONFIG_HW_RANDOM=y
+ # Depend on PCI_SUPPORT to make sure we can select kmod-bcma or kmod-ssb
+ DEPENDS += \
+ @PCI_SUPPORT +kmod-mac80211 \
+ $(if $(CONFIG_PACKAGE_B43_USE_SSB),+kmod-ssb) \
+ $(if $(CONFIG_PACKAGE_B43_USE_BCMA),+kmod-bcma)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
+ AUTOLOAD:=$(call AutoProbe,b43)
+ MENU:=1
+endef
+
+define KernelPackage/b43/config
+
+config PACKAGE_B43_USE_SSB
+ select PACKAGE_kmod-ssb
+ tristate
+ depends on !TARGET_brcm47xx && !TARGET_brcm63xx
+ default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
+ default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_SSB
+
+config PACKAGE_B43_USE_BCMA
+ select PACKAGE_kmod-bcma
+ tristate
+ depends on !TARGET_brcm47xx && !TARGET_bcm53xx
+ default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA_AND_SSB
+ default PACKAGE_kmod-b43 if PACKAGE_B43_BUSES_BCMA
+
+ if PACKAGE_kmod-b43
+
+ choice
+ prompt "b43 firmware version"
+ default B43_FW_5_100_138
+ help
+ This option allows you to select the version of the b43 firmware.
+
+ config B43_FW_4_150
+ bool "Firmware 410.2160 from driver 4.150.10.5 (old stable)"
+ help
+ Old stable firmware for BCM43xx devices.
+
+ If unsure, select this.
+
+ config B43_FW_4_178
+ bool "Firmware 478.104 from driver 4.178.10.4"
+ help
+ Older firmware for BCM43xx devices.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_FW_5_10
+ bool "Firmware 508.1084 from driver 5.10.56.27"
+ help
+ Older firmware for BCM43xx devices.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_FW_5_100_138
+ bool "Firmware 666.2 from driver 5.100.138 (stable)"
+ help
+ The currently default firmware for BCM43xx devices.
+
+ This firmware currently gets most of the testing and is needed for some N-PHY devices.
+
+ If unsure, select the this firmware.
+
+ config B43_FW_6_30
+ bool "Firmware 784.2 from driver 6.30.163.46 (experimental)"
+ help
+ Newer experimental firmware for BCM43xx devices.
+
+ This firmware is mostly untested.
+
+ If unsure, select the "stable" firmware.
+
+ config B43_OPENFIRMWARE
+ bool "Open FirmWare for WiFi networks"
+ help
+ Opensource firmware for BCM43xx devices.
+
+ Do _not_ select this, unless you know what you are doing.
+ The Opensource firmware is not suitable for embedded devices, yet.
+ It does not support QoS, which is bad for AccessPoints.
+ It does not support hardware crypto acceleration, which is a showstopper
+ for embedded devices with low CPU resources.
+
+ If unsure, select the "stable" firmware.
+
+ endchoice
+
+ config B43_FW_SQUASH
+ bool "Remove unnecessary firmware files"
+ depends on !B43_OPENFIRMWARE
+ default y
+ help
+ This options allows you to remove unnecessary b43 firmware files
+ from the final rootfs image. This can reduce the rootfs size by
+ up to 200k.
+
+ If unsure, say Y.
+
+ config B43_FW_SQUASH_COREREVS
+ string "Core revisions to include"
+ depends on B43_FW_SQUASH
+ default "5,6,7,8,9,10,11,13,15" if TARGET_brcm47xx_legacy
+ default "16,28,29,30" if TARGET_brcm47xx_mips74k
+ default "5,6,7,8,9,10,11,13,15,16,28,29,30"
+ help
+ This is a comma seperated list of core revision numbers.
+
+ Example (keep files for rev5 only):
+ 5
+
+ Example (keep files for rev5 and rev11):
+ 5,11
+
+ config B43_FW_SQUASH_PHYTYPES
+ string "PHY types to include"
+ depends on B43_FW_SQUASH
+ default "G,N,LP" if TARGET_brcm47xx_legacy
+ default "N,HT" if TARGET_brcm47xx_mips74k
+ default "G,N,LP,HT"
+ help
+ This is a comma seperated list of PHY types:
+ A => A-PHY
+ AG => Dual A-PHY G-PHY
+ G => G-PHY
+ LP => LP-PHY
+ N => N-PHY
+ HT => HT-PHY
+ LCN => LCN-PHY
+ LCN40 => LCN40-PHY
+ AC => AC-PHY
+
+ Example (keep files for G-PHY only):
+ G
+
+ Example (keep files for G-PHY and N-PHY):
+ G,N
+
+ choice
+ prompt "Supported buses"
+ default PACKAGE_B43_BUSES_BCMA_AND_SSB
+ help
+ This allows choosing buses that b43 should support.
+
+ config PACKAGE_B43_BUSES_BCMA_AND_SSB
+ depends on !TARGET_brcm47xx_legacy && !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
+ bool "BCMA and SSB"
+
+ config PACKAGE_B43_BUSES_BCMA
+ depends on !TARGET_brcm47xx_legacy
+ bool "BCMA only"
+
+ config PACKAGE_B43_BUSES_SSB
+ depends on !TARGET_brcm47xx_mips74k && !TARGET_bcm53xx
+ bool "SSB only"
+
+ endchoice
+
+ config PACKAGE_B43_DEBUG
+ bool "Enable debug output and debugfs for b43"
+ default n
+ help
+ Enable additional debug output and runtime sanity checks for b43
+ and enables the debugfs interface.
+
+ If unsure, say N.
+
+ config PACKAGE_B43_PIO
+ bool "Enable support for PIO transfer mode"
+ default n
+ help
+ Enable support for using PIO instead of DMA. Unless you have DMA
+ transfer problems you don't need this.
+
+ If unsure, say N.
+
+ config PACKAGE_B43_PHY_G
+ bool "Enable support for G-PHYs"
+ default n if TARGET_brcm47xx_mips74k
+ default y
+ help
+ Enable support for G-PHY. This includes support for the following devices:
+ PCI: BCM4306, BCM4311, BCM4318
+ SoC: BCM5352E, BCM4712
+
+ If unsure, say Y.
+
+ config PACKAGE_B43_PHY_N
+ bool "Enable support for N-PHYs"
+ default y
+ help
+ Enable support for N-PHY. This includes support for the following devices:
+ PCI: BCM4321, BCM4322, BCM43222, BCM43224, BCM43225
+ SoC: BCM4716, BCM4717, BCM4718
+
+ Currently only 11g speed is available.
+
+ If unsure, say Y.
+
+ config PACKAGE_B43_PHY_LP
+ bool "Enable support for LP-PHYs"
+ default n if TARGET_brcm47xx_mips74k
+ default y
+ help
+ Enable support for LP-PHY. This includes support for the following devices:
+ PCI: BCM4312
+ SoC: BCM5354
+
+ If unsure, say Y.
+
+ config PACKAGE_B43_PHY_HT
+ bool "Enable support for HT-PHYs"
+ default n if TARGET_brcm47xx_legacy
+ default y
+ help
+ Enable support for HT-PHY. This includes support for the following devices:
+ PCI: BCM4331
+
+ Currently only 11g speed is available.
+
+ If unsure, say Y.
+
+ config PACKAGE_B43_PHY_LCN
+ bool "Enable support for LCN-PHYs"
+ depends on BROKEN
+ default n
+ help
+ Currently broken.
+
+ If unsure, say N.
+
+ endif
+endef
+
+define KernelPackage/b43/description
+Kernel module for Broadcom 43xx wireless support (mac80211 stack) new
+endef
+
+define KernelPackage/b43legacy
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom 43xx-legacy wireless support
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/b43
+ KCONFIG:= \
+ CONFIG_HW_RANDOM=y
+ DEPENDS+= +kmod-mac80211 +!(TARGET_brcm47xx||TARGET_brcm63xx):kmod-ssb
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43legacy/b43legacy.ko
+ AUTOLOAD:=$(call AutoProbe,b43legacy)
+ MENU:=1
+endef
+
+define KernelPackage/b43legacy/config
+ if PACKAGE_kmod-b43legacy
+
+ config B43LEGACY_FW_SQUASH
+ bool "Remove unnecessary firmware files"
+ default y
+ help
+ This options allows you to remove unnecessary b43legacy firmware files
+ from the final rootfs image. This can reduce the rootfs size by
+ up to 50k.
+
+ If unsure, say Y.
+
+ config B43LEGACY_FW_SQUASH_COREREVS
+ string "Core revisions to include"
+ depends on B43LEGACY_FW_SQUASH
+ default "1,2,3,4"
+ help
+ This is a comma seperated list of core revision numbers.
+
+ Example (keep files for rev4 only):
+ 4
+
+ Example (keep files for rev2 and rev4):
+ 2,4
+
+ endif
+endef
+
+define KernelPackage/b43legacy/description
+Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new
+endef
+
+
+define KernelPackage/brcmutil
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n common driver parts
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+ DEPENDS+=@PCI_SUPPORT||USB_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmutil/brcmutil.ko
+ AUTOLOAD:=$(call AutoProbe,brcmutil)
+ MENU:=1
+endef
+
+define KernelPackage/brcmutil/description
+ This module contains some common parts needed by Broadcom Wireless drivers brcmsmac and brcmfmac.
+endef
+
+define KernelPackage/brcmutil/config
+ if PACKAGE_kmod-brcmutil
+
+ config PACKAGE_BRCM80211_DEBUG
+ bool "Broadcom wireless driver debugging"
+ help
+ Say Y, if you want to debug brcmsmac and brcmfmac wireless driver.
+
+ endif
+endef
+
+PKG_BRCMSMAC_FW_NAME:=broadcom-wl
+PKG_BRCMSMAC_FW_VERSION:=5.100.138
+PKG_BRCMSMAC_FW_OBJECT:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION)/linux/wl_apsta.o
+PKG_BRCMSMAC_FW_SOURCE:=$(PKG_BRCMSMAC_FW_NAME)-$(PKG_BRCMSMAC_FW_VERSION).tar.bz2
+PKG_BRCMSMAC_FW_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+PKG_BRCMSMAC_FW_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
+
+define Download/brcmsmac
+ FILE:=$(PKG_BRCMSMAC_FW_SOURCE)
+ URL:=$(PKG_BRCMSMAC_FW_SOURCE_URL)
+ MD5SUM:=$(PKG_BRCMSMAC_FW_MD5SUM)
+endef
+$(eval $(call Download,brcmsmac))
+
+define KernelPackage/brcmsmac
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n PCIe SoftMAC WLAN driver
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+ DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma +kmod-lib-cordic +kmod-lib-crc8 +kmod-brcmutil
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmsmac/brcmsmac.ko
+ AUTOLOAD:=$(call AutoProbe,brcmsmac)
+ MENU:=1
+endef
+
+define KernelPackage/brcmsmac/description
+ Kernel module for Broadcom IEEE802.11n PCIe Wireless cards
+endef
+
+define KernelPackage/brcmsmac/config
+ if PACKAGE_kmod-brcmsmac
+
+ config BRCMSMAC_USE_FW_FROM_WL
+ bool "Use firmware extracted from broadcom proprietary driver"
+ default y
+ help
+ Instead of using the official brcmsmac firmware a firmware
+ version 666.2 extracted from the proprietary Broadcom driver
+ is used. This is needed to get core rev 17 used in bcm4716
+ to work.
+
+ If unsure, say Y.
+
+ endif
+endef
+
+
+define KernelPackage/brcmfmac
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Broadcom IEEE802.11n USB FullMAC WLAN driver
+ URL:=https://wireless.wiki.kernel.org/en/users/drivers/brcm80211
+ DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +@DRIVER_11N_SUPPORT +kmod-brcmutil +BRCMFMAC_SDIO:kmod-mmc +BRCMFMAC_USB:kmod-usb-core
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/brcm80211/brcmfmac/brcmfmac.ko
+ AUTOLOAD:=$(call AutoProbe,brcmfmac)
+endef
+
+define KernelPackage/brcmfmac/description
+ Kernel module for Broadcom IEEE802.11n USB Wireless cards
+endef
+
+define KernelPackage/brcmfmac/config
+ if PACKAGE_kmod-brcmfmac
+
+ config BRCMFMAC_SDIO
+ bool "Enable SDIO bus interface support"
+ default n
+ help
+ Enable support for cards attached to an SDIO bus.
+ Select this option only if you are sure that your
+ board has a Broadcom wireless chip atacched to
+ that bus.
+
+ config BRCMFMAC_USB
+ bool "Enable USB bus interface support"
+ depends on USB_SUPPORT
+ default y
+ help
+ Supported USB connected chipsets:
+ BCM43235, BCM43236, BCM43238 (all in revision 3 only)
+ BCM43143, BCM43242, BCM43566, BCM43569
+
+ config BRCMFMAC_PCIE
+ bool "Enable PCIE bus interface support"
+ depends on PCI_SUPPORT
+ default y
+ help
+ Supported PCIe connected chipsets:
+ BCM4354, BCM4356, BCM43567, BCM43570, BCM43602
+
+ endif
+endef
+
+
+define KernelPackage/carl9170
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for Atheros AR9170 USB sticks
+ DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko
+ AUTOLOAD:=$(call AutoProbe,carl9170)
+endef
+
+
+define KernelPackage/hermes
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Hermes 802.11b chipset support
+ DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT +kmod-crypto-michael-mic
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco.ko
+ AUTOLOAD:=$(call AutoProbe,orinoco)
+endef
+
+define KernelPackage/hermes/description
+ Kernel support for Hermes 802.11b chipsets
+endef
+
+define KernelPackage/hermes-pci
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intersil Prism 2.5 PCI support
+ DEPENDS:=@PCI_SUPPORT +kmod-hermes
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_pci.ko
+ AUTOLOAD:=$(call AutoProbe,orinoco_pci)
+endef
+
+define KernelPackage/hermes-pci/description
+ Kernel modules for Intersil Prism 2.5 PCI support
+endef
+
+define KernelPackage/hermes-plx
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=PLX9052 based PCI adaptor
+ DEPENDS:=@PCI_SUPPORT +kmod-hermes
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_plx.ko
+ AUTOLOAD:=$(call AutoProbe,orinoco_plx)
+endef
+
+define KernelPackage/hermes-plx/description
+ Kernel modules for Hermes in PLX9052 based PCI adaptors
+endef
+
+define KernelPackage/hermes-pcmcia
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Hermes based PCMCIA adaptors
+ DEPENDS:=@PCMCIA_SUPPORT +kmod-hermes @BROKEN
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_cs.ko
+ AUTOLOAD:=$(call AutoProbe,orinoco_cs)
+endef
+
+define KernelPackage/hermes-pcmcia/description
+ Kernel modules for Hermes based PCMCIA adaptors
+endef
+
+
+define KernelPackage/iwlwifi
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT
+ TITLE:=Intel AGN Wireless support
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/dvm/iwldvm.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/mvm/iwlmvm.ko
+ AUTOLOAD:=$(call AutoProbe,iwlwifi iwldvm iwlmvm)
+ MENU:=1
+endef
+
+define KernelPackage/iwlwifi/description
+ iwlwifi kernel module for
+ Intel Wireless WiFi Link 6250AGN Adapter
+ Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
+ Intel WiFi Link 1000BGN
+ Intel Wireless WiFi 5150AGN
+ Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+ Intel 6005 Series Wi-Fi Adapters
+ Intel 6030 Series Wi-Fi Adapters
+ Intel Wireless WiFi Link 6150BGN 2 Adapter
+ Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
+ Intel 2000 Series Wi-Fi Adapters
+ Intel 7260 Wi-Fi Adapter
+ Intel 3160 Wi-Fi Adapter
+ Intel 7265 Wi-Fi Adapter
+ Intel 8260 Wi-Fi Adapter
+ Intel 3165 Wi-Fi Adapter
+endef
+
+define KernelPackage/iwlwifi/config
+ if PACKAGE_kmod-iwlwifi
+
+ config PACKAGE_IWLWIFI_DEBUG
+ bool "Enable full debugging output in the iwlwifi driver"
+ default n
+ help
+ This option will enable debug tracing output for the iwlwifi drivers
+
+ This will result in the kernel module being ~100k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/module/iwlwifi/parameters/debug
+
+ This entry will only exist if this option is enabled.
+
+ To set a value, simply echo an 8-byte hex value to the same file:
+
+ % echo 0x43fff > /sys/module/iwlwifi/parameters/debug
+
+ You can find the list of debug mask values in:
+ drivers/net/wireless/iwlwifi/iwl-debug.h
+
+ If this is your first time using this driver, you should say Y here
+ as the debug information can assist others in helping you resolve
+ any problems you may encounter.
+
+ config PACKAGE_IWLWIFI_DEBUGFS
+ bool "iwlwifi debugfs support"
+ depends on PACKAGE_MAC80211_DEBUGFS
+ default n
+ help
+ Enable creation of debugfs files for the iwlwifi drivers. This
+ is a low-impact option that allows getting insight into the
+ driver's state at runtime.
+
+ config IWL100_FW
+ bool "Intel 100 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 100
+
+ config IWL1000_FW
+ bool "Intel 1000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 1000
+
+ config IWL105_FW
+ bool "Intel 105 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 105
+
+ config IWL135_FW
+ bool "Intel 135 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 135
+
+ config IWL2000_FW
+ bool "Intel 2000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 2200
+
+ config IWL2030_FW
+ bool "Intel 2030 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Wireless-N 2230
+
+ config IWL3160_FW
+ bool "Intel 3160 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Wireless WiFi 3160
+
+ config IWL5000_FW
+ bool "Intel 5000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+
+ config IWL5150_FW
+ bool "Intel 5150 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Wireless WiFi 5150AGN
+
+ config IWL6000_FW
+ bool "Intel 6000 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Ultimate-N 6300 and Advanced-N 6200
+
+ config IWL6005_FW
+ bool "Intel 6005 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Advanced-N 6205
+
+ config IWL6030_FW
+ bool "Intel 6030 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Advanced-N 6230, Wireless-N 1030, Wireless-N 130 and Advanced-N 6235
+
+ config IWL6050_FW
+ bool "Intel 6050 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Centrino Advanced-N + WiMAX 6250 and Wireless-N + WiMAX 6150
+
+ config IWL7260_FW
+ bool "Intel 7260 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Dual Band Wireless-N 7260 and Intel Dual Band Wireless-AC 7260
+
+ config IWL7265_FW
+ bool "Intel 7265 Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Wireless 7265, 7265D, 3165
+
+ config IWL8000_FW
+ bool "Intel 8000 Series Firmware"
+ default y
+ help
+ Download and install firmware for:
+ Intel Wireless Series 8260, 4165
+
+ endif
+endef
+
+define KernelPackage/iwl-legacy
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
+ TITLE:=Intel legacy Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwlegacy.ko
+ AUTOLOAD:=$(call AutoProbe,iwlegacy)
+endef
+
+define KernelPackage/iwl-legacy/description
+ iwl-legacy kernel module for legacy Intel wireless support
+endef
+
+define KernelPackage/iwl3945
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
+ TITLE:=Intel iwl3945 Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.ko
+ AUTOLOAD:=$(call AutoProbe,iwl3945)
+endef
+
+define KernelPackage/iwl3945/description
+ iwl3945 kernel module for Intel 3945 support
+endef
+
+define KernelPackage/iwl4965
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy +@DRIVER_11N_SUPPORT
+ TITLE:=Intel iwl4965 Wireless support
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.ko
+ AUTOLOAD:=$(call AutoProbe,iwl4965)
+endef
+
+define KernelPackage/iwl4965/description
+ iwl4965 kernel module for Intel 4965 support
+endef
+
+
+define KernelPackage/lib80211
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=802.11 Networking stack
+ DEPENDS:=+kmod-cfg80211
+ FILES:= \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_ccmp.ko \
+ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_tkip.ko
+ AUTOLOAD:=$(call AutoProbe, \
+ lib80211 \
+ lib80211_crypt_wep \
+ lib80211_crypt_ccmp \
+ lib80211_crypt_tkip \
+ )
+endef
+
+define KernelPackage/lib80211/description
+ Kernel modules for 802.11 Networking stack
+ Includes:
+ - lib80211
+ - lib80211_crypt_wep
+ - lib80211_crypt_tkip
+ - lib80211_crytp_ccmp
+endef
+
+
+define KernelPackage/libipw
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=libipw for ipw2100 and ipw2200
+ DEPENDS:=@PCI_SUPPORT +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko
+ AUTOLOAD:=$(call AutoProbe,libipw)
+endef
+
+define KernelPackage/libipw/description
+ Hardware independent IEEE 802.11 networking stack for ipw2100 and ipw2200.
+endef
+
+IPW2100_NAME:=ipw2100-fw
+IPW2100_VERSION:=1.3
+
+define Download/ipw2100
+ URL:=http://bughost.org/firmware/
+ FILE:=$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+ MD5SUM=46aa75bcda1a00efa841f9707bbbd113
+endef
+$(eval $(call Download,ipw2100))
+
+define KernelPackage/ipw2100
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intel IPW2100 driver
+ DEPENDS:=@PCI_SUPPORT +kmod-libipw
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2100.ko
+ AUTOLOAD:=$(call AutoProbe,ipw2100)
+endef
+
+define KernelPackage/ipw2100/description
+ Kernel support for Intel IPW2100
+ Includes:
+ - ipw2100
+endef
+
+IPW2200_NAME:=ipw2200-fw
+IPW2200_VERSION:=3.1
+
+define Download/ipw2200
+ URL:=http://bughost.org/firmware/
+ FILE:=$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+ MD5SUM=eaba788643c7cc7483dd67ace70f6e99
+endef
+$(eval $(call Download,ipw2200))
+
+define KernelPackage/ipw2200
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Intel IPW2200 driver
+ DEPENDS:=@PCI_SUPPORT +kmod-libipw
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/ipw2200.ko
+ AUTOLOAD:=$(call AutoProbe,ipw2200)
+endef
+
+define KernelPackage/ipw2200/description
+ Kernel support for Intel IPW2200
+ Includes:
+ - ipw2200
+endef
+
+
+define KernelPackage/libertas-usb
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
+ TITLE:=Marvell 88W8015 Wireless Driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/usb8xxx.ko
+ AUTOLOAD:=$(call AutoProbe,libertas usb8xxx)
+endef
+
+define KernelPackage/libertas-sdio
+ $(call KernelPackage/mac80211/Default)
+ DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +kmod-mmc +@DRIVER_WEXT_SUPPORT @!TARGET_uml
+ TITLE:=Marvell 88W8686 Wireless Driver
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas_sdio.ko
+ AUTOLOAD:=$(call AutoProbe,libertas libertas_sdio)
+endef
+
+define KernelPackage/mac80211-hwsim
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=mac80211 HW simulation device
+ DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mac80211_hwsim.ko
+ AUTOLOAD:=$(call AutoProbe,mac80211_hwsim)
+endef
+
+PKG_MT7601U_FW_NAME:=DPO_MT7601U_LinuxSTA
+PKG_MT7601U_FW_VERSION:=3.0.0.4_20130913
+PKG_MT7601U_FW_MD5SUM:=5f440dccc8bc952745a191994fc34699
+PKG_MT7601U_FW_SOURCE:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION).tar.bz2
+PKG_MT7601U_FW_SOURCE_URL:=http://www.mediatek.com/AmazonS3/Downloads/linux/
+define Download/mt7601u-firmware
+ FILE:=$(PKG_MT7601U_FW_SOURCE)
+ URL:=$(PKG_MT7601U_FW_SOURCE_URL)
+ MD5SUM:=$(PKG_MT7601U_FW_MD5SUM)
+ SUBDIR:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION)
+endef
+$(eval $(call Download,mt7601u-firmware))
+
+define KernelPackage/mt7601u
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=MT7601U-based USB dongles Wireless Driver
+ DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko
+ AUTOLOAD:=$(call AutoProbe,mt7601)
+endef
+
+
+define KernelPackage/mwl8k
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for Marvell TOPDOG 802.11 Wireless cards
+ URL:=http://wireless.kernel.org/en/users/Drivers/mwl8k
+ DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mwl8k.ko
+ AUTOLOAD:=$(call AutoProbe,mwl8k)
+endef
+
+define KernelPackage/mwl8k/description
+ Kernel modules for Marvell TOPDOG 802.11 Wireless cards
+endef
+
+
+define KernelPackage/mwifiex-pcie
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for Marvell 802.11n/802.11ac PCIe Wireless cards
+ URL:=http://wireless.kernel.org/en/users/Drivers/mwifiex
+ DEPENDS+= @PCI_SUPPORT +kmod-mac80211 +@DRIVER_11N_SUPPORT
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/mwifiex/mwifiex_pcie.ko
+ AUTOLOAD:=$(call AutoProbe,mwifiex_pcie)
+endef
+
+define KernelPackage/mwifiex-pcie/description
+ Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards
+endef
+
+
+# Prism54 drivers
+P54PCIFW:=2.13.12.0.arm
+P54USBFW:=2.13.24.0.lm87.arm
+P54SPIFW:=2.13.0.0.a.13.14.arm
+
+define Download/p54usb
+ FILE:=$(P54USBFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb
+ MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6
+endef
+$(eval $(call Download,p54usb))
+
+define Download/p54pci
+ FILE:=$(P54PCIFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac
+ MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4
+endef
+$(eval $(call Download,p54pci))
+
+define Download/p54spi
+ FILE:=$(P54SPIFW)
+ URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560
+ MD5SUM:=42661f8ecbadd88012807493f596081d
+endef
+$(eval $(call Download,p54spi))
+
+define KernelPackage/p54/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Prism54 Drivers
+endef
+
+define KernelPackage/p54/description
+ Kernel module for Prism54 chipsets (mac80211)
+endef
+
+define KernelPackage/p54-common
+ $(call KernelPackage/p54/Default)
+ DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-lib-crc-ccitt
+ TITLE+= (COMMON)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
+endef
+
+define KernelPackage/p54-pci
+ $(call KernelPackage/p54/Default)
+ TITLE+= (PCI)
+ DEPENDS+= @PCI_SUPPORT +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54pci.ko
+ AUTOLOAD:=$(call AutoProbe,p54pci)
+endef
+
+define KernelPackage/p54-usb
+ $(call KernelPackage/p54/Default)
+ TITLE+= (USB)
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54usb.ko
+ AUTOLOAD:=$(call AutoProbe,p54usb)
+endef
+
+define KernelPackage/p54-spi
+ $(call KernelPackage/p54/Default)
+ TITLE+= (SPI)
+ DEPENDS+= @TARGET_omap24xx +kmod-p54-common
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54spi.ko
+ AUTOLOAD:=$(call AutoProbe,p54spi)
+endef
+
+define KernelPackage/rt2x00/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Ralink Drivers for RT2x00 cards
+endef
+
+define KernelPackage/rt2x00-lib
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-lib-crc-itu-t
+ TITLE+= (LIB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.ko
+ MENU:=1
+endef
+
+define KernelPackage/rt2x00-lib/config
+ if PACKAGE_kmod-rt2x00-lib
+
+ config PACKAGE_RT2X00_LIB_DEBUGFS
+ bool "Enable rt2x00 debugfs support"
+ depends on PACKAGE_MAC80211_DEBUGFS
+ help
+ Enable creation of debugfs files for the rt2x00 drivers.
+ These debugfs files support both reading and writing of the
+ most important register types of the rt2x00 hardware.
+
+ config PACKAGE_RT2X00_DEBUG
+ bool "Enable rt2x00 debug output"
+ help
+ Enable debugging output for all rt2x00 modules
+
+ endif
+endef
+
+define KernelPackage/rt2x00-mmio
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6
+ HIDDEN:=1
+ TITLE+= (MMIO)
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00mmio.ko
+endef
+
+define KernelPackage/rt2x00-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib
+ HIDDEN:=1
+ TITLE+= (PCI)
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.ko
+ AUTOLOAD:=$(call AutoProbe,rt2x00pci)
+endef
+
+define KernelPackage/rt2x00-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core
+ HIDDEN:=1
+ TITLE+= (USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00usb.ko
+ AUTOLOAD:=$(call AutoProbe,rt2x00usb)
+endef
+
+define KernelPackage/rt2800-lib
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT
+ HIDDEN:=1
+ TITLE+= (rt2800 LIB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.ko
+endef
+
+define KernelPackage/rt2400-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2400 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2400pci.ko
+ AUTOLOAD:=$(call AutoProbe,rt2400pci)
+endef
+
+define KernelPackage/rt2500-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2500 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500pci.ko
+ AUTOLOAD:=$(call AutoProbe,rt2500pci)
+endef
+
+define KernelPackage/rt2500-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+ TITLE+= (RT2500 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2500usb.ko
+ AUTOLOAD:=$(call AutoProbe,rt2500usb)
+endef
+
+define KernelPackage/rt2800-mmio
+$(call KernelPackage/rt2x00/Default)
+ TITLE += (RT28xx/RT3xxx MMIO)
+ DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio
+ HIDDEN:=1
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800mmio.ko
+endef
+
+define KernelPackage/rt2800-soc
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS += @(TARGET_ramips_rt288x||TARGET_ramips_rt305x||TARGET_ramips_rt3883||TARGET_ramips_mt7620) +kmod-rt2800-mmio +kmod-rt2800-lib
+ TITLE += (RT28xx/RT3xxx SoC)
+ FILES := \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800soc.ko
+ AUTOLOAD:=$(call AutoProbe,rt2800soc)
+endef
+
+define KernelPackage/rt2800-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio
+ TITLE+= (RT2860 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
+ AUTOLOAD:=$(call AutoProbe,rt2800pci)
+endef
+
+define KernelPackage/rt2800-usb
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt
+ TITLE+= (RT2870 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800usb.ko
+ AUTOLOAD:=$(call AutoProbe,rt2800usb)
+endef
+
+
+define KernelPackage/rt61-pci
+$(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci
+ TITLE+= (RT2x61 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt61pci.ko
+ AUTOLOAD:=$(call AutoProbe,rt61pci)
+endef
+
+define KernelPackage/rt73-usb
+ $(call KernelPackage/rt2x00/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb
+ TITLE+= (RT73 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt73usb.ko
+ AUTOLOAD:=$(call AutoProbe,rt73usb)
+endef
+
+
+define KernelPackage/rtl818x/Default
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek Drivers for RTL818x devices
+ URL:=http://wireless.kernel.org/en/users/Drivers/rtl8187
+ DEPENDS+= +kmod-eeprom-93cx6 +kmod-mac80211
+endef
+
+define KernelPackage/rtl8180
+ $(call KernelPackage/rtl818x/Default)
+ DEPENDS+= @PCI_SUPPORT
+ TITLE+= (RTL8180 PCI)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl818x_pci.ko
+ AUTOLOAD:=$(call AutoProbe,rtl818x_pci)
+endef
+
+define KernelPackage/rtl8187
+$(call KernelPackage/rtl818x/Default)
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core
+ TITLE+= (RTL8187 USB)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.ko
+ AUTOLOAD:=$(call AutoProbe,rtl8187)
+endef
+
+define KernelPackage/rtlwifi/config
+ config PACKAGE_RTLWIFI_DEBUG
+ bool "Realtek wireless debugging"
+ depends on PACKAGE_kmod-rtlwifi
+ help
+ Say Y, if you want to debug realtek wireless drivers.
+
+endef
+
+define KernelPackage/rtlwifi
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek common driver part
+ DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtlwifi.ko
+ HIDDEN:=1
+endef
+
+define KernelPackage/rtlwifi-pci
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek common driver part (PCI support)
+ DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_pci.ko
+ AUTOLOAD:=$(call AutoProbe,rtl_pci)
+ HIDDEN:=1
+endef
+
+define KernelPackage/rtlwifi-usb
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek common driver part (USB support)
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl_usb.ko
+ AUTOLOAD:=$(call AutoProbe,rtl_usb)
+ HIDDEN:=1
+endef
+
+define KernelPackage/rtl8192c-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192CE/RTL8192CU common support module
+ DEPENDS+= +kmod-rtlwifi
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192c/rtl8192c-common.ko
+ HIDDEN:=1
+endef
+
+define KernelPackage/rtl8192ce
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192CE/RTL8188CE support
+ DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rtl8192ce.ko
+ AUTOLOAD:=$(call AutoProbe,rtl8192ce)
+endef
+
+define KernelPackage/rtl8192ce/install
+ $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfw.bin $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU.bin $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfwU_B.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192se
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192SE/RTL8191SE support
+ DEPENDS+= +kmod-rtlwifi-pci
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rtl8192se.ko
+ AUTOLOAD:=$(call AutoProbe,rtl8192se)
+endef
+
+define KernelPackage/rtl8192se/install
+ $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192sefw.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192de
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192DE/RTL8188DE support
+ DEPENDS+= +kmod-rtlwifi-pci
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rtl8192de.ko
+ AUTOLOAD:=$(call AutoProbe,rtl8192de)
+endef
+
+define KernelPackage/rtl8192de/install
+ $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192defw.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192cu
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192CU/RTL8188CU support
+ DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rtl8192cu.ko
+ AUTOLOAD:=$(call AutoProbe,rtl8192cu)
+endef
+
+define KernelPackage/rtl8192cu/install
+ $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw.bin $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_A.bin $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_B.bin $(1)/lib/firmware/rtlwifi
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw_TMSC.bin $(1)/lib/firmware/rtlwifi
+endef
+
+
+define KernelPackage/wlcore
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=TI common driver part
+ DEPENDS+= @TARGET_omap +kmod-mac80211 +@DRIVER_11N_SUPPORT
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko
+ AUTOLOAD:=$(call AutoProbe,wlcore wlcore_sdio)
+endef
+
+define KernelPackage/wlcore/description
+ This module contains some common parts needed by TI Wireless drivers.
+endef
+
+define KernelPackage/wl12xx
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for TI WL12xx
+ URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
+ DEPENDS+= +kmod-wlcore
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko
+ AUTOLOAD:=$(call AutoProbe,wl12xx)
+endef
+
+define KernelPackage/wl12xx/description
+ Kernel modules for TI WL12xx
+endef
+
+define KernelPackage/wl18xx
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Driver for TI WL18xx
+ URL:=http://wireless.kernel.org/en/users/Drivers/wl18xx
+ DEPENDS+= +kmod-wlcore
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko
+ AUTOLOAD:=$(call AutoProbe,wl18xx)
+endef
+
+define KernelPackage/wl18xx/description
+ Kernel modules for TI WL18xx
+endef
+
+
+ZD1211FW_NAME:=zd1211-firmware
+ZD1211FW_VERSION:=1.4
+define Download/zd1211rw
+ FILE:=$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+ URL:=@SF/zd1211/
+ MD5SUM:=19f28781d76569af8551c9d11294c870
+endef
+$(eval $(call Download,zd1211rw))
+
+define KernelPackage/zd1211rw
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Zydas ZD1211 support
+ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-mac80211
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/zd1211rw/zd1211rw.ko
+ AUTOLOAD:=$(call AutoProbe,zd1211rw)
+endef
+
+
+
+config_package=$(if $(CONFIG_PACKAGE_kmod-$(1)),m)
+
+config-y:= \
+ WLAN \
+ NL80211_TESTMODE \
+ CFG80211_WEXT \
+ CFG80211_INTERNAL_REGDB \
+ CFG80211_CERTIFICATION_ONUS \
+ MAC80211_RC_MINSTREL \
+ MAC80211_RC_MINSTREL_HT \
+ MAC80211_RC_MINSTREL_VHT \
+ MAC80211_RC_DEFAULT_MINSTREL \
+
+config-$(call config_package,cfg80211) += CFG80211
+
+config-$(call config_package,mac80211) += MAC80211
+config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH
+ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS
+ config-y += \
+ CFG80211_DEBUGFS \
+ MAC80211_DEBUGFS \
+ ATH9K_DEBUGFS \
+ ATH9K_HTC_DEBUGFS \
+ ATH10K_DEBUGFS \
+ CARL9170_DEBUGFS \
+ ATH5K_DEBUG
+endif
+
+config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP
+
+config-$(call config_package,ath) += ATH_CARDS ATH_COMMON
+config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG
+config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED
+
+config-$(call config_package,ath9k) += ATH9K
+config-$(call config_package,ath9k-common) += ATH9K_COMMON
+config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB
+config-$(CONFIG_PCI) += ATH9K_PCI
+config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD
+config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM
+
+config-$(call config_package,ath9k-htc) += ATH9K_HTC
+config-$(call config_package,ath10k) += ATH10K ATH10K_PCI
+
+config-$(call config_package,ath5k) += ATH5K
+ifdef CONFIG_TARGET_ath25
+ config-y += ATH5K_AHB
+else
+ config-y += ATH5K_PCI
+endif
+
+config-$(call config_package,carl9170) += CARL9170
+
+config-$(call config_package,b43) += B43
+config-$(CONFIG_PACKAGE_B43_BUSES_BCMA_AND_SSB) += B43_BUSES_BCMA_AND_SSB
+config-$(CONFIG_PACKAGE_B43_BUSES_BCMA) += B43_BUSES_BCMA
+config-$(CONFIG_PACKAGE_B43_BUSES_SSB) += B43_BUSES_SSB
+config-$(CONFIG_PACKAGE_B43_PHY_G) += B43_PHY_G
+config-$(CONFIG_PACKAGE_B43_PHY_N) += B43_PHY_N
+config-$(CONFIG_PACKAGE_B43_PHY_LP) += B43_PHY_LP
+config-$(CONFIG_PACKAGE_B43_PHY_HT) += B43_PHY_HT
+config-$(CONFIG_PACKAGE_B43_PIO) += B43_PIO
+config-$(CONFIG_PACKAGE_B43_DEBUG) += B43_DEBUG
+
+config-$(call config_package,b43legacy) += B43LEGACY
+config-y += B43LEGACY_DMA_MODE
+
+config-$(call config_package,brcmutil) += BRCMUTIL
+config-$(call config_package,brcmsmac) += BRCMSMAC
+config-$(call config_package,brcmfmac) += BRCMFMAC
+config-$(CONFIG_BRCMFMAC_SDIO) += BRCMFMAC_SDIO
+config-$(CONFIG_BRCMFMAC_USB) += BRCMFMAC_USB
+config-$(CONFIG_BRCMFMAC_PCIE) += BRCMFMAC_PCIE
+config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG
+
+config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM
+config-$(call config_package,mt7601u) += MT7601U
+config-y += WL_MEDIATEK
+
+config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB
+config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI
+config-$(call config_package,rt2x00-mmio) += RT2X00_LIB_MMIO
+config-$(call config_package,rt2x00-usb) += RT2X00_LIB_USB
+config-$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) += RT2X00_LIB_DEBUGFS
+config-$(CONFIG_PACKAGE_RT2X00_DEBUG) += RT2X00_DEBUG
+
+config-$(call config_package,rt2400-pci) += RT2400PCI
+config-$(call config_package,rt2500-pci) += RT2500PCI
+config-$(call config_package,rt2500-usb) += RT2500USB
+config-$(call config_package,rt61-pci) += RT61PCI
+config-$(call config_package,rt73-usb) += RT73USB
+
+config-$(call config_package,rt2800-lib) += RT2800_LIB
+
+config-$(call config_package,rt2800-soc) += RT2800SOC
+config-$(call config_package,rt2800-pci) += RT2800PCI
+config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290
+
+config-$(call config_package,rt2800-usb) += RT2800USB
+config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX RT2800USB_UNKNOWN
+
+config-$(call config_package,iwl-legacy) += IWLEGACY
+config-$(call config_package,iwl3945) += IWL3945
+config-$(call config_package,iwl4965) += IWL4965
+config-$(call config_package,iwlwifi) += IWLWIFI IWLDVM IWLMVM
+config-$(CONFIG_PACKAGE_IWLWIFI_DEBUG)+= IWLWIFI_DEBUG
+config-$(CONFIG_PACKAGE_IWLWIFI_DEBUGFS)+= IWLWIFI_DEBUGFS
+
+config-$(call config_package,libipw) += LIBIPW
+config-$(call config_package,ipw2100) += IPW2100
+config-$(call config_package,ipw2200) += IPW2200
+
+config-$(call config_package,p54-common) += P54_COMMON
+config-$(call config_package,p54-pci) += P54_PCI
+config-$(call config_package,p54-usb) += P54_USB
+config-$(call config_package,p54-spi) += P54_SPI
+
+config-$(call config_package,hermes) += HERMES
+config-$(call config_package,hermes-pci) += PCI_HERMES
+config-$(call config_package,hermes-plx) += PLX_HERMES
+config-$(call config_package,hermes-pcmcia) += PCMCIA_HERMES
+config-y += HERMES_PRISM
+
+config-$(call config_package,adm8211) += ADM8211
+config-$(call config_package,libertas-sdio) += LIBERTAS LIBERTAS_SDIO
+config-$(call config_package,libertas-usb) += LIBERTAS LIBERTAS_USB
+config-$(call config_package,mwl8k) += MWL8K
+config-$(call config_package,mwifiex-pcie) += MWIFIEX MWIFIEX_PCIE
+config-$(call config_package,rtl8180) += RTL8180
+config-$(call config_package,rtl8187) += RTL8187
+config-$(call config_package,wlcore) += WLCORE WLCORE_SDIO
+config-$(call config_package,wl12xx) += WL12XX
+config-$(call config_package,wl18xx) += WL18XX
+config-y += WL_TI WILINK_PLATFORM_DATA
+config-$(call config_package,zd1211rw) += ZD1211RW
+
+config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI
+config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI
+config-$(call config_package,rtlwifi-usb) += RTLWIFI_USB
+config-$(call config_package,rtl8192c-common) += RTL8192C_COMMON
+config-$(call config_package,rtl8192ce) += RTL8192CE
+config-$(call config_package,rtl8192se) += RTL8192SE
+config-$(call config_package,rtl8192de) += RTL8192DE
+config-$(call config_package,rtl8192cu) += RTL8192CU
+config-$(CONFIG_PACKAGE_RTLWIFI_DEBUG) += RTLWIFI_DEBUG
+
+config-$(CONFIG_LEDS_TRIGGERS) += MAC80211_LEDS B43_LEDS B43LEGACY_LEDS
+
+MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
+ CROSS_COMPILE="$(KERNEL_CROSS)" \
+ ARCH="$(LINUX_KARCH)" \
+ EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include" \
+ KLIB_BUILD="$(LINUX_DIR)" \
+ MODPROBE=true \
+ KLIB=$(TARGET_MODULES_DIR) \
+ KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \
+ KBUILD_LDFLAGS_MODULE_PREREQ=
+
+ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
+ MAKE_OPTS += V=1
+endif
+
+define ConfigVars
+$(subst $(space),,$(foreach opt,$(config-$(1)),CPTCFG_$(opt)=$(1)
+))
+endef
+
+define mac80211_config
+$(call ConfigVars,m)$(call ConfigVars,y)
+endef
+$(eval $(call shexport,mac80211_config))
+
+define Build/Prepare
+ rm -rf $(PKG_BUILD_DIR)
+ mkdir -p $(PKG_BUILD_DIR)
+ $(PKG_UNPACK)
+ $(Build/Patch)
+ $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2100_NAME)-$(IPW2100_VERSION).tgz
+ $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
+ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+ $(TAR) -C $(PKG_BUILD_DIR) -xJf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
+ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_MT7601U_FW_SOURCE)
+ rm -rf \
+ $(PKG_BUILD_DIR)/include/linux/ssb \
+ $(PKG_BUILD_DIR)/include/linux/bcma \
+ $(PKG_BUILD_DIR)/include/net/bluetooth
+
+ rm -f \
+ $(PKG_BUILD_DIR)/include/linux/cordic.h \
+ $(PKG_BUILD_DIR)/include/linux/crc8.h \
+ $(PKG_BUILD_DIR)/include/linux/eeprom_93cx6.h \
+ $(PKG_BUILD_DIR)/include/linux/wl12xx.h \
+ $(PKG_BUILD_DIR)/include/linux/spi/libertas_spi.h \
+ $(PKG_BUILD_DIR)/include/net/ieee80211.h
+
+ echo 'compat-wireless-$(PKG_VERSION)-$(PKG_RELEASE)-$(REVISION)' > $(PKG_BUILD_DIR)/compat_version
+ $(CP) ./files/regdb.txt $(PKG_BUILD_DIR)/net/wireless/db.txt
+endef
+
+ifneq ($(CONFIG_PACKAGE_kmod-cfg80211)$(CONFIG_PACKAGE_kmod-lib80211),)
+ define Build/Compile/kmod
+ rm -rf $(PKG_BUILD_DIR)/modules
+ +$(MAKE) $(PKG_JOBS) $(MAKE_OPTS) modules
+ endef
+endif
+
+define Build/Configure
+ cmp $(PKG_BUILD_DIR)/include/linux/ath9k_platform.h $(LINUX_DIR)/include/linux/ath9k_platform.h
+ cmp $(PKG_BUILD_DIR)/include/linux/ath5k_platform.h $(LINUX_DIR)/include/linux/ath5k_platform.h
+ cmp $(PKG_BUILD_DIR)/include/linux/rt2x00_platform.h $(LINUX_DIR)/include/linux/rt2x00_platform.h
+endef
+
+define Build/Compile
+ $(SH_FUNC) var2file "$(call shvar,mac80211_config)" $(PKG_BUILD_DIR)/.config
+ $(MAKE) $(MAKE_OPTS) allnoconfig
+ $(call Build/Compile/kmod)
+endef
+
+define Build/InstallDev
+ mkdir -p \
+ $(1)/usr/include/mac80211 \
+ $(1)/usr/include/mac80211-backport \
+ $(1)/usr/include/mac80211/ath \
+ $(1)/usr/include/net/mac80211
+ $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/
+ $(CP) $(PKG_BUILD_DIR)/backport-include/* $(1)/usr/include/mac80211-backport/
+ $(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/
+ $(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/
+ rm -f $(1)/usr/include/mac80211-backport/linux/module.h
+endef
+
+
+define KernelPackage/ath9k-htc/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_9271.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/htc_7010.fw \
+ $(1)/lib/firmware/
+endef
+
+define KernelPackage/b43/install
+ rm -rf $(1)/lib/firmware/
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ tar xzf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)"
+else
+ tar xjf "$(DL_DIR)/$(PKG_B43_FWV4_SOURCE)" -C "$(PKG_BUILD_DIR)"
+endif
+ $(INSTALL_DIR) $(1)/lib/firmware/
+ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
+ $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/"
+ $(INSTALL_DIR) $(1)/lib/firmware/b43-open/
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/ucode5.fw $(1)/lib/firmware/b43-open/ucode5.fw
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0bsinitvals5.fw $(1)/lib/firmware/b43-open/b0g0bsinitvals5.fw
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)/b0g0initvals5.fw $(1)/lib/firmware/b43-open/b0g0initvals5.fw
+else
+ b43-fwcutter -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_B43_FWV4_OBJECT)
+endif
+ifneq ($(CONFIG_B43_FW_SQUASH),)
+ b43-fwsquash.py "$(CONFIG_B43_FW_SQUASH_PHYTYPES)" "$(CONFIG_B43_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43"
+endif
+endef
+
+define KernelPackage/b43legacy/install
+ $(INSTALL_DIR) $(1)/lib/firmware/
+ b43-fwcutter --unsupported -w $(1)/lib/firmware/ $(DL_DIR)/$(PKG_B43_FWV3_SOURCE)
+ifneq ($(CONFIG_B43LEGACY_FW_SQUASH),)
+ b43-fwsquash.py "G" "$(CONFIG_B43LEGACY_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43legacy"
+endif
+endef
+
+define KernelPackage/brcmsmac/install
+ $(INSTALL_DIR) $(1)/lib/firmware/brcm
+ifeq ($(CONFIG_BRCMSMAC_USE_FW_FROM_WL),y)
+ tar xjf "$(DL_DIR)/$(PKG_BRCMSMAC_FW_SOURCE)" -C "$(PKG_BUILD_DIR)"
+ b43-fwcutter --brcmsmac -w $(1)/lib/firmware/ $(PKG_BUILD_DIR)/$(PKG_BRCMSMAC_FW_OBJECT)
+else
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx-0.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/bcm43xx_hdr-0.fw \
+ $(1)/lib/firmware/brcm/
+endif
+endef
+
+define KernelPackage/brcmfmac/install
+ $(INSTALL_DIR) $(1)/lib/firmware/brcm
+ifneq ($(CONFIG_BRCMFMAC_USB),)
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/brcmfmac43236b.bin \
+ $(1)/lib/firmware/brcm/
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/brcmfmac43143.bin \
+ $(1)/lib/firmware/brcm/
+endif
+ifneq ($(CONFIG_BRCMFMAC_PCIE),)
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/brcm/brcmfmac43602-pcie.ap.bin \
+ $(1)/lib/firmware/brcm/brcmfmac43602-pcie.bin
+endif
+endef
+
+define KernelPackage/carl9170/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/carl9170-1.fw $(1)/lib/firmware
+endef
+
+define KernelPackage/cfg80211/install
+ $(INSTALL_DIR) $(1)/lib/wifi $(1)/lib/netifd/wireless
+ $(INSTALL_DATA) ./files/lib/wifi/mac80211.sh $(1)/lib/wifi
+ $(INSTALL_BIN) ./files/lib/netifd/wireless/mac80211.sh $(1)/lib/netifd/wireless
+endef
+
+define KernelPackage/ipw2100/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/ipw2100-$(IPW2100_VERSION)*.fw $(1)/lib/firmware
+endef
+
+define KernelPackage/ipw2200/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware
+endef
+
+define KernelPackage/iwlwifi/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ifneq ($(CONFIG_IWL100_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL1000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-1000-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL105_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-105-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL135_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-135-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL2000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2000-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL2030_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-2030-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL3160_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3160-13.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL5000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5000-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL5150_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-5150-2.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000-4.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6005_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2a-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6030_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-6.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL6050_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6050-5.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL7260_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7260-13.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL7265_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7265-13.ucode $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7265D-13.ucode $(1)/lib/firmware
+endif
+ifneq ($(CONFIG_IWL8000_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-8000C-13.ucode $(1)/lib/firmware
+endif
+endef
+
+define KernelPackage/iwl3945/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-3945-2.ucode $(1)/lib/firmware
+endef
+
+define KernelPackage/iwl4965/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-4965-2.ucode $(1)/lib/firmware
+endef
+
+define KernelPackage/libertas-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware/libertas
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8388_v9.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/usb8682.bin \
+ $(1)/lib/firmware/libertas/
+endef
+
+define KernelPackage/libertas-sdio/install
+ $(INSTALL_DIR) $(1)/lib/firmware/libertas
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v9.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688_helper.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688.bin \
+ $(1)/lib/firmware/libertas
+endef
+
+define KernelPackage/mt7601u/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION)/mcu/bin/MT7601.bin \
+ $(1)/lib/firmware/mt7601u.bin
+endef
+
+define KernelPackage/mwl8k/install
+ $(INSTALL_DIR) $(1)/lib/firmware/mwl8k
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366_ap-3.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8366.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8366.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/fmimage_8687.fw \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mwl8k/helper_8687.fw \
+ $(1)/lib/firmware/mwl8k/
+endef
+
+define KernelPackage/mwifiex-pcie/install
+ $(INSTALL_DIR) $(1)/lib/firmware/mrvl
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/mrvl/pcie8897_uapsta.bin \
+ $(1)/lib/firmware/mrvl/
+endef
+
+define KernelPackage/p54-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54PCIFW) $(1)/lib/firmware/isl3886pci
+endef
+
+define KernelPackage/p54-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3887usb
+endef
+
+define KernelPackage/p54-spi/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(DL_DIR)/$(P54SPIFW) $(1)/lib/firmware/3826.arm
+endef
+
+define KernelPackage/rt2800-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2860.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt3290.bin \
+ $(1)/lib/firmware
+endef
+
+define KernelPackage/rt2800-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2870.bin $(1)/lib/firmware/
+endef
+
+define KernelPackage/rt61-pci/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2561s.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt2661.bin \
+ $(1)/lib/firmware/
+endef
+
+define KernelPackage/rt73-usb/install
+ $(INSTALL_DIR) $(1)/lib/firmware
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rt73.bin $(1)/lib/firmware/
+endef
+
+define KernelPackage/wl12xx/install
+ $(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-mr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-plt.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-sr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl1271-nvs.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-mr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-plt.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-sr.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-nvs.bin \
+ $(1)/lib/firmware/ti-connectivity
+endef
+
+define KernelPackage/wl18xx/install
+ $(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-4.bin \
+ $(1)/lib/firmware/ti-connectivity
+endef
+
+define KernelPackage/zd1211rw/install
+ $(INSTALL_DIR) $(1)/lib/firmware/zd1211
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
+endef
+
+
+$(eval $(call KernelPackage,adm8211))
+$(eval $(call KernelPackage,ath))
+$(eval $(call KernelPackage,ath10k))
+$(eval $(call KernelPackage,ath5k))
+$(eval $(call KernelPackage,ath9k))
+$(eval $(call KernelPackage,ath9k-common))
+$(eval $(call KernelPackage,ath9k-htc))
+$(eval $(call KernelPackage,b43))
+$(eval $(call KernelPackage,b43legacy))
+$(eval $(call KernelPackage,brcmsmac))
+$(eval $(call KernelPackage,brcmfmac))
+$(eval $(call KernelPackage,brcmutil))
+$(eval $(call KernelPackage,carl9170))
+$(eval $(call KernelPackage,cfg80211))
+$(eval $(call KernelPackage,hermes))
+$(eval $(call KernelPackage,hermes-pci))
+$(eval $(call KernelPackage,hermes-plx))
+$(eval $(call KernelPackage,hermes-pcmcia))
+$(eval $(call KernelPackage,iwlwifi))
+$(eval $(call KernelPackage,iwl-legacy))
+$(eval $(call KernelPackage,iwl4965))
+$(eval $(call KernelPackage,iwl3945))
+$(eval $(call KernelPackage,lib80211))
+$(eval $(call KernelPackage,libertas-usb))
+$(eval $(call KernelPackage,libertas-sdio))
+$(eval $(call KernelPackage,libipw))
+$(eval $(call KernelPackage,ipw2100))
+$(eval $(call KernelPackage,ipw2200))
+$(eval $(call KernelPackage,mac80211))
+$(eval $(call KernelPackage,mac80211-hwsim))
+$(eval $(call KernelPackage,mt7601u))
+$(eval $(call KernelPackage,mwl8k))
+$(eval $(call KernelPackage,mwifiex-pcie))
+$(eval $(call KernelPackage,p54-common))
+$(eval $(call KernelPackage,p54-pci))
+$(eval $(call KernelPackage,p54-usb))
+$(eval $(call KernelPackage,p54-spi))
+$(eval $(call KernelPackage,rt2x00-lib))
+$(eval $(call KernelPackage,rt2x00-mmio))
+$(eval $(call KernelPackage,rt2x00-pci))
+$(eval $(call KernelPackage,rt2x00-usb))
+$(eval $(call KernelPackage,rt2800-lib))
+$(eval $(call KernelPackage,rt2400-pci))
+$(eval $(call KernelPackage,rt2500-pci))
+$(eval $(call KernelPackage,rt2500-usb))
+$(eval $(call KernelPackage,rt2800-mmio))
+$(eval $(call KernelPackage,rt2800-soc))
+$(eval $(call KernelPackage,rt2800-pci))
+$(eval $(call KernelPackage,rt2800-usb))
+$(eval $(call KernelPackage,rt61-pci))
+$(eval $(call KernelPackage,rt73-usb))
+$(eval $(call KernelPackage,rtl8180))
+$(eval $(call KernelPackage,rtl8187))
+$(eval $(call KernelPackage,rtlwifi))
+$(eval $(call KernelPackage,rtlwifi-pci))
+$(eval $(call KernelPackage,rtlwifi-usb))
+$(eval $(call KernelPackage,rtl8192c-common))
+$(eval $(call KernelPackage,rtl8192ce))
+$(eval $(call KernelPackage,rtl8192se))
+$(eval $(call KernelPackage,rtl8192de))
+$(eval $(call KernelPackage,rtl8192cu))
+$(eval $(call KernelPackage,wlcore))
+$(eval $(call KernelPackage,wl12xx))
+$(eval $(call KernelPackage,wl18xx))
+$(eval $(call KernelPackage,zd1211rw))
diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
new file mode 100644
index 0000000..2a8d2f9
--- /dev/null
+++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
@@ -0,0 +1,748 @@
+#!/bin/sh
+. /lib/netifd/netifd-wireless.sh
+. /lib/netifd/hostapd.sh
+
+init_wireless_driver "$@"
+
+MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh_max_peer_links
+ mesh_max_retries mesh_ttl mesh_element_ttl mesh_hwmp_max_preq_retries
+ mesh_path_refresh_time mesh_min_discovery_timeout mesh_hwmp_active_path_timeout
+ mesh_hwmp_preq_min_interval mesh_hwmp_net_diameter_traversal_time mesh_hwmp_rootmode
+ mesh_hwmp_rann_interval mesh_gate_announcements mesh_sync_offset_max_neighor
+ mesh_rssi_threshold mesh_hwmp_active_path_to_root_timeout mesh_hwmp_root_interval
+ mesh_hwmp_confirmation_interval mesh_awake_window mesh_plink_timeout"
+MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
+MP_CONFIG_STRING="mesh_power_mode"
+
+drv_mac80211_init_device_config() {
+ hostapd_common_add_device_config
+
+ config_add_string path phy 'macaddr:macaddr'
+ config_add_string hwmode
+ config_add_int beacon_int chanbw frag rts
+ config_add_int rxantenna txantenna antenna_gain txpower distance
+ config_add_boolean noscan ht_coex
+ config_add_array ht_capab
+ config_add_boolean \
+ rxldpc \
+ short_gi_80 \
+ short_gi_160 \
+ tx_stbc_2by1 \
+ su_beamformer \
+ su_beamformee \
+ mu_beamformer \
+ mu_beamformee \
+ vht_txop_ps \
+ htc_vht \
+ rx_antenna_pattern \
+ tx_antenna_pattern
+ config_add_int vht_max_a_mpdu_len_exp vht_max_mpdu vht_link_adapt vht160 rx_stbc tx_stbc
+ config_add_boolean \
+ ldpc \
+ greenfield \
+ short_gi_20 \
+ short_gi_40 \
+ max_amsdu \
+ dsss_cck_40
+}
+
+drv_mac80211_init_iface_config() {
+ hostapd_common_add_bss_config
+
+ config_add_string 'macaddr:macaddr' ifname
+
+ config_add_boolean wds powersave
+ config_add_int maxassoc
+ config_add_int max_listen_int
+ config_add_int dtim_period
+ config_add_int start_disabled
+
+ # mesh
+ config_add_string mesh_id
+ config_add_int $MP_CONFIG_INT
+ config_add_boolean $MP_CONFIG_BOOL
+ config_add_string $MP_CONFIG_STRING
+}
+
+mac80211_add_capabilities() {
+ local __var="$1"; shift
+ local __mask="$1"; shift
+ local __out= oifs
+
+ oifs="$IFS"
+ IFS=:
+ for capab in "$@"; do
+ set -- $capab
+
+ [ "$(($4))" -gt 0 ] || continue
+ [ "$(($__mask & $2))" -eq "$((${3:-$2}))" ] || continue
+ __out="$__out[$1]"
+ done
+ IFS="$oifs"
+
+ export -n -- "$__var=$__out"
+}
+
+mac80211_hostapd_setup_base() {
+ local phy="$1"
+
+ json_select config
+
+ [ "$auto_channel" -gt 0 ] && channel=acs_survey
+
+ json_get_vars noscan ht_coex
+ json_get_values ht_capab_list ht_capab
+
+ ieee80211n=1
+ ht_capab=
+ case "$htmode" in
+ VHT20|HT20) ;;
+ HT40*|VHT40|VHT80|VHT160)
+ case "$hwmode" in
+ a)
+ case "$(( ($channel / 4) % 2 ))" in
+ 1) ht_capab="[HT40+]";;
+ 0) ht_capab="[HT40-]";;
+ esac
+ ;;
+ *)
+ case "$htmode" in
+ HT40+) ht_capab="[HT40+]";;
+ HT40-) ht_capab="[HT40-]";;
+ *)
+ if [ "$channel" -lt 7 ]; then
+ ht_capab="[HT40+]"
+ else
+ ht_capab="[HT40-]"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ [ "$auto_channel" -gt 0 ] && ht_capab="[HT40+]"
+ ;;
+ *) ieee80211n= ;;
+ esac
+
+ [ -n "$ieee80211n" ] && {
+ append base_cfg "ieee80211n=1" "$N"
+
+ set_default ht_coex 0
+ append base_cfg "ht_coex=$ht_coex" "$N"
+
+ json_get_vars \
+ ldpc:1 \
+ greenfield:0 \
+ short_gi_20:1 \
+ short_gi_40:1 \
+ tx_stbc:1 \
+ rx_stbc:3 \
+ max_amsdu:1 \
+ dsss_cck_40:1
+
+ ht_cap_mask=0
+ for cap in $(iw phy "$phy" info | grep 'Capabilities:' | cut -d: -f2); do
+ ht_cap_mask="$(($ht_cap_mask | $cap))"
+ done
+
+ cap_rx_stbc=$((($ht_cap_mask >> 8) & 3))
+ [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
+ ht_cap_mask="$(( ($ht_cap_mask & ~(0x300)) | ($cap_rx_stbc << 8) ))"
+
+ mac80211_add_capabilities ht_capab_flags $ht_cap_mask \
+ LDPC:0x1::$ldpc \
+ GF:0x10::$greenfield \
+ SHORT-GI-20:0x20::$short_gi_20 \
+ SHORT-GI-40:0x40::$short_gi_40 \
+ TX-STBC:0x80::$tx_stbc \
+ RX-STBC1:0x300:0x100:1 \
+ RX-STBC12:0x300:0x200:1 \
+ RX-STBC123:0x300:0x300:1 \
+ MAX-AMSDU-7935:0x800::$max_amsdu \
+ DSSS_CCK-40:0x1000::$dsss_cck_40
+
+ ht_capab="$ht_capab$ht_capab_flags"
+ [ -n "$ht_capab" ] && append base_cfg "ht_capab=$ht_capab" "$N"
+ }
+
+ # 802.11ac
+ enable_ac=0
+ idx="$channel"
+ case "$htmode" in
+ VHT20) enable_ac=1;;
+ VHT40)
+ case "$(( ($channel / 4) % 2 ))" in
+ 1) idx=$(($channel + 2));;
+ 0) idx=$(($channel - 2));;
+ esac
+ enable_ac=1
+ append base_cfg "vht_oper_chwidth=0" "$N"
+ append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+ ;;
+ VHT80)
+ case "$(( ($channel / 4) % 4 ))" in
+ 1) idx=$(($channel + 6));;
+ 2) idx=$(($channel + 2));;
+ 3) idx=$(($channel - 2));;
+ 0) idx=$(($channel - 6));;
+ esac
+ enable_ac=1
+ append base_cfg "vht_oper_chwidth=1" "$N"
+ append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+ ;;
+ VHT160)
+ case "$channel" in
+ 36|40|44|48|52|56|60|64) idx=50;;
+ 100|104|108|112|116|120|124|128) idx=114;;
+ esac
+ enable_ac=1
+ append base_cfg "vht_oper_chwidth=2" "$N"
+ append base_cfg "vht_oper_centr_freq_seg0_idx=$idx" "$N"
+ ;;
+ esac
+
+ if [ "$enable_ac" != "0" ]; then
+ json_get_vars \
+ rxldpc:1 \
+ short_gi_80:1 \
+ short_gi_160:1 \
+ tx_stbc_2by1:1 \
+ su_beamformer:1 \
+ su_beamformee:1 \
+ mu_beamformer:1 \
+ mu_beamformee:1 \
+ vht_txop_ps:1 \
+ htc_vht:1 \
+ rx_antenna_pattern:1 \
+ tx_antenna_pattern:1 \
+ vht_max_a_mpdu_len_exp:7 \
+ vht_max_mpdu:11454 \
+ rx_stbc:4 \
+ tx_stbc:4 \
+ vht_link_adapt:3 \
+ vht160:2
+
+ append base_cfg "ieee80211ac=1" "$N"
+ vht_cap=0
+ for cap in $(iw phy "$phy" info | awk -F "[()]" '/VHT Capabilities/ { print $2 }'); do
+ vht_cap="$(($vht_cap | $cap))"
+ done
+
+ cap_rx_stbc=$((($vht_cap >> 8) & 7))
+ [ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
+ ht_cap_mask="$(( ($vht_cap & ~(0x700)) | ($cap_rx_stbc << 8) ))"
+
+ mac80211_add_capabilities vht_capab $vht_cap \
+ RXLDPC:0x10::$rxldpc \
+ SHORT-GI-80:0x20::$short_gi_80 \
+ SHORT-GI-160:0x40::$short_gi_160 \
+ TX-STBC-2BY1:0x80::$tx_stbc \
+ SU-BEAMFORMER:0x800::$su_beamformer \
+ SU-BEAMFORMEE:0x1000::$su_beamformee \
+ MU-BEAMFORMER:0x80000::$mu_beamformer \
+ MU-BEAMFORMEE:0x100000::$mu_beamformee \
+ VHT-TXOP-PS:0x200000::$vht_txop_ps \
+ HTC-VHT:0x400000::$htc_vht \
+ RX-ANTENNA-PATTERN:0x10000000::$rx_antenna_pattern \
+ TX-ANTENNA-PATTERN:0x20000000::$tx_antenna_pattern \
+ RX-STBC1:0x700:0x100:1 \
+ RX-STBC12:0x700:0x200:1 \
+ RX-STBC123:0x700:0x300:1 \
+ RX-STBC1234:0x700:0x400:1 \
+
+ # supported Channel widths
+ vht160_hw=0
+ [ "$(($vht_cap & 12))" -eq 4 -a 1 -le "$vht160" ] && \
+ vht160_hw=1
+ [ "$(($vht_cap & 12))" -eq 8 -a 2 -le "$vht160" ] && \
+ vht160_hw=2
+ [ "$vht160_hw" = 1 ] && vht_capab="$vht_capab[VHT160]"
+ [ "$vht160_hw" = 2 ] && vht_capab="$vht_capab[VHT160-80PLUS80]"
+
+ # maximum MPDU length
+ vht_max_mpdu_hw=3895
+ [ "$(($vht_cap & 3))" -ge 1 -a 7991 -le "$vht_max_mpdu" ] && \
+ vht_max_mpdu_hw=7991
+ [ "$(($vht_cap & 3))" -ge 2 -a 11454 -le "$vht_max_mpdu" ] && \
+ vht_max_mpdu_hw=11454
+ [ "$vht_max_mpdu_hw" != 3895 ] && \
+ vht_capab="$vht_capab[MAX-MPDU-$vht_max_mpdu_hw]"
+
+ # maximum A-MPDU length exponent
+ vht_max_a_mpdu_len_exp_hw=0
+ [ "$(($vht_cap & 58720256))" -ge 8388608 -a 1 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=1
+ [ "$(($vht_cap & 58720256))" -ge 16777216 -a 2 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=2
+ [ "$(($vht_cap & 58720256))" -ge 25165824 -a 3 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=3
+ [ "$(($vht_cap & 58720256))" -ge 33554432 -a 4 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=4
+ [ "$(($vht_cap & 58720256))" -ge 41943040 -a 5 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=5
+ [ "$(($vht_cap & 58720256))" -ge 50331648 -a 6 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=6
+ [ "$(($vht_cap & 58720256))" -ge 58720256 -a 7 -le "$vht_max_a_mpdu_len_exp" ] && \
+ vht_max_a_mpdu_len_exp_hw=7
+ vht_capab="$vht_capab[MAX-A-MPDU-LEN-EXP$vht_max_a_mpdu_len_exp_hw]"
+
+ # whether or not the STA supports link adaptation using VHT variant
+ vht_link_adapt_hw=0
+ [ "$(($vht_cap & 201326592))" -ge 134217728 -a 2 -le "$vht_link_adapt" ] && \
+ vht_link_adapt_hw=2
+ [ "$(($vht_cap & 201326592))" -ge 201326592 -a 3 -le "$vht_link_adapt" ] && \
+ vht_link_adapt_hw=3
+ [ "$vht_link_adapt_hw" != 0 ] && \
+ vht_capab="$vht_capab[VHT-LINK-ADAPT-$vht_link_adapt_hw]"
+
+ [ -n "$vht_capab" ] && append base_cfg "vht_capab=$vht_capab" "$N"
+ fi
+
+ hostapd_prepare_device_config "$hostapd_conf_file" nl80211
+ cat >> "$hostapd_conf_file" <<EOF
+${channel:+channel=$channel}
+${noscan:+noscan=$noscan}
+$base_cfg
+
+EOF
+ json_select ..
+}
+
+mac80211_hostapd_setup_bss() {
+ local phy="$1"
+ local ifname="$2"
+ local macaddr="$3"
+ local type="$4"
+
+ hostapd_cfg=
+ append hostapd_cfg "$type=$ifname" "$N"
+
+ hostapd_set_bss_options hostapd_cfg "$vif" || return 1
+ json_get_vars wds dtim_period max_listen_int start_disabled
+
+ set_default wds 0
+ set_default start_disabled 0
+
+ [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
+ [ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
+
+ cat >> /var/run/hostapd-$phy.conf <<EOF
+$hostapd_cfg
+bssid=$macaddr
+${dtim_period:+dtim_period=$dtim_period}
+${max_listen_int:+max_listen_interval=$max_listen_int}
+EOF
+}
+
+mac80211_get_addr() {
+ local phy="$1"
+ local idx="$(($2 + 1))"
+
+ head -n $(($macidx + 1)) /sys/class/ieee80211/${phy}/addresses | tail -n1
+}
+
+mac80211_generate_mac() {
+ local phy="$1"
+ local id="${macidx:-0}"
+
+ local ref="$(cat /sys/class/ieee80211/${phy}/macaddress)"
+ local mask="$(cat /sys/class/ieee80211/${phy}/address_mask)"
+
+ [ "$mask" = "00:00:00:00:00:00" ] && {
+ mask="ff:ff:ff:ff:ff:ff";
+
+ [ "$(wc -l < /sys/class/ieee80211/${phy}/addresses)" -gt 1 ] && {
+ addr="$(mac80211_get_addr "$phy" "$id")"
+ [ -n "$addr" ] && {
+ echo "$addr"
+ return
+ }
+ }
+ }
+
+ local oIFS="$IFS"; IFS=":"; set -- $mask; IFS="$oIFS"
+
+ local mask1=$1
+ local mask6=$6
+
+ local oIFS="$IFS"; IFS=":"; set -- $ref; IFS="$oIFS"
+
+ macidx=$(($id + 1))
+ [ "$((0x$mask1))" -gt 0 ] && {
+ b1="0x$1"
+ [ "$id" -gt 0 ] && \
+ b1=$(($b1 ^ ((($id - 1) << 2) | 0x2)))
+ printf "%02x:%s:%s:%s:%s:%s" $b1 $2 $3 $4 $5 $6
+ return
+ }
+
+ [ "$((0x$mask6))" -lt 255 ] && {
+ printf "%s:%s:%s:%s:%s:%02x" $1 $2 $3 $4 $5 $(( 0x$6 ^ $id ))
+ return
+ }
+
+ off2=$(( (0x$6 + $id) / 0x100 ))
+ printf "%s:%s:%s:%s:%02x:%02x" \
+ $1 $2 $3 $4 \
+ $(( (0x$5 + $off2) % 0x100 )) \
+ $(( (0x$6 + $id) % 0x100 ))
+}
+
+find_phy() {
+ [ -n "$phy" -a -d /sys/class/ieee80211/$phy ] && return 0
+ [ -n "$path" ] && {
+ for phy in /sys/devices/$path/ieee80211/phy*; do
+ [ -e "$phy" ] && {
+ phy="${phy##*/}"
+ return 0
+ }
+ done
+ }
+ [ -n "$macaddr" ] && {
+ for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
+ grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0
+ done
+ }
+ return 1
+}
+
+mac80211_check_ap() {
+ has_ap=1
+}
+
+mac80211_prepare_vif() {
+ json_select config
+
+ json_get_vars ifname mode ssid wds powersave macaddr
+
+ [ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}"
+ if_idx=$((${if_idx:-0} + 1))
+
+ set_default wds 0
+ set_default powersave 0
+
+ json_select ..
+
+ [ -n "$macaddr" ] || {
+ macaddr="$(mac80211_generate_mac $phy)"
+ macidx="$(($macidx + 1))"
+ }
+
+ json_add_object data
+ json_add_string ifname "$ifname"
+ json_close_object
+ json_select config
+
+ # It is far easier to delete and create the desired interface
+ case "$mode" in
+ adhoc)
+ iw phy "$phy" interface add "$ifname" type adhoc
+ ;;
+ ap)
+ # Hostapd will handle recreating the interface and
+ # subsequent virtual APs belonging to the same PHY
+ if [ -n "$hostapd_ctrl" ]; then
+ type=bss
+ else
+ type=interface
+ fi
+
+ mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
+
+ [ -n "$hostapd_ctrl" ] || {
+ iw phy "$phy" interface add "$ifname" type __ap
+ hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
+ }
+ ;;
+ mesh)
+ json_get_vars key mesh_id
+ if [ -n "$key" ]; then
+ iw phy "$phy" interface add "$ifname" type mp
+ else
+ iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
+ fi
+ ;;
+ monitor)
+ iw phy "$phy" interface add "$ifname" type monitor
+ ;;
+ sta)
+ local wdsflag=
+ staidx="$(($staidx + 1))"
+ [ "$wds" -gt 0 ] && wdsflag="4addr on"
+ iw phy "$phy" interface add "$ifname" type managed $wdsflag
+ [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
+ iw "$ifname" set power_save "$powersave"
+ ;;
+ esac
+
+ case "$mode" in
+ monitor|mesh)
+ [ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $htmode
+ ;;
+ esac
+
+ if [ "$mode" != "ap" ]; then
+ # ALL ap functionality will be passed to hostapd
+ # All interfaces must have unique mac addresses
+ # which can either be explicitly set in the device
+ # section, or automatically generated
+ ip link set dev "$ifname" address "$macaddr"
+ fi
+
+ json_select ..
+}
+
+mac80211_setup_supplicant() {
+ wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
+ wpa_supplicant_add_network "$ifname"
+ wpa_supplicant_run "$ifname" ${hostapd_ctrl:+-H $hostapd_ctrl}
+}
+
+mac80211_setup_adhoc_htmode() {
+ case "$htmode" in
+ VHT20|HT20) ibss_htmode=HT20;;
+ HT40*|VHT40|VHT80|VHT160)
+ case "$hwmode" in
+ a)
+ case "$(( ($channel / 4) % 2 ))" in
+ 1) ibss_htmode="HT40+" ;;
+ 0) ibss_htmode="HT40-";;
+ esac
+ ;;
+ *)
+ case "$htmode" in
+ HT40+) ibss_htmode="HT40+";;
+ HT40-) ibss_htmode="HT40-";;
+ *)
+ if [ "$channel" -lt 7 ]; then
+ ibss_htmode="HT40+"
+ else
+ ibss_htmode="HT40-"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ [ "$auto_channel" -gt 0 ] && ibss_htmode="HT40+"
+ ;;
+ *) ibss_htmode="" ;;
+ esac
+
+}
+
+mac80211_setup_adhoc() {
+ json_get_vars bssid ssid key mcast_rate
+
+ keyspec=
+ [ "$auth_type" = "wep" ] && {
+ set_default key 1
+ case "$key" in
+ [1234])
+ local idx
+ for idx in 1 2 3 4; do
+ json_get_var ikey "key$idx"
+
+ [ -n "$ikey" ] && {
+ ikey="$(($idx - 1)):$(prepare_key_wep "$ikey")"
+ [ $idx -eq $key ] && ikey="d:$ikey"
+ append keyspec "$ikey"
+ }
+ done
+ ;;
+ *)
+ append keyspec "d:0:$(prepare_key_wep "$key")"
+ ;;
+ esac
+ }
+
+ brstr=
+ for br in $basic_rate_list; do
+ wpa_supplicant_add_rate brstr "$br"
+ done
+
+ mcval=
+ [ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
+
+ iw dev "$ifname" ibss join "$ssid" $freq $ibss_htmode fixed-freq $bssid \
+ ${beacon_int:+beacon-interval $beacon_int} \
+ ${brstr:+basic-rates $brstr} \
+ ${mcval:+mcast-rate $mcval} \
+ ${keyspec:+keys $keyspec}
+}
+
+mac80211_setup_vif() {
+ local name="$1"
+ local failed
+
+ json_select data
+ json_get_vars ifname
+ json_select ..
+
+ json_select config
+ json_get_vars mode
+ json_get_var vif_txpower txpower
+
+ ip link set dev "$ifname" up || {
+ wireless_setup_vif_failed IFUP_ERROR
+ json_select ..
+ return
+ }
+
+ set_default vif_txpower "$txpower"
+ [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
+
+ case "$mode" in
+ mesh)
+ # authsae or wpa_supplicant
+ json_get_vars key
+ if [ -n "$key" ]; then
+ if [ -e "/lib/wifi/authsae.sh" ]; then
+ . /lib/wifi/authsae.sh
+ authsae_start_interface || failed=1
+ else
+ wireless_vif_parse_encryption
+ mac80211_setup_supplicant || failed=1
+ fi
+ fi
+
+ for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
+ json_get_var mp_val "$var"
+ [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val"
+ done
+ ;;
+ adhoc)
+ wireless_vif_parse_encryption
+ mac80211_setup_adhoc_htmode
+ if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
+ mac80211_setup_supplicant || failed=1
+ else
+ mac80211_setup_adhoc
+ fi
+ ;;
+ sta)
+ mac80211_setup_supplicant || failed=1
+ ;;
+ esac
+
+ json_select ..
+ [ -n "$failed" ] || wireless_add_vif "$name" "$ifname"
+}
+
+get_freq() {
+ local phy="$1"
+ local chan="$2"
+ iw "$phy" info | grep -E -m1 "(\* ${chan:-....} MHz${chan:+|\\[$chan\\]})" | grep MHz | awk '{print $2}'
+}
+
+mac80211_interface_cleanup() {
+ local phy="$1"
+
+ for wdev in $(list_phy_interfaces "$phy"); do
+ ip link set dev "$wdev" down 2>/dev/null
+ iw dev "$wdev" del
+ done
+}
+
+drv_mac80211_cleanup() {
+ hostapd_common_cleanup
+}
+
+drv_mac80211_setup() {
+ json_select config
+ json_get_vars \
+ phy macaddr path \
+ country chanbw distance \
+ txpower antenna_gain \
+ rxantenna txantenna \
+ frag rts beacon_int htmode
+ json_get_values basic_rate_list basic_rate
+ json_select ..
+
+ find_phy || {
+ echo "Could not find PHY for device '$1'"
+ wireless_set_retry 0
+ return 1
+ }
+
+ wireless_set_data phy="$phy"
+ mac80211_interface_cleanup "$phy"
+
+ # convert channel to frequency
+ [ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel")"
+
+ [ -n "$country" ] && {
+ iw reg get | grep -q "^country $country:" || {
+ iw reg set "$country"
+ sleep 1
+ }
+ }
+
+ hostapd_conf_file="/var/run/hostapd-$phy.conf"
+
+ no_ap=1
+ macidx=0
+ staidx=0
+
+ [ -n "$chanbw" ] && {
+ for file in /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw /sys/kernel/debug/ieee80211/$phy/ath5k/bwmode; do
+ [ -f "$file" ] && echo "$chanbw" > "$file"
+ done
+ }
+
+ set_default rxantenna all
+ set_default txantenna all
+ set_default distance 0
+ set_default antenna_gain 0
+
+ iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
+ iw phy "$phy" set antenna_gain $antenna_gain
+ iw phy "$phy" set distance "$distance"
+
+ [ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
+ [ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
+
+ has_ap=
+ hostapd_ctrl=
+ for_each_interface "ap" mac80211_check_ap
+
+ rm -f "$hostapd_conf_file"
+ [ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
+
+ for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
+ for_each_interface "ap" mac80211_prepare_vif
+
+ [ -n "$hostapd_ctrl" ] && {
+ /usr/sbin/hostapd -P /var/run/wifi-$phy.pid -B "$hostapd_conf_file"
+ ret="$?"
+ wireless_add_process "$(cat /var/run/wifi-$phy.pid)" "/usr/sbin/hostapd" 1
+ [ "$ret" != 0 ] && {
+ wireless_setup_failed HOSTAPD_START_FAILED
+ return
+ }
+ }
+
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
+
+ wireless_set_up
+}
+
+list_phy_interfaces() {
+ local phy="$1"
+ if [ -d "/sys/class/ieee80211/${phy}/device/net" ]; then
+ ls "/sys/class/ieee80211/${phy}/device/net" 2>/dev/null;
+ else
+ ls "/sys/class/ieee80211/${phy}/device" 2>/dev/null | grep net: | sed -e 's,net:,,g'
+ fi
+}
+
+drv_mac80211_teardown() {
+ wireless_process_kill_all
+
+ json_select data
+ json_get_vars phy
+ json_select ..
+
+ mac80211_interface_cleanup "$phy"
+}
+
+add_driver mac80211
diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh
new file mode 100644
index 0000000..ea229d6
--- /dev/null
+++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh
@@ -0,0 +1,131 @@
+#!/bin/sh
+append DRIVERS "mac80211"
+
+lookup_phy() {
+ [ -n "$phy" ] && {
+ [ -d /sys/class/ieee80211/$phy ] && return
+ }
+
+ local devpath
+ config_get devpath "$device" path
+ [ -n "$devpath" ] && {
+ for _phy in /sys/devices/$devpath/ieee80211/phy*; do
+ [ -e "$_phy" ] && {
+ phy="${_phy##*/}"
+ return
+ }
+ done
+ }
+
+ local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
+ [ -n "$macaddr" ] && {
+ for _phy in /sys/class/ieee80211/*; do
+ [ -e "$_phy" ] || continue
+
+ [ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue
+ phy="${_phy##*/}"
+ return
+ done
+ }
+ phy=
+ return
+}
+
+find_mac80211_phy() {
+ local device="$1"
+
+ config_get phy "$device" phy
+ lookup_phy
+ [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
+ echo "PHY for wifi device $1 not found"
+ return 1
+ }
+ config_set "$device" phy "$phy"
+
+ config_get macaddr "$device" macaddr
+ [ -z "$macaddr" ] && {
+ config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
+ }
+
+ return 0
+}
+
+check_mac80211_device() {
+ config_get phy "$1" phy
+ [ -z "$phy" ] && {
+ find_mac80211_phy "$1" >/dev/null || return 0
+ config_get phy "$1" phy
+ }
+ [ "$phy" = "$dev" ] && found=1
+}
+
+detect_mac80211() {
+ devidx=0
+ config_load wireless
+ while :; do
+ config_get type "radio$devidx" type
+ [ -n "$type" ] || break
+ devidx=$(($devidx + 1))
+ done
+
+ for _dev in /sys/class/ieee80211/*; do
+ [ -e "$_dev" ] || continue
+
+ dev="${_dev##*/}"
+
+ found=0
+ config_foreach check_mac80211_device wifi-device
+ [ "$found" -gt 0 ] && continue
+
+ mode_band="g"
+ channel="11"
+ htmode=""
+ ht_capab=""
+
+ iw phy "$dev" info | grep -q 'Capabilities:' && htmode=HT20
+ iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; }
+
+ vht_cap=$(iw phy "$dev" info | grep -c 'VHT Capabilities')
+ cap_5ghz=$(iw phy "$dev" info | grep -c "Band 2")
+ [ "$vht_cap" -gt 0 -a "$cap_5ghz" -gt 0 ] && {
+ mode_band="a";
+ channel="36"
+ htmode="VHT80"
+ }
+
+ [ -n $htmode ] && append ht_capab " option htmode $htmode" "$N"
+
+ if [ -x /usr/bin/readlink -a -h /sys/class/ieee80211/${dev} ]; then
+ path="$(readlink -f /sys/class/ieee80211/${dev}/device)"
+ else
+ path=""
+ fi
+ if [ -n "$path" ]; then
+ path="${path##/sys/devices/}"
+ dev_id=" option path '$path'"
+ else
+ dev_id=" option macaddr $(cat /sys/class/ieee80211/${dev}/macaddress)"
+ fi
+
+ cat <<EOF
+config wifi-device radio$devidx
+ option type mac80211
+ option channel ${channel}
+ option hwmode 11${mode_band}
+$dev_id
+$ht_capab
+ # REMOVE THIS LINE TO ENABLE WIFI:
+ option disabled 1
+
+config wifi-iface
+ option device radio$devidx
+ option network lan
+ option mode ap
+ option ssid OpenWrt
+ option encryption none
+
+EOF
+ devidx=$(($devidx + 1))
+ done
+}
+
diff --git a/package/kernel/mac80211/files/regdb.txt b/package/kernel/mac80211/files/regdb.txt
new file mode 100644
index 0000000..f318326
--- /dev/null
+++ b/package/kernel/mac80211/files/regdb.txt
@@ -0,0 +1,1262 @@
+# This is the world regulatory domain
+country 00:
+ (2402 - 2472 @ 40), (20)
+ # Channel 12 - 13.
+ (2457 - 2482 @ 40), (20), NO-IR
+ # Channel 14. Only JP enables this and for 802.11b only
+ (2474 - 2494 @ 20), (20), NO-IR, NO-OFDM
+ # Channel 36 - 48
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ # Channel 52 - 64
+ (5250 - 5330 @ 80), (20), NO-IR, DFS, AUTO-BW
+ # Channel 100 - 144
+ (5490 - 5730 @ 160), (20), NO-IR, DFS
+ # Channel 149 - 165
+ (5735 - 5835 @ 80), (20), NO-IR
+ # IEEE 802.11ad (60GHz), channels 1..3
+ (57240 - 63720 @ 2160), (0)
+
+
+country AD:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country AE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source:
+# http://pucanguilla.org/Downloads/January2005-Anguilla%20Table%20of%20Allocations.pdf
+country AI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country AL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20.00), AUTO-BW
+ (5250 - 5330 @ 80), (20.00), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27.00), DFS
+
+country AM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (18)
+ (5250 - 5330 @ 20), (18), DFS
+
+country AN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country AR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AS: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country AU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country AZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18), AUTO-BW
+ (5250 - 5330 @ 80), (18), DFS, AUTO-BW
+
+country BA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country BB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country BD: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country BE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country BF: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 5 GHz Short Range Devices, ref:
+ # Etsi EN 300 440-1
+ # Etsi EN 300 440-2
+ # http://crc.bg/files/_bg/Spisak_2015.pdf
+ # http://crc.bg/files/_bg/Pravila_2015_resh24.pdf
+ (5725 - 5875 @ 80), (14)
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country BH: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (20)
+ (5250 - 5330 @ 20), (20), DFS
+ (5735 - 5835 @ 20), (20)
+
+country BL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country BM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BN: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country BO: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5250 - 5330 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BS: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://www.bicma.gov.bt/paper/publication/nrrpart4.pdf
+country BT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country BY: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country BZ: DFS-JP
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5835 @ 80), (30)
+
+country CA: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5600 @ 80), (24), DFS
+ (5650 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://www.art-rca.org
+country CF: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (17)
+ (5250 - 5330 @ 40), (24), DFS
+ (5490 - 5730 @ 40), (24), DFS
+ (5735 - 5835 @ 40), (30)
+
+country CH: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country CI: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CL: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country CN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+ # 60 GHz band channels 1,4: 28dBm, channels 2,3: 44dBm
+ # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf
+ (57240 - 59400 @ 2160), (28)
+ (59400 - 63720 @ 2160), (44)
+ (63720 - 65880 @ 2160), (28)
+
+country CO: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (17)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country CX: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CY: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
+# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
+# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
+# implemented.
+country CZ: DFS-ETSI
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW
+ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW
+ (5470 - 5725 @ 160), (500 mW), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
+# For the 5GHz range also see
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
+# The values have been reduced by a factor of 2 (3db) for non TPC devices
+# (in other words: devices with TPC can use twice the tx power of this table).
+# Note that the docs do not require TPC for 5150--5250; the reduction to
+# 100mW thus is not strictly required -- however the conservative 100mW
+# limit is used here as the non-interference with radar and satellite
+# apps relies on the attenuation by the building walls only in the
+# absence of DFS; the neighbour countries have 100mW limit here as well.
+
+country DE: DFS-ETSI
+ # entries 279004 and 280006
+ (2400 - 2483.5 @ 40), (100 mW)
+ # entry 303005
+ (5150 - 5250 @ 80), (100 mW), NO-OUTDOOR, AUTO-BW
+ # entries 304002 and 305002
+ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW
+ # entries 308002, 309001 and 310003
+ (5470 - 5725 @ 160), (500 mW), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country DK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+# Source:
+# http://www.ntrcdom.org/index.php?option=com_content&view=category&layout=blog&id=10&Itemid=55
+country DM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country DO: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country DZ: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170.000 - 5250.000 @ 80.000), (23.00), AUTO-BW
+ (5250.000 - 5330.000 @ 80.000), (23.00), DFS, AUTO-BW
+ (5490.000 - 5670.000 @ 160.000), (23.00), DFS
+
+country EC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (17)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country EE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country EG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (20)
+ (5250 - 5330 @ 40), (20), DFS
+
+# Orden IET/787/2013, de 25 de abril, por la que se aprueba
+# el cuadro nacional de atribución de frecuencias.
+# http://www.boe.es/diario_boe/txt.php?id=BOE-A-2013-4845
+#
+# more info at "Cuadro nacional de atribución de frecuencias (CNAF)":
+# http://www.minetur.gob.es/telecomunicaciones/espectro/paginas/cnaf.aspx
+
+country ES: DFS-ETSI
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW
+ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW
+ (5470 - 5725 @ 160), (500 mW), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country ET: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country FI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country FM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country FR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country GB: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country GD: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18), AUTO-BW
+ (5250 - 5330 @ 80), (18), DFS, AUTO-BW
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country GF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country GH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country GP: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country GR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country GT: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country GU: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 20), (17)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country GY:
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5835 @ 80), (30)
+
+country HK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HR: DFS-ETSI
+ (2400 - 2483.5 @ 40), (20)
+ (5150 - 5250 @ 80), (23), NO-OUTDOOR, AUTO-BW
+ (5250 - 5350 @ 80), (20), NO-OUTDOOR, DFS, AUTO-BW
+ (5470 - 5725 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country HT: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country ID: DFS-JP
+ # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
+ (2402 - 2482 @ 20), (20)
+ (5735 - 5815 @ 20), (23)
+
+country IE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country IL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW
+ (5250 - 5350 @ 80), (200 mW), NO-OUTDOOR, DFS, AUTO-BW
+
+country IN: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country IR: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country IS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country IT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country JM: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country JO: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5735 - 5835 @ 80), (23)
+
+country JP: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (2474 - 2494 @ 20), (20), NO-OFDM
+ (4910 - 4990 @ 40), (23)
+ (5030 - 5090 @ 40), (23)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (23), DFS
+ # 60 GHz band channels 2-4 at 10mW,
+ # ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf
+ (59000 - 66000 @ 2160), (10 mW)
+
+country KE: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5490 - 5570 @ 80), (30), DFS
+ (5735 - 5775 @ 40), (23)
+
+country KH: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source
+# http://ntrc.kn/?page_id=7
+country KN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country KP: DFS-JP
+ (2402 - 2482 @ 20), (20)
+ (5170 - 5250 @ 20), (20)
+ (5250 - 5330 @ 20), (20), DFS
+ (5490 - 5630 @ 20), (30), DFS
+ (5735 - 5815 @ 20), (30)
+
+country KR: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country KW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+
+country KY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country KZ:
+ (2402 - 2482 @ 40), (20)
+
+country LB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://www.ntrc.org.lc/operational_structures.htm
+country LC: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country LI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country LK: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (17)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+# Source:
+# http://lca.org.ls/images/documents/lesotho_national_frequency_allocation_plan.pdf
+country LS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country LT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country LU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country LV: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country MA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+
+country MC: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source:
+# http://www.cnfr.md/index.php?pag=sec&id=117&l=en
+country MD: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source:
+# http://www.cept.org/files/1050/Tools%20and%20Services/EFIS%20-%20ECO%20Frequency%20Information%20System/National%20frequency%20tables/Montenegro%20NAFT%20-%202010.pdf
+country ME: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country MF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country MH: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country MN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MO: DFS-FCC
+ (2402 - 2482 @ 40), (23)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MP: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MQ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source:
+# http://www.are.mr/pdfs/telec_freq_TNAbf_2010.pdf
+country MR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country MT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country MU: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://www.cam.gov.mv/docs/tech_standards/TAM-TS-100-2004-WLAN.pdf
+country MV: DFS-ETSI
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (200 mW), AUTO-BW
+ (5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW
+ (5725 - 5850 @ 80), (100 mW)
+
+country MW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country MX: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5650 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (24)
+
+country NG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5250 - 5330 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country NI: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country NL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), NO-OUTDOOR, AUTO-BW
+ (5250 - 5330 @ 80), (20), NO-OUTDOOR, DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+# Data from http://www.lovdata.no/dokument/SF/forskrift/2012-01-19-77
+# Power at 5250 - 5350 MHz, 5470 - 5725 MHz and 5815 – 5850 MHz can
+# be doubled if TPC is implemented.
+# Up to 2W (or 4W with TPC) is allowed in the 5725 – 5795 MHz band
+# which has been merged with 5470 - 5725 MHz to allow wide channels
+country NO: DFS-ETSI
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (200 mW), AUTO-BW
+ (5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW
+ (5470 - 5795 @ 160), (500 mW), DFS
+ (5815 - 5850 @ 35), (2000 mW), DFS
+ (17100 - 17300 @ 200), (100 mW)
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country NP: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country NZ: DFS-ETSI
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country OM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country PA: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country PE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country PG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PK: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country PL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country PM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country PR: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country PW: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country QA: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country RE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country RO: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+
+# Source:
+# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
+country RS: DFS-ETSI
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5350 @ 40), (200 mW), NO-OUTDOOR
+ (5470 - 5725 @ 20), (1000 mW), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country RU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5650 - 5730 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+ # 60 GHz band channels 1-4, ref: Changes to NLA 124_Order â„–129_22042015.pdf
+ (57000 - 66000 @ 2160), (40)
+
+country RW: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country SE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country SG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country SK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+# Source:
+# Regulation N° 2004-005 ART/DG/DRC/D.Rég
+country SN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country SV: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (17)
+ (5250 - 5330 @ 20), (23), DFS
+ (5735 - 5835 @ 20), (30)
+
+country SY:
+ (2402 - 2482 @ 40), (20)
+
+# Source:
+# http://www.telecommission.tc/Spectrum-plan20110324-101210.html
+country TC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TD: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country TG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (20)
+ (5250 - 5330 @ 40), (20), DFS
+ (5490 - 5710 @ 40), (27), DFS
+
+country TH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+
+country TR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country TT: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# Table of Frequency Allocations of Republic of China (Taiwan) / Nov 2014:
+# http://www.motc.gov.tw/websitedowndoc?file=post/201411171137330.doc& \
+# filedisplay=Table+of+radio+frequency+allocation.doc
+# LP0002 Low-power Radio-frequency Devices Technical Regulations / 28 Jun 2011:
+# http://www.ncc.gov.tw/english/show_file.aspx?table_name=news&file_sn=681
+# (section 3.10.1, 4.7)
+country TW: DFS-FCC
+ (2400 - 2483.5 @ 40), (30)
+ # Follow US 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients
+ (5150 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5350 @ 80), (23), DFS, AUTO-BW
+ (5470 - 5725 @ 160), (23), DFS
+ (5725 - 5850 @ 80), (30)
+
+country TZ:
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
+# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
+# (appendix 8)
+# Listed 5GHz range is a lowest common denominator for all related
+# rules in the referenced laws. Such a range is used because of
+# disputable definitions there.
+country UA: DFS-ETSI
+ (2400 - 2483.5 @ 40), (20), NO-OUTDOOR
+ (5150 - 5250 @ 80), (20), NO-OUTDOOR, AUTO-BW
+ (5250 - 5350 @ 80), (20), DFS, NO-OUTDOOR, AUTO-BW
+ (5490 - 5670 @ 160), (20), DFS
+ (5735 - 5835 @ 80), (20)
+ # 60 GHz band channels 1-4, ref: Etsi En 302 567
+ (57000 - 66000 @ 2160), (40)
+
+country UG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country US: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ # 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (23), DFS
+ (5735 - 5835 @ 80), (30)
+ # 60g band
+ # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
+ # channels 1,2,3, EIRP=40dBm(43dBm peak)
+ (57240 - 63720 @ 2160), (40)
+
+country UY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://cemc.uz/article/1976/
+country UZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+
+# Source:
+# http://www.ntrc.vc/regulations/Jun_2006_Spectrum_Managment_Regulations.pdf
+country VC: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+# Source:
+# Official Gazette (Gaceta Oficial) concerning Unlicensed transmitter use
+# (10 June 2013)
+# http://www.conatel.gob.ve/
+country VE: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country VI: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country VN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# http://www.trr.vu/attachments/category/130/GURL_for_Short-range_Radiocommunication_Devices2.pdf
+country VU: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country WF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country WS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (20)
+ (5250 - 5330 @ 40), (20), DFS
+ (5490 - 5710 @ 40), (27), DFS
+
+country YE:
+ (2402 - 2482 @ 40), (20)
+
+country YT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
+country ZA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30)
+
+country ZW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (27), DFS
+
diff --git a/package/kernel/mac80211/patches/000-fix_kconfig.patch b/package/kernel/mac80211/patches/000-fix_kconfig.patch
new file mode 100644
index 0000000..3987aae
--- /dev/null
+++ b/package/kernel/mac80211/patches/000-fix_kconfig.patch
@@ -0,0 +1,14 @@
+--- a/kconf/Makefile
++++ b/kconf/Makefile
+@@ -1,9 +1,9 @@
+-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
+
+ LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
+
+ conf: conf.o zconf.tab.o
+-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
+ mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
+ mconf: CFLAGS += $(mconf_CFLAGS)
+
diff --git a/package/kernel/mac80211/patches/001-fix_build.patch b/package/kernel/mac80211/patches/001-fix_build.patch
new file mode 100644
index 0000000..402649d
--- /dev/null
+++ b/package/kernel/mac80211/patches/001-fix_build.patch
@@ -0,0 +1,167 @@
+--- a/Makefile
++++ b/Makefile
+@@ -5,7 +5,7 @@
+ ifeq ($(KERNELRELEASE),)
+
+ MAKEFLAGS += --no-print-directory
+-SHELL := /bin/bash
++SHELL := /usr/bin/env bash
+ BACKPORT_DIR := $(shell pwd)
+
+ KMODDIR ?= updates
+@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
+ KERNEL_CONFIG := $(KLIB_BUILD)/.config
+ KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
+ CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
+
+ export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
+
+@@ -36,7 +37,8 @@ mrproper:
+ @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
+ @rm -f backport-include/backport/autoconf.h
+
+-.DEFAULT:
++.SILENT: $(STAMP_KERNEL_CONFIG)
++$(STAMP_KERNEL_CONFIG):
+ @set -e ; test -f .local-symbols || ( \
+ echo "/--------------" ;\
+ echo "| You shouldn't run make in the backports tree, but only in" ;\
+@@ -60,57 +62,61 @@ mrproper:
+ echo "| (that isn't currently running.)" ;\
+ echo "\\--" ;\
+ false)
+- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
+- then \
+- echo -n "Generating local configuration database from kernel ..." ;\
+- grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \
+- while read l ; do \
+- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
+- continue ;\
+- fi ;\
+- l=$${l:7} ;\
+- n=$${l%%=*} ;\
+- v=$${l#*=} ;\
+- if [ "$$v" = "m" ] ; then \
+- echo config $$n ;\
+- echo ' tristate' ;\
+- elif [ "$$v" = "y" ] ; then \
+- echo config $$n ;\
+- echo ' bool' ;\
+- else \
+- continue ;\
+- fi ;\
+- echo " default $$v" ;\
+- echo "" ;\
+- done \
+- ) > Kconfig.kernel ;\
+- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
+- sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
+- test "$$kver" != "" || echo "Kernel version parse failed!" ;\
+- test "$$kver" != "" ;\
+- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
+- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
+- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
+- print=0 ;\
+- for v in $$kvers ; do \
+- if [ "$$print" = "1" ] ; then \
+- echo config KERNEL_$$(echo $$v | tr . _) ;\
+- echo " def_bool y" ;\
+- fi ;\
+- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
+- done > Kconfig.versions ;\
+- # RHEL as well, sadly we need to grep for it ;\
+- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- for v in $$(seq 0 $$RHEL_MINOR) ; do \
+- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
+- echo " def_bool y" ;\
+- done >> Kconfig.versions ;\
+- echo " done." ;\
+- fi ;\
+- echo "$(CONFIG_MD5)" > .kernel_config_md5
++ @rm -f .kernel_config_md5_*
++ @touch $@
++
++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) .local-symbols
++ @printf "Generating local configuration database from kernel ..."
++ @grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \
++ while read l ; do \
++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
++ continue ;\
++ fi ;\
++ l=$${l:7} ;\
++ n=$${l%%=*} ;\
++ v=$${l#*=} ;\
++ if [ "$$v" = "m" ] ; then \
++ echo config $$n ;\
++ echo ' tristate' ;\
++ elif [ "$$v" = "y" ] ; then \
++ echo config $$n ;\
++ echo ' bool' ;\
++ else \
++ continue ;\
++ fi ;\
++ echo " default $$v" ;\
++ echo "" ;\
++ done \
++ ) > $@
++ @echo " done."
++
++Kconfig.versions: Kconfig.kernel
++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
++ sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\
++ test "$$kver" != "" || echo "Kernel version parse failed!" ;\
++ test "$$kver" != "" ;\
++ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\
++ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\
++ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
++ print=0 ;\
++ for v in $$kvers ; do \
++ if [ "$$print" = "1" ] ; then \
++ echo config KERNEL_$$(echo $$v | tr . _) ;\
++ echo " def_bool y" ;\
++ fi ;\
++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
++ done > $@
++ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ for v in $$(seq 0 $$RHEL_MINOR) ; do \
++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
++ echo " def_bool y" ;\
++ done >> $@
++
++.DEFAULT:
++ @$(MAKE) Kconfig.versions
+ @$(MAKE) -f Makefile.real "$@"
+
+ .PHONY: defconfig-help
+--- a/Makefile.real
++++ b/Makefile.real
+@@ -59,7 +59,7 @@ defconfig-%::
+
+ backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
+ @$(MAKE) oldconfig
+- @echo -n "Building backport-include/backport/autoconf.h ..."
++ @printf "Building backport-include/backport/autoconf.h ..."
+ @grep -f .local-symbols .config | ( \
+ echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
+ echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
+@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
+ esac ;\
+ done ;\
+ echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
+- ) > backport-include/backport/autoconf.h
++ ) > $@.new
++ @if cmp -s $@ $@.new; then \
++ rm -f $@.new; \
++ else \
++ mv $@.new $@; \
++ fi
+ @echo " done."
+
+ .PHONY: modules
diff --git a/package/kernel/mac80211/patches/002-change_allconfig.patch b/package/kernel/mac80211/patches/002-change_allconfig.patch
new file mode 100644
index 0000000..bd5bebf
--- /dev/null
+++ b/package/kernel/mac80211/patches/002-change_allconfig.patch
@@ -0,0 +1,64 @@
+--- a/kconf/conf.c
++++ b/kconf/conf.c
+@@ -593,40 +593,12 @@ int main(int ac, char **av)
+ case oldconfig:
+ case listnewconfig:
+ case olddefconfig:
+- conf_read(NULL);
+- break;
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
+- name = getenv("KCONFIG_ALLCONFIG");
+- if (!name)
+- break;
+- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
+- if (conf_read_simple(name, S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** Can't read seed configuration \"%s\"!\n"),
+- name);
+- exit(1);
+- }
+- break;
+- }
+- switch (input_mode) {
+- case allnoconfig: name = "allno.config"; break;
+- case allyesconfig: name = "allyes.config"; break;
+- case allmodconfig: name = "allmod.config"; break;
+- case alldefconfig: name = "alldef.config"; break;
+- case randconfig: name = "allrandom.config"; break;
+- default: break;
+- }
+- if (conf_read_simple(name, S_DEF_USER) &&
+- conf_read_simple("all.config", S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
+- name);
+- exit(1);
+- }
++ conf_read(NULL);
+ break;
+ default:
+ break;
+--- a/kconf/confdata.c
++++ b/kconf/confdata.c
+@@ -1169,6 +1169,8 @@ bool conf_set_all_new_symbols(enum conf_
+ }
+ bool has_changed = false;
+
++ sym_clear_all_valid();
++
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
+ continue;
+@@ -1212,8 +1214,6 @@ bool conf_set_all_new_symbols(enum conf_
+
+ }
+
+- sym_clear_all_valid();
+-
+ /*
+ * We have different type of choice blocks.
+ * If curr.tri equals to mod then we can select several
diff --git a/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch b/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch
new file mode 100644
index 0000000..8fa465a
--- /dev/null
+++ b/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch
@@ -0,0 +1,34 @@
+--- a/compat/main.c
++++ b/compat/main.c
+@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
+ #error "You need a CPTCFG_VERSION"
+ #endif
+
+-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
+-
+-module_param(backported_kernel_name, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_name,
+- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
+-
+-#ifdef BACKPORTS_GIT_TRACKED
+-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
+-module_param(backports_tracker_id, charp, 0400);
+-MODULE_PARM_DESC(backports_tracker_id,
+- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
+-#else
+-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
+-static char *backports_version = CPTCFG_VERSION;
+-
+-module_param(backported_kernel_version, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_version,
+- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
+-
+-module_param(backports_version, charp, 0400);
+-MODULE_PARM_DESC(backports_version,
+- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
+-
+-#endif
+-
+ void backport_dependency_symbol(void)
+ {
+ }
diff --git a/package/kernel/mac80211/patches/010-disable_rfkill.patch b/package/kernel/mac80211/patches/010-disable_rfkill.patch
new file mode 100644
index 0000000..c5a92d6
--- /dev/null
+++ b/package/kernel/mac80211/patches/010-disable_rfkill.patch
@@ -0,0 +1,13 @@
+--- a/backport-include/linux/rfkill.h
++++ b/backport-include/linux/rfkill.h
+@@ -2,6 +2,10 @@
+ #define __COMPAT_RFKILL_H
+ #include <linux/version.h>
+
++#undef CONFIG_RFKILL
++#undef CONFIG_RFKILL_LEDS
++#undef CONFIG_RFKILL_MODULE
++
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+ #include_next <linux/rfkill.h>
+ #else
diff --git a/package/kernel/mac80211/patches/030-rt2x00_options.patch b/package/kernel/mac80211/patches/030-rt2x00_options.patch
new file mode 100644
index 0000000..a25aeb2
--- /dev/null
+++ b/package/kernel/mac80211/patches/030-rt2x00_options.patch
@@ -0,0 +1,47 @@
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -225,36 +225,37 @@ config RT2800SOC
+
+
+ config RT2800_LIB
+- tristate
++ tristate "RT2800 USB/PCI support"
+ depends on m
+
+ config RT2800_LIB_MMIO
+- tristate
++ tristate "RT2800 MMIO support"
+ depends on m
+ select RT2X00_LIB_MMIO
+ select RT2800_LIB
+
+ config RT2X00_LIB_MMIO
+- tristate
++ tristate "RT2x00 MMIO support"
+ depends on m
+
+ config RT2X00_LIB_PCI
+- tristate
++ tristate "RT2x00 PCI support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_SOC
+- tristate
++ tristate "RT2x00 SoC support"
++ depends on SOC_RT288X || SOC_RT305X
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_USB
+- tristate
++ tristate "RT2x00 USB support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB
+- tristate
++ tristate "RT2x00 support"
+ depends on m
+
+ config RT2X00_LIB_FIRMWARE
diff --git a/package/kernel/mac80211/patches/040-brcmutil_option.patch b/package/kernel/mac80211/patches/040-brcmutil_option.patch
new file mode 100644
index 0000000..8a6cae6
--- /dev/null
+++ b/package/kernel/mac80211/patches/040-brcmutil_option.patch
@@ -0,0 +1,9 @@
+--- a/drivers/net/wireless/brcm80211/Kconfig
++++ b/drivers/net/wireless/brcm80211/Kconfig
+@@ -1,5 +1,5 @@
+ config BRCMUTIL
+- tristate
++ tristate "Broadcom 802.11 driver utility functions"
+ depends on m
+
+ config BRCMSMAC
diff --git a/package/kernel/mac80211/patches/050-lib80211_option.patch b/package/kernel/mac80211/patches/050-lib80211_option.patch
new file mode 100644
index 0000000..50d3df8
--- /dev/null
+++ b/package/kernel/mac80211/patches/050-lib80211_option.patch
@@ -0,0 +1,30 @@
+--- a/net/wireless/Kconfig
++++ b/net/wireless/Kconfig
+@@ -184,7 +184,7 @@ config CFG80211_WEXT_EXPORT
+ wext compatibility symbols to be exported.
+
+ config LIB80211
+- tristate
++ tristate "lib80211"
+ depends on m
+ default n
+ help
+@@ -194,15 +194,15 @@ config LIB80211
+ Drivers should select this themselves if needed.
+
+ config LIB80211_CRYPT_WEP
+- tristate
++ tristate "lib80211 WEP support"
+ depends on m
+
+ config LIB80211_CRYPT_CCMP
+- tristate
++ tristate "lib80211 CCMP support"
+ depends on m
+
+ config LIB80211_CRYPT_TKIP
+- tristate
++ tristate "lib80211 TKIP support"
+ depends on m
+
+ config LIB80211_DEBUG
diff --git a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
new file mode 100644
index 0000000..69c9e01
--- /dev/null
+++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch
@@ -0,0 +1,130 @@
+--- a/.local-symbols
++++ b/.local-symbols
+@@ -454,43 +454,6 @@ USB_IPHETH=
+ USB_SIERRA_NET=
+ USB_VL600=
+ USB_NET_CH9200=
+-SSB_POSSIBLE=
+-SSB=
+-SSB_SPROM=
+-SSB_BLOCKIO=
+-SSB_PCIHOST_POSSIBLE=
+-SSB_PCIHOST=
+-SSB_B43_PCI_BRIDGE=
+-SSB_PCMCIAHOST_POSSIBLE=
+-SSB_PCMCIAHOST=
+-SSB_SDIOHOST_POSSIBLE=
+-SSB_SDIOHOST=
+-SSB_SILENT=
+-SSB_DEBUG=
+-SSB_SERIAL=
+-SSB_DRIVER_PCICORE_POSSIBLE=
+-SSB_DRIVER_PCICORE=
+-SSB_PCICORE_HOSTMODE=
+-SSB_DRIVER_MIPS=
+-SSB_SFLASH=
+-SSB_EMBEDDED=
+-SSB_DRIVER_EXTIF=
+-SSB_DRIVER_GIGE=
+-SSB_DRIVER_GPIO=
+-BCMA_POSSIBLE=
+-BCMA=
+-BCMA_BLOCKIO=
+-BCMA_HOST_PCI_POSSIBLE=
+-BCMA_HOST_PCI=
+-BCMA_HOST_SOC=
+-BCMA_DRIVER_PCI=
+-BCMA_DRIVER_PCI_HOSTMODE=
+-BCMA_DRIVER_MIPS=
+-BCMA_SFLASH=
+-BCMA_NFLASH=
+-BCMA_DRIVER_GMAC_CMN=
+-BCMA_DRIVER_GPIO=
+-BCMA_DEBUG=
+ NFC=
+ NFC_DIGITAL=
+ NFC_NCI=
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -2867,7 +2867,7 @@ static struct ssb_device *b43_ssb_gpio_d
+ {
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+ #else
+ return bus->chipco.dev;
+@@ -4904,7 +4904,7 @@ static int b43_wireless_core_init(struct
+ }
+ if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
+ hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
+-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
+--- a/drivers/net/wireless/b43legacy/main.c
++++ b/drivers/net/wireless/b43legacy/main.c
+@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4
+ if (dev->dev->id.revision >= 2)
+ mask |= 0x0010; /* FIXME: This is redundant. */
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc
+ struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_device *gpiodev, *pcidev = NULL;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
++++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+@@ -43,6 +43,6 @@ brcmsmac-y := \
+ brcms_trace_events.o \
+ debug.o
+
+-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
++brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
+
+ obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
+--- a/drivers/net/wireless/brcm80211/brcmsmac/led.h
++++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h
+@@ -22,7 +22,7 @@ struct brcms_led {
+ bool active_low;
+ };
+
+-#ifdef CPTCFG_BCMA_DRIVER_GPIO
++#ifdef CONFIG_BCMA_DRIVER_GPIO
+ void brcms_led_unregister(struct brcms_info *wl);
+ int brcms_led_register(struct brcms_info *wl);
+ #else
+--- a/Kconfig.sources
++++ b/Kconfig.sources
+@@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele
+ source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
+ source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
+
+-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
+-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
+-
+ source "$BACKPORT_DIR/net/nfc/Kconfig"
+
+ source "$BACKPORT_DIR/drivers/media/Kconfig"
+--- a/Makefile.kernel
++++ b/Makefile.kernel
+@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
+ #obj-$(CPTCFG_WLAN += drivers/net/wireless/
+ obj-$(CPTCFG_BT) += net/bluetooth/
+ obj-$(CPTCFG_BT) += drivers/bluetooth/
+-obj-$(CPTCFG_SSB) += drivers/ssb/
+-obj-$(CPTCFG_BCMA) += drivers/bcma/
+ obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
+ obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
+ obj-$(CPTCFG_NFC) += net/nfc/
diff --git a/package/kernel/mac80211/patches/070-ath_common_config.patch b/package/kernel/mac80211/patches/070-ath_common_config.patch
new file mode 100644
index 0000000..c6e9cd8
--- /dev/null
+++ b/package/kernel/mac80211/patches/070-ath_common_config.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/ath/Kconfig
++++ b/drivers/net/wireless/ath/Kconfig
+@@ -6,6 +6,7 @@ menuconfig ATH_CARDS
+ tristate "Atheros Wireless Cards"
+ depends on m
+ depends on CFG80211 && (!UML || BROKEN)
++ select ATH_COMMON
+ ---help---
+ This will enable the support for the Atheros wireless drivers.
+ ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option
diff --git a/package/kernel/mac80211/patches/080-disable_clk_backport.patch b/package/kernel/mac80211/patches/080-disable_clk_backport.patch
new file mode 100644
index 0000000..3765591
--- /dev/null
+++ b/package/kernel/mac80211/patches/080-disable_clk_backport.patch
@@ -0,0 +1,20 @@
+--- a/compat/compat-3.6.c
++++ b/compat/compat-3.6.c
+@@ -147,17 +147,3 @@ int sg_alloc_table_from_pages(struct sg_
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(sg_alloc_table_from_pages);
+-
+-/* whoopsie ! */
+-#ifndef CONFIG_COMMON_CLK
+-int clk_enable(struct clk *clk)
+-{
+- return 0;
+-}
+-EXPORT_SYMBOL_GPL(clk_enable);
+-
+-void clk_disable(struct clk *clk)
+-{
+-}
+-EXPORT_SYMBOL_GPL(clk_disable);
+-#endif
diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
new file mode 100644
index 0000000..02f46c7
--- /dev/null
+++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch
@@ -0,0 +1,376 @@
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -5,8 +5,6 @@ config MAC80211
+ depends on CRYPTO
+ depends on CRYPTO_ARC4
+ depends on CRYPTO_AES
+- select BPAUTO_CRYPTO_CCM
+- depends on CRYPTO_GCM
+ depends on CRC32
+ ---help---
+ This option enables the hardware independent IEEE 802.11
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -16,9 +16,7 @@ mac80211-y := \
+ michael.o \
+ tkip.o \
+ aes_ccm.o \
+- aes_gcm.o \
+ aes_cmac.o \
+- aes_gmac.o \
+ cfg.o \
+ ethtool.o \
+ rx.o \
+--- a/net/mac80211/aes_ccm.c
++++ b/net/mac80211/aes_ccm.c
+@@ -13,89 +13,132 @@
+ #include <linux/types.h>
+ #include <linux/err.h>
+ #include <crypto/aead.h>
++#include <crypto/aes.h>
+
+ #include <net/mac80211.h>
+ #include "key.h"
+ #include "aes_ccm.h"
+
+-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+- u8 *data, size_t data_len, u8 *mic,
+- size_t mic_len)
++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
++ u8 *a, u8 *b)
+ {
+- struct scatterlist sg[3];
++ int i;
++
++ crypto_cipher_encrypt_one(tfm, b, b_0);
++
++ /* Extra Authenticate-only data (always two AES blocks) */
++ for (i = 0; i < AES_BLOCK_SIZE; i++)
++ aad[i] ^= b[i];
++ crypto_cipher_encrypt_one(tfm, b, aad);
++
++ aad += AES_BLOCK_SIZE;
++
++ for (i = 0; i < AES_BLOCK_SIZE; i++)
++ aad[i] ^= b[i];
++ crypto_cipher_encrypt_one(tfm, a, aad);
+
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
++ /* Mask out bits from auth-only-b_0 */
++ b_0[0] &= 0x07;
+
+- memset(aead_req, 0, sizeof(aead_req_data));
++ /* S_0 is used to encrypt T (= MIC) */
++ b_0[14] = 0;
++ b_0[15] = 0;
++ crypto_cipher_encrypt_one(tfm, s_0, b_0);
++}
+
+- sg_init_table(sg, 3);
+- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+- sg_set_buf(&sg[1], data, data_len);
+- sg_set_buf(&sg[2], mic, mic_len);
+
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0);
+- aead_request_set_ad(aead_req, sg[0].length);
++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic,
++ size_t mic_len)
++{
++ int i, j, last_len, num_blocks;
++ u8 b[AES_BLOCK_SIZE];
++ u8 s_0[AES_BLOCK_SIZE];
++ u8 e[AES_BLOCK_SIZE];
++ u8 *pos, *cpos;
++
++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
++ last_len = data_len % AES_BLOCK_SIZE;
++ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b);
++
++ /* Process payload blocks */
++ pos = data;
++ cpos = data;
++ for (j = 1; j <= num_blocks; j++) {
++ int blen = (j == num_blocks && last_len) ?
++ last_len : AES_BLOCK_SIZE;
++
++ /* Authentication followed by encryption */
++ for (i = 0; i < blen; i++)
++ b[i] ^= pos[i];
++ crypto_cipher_encrypt_one(tfm, b, b);
++
++ b_0[14] = (j >> 8) & 0xff;
++ b_0[15] = j & 0xff;
++ crypto_cipher_encrypt_one(tfm, e, b_0);
++ for (i = 0; i < blen; i++)
++ *cpos++ = *pos++ ^ e[i];
++ }
+
+- crypto_aead_encrypt(aead_req);
++ for (i = 0; i < mic_len; i++)
++ mic[i] = b[i] ^ s_0[i];
+ }
+
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len)
+ {
+- struct scatterlist sg[3];
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
+-
+- if (data_len == 0)
+- return -EINVAL;
+-
+- memset(aead_req, 0, sizeof(aead_req_data));
+-
+- sg_init_table(sg, 3);
+- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+- sg_set_buf(&sg[1], data, data_len);
+- sg_set_buf(&sg[2], mic, mic_len);
+-
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
+- aead_request_set_ad(aead_req, sg[0].length);
++ int i, j, last_len, num_blocks;
++ u8 *pos, *cpos;
++ u8 a[AES_BLOCK_SIZE];
++ u8 b[AES_BLOCK_SIZE];
++ u8 s_0[AES_BLOCK_SIZE];
++
++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
++ last_len = data_len % AES_BLOCK_SIZE;
++ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b);
++
++ /* Process payload blocks */
++ cpos = data;
++ pos = data;
++ for (j = 1; j <= num_blocks; j++) {
++ int blen = (j == num_blocks && last_len) ?
++ last_len : AES_BLOCK_SIZE;
++
++ /* Decryption followed by authentication */
++ b_0[14] = (j >> 8) & 0xff;
++ b_0[15] = j & 0xff;
++ crypto_cipher_encrypt_one(tfm, b, b_0);
++ for (i = 0; i < blen; i++) {
++ *pos = *cpos++ ^ b[i];
++ a[i] ^= *pos++;
++ }
++ crypto_cipher_encrypt_one(tfm, a, a);
++ }
++
++ for (i = 0; i < mic_len; i++) {
++ if ((mic[i] ^ s_0[i]) != a[i])
++ return -1;
++ }
+
+- return crypto_aead_decrypt(aead_req);
++ return 0;
+ }
+
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
+- size_t key_len,
+- size_t mic_len)
++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
++ size_t key_len,
++ size_t mic_len)
+ {
+- struct crypto_aead *tfm;
+- int err;
++ struct crypto_cipher *tfm;
+
+- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
+- if (IS_ERR(tfm))
+- return tfm;
+-
+- err = crypto_aead_setkey(tfm, key, key_len);
+- if (err)
+- goto free_aead;
+- err = crypto_aead_setauthsize(tfm, mic_len);
+- if (err)
+- goto free_aead;
++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
++ if (!IS_ERR(tfm))
++ crypto_cipher_setkey(tfm, key, key_len);
+
+ return tfm;
+-
+-free_aead:
+- crypto_free_aead(tfm);
+- return ERR_PTR(err);
+ }
+
+-void ieee80211_aes_key_free(struct crypto_aead *tfm)
++
++void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+ {
+- crypto_free_aead(tfm);
++ crypto_free_cipher(tfm);
+ }
+--- a/net/mac80211/aes_ccm.h
++++ b/net/mac80211/aes_ccm.h
+@@ -12,15 +12,15 @@
+
+ #include <linux/crypto.h>
+
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
+- size_t key_len,
+- size_t mic_len);
+-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
++ size_t key_len,
++ size_t mic_len);
++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len);
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad,
+ u8 *data, size_t data_len, u8 *mic,
+ size_t mic_len);
+-void ieee80211_aes_key_free(struct crypto_aead *tfm);
++void ieee80211_aes_key_free(struct crypto_cipher *tfm);
+
+ #endif /* AES_CCM_H */
+--- a/net/mac80211/aes_gcm.h
++++ b/net/mac80211/aes_gcm.h
+@@ -11,12 +11,28 @@
+
+ #include <linux/crypto.h>
+
+-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+- u8 *data, size_t data_len, u8 *mic);
+-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+- u8 *data, size_t data_len, u8 *mic);
+-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
+- size_t key_len);
+-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
++static inline void
++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic)
++{
++}
++
++static inline int
++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline struct crypto_aead *
++ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
++{
++ return NULL;
++}
++
++static inline void
++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
++{
++}
+
+ #endif /* AES_GCM_H */
+--- a/net/mac80211/aes_gmac.h
++++ b/net/mac80211/aes_gmac.h
+@@ -11,10 +11,22 @@
+
+ #include <linux/crypto.h>
+
+-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
+- size_t key_len);
+-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
+- const u8 *data, size_t data_len, u8 *mic);
+-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
++static inline struct crypto_aead *
++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len)
++{
++ return NULL;
++}
++
++static inline int
++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
++ const u8 *data, size_t data_len, u8 *mic)
++{
++ return -EOPNOTSUPP;
++}
++
++static inline void
++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
++{
++}
+
+ #endif /* AES_GMAC_H */
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -84,7 +84,7 @@ struct ieee80211_key {
+ * Management frames.
+ */
+ u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
+- struct crypto_aead *tfm;
++ struct crypto_cipher *tfm;
+ u32 replays; /* dot11RSNAStatsCCMPReplays */
+ } ccmp;
+ struct {
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -307,7 +307,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
+ }
+
+
+-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
++ u16 data_len)
+ {
+ __le16 mask_fc;
+ int a4_included, mgmt;
+@@ -337,14 +338,8 @@ static void ccmp_special_blocks(struct s
+ else
+ qos_tid = 0;
+
+- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
+- * mode authentication are not allowed to collide, yet both are derived
+- * from this vector b_0. We only set L := 1 here to indicate that the
+- * data size can be represented in (L+1) bytes. The CCM layer will take
+- * care of storing the data length in the top (L+1) bytes and setting
+- * and clearing the other bits as is required to derive the two IVs.
+- */
+- b_0[0] = 0x1;
++ /* First block, b_0 */
++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
+
+ /* Nonce: Nonce Flags | A2 | PN
+ * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
+@@ -352,6 +347,8 @@ static void ccmp_special_blocks(struct s
+ b_0[1] = qos_tid | (mgmt << 4);
+ memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
+ memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
++ /* l(m) */
++ put_unaligned_be16(data_len, &b_0[14]);
+
+ /* AAD (extra authenticate-only data) / masked 802.11 header
+ * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
+@@ -463,7 +460,7 @@ static int ccmp_encrypt_skb(struct ieee8
+ return 0;
+
+ pos += IEEE80211_CCMP_HDR_LEN;
+- ccmp_special_blocks(skb, pn, b_0, aad);
++ ccmp_special_blocks(skb, pn, b_0, aad, len);
+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+ skb_put(skb, mic_len), mic_len);
+
+@@ -534,7 +531,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+ u8 aad[2 * AES_BLOCK_SIZE];
+ u8 b_0[AES_BLOCK_SIZE];
+ /* hardware didn't decrypt/verify MIC */
+- ccmp_special_blocks(skb, pn, b_0, aad);
++ ccmp_special_blocks(skb, pn, b_0, aad, data_len);
+
+ if (ieee80211_aes_ccm_decrypt(
+ key->u.ccmp.tfm, b_0, aad,
diff --git a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch
new file mode 100644
index 0000000..d1d9fbd
--- /dev/null
+++ b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch
@@ -0,0 +1,12 @@
+Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -846,7 +846,6 @@ static int ieee80211_stop_ap(struct wiph
+ sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
+
+ __sta_info_flush(sdata, true);
+- ieee80211_free_keys(sdata, true);
+
+ sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
diff --git a/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch b/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch
new file mode 100644
index 0000000..ffd8807
--- /dev/null
+++ b/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch
@@ -0,0 +1,43 @@
+--- a/net/wireless/sysfs.c
++++ b/net/wireless/sysfs.c
+@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
+ return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
+ }
+
+-#define SHOW_FMT(name, fmt, member) \
++#define SHOW_FMT(name, fmt, member, mode) \
+ static ssize_t name ## _show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
+ } \
+-static DEVICE_ATTR_RO(name)
++static DEVICE_ATTR_##mode(name)
+
+-SHOW_FMT(index, "%d", wiphy_idx);
+-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
+-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
++static ssize_t macaddress_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ u8 mac[ETH_ALEN];
++
++ if (!mac_pton(buf, mac))
++ return -EINVAL;
++
++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
++ return -EINVAL;
++
++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
++
++ return strnlen(buf, len);
++}
++
++SHOW_FMT(index, "%d", wiphy_idx, RO);
++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
+
+ static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch
new file mode 100644
index 0000000..cafed72
--- /dev/null
+++ b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch
@@ -0,0 +1,67 @@
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -285,7 +285,7 @@ void ieee80211_restart_hw(struct ieee802
+ }
+ EXPORT_SYMBOL(ieee80211_restart_hw);
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ static int ieee80211_ifa_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
+ {
+@@ -344,7 +344,7 @@ static int ieee80211_ifa_changed(struct
+ }
+ #endif
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ static int ieee80211_ifa6_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
+ {
+@@ -1081,14 +1081,14 @@ int ieee80211_register_hw(struct ieee802
+
+ rtnl_unlock();
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
+ result = register_inetaddr_notifier(&local->ifa_notifier);
+ if (result)
+ goto fail_ifa;
+ #endif
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
+ result = register_inet6addr_notifier(&local->ifa6_notifier);
+ if (result)
+@@ -1097,13 +1097,13 @@ int ieee80211_register_hw(struct ieee802
+
+ return 0;
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ fail_ifa6:
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ unregister_inetaddr_notifier(&local->ifa_notifier);
+ #endif
+ #endif
+-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
++#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
+ fail_ifa:
+ #endif
+ rtnl_lock();
+@@ -1131,10 +1131,10 @@ void ieee80211_unregister_hw(struct ieee
+ tasklet_kill(&local->tx_pending_tasklet);
+ tasklet_kill(&local->tasklet);
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ unregister_inetaddr_notifier(&local->ifa_notifier);
+ #endif
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ unregister_inet6addr_notifier(&local->ifa6_notifier);
+ #endif
+
diff --git a/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
new file mode 100644
index 0000000..21516ff
--- /dev/null
+++ b/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
@@ -0,0 +1,38 @@
+--- a/drivers/net/wireless/ath/ath5k/initvals.c
++++ b/drivers/net/wireless/ath/ath5k/initvals.c
+@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
+ { AR5K_IMR, 0 },
+ { AR5K_IER, AR5K_IER_DISABLE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
++#else
++ /* WAR for AR71xx PCI bug */
++ { AR5K_TXCFG, AR5K_DMASIZE_128B },
++ { AR5K_RXCFG, AR5K_DMASIZE_4B },
++#endif
+ { AR5K_CFG, AR5K_INIT_CFG },
+ { AR5K_TOPS, 8 },
+ { AR5K_RXNOFRM, 8 },
+--- a/drivers/net/wireless/ath/ath5k/dma.c
++++ b/drivers/net/wireless/ath/ath5k/dma.c
+@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
++#else
++ /* WAR for AR71xx PCI bug */
++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
++#endif
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
diff --git a/package/kernel/mac80211/patches/210-ap_scan.patch b/package/kernel/mac80211/patches/210-ap_scan.patch
new file mode 100644
index 0000000..2980f8b
--- /dev/null
+++ b/package/kernel/mac80211/patches/210-ap_scan.patch
@@ -0,0 +1,11 @@
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1981,7 +1981,7 @@ static int ieee80211_scan(struct wiphy *
+ * the frames sent while scanning on other channel will be
+ * lost)
+ */
+- if (sdata->u.ap.beacon &&
++ if (0 && sdata->u.ap.beacon &&
+ (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
+ !(req->flags & NL80211_SCAN_FLAG_AP)))
+ return -EOPNOTSUPP;
diff --git a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
new file mode 100644
index 0000000..bddb15a
--- /dev/null
+++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch
@@ -0,0 +1,31 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 7 Jun 2015 13:53:35 +0200
+Subject: [PATCH] ath9k: force rx_clear when disabling rx
+
+This makes stopping Rx more reliable and should reduce the frequency of
+Rx related DMA stop warnings
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath
+
+ ath9k_ani_reset(ah, is_scanning);
+
+- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
++ REG_CLR_BIT(ah, AR_DIAG_SW,
++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+ }
+ EXPORT_SYMBOL(ath9k_hw_startpcureceive);
+
+ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
+ {
+- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
++ REG_SET_BIT(ah, AR_DIAG_SW,
++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR);
+
+ ath9k_hw_disable_mib_counters(ah);
+ }
diff --git a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
new file mode 100644
index 0000000..33b21e6
--- /dev/null
+++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch
@@ -0,0 +1,121 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Thu, 2 Jul 2015 15:20:56 +0200
+Subject: [PATCH] ath9k: limit retries for powersave response frames
+
+In some cases, the channel might be busy enough that an ath9k AP's
+response to PS-Poll frames might be too slow and the station has already
+gone to sleep. To avoid wasting too much airtime on this, limit the
+number of retries on such frames and ensure that no sample rate gets
+used.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -136,10 +136,25 @@ static void ath_send_bar(struct ath_atx_
+ }
+
+ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+- struct ath_buf *bf)
++ struct ath_buf *bf, bool ps)
+ {
++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
++
++ if (ps) {
++ /* Clear the first rate to avoid using a sample rate for PS frames */
++ info->control.rates[0].idx = -1;
++ info->control.rates[0].count = 0;
++ }
++
+ ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
+ ARRAY_SIZE(bf->rates));
++ if (!ps)
++ return;
++
++ if (bf->rates[0].count > 2)
++ bf->rates[0].count = 2;
++
++ bf->rates[1].idx = -1;
+ }
+
+ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
+@@ -1419,7 +1434,7 @@ ath_tx_form_burst(struct ath_softc *sc,
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+ break;
+
+- ath_set_rates(tid->an->vif, tid->an->sta, bf);
++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
+ } while (1);
+ }
+
+@@ -1450,7 +1465,7 @@ static bool ath_tx_sched_aggr(struct ath
+ return false;
+ }
+
+- ath_set_rates(tid->an->vif, tid->an->sta, bf);
++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false);
+ if (aggr)
+ last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf,
+ tid_q, &aggr_len);
+@@ -1632,7 +1647,7 @@ void ath9k_release_buffered_frames(struc
+
+ __skb_unlink(bf->bf_mpdu, tid_q);
+ list_add_tail(&bf->list, &bf_q);
+- ath_set_rates(tid->an->vif, tid->an->sta, bf);
++ ath_set_rates(tid->an->vif, tid->an->sta, bf, true);
+ if (bf_isampdu(bf)) {
+ ath_tx_addto_baw(sc, tid, bf);
+ bf->bf_state.bf_type &= ~BUF_AGGR;
+@@ -2278,7 +2293,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ struct ath_txq *txq = txctl->txq;
+ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
+- bool queue, skip_uapsd = false, ps_resp;
++ bool queue, ps_resp;
+ int q, ret;
+
+ if (vif)
+@@ -2325,13 +2340,13 @@ int ath_tx_start(struct ieee80211_hw *hw
+ if (!txctl->an)
+ txctl->an = &avp->mcast_node;
+ queue = true;
+- skip_uapsd = true;
++ ps_resp = false;
+ }
+
+ if (txctl->an && queue)
+ tid = ath_get_skb_tid(sc, txctl->an, skb);
+
+- if (!skip_uapsd && ps_resp) {
++ if (ps_resp) {
+ ath_txq_unlock(sc, txq);
+ txq = sc->tx.uapsdq;
+ ath_txq_lock(sc, txq);
+@@ -2369,7 +2384,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+- ath_set_rates(vif, sta, bf);
++ ath_set_rates(vif, sta, bf, ps_resp);
+ ath_tx_send_normal(sc, txq, tid, skb);
+
+ out:
+@@ -2408,7 +2423,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
+ break;
+
+ bf->bf_lastbf = bf;
+- ath_set_rates(vif, NULL, bf);
++ ath_set_rates(vif, NULL, bf, false);
+ ath_buf_set_rate(sc, bf, &info, fi->framelen, false);
+ duration += info.rates[0].PktDuration;
+ if (bf_tail)
+@@ -2911,7 +2926,7 @@ int ath9k_tx99_send(struct ath_softc *sc
+ return -EINVAL;
+ }
+
+- ath_set_rates(sc->tx99_vif, NULL, bf);
++ ath_set_rates(sc->tx99_vif, NULL, bf, false);
+
+ ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr);
+ ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum);
diff --git a/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch
new file mode 100644
index 0000000..944b8e7
--- /dev/null
+++ b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch
@@ -0,0 +1,108 @@
+From: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+Date: Tue, 20 Oct 2015 14:19:26 +0200
+Subject: [PATCH] ath9k: fix phyerror codes
+
+Some of the ath9k_phyerr enums were wrong from the
+beginning (and even before). Most of the time the
+codes were used for counters to be displayed over
+debugfs, which made this a non-functional issue.
+
+Some (e.g. ATH9K_PHYERR_FALSE_RADAR_EXT) are used
+for radar detection and require the correct code
+to work as intended.
+
+This patch includes:
+a) fixes
+ ATH9K_PHYERR_FALSE_RADAR_EXT: 24 => 36
+ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL: 32 => 28
+ ATH9K_PHYERR_CCK_POWER_DROP: 33 => 29
+ ATH9K_PHYERR_HT_CRC_ERROR: 34 => 32
+ ATH9K_PHYERR_HT_LENGTH_ILLEGAL: 35 => 33
+ ATH9K_PHYERR_HT_RATE_ILLEGAL: 36 => 34
+
+b) extensions
+ ATH9K_PHYERR_CCK_BLOCKER = 24
+ ATH9K_PHYERR_HT_ZLF = 35
+ ATH9K_PHYERR_GREEN_FIELD = 37
+
+Aside from the correction and completion made in
+the enum, the patch also extends the display of
+the related counters in the debugfs.
+
+Signed-off-by: Zefir Kurtisi <zefir.kurtisi@neratec.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/common-debug.c
++++ b/drivers/net/wireless/ath/ath9k/common-debug.c
+@@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct
+ PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
+ PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
+ PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
++
+ PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
+ PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
+ PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
+@@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct
+ PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
+ PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
+ PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
+- PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
++
++ PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER);
+ PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
+ PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
+ PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
+- PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
+- PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
+ PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
+ PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
++ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
++ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
++
+ PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
+ PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
+ PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
++ PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF);
++
++ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
++ PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD);
++ PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL);
+
+ if (len > size)
+ len = size;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -209,21 +209,25 @@ enum ath9k_phyerr {
+ ATH9K_PHYERR_OFDM_POWER_DROP = 21,
+ ATH9K_PHYERR_OFDM_SERVICE = 22,
+ ATH9K_PHYERR_OFDM_RESTART = 23,
+- ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
+
++ ATH9K_PHYERR_CCK_BLOCKER = 24,
+ ATH9K_PHYERR_CCK_TIMING = 25,
+ ATH9K_PHYERR_CCK_HEADER_CRC = 26,
+ ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
++ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28,
++ ATH9K_PHYERR_CCK_POWER_DROP = 29,
+ ATH9K_PHYERR_CCK_SERVICE = 30,
+ ATH9K_PHYERR_CCK_RESTART = 31,
+- ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
+- ATH9K_PHYERR_CCK_POWER_DROP = 33,
+
+- ATH9K_PHYERR_HT_CRC_ERROR = 34,
+- ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
+- ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
++ ATH9K_PHYERR_HT_CRC_ERROR = 32,
++ ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33,
++ ATH9K_PHYERR_HT_RATE_ILLEGAL = 34,
++ ATH9K_PHYERR_HT_ZLF = 35,
++
++ ATH9K_PHYERR_FALSE_RADAR_EXT = 36,
++ ATH9K_PHYERR_GREEN_FIELD = 37,
++ ATH9K_PHYERR_SPECTRAL = 38,
+
+- ATH9K_PHYERR_SPECTRAL = 38,
+ ATH9K_PHYERR_MAX = 39,
+ };
+
diff --git a/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch
new file mode 100644
index 0000000..dea65bb
--- /dev/null
+++ b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch
@@ -0,0 +1,239 @@
+From: Maharaja <c_mkenna@qti.qualcomm.com>
+Date: Wed, 21 Oct 2015 11:49:18 +0300
+Subject: [PATCH] ath10k: enable adaptive CCA
+
+European Union has made it mandatory that all devices working in 2.4 GHz
+has to adhere to the ETSI specification (ETSI EN 300 328 V1.9.1)
+beginnig this year. The standard basically speaks about interferences
+in 2.4Ghz band.
+For example, when 802.11 device detects interference, TX must be stopped
+as long as interference is present.
+
+Adaptive CCA is a feature, when enabled the device learns from the
+environment and configures CCA levels adaptively. This will improve
+detecting interferences and the device can stop trasmissions till the
+interference is present eventually leading to good performances in
+varying interference conditions.
+
+The patch includes code for enabling adaptive CCA for 10.2.4 firmware on
+QCA988X.
+
+Signed-off-by: Maharaja <c_mkenna@qti.qualcomm.com>
+Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -151,6 +151,7 @@ static const char *const ath10k_core_fw_
+ [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
+ [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
+ [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
++ [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
+ };
+
+ static unsigned int ath10k_core_get_fw_feature_str(char *buf,
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -497,6 +497,9 @@ enum ath10k_fw_features {
+ */
+ ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,
+
++ /* Firmware Supports Adaptive CCA*/
++ ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
++
+ /* keep last */
+ ATH10K_FW_FEATURE_COUNT,
+ };
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -3905,6 +3905,18 @@ static int ath10k_start(struct ieee80211
+ goto err_core_stop;
+ }
+
++ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
++ ar->fw_features)) {
++ ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1,
++ WMI_CCA_DETECT_LEVEL_AUTO,
++ WMI_CCA_DETECT_MARGIN_AUTO);
++ if (ret) {
++ ath10k_warn(ar, "failed to enable adaptive cca: %d\n",
++ ret);
++ goto err_core_stop;
++ }
++ }
++
+ ret = ath10k_wmi_pdev_set_param(ar,
+ ar->wmi.pdev_param->ani_enable, 1);
+ if (ret) {
+--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
+@@ -182,6 +182,10 @@ struct wmi_ops {
+ void (*fw_stats_fill)(struct ath10k *ar,
+ struct ath10k_fw_stats *fw_stats,
+ char *buf);
++ struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar,
++ u8 enable,
++ u32 detect_level,
++ u32 detect_margin);
+ };
+
+ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+@@ -1302,4 +1306,25 @@ ath10k_wmi_fw_stats_fill(struct ath10k *
+ ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf);
+ return 0;
+ }
++
++static inline int
++ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
++ u32 detect_level, u32 detect_margin)
++{
++ struct sk_buff *skb;
++
++ if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca)
++ return -EOPNOTSUPP;
++
++ skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable,
++ detect_level,
++ detect_margin);
++
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ return ath10k_wmi_cmd_send(ar, skb,
++ ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
++}
++
+ #endif
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map =
+ .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
+ .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
+ .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
+ .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+@@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
+ .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
+ .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
+ .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
+ .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+@@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd
+ .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,
++ .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS,
+ .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+@@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m
+ .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,
++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
+ .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+ .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+@@ -6996,6 +7000,28 @@ unlock:
+ buf[len] = 0;
+ }
+
++static struct sk_buff *
++ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
++ u32 detect_level, u32 detect_margin)
++{
++ struct wmi_pdev_set_adaptive_cca_params *cmd;
++ struct sk_buff *skb;
++
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++ if (!skb)
++ return ERR_PTR(-ENOMEM);
++
++ cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data;
++ cmd->enable = __cpu_to_le32(enable);
++ cmd->cca_detect_level = __cpu_to_le32(detect_level);
++ cmd->cca_detect_margin = __cpu_to_le32(detect_margin);
++
++ ath10k_dbg(ar, ATH10K_DBG_WMI,
++ "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n",
++ enable, detect_level, detect_margin);
++ return skb;
++}
++
+ static const struct wmi_ops wmi_ops = {
+ .rx = ath10k_wmi_op_rx,
+ .map_svc = wmi_main_svc_map,
+@@ -7059,6 +7085,7 @@ static const struct wmi_ops wmi_ops = {
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+ /* .gen_adaptive_qcs not implemented */
++ /* .gen_pdev_enable_adaptive_cca not implemented */
+ };
+
+ static const struct wmi_ops wmi_10_1_ops = {
+@@ -7125,6 +7152,7 @@ static const struct wmi_ops wmi_10_1_ops
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+ /* .gen_adaptive_qcs not implemented */
++ /* .gen_pdev_enable_adaptive_cca not implemented */
+ };
+
+ static const struct wmi_ops wmi_10_2_ops = {
+@@ -7188,6 +7216,7 @@ static const struct wmi_ops wmi_10_2_ops
+ .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
+ .gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
++ /* .gen_pdev_enable_adaptive_cca not implemented */
+ };
+
+ static const struct wmi_ops wmi_10_2_4_ops = {
+@@ -7251,6 +7280,8 @@ static const struct wmi_ops wmi_10_2_4_o
+ .gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
++ .gen_pdev_enable_adaptive_cca =
++ ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -772,6 +772,7 @@ struct wmi_cmd_map {
+ u32 mu_cal_start_cmdid;
+ u32 set_cca_params_cmdid;
+ u32 pdev_bss_chan_info_request_cmdid;
++ u32 pdev_enable_adaptive_cca_cmdid;
+ };
+
+ /*
+@@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id {
+ WMI_10_2_VDEV_ATF_REQUEST_CMDID,
+ WMI_10_2_PEER_ATF_REQUEST_CMDID,
+ WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
++ WMI_10_2_MU_CAL_START_CMDID,
++ WMI_10_2_SET_LTEU_CONFIG_CMDID,
++ WMI_10_2_SET_CCA_PARAMS,
+ WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
+ };
+
+@@ -6094,6 +6098,15 @@ enum wmi_txbf_conf {
+ WMI_TXBF_CONF_AFTER_ASSOC,
+ };
+
++#define WMI_CCA_DETECT_LEVEL_AUTO 0
++#define WMI_CCA_DETECT_MARGIN_AUTO 0
++
++struct wmi_pdev_set_adaptive_cca_params {
++ __le32 enable;
++ __le32 cca_detect_level;
++ __le32 cca_detect_margin;
++} __packed;
++
+ struct ath10k;
+ struct ath10k_vif;
+ struct ath10k_fw_stats_pdev;
diff --git a/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch
new file mode 100644
index 0000000..e4ccac3
--- /dev/null
+++ b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch
@@ -0,0 +1,331 @@
+From: Alan Liu <alanliu@qca.qualcomm.com>
+Date: Wed, 28 Oct 2015 21:38:32 +0200
+Subject: [PATCH] ath10k: add FW API support to test mode
+
+Add WMI-TLV and FW API support in ath10k testmode.
+Ath10k can get right wmi command format from UTF image
+to communicate UTF firmware.
+
+Signed-off-by: Alan Liu <alanliu@qca.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -569,8 +569,8 @@ static int ath10k_download_fw(struct ath
+ }
+ break;
+ case ATH10K_FIRMWARE_MODE_UTF:
+- data = ar->testmode.utf->data;
+- data_len = ar->testmode.utf->size;
++ data = ar->testmode.utf_firmware_data;
++ data_len = ar->testmode.utf_firmware_len;
+ mode_name = "utf";
+ break;
+ default:
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -817,9 +817,12 @@ struct ath10k {
+ struct {
+ /* protected by conf_mutex */
+ const struct firmware *utf;
++ char utf_version[32];
++ const void *utf_firmware_data;
++ size_t utf_firmware_len;
+ DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
+ enum ath10k_fw_wmi_op_version orig_wmi_op_version;
+-
++ enum ath10k_fw_wmi_op_version op_version;
+ /* protected by data_lock */
+ bool utf_monitor;
+ } testmode;
+--- a/drivers/net/wireless/ath/ath10k/hw.h
++++ b/drivers/net/wireless/ath/ath10k/hw.h
+@@ -94,6 +94,7 @@ enum qca6174_chip_id_rev {
+ #define ATH10K_FW_API5_FILE "firmware-5.bin"
+
+ #define ATH10K_FW_UTF_FILE "utf.bin"
++#define ATH10K_FW_UTF_API2_FILE "utf-2.bin"
+
+ /* includes also the null byte */
+ #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
+--- a/drivers/net/wireless/ath/ath10k/testmode.c
++++ b/drivers/net/wireless/ath/ath10k/testmode.c
+@@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(str
+ return cfg80211_testmode_reply(skb);
+ }
+
+-static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
++static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
++{
++ size_t len, magic_len, ie_len;
++ struct ath10k_fw_ie *hdr;
++ char filename[100];
++ __le32 *version;
++ const u8 *data;
++ int ie_id, ret;
++
++ snprintf(filename, sizeof(filename), "%s/%s",
++ ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_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);
++ return ret;
++ }
++
++ data = ar->testmode.utf->data;
++ len = ar->testmode.utf->size;
++
++ /* FIXME: call release_firmware() in error cases */
++
++ /* magic also includes the null byte, check that as well */
++ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
++
++ if (len < magic_len) {
++ ath10k_err(ar, "utf firmware file is too small to contain magic\n");
++ ret = -EINVAL;
++ goto err;
++ }
++
++ if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
++ ath10k_err(ar, "invalid firmware magic\n");
++ ret = -EINVAL;
++ goto err;
++ }
++
++ /* jump over the padding */
++ magic_len = ALIGN(magic_len, 4);
++
++ len -= magic_len;
++ data += magic_len;
++
++ /* loop elements */
++ while (len > sizeof(struct ath10k_fw_ie)) {
++ hdr = (struct ath10k_fw_ie *)data;
++
++ ie_id = le32_to_cpu(hdr->id);
++ ie_len = le32_to_cpu(hdr->len);
++
++ len -= sizeof(*hdr);
++ data += sizeof(*hdr);
++
++ if (len < ie_len) {
++ ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
++ ie_id, len, ie_len);
++ ret = -EINVAL;
++ goto err;
++ }
++
++ switch (ie_id) {
++ case ATH10K_FW_IE_FW_VERSION:
++ if (ie_len > sizeof(ar->testmode.utf_version) - 1)
++ break;
++
++ memcpy(ar->testmode.utf_version, data, ie_len);
++ ar->testmode.utf_version[ie_len] = '\0';
++
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
++ "testmode found fw utf version %s\n",
++ ar->testmode.utf_version);
++ break;
++ case ATH10K_FW_IE_TIMESTAMP:
++ /* ignore timestamp, but don't warn about it either */
++ break;
++ case ATH10K_FW_IE_FW_IMAGE:
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
++ "testmode found fw image ie (%zd B)\n",
++ ie_len);
++
++ ar->testmode.utf_firmware_data = data;
++ ar->testmode.utf_firmware_len = ie_len;
++ break;
++ case ATH10K_FW_IE_WMI_OP_VERSION:
++ if (ie_len != sizeof(u32))
++ break;
++ version = (__le32 *)data;
++ ar->testmode.op_version = le32_to_cpup(version);
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
++ ar->testmode.op_version);
++ break;
++ default:
++ ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
++ le32_to_cpu(hdr->id));
++ break;
++ }
++ /* jump over the padding */
++ ie_len = ALIGN(ie_len, 4);
++
++ len -= ie_len;
++ data += ie_len;
++ }
++
++ if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
++ ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
++ ret = -EINVAL;
++ goto err;
++ }
++
++ return 0;
++
++err:
++ release_firmware(ar->testmode.utf);
++
++ return ret;
++}
++
++static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
+ {
+ char filename[100];
+ int ret;
+
++ 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);
++ return ret;
++ }
++
++ /* We didn't find FW UTF API 1 ("utf.bin") does not advertise
++ * firmware features. Do an ugly hack where we force the firmware
++ * features to match with 10.1 branch so that wmi.c will use the
++ * correct WMI interface.
++ */
++
++ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
++ ar->testmode.utf_firmware_data = ar->testmode.utf->data;
++ ar->testmode.utf_firmware_len = ar->testmode.utf->size;
++
++ return 0;
++}
++
++static int ath10k_tm_fetch_firmware(struct ath10k *ar)
++{
++ int ret;
++
++ ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
++ if (ret == 0) {
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
++ return 0;
++ }
++
++ ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
++ if (ret) {
++ ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
++ return ret;
++ }
++
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
++
++ return 0;
++}
++
++static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
++{
++ const char *ver;
++ int ret;
++
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
+
+ mutex_lock(&ar->conf_mutex);
+@@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struc
+ 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);
++ ret = ath10k_tm_fetch_firmware(ar);
+ if (ret) {
+- ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+- filename, ret);
++ ath10k_err(ar, "failed to fetch UTF firmware: %d", 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;
++
++ ar->wmi.op_version = ar->testmode.op_version;
++
++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
++ ar->wmi.op_version);
+
+ ret = ath10k_hif_power_up(ar);
+ if (ret) {
+@@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struc
+
+ ar->state = ATH10K_STATE_UTF;
+
+- ath10k_info(ar, "UTF firmware started\n");
++ if (strlen(ar->testmode.utf_version) > 0)
++ ver = ar->testmode.utf_version;
++ else
++ ver = "API 1";
++
++ ath10k_info(ar, "UTF firmware %s started\n", ver);
+
+ mutex_unlock(&ar->conf_mutex);
+
+--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -23,6 +23,7 @@
+ #include "wmi-ops.h"
+ #include "wmi-tlv.h"
+ #include "p2p.h"
++#include "testmode.h"
+
+ /***************/
+ /* TLV helpers */
+@@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct
+ {
+ struct wmi_cmd_hdr *cmd_hdr;
+ enum wmi_tlv_event_id id;
++ bool consumed;
+
+ cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
+ id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
+@@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct
+
+ trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
+
++ consumed = ath10k_tm_event_wmi(ar, id, skb);
++
++ /* 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_TLV_READY_EVENTID) {
++ ath10k_dbg(ar, ATH10K_DBG_WMI,
++ "wmi tlv testmode consumed 0x%x\n", id);
++ goto out;
++ }
++
+ switch (id) {
+ case WMI_TLV_MGMT_RX_EVENTID:
+ ath10k_wmi_event_mgmt_rx(ar, skb);
diff --git a/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch
new file mode 100644
index 0000000..7deb19c
--- /dev/null
+++ b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch
@@ -0,0 +1,468 @@
+From: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
+Date: Wed, 28 Oct 2015 21:38:33 +0200
+Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware
+
+This patch adds support for getting firmware debug stats in 10.4 fw.
+
+Signed-off-by: Manikanta Pubbisetty <c_mpubbi@qti.qualcomm.com>
+Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
+ s32 hw_queued;
+ s32 hw_reaped;
+ s32 underrun;
++ u32 hw_paused;
+ s32 tx_abort;
+ s32 mpdus_requed;
+ u32 tx_ko;
+@@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
+ u32 pdev_resets;
+ u32 phy_underrun;
+ u32 txop_ovf;
++ u32 seq_posted;
++ u32 seq_failed_queueing;
++ u32 seq_completed;
++ u32 seq_restarted;
++ u32 mu_seq_posted;
++ u32 mpdus_sw_flush;
++ u32 mpdus_hw_filter;
++ u32 mpdus_truncated;
++ u32 mpdus_ack_failed;
++ u32 mpdus_expired;
+
+ /* PDEV RX stats */
+ s32 mid_ppdu_route_change;
+@@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
+ s32 phy_errs;
+ s32 phy_err_drop;
+ s32 mpdu_errs;
++ s32 rx_ovfl_errs;
+ };
+
+ struct ath10k_fw_stats {
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const
+ dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
+ }
+
++static void
++ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_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);
++ dst->hw_paused = __le32_to_cpu(src->hw_paused);
++ dst->seq_posted = __le32_to_cpu(src->seq_posted);
++ dst->seq_failed_queueing =
++ __le32_to_cpu(src->seq_failed_queueing);
++ dst->seq_completed = __le32_to_cpu(src->seq_completed);
++ dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
++ dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
++ dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
++ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
++ dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
++ dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
++ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
++ dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
++}
++
+ void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
+ struct ath10k_fw_stats_pdev *dst)
+ {
+@@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_
+ return 0;
+ }
+
++static int ath10k_wmi_10_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_4_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_10_4_pull_pdev_stats_tx(&src->tx, dst);
++ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
++ dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
++ ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
++
++ 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_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;
++
++ 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);
++ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
++ /* FIXME: expose 10.4 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");
+@@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "received event id %d not implemented\n", id);
+ break;
++ case WMI_10_4_UPDATE_STATS_EVENTID:
++ ath10k_wmi_event_update_stats(ar, skb);
++ break;
+ default:
+ ath10k_warn(ar, "Unknown eventid: %d\n", id);
+ break;
+@@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c
+ return skb;
+ }
+
++void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
++ struct ath10k_fw_stats *fw_stats,
++ char *buf)
++{
++ u32 len = 0;
++ u32 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;
++
++ 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_wmi_fw_stats_num_peers(&fw_stats->peers);
++ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
++
++ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
++ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
++ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
++
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "HW paused", pdev->hw_paused);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "Seqs posted", pdev->seq_posted);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "Seqs failed queueing", pdev->seq_failed_queueing);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "Seqs completed", pdev->seq_completed);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "Seqs restarted", pdev->seq_restarted);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MU Seqs posted", pdev->mu_seq_posted);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MPDUs SW flushed", pdev->mpdus_sw_flush);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MPDUs HW filtered", pdev->mpdus_hw_filter);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MPDUs truncated", pdev->mpdus_truncated);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MPDUs receive no ACK", pdev->mpdus_ack_failed);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "MPDUs expired", pdev->mpdus_expired);
++
++ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
++ "Num Rx Overflow errors", pdev->rx_ovfl_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) {
++ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
++ }
++
++ len += scnprintf(buf + len, buf_len - len, "\n");
++ 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",
++ "=================");
++
++ list_for_each_entry(peer, &fw_stats->peers, list) {
++ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
++ }
++
++unlock:
++ spin_unlock_bh(&ar->data_lock);
++
++ if (len >= buf_len)
++ buf[len - 1] = 0;
++ else
++ buf[len] = 0;
++}
++
+ static const struct wmi_ops wmi_ops = {
+ .rx = ath10k_wmi_op_rx,
+ .map_svc = wmi_main_svc_map,
+@@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops
+ .rx = ath10k_wmi_10_4_op_rx,
+ .map_svc = wmi_10_4_svc_map,
+
++ .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
+ .pull_scan = ath10k_wmi_op_pull_scan_ev,
+ .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
+ .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
+@@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops
+ .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,
++ .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
+
+ /* shared with 10.2 */
+ .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
++ .gen_request_stats = ath10k_wmi_op_gen_request_stats,
+ };
+
+ int ath10k_wmi_attach(struct ath10k *ar)
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx {
+ __le32 txop_ovf;
+ } __packed;
+
++struct wmi_10_4_pdev_stats_tx {
++ /* Num HTT cookies queued to dispatch list */
++ __le32 comp_queued;
++
++ /* Num HTT cookies dispatched */
++ __le32 comp_delivered;
++
++ /* Num MSDU queued to WAL */
++ __le32 msdu_enqued;
++
++ /* Num MPDU queue to WAL */
++ __le32 mpdu_enqued;
++
++ /* Num MSDUs dropped by WMM limit */
++ __le32 wmm_drop;
++
++ /* Num Local frames queued */
++ __le32 local_enqued;
++
++ /* Num Local frames done */
++ __le32 local_freed;
++
++ /* Num queued to HW */
++ __le32 hw_queued;
++
++ /* Num PPDU reaped from HW */
++ __le32 hw_reaped;
++
++ /* Num underruns */
++ __le32 underrun;
++
++ /* HW Paused. */
++ __le32 hw_paused;
++
++ /* Num PPDUs cleaned up in TX abort */
++ __le32 tx_abort;
++
++ /* Num MPDUs requed by SW */
++ __le32 mpdus_requed;
++
++ /* excessive retries */
++ __le32 tx_ko;
++
++ /* data hw rate code */
++ __le32 data_rc;
++
++ /* Scheduler self triggers */
++ __le32 self_triggers;
++
++ /* frames dropped due to excessive sw retries */
++ __le32 sw_retry_failure;
++
++ /* illegal rate phy errors */
++ __le32 illgl_rate_phy_err;
++
++ /* wal pdev continuous xretry */
++ __le32 pdev_cont_xretry;
++
++ /* wal pdev tx timeouts */
++ __le32 pdev_tx_timeout;
++
++ /* wal pdev resets */
++ __le32 pdev_resets;
++
++ /* frames dropped due to non-availability of stateless TIDs */
++ __le32 stateless_tid_alloc_failure;
++
++ __le32 phy_underrun;
++
++ /* MPDU is more than txop limit */
++ __le32 txop_ovf;
++
++ /* Number of Sequences posted */
++ __le32 seq_posted;
++
++ /* Number of Sequences failed queueing */
++ __le32 seq_failed_queueing;
++
++ /* Number of Sequences completed */
++ __le32 seq_completed;
++
++ /* Number of Sequences restarted */
++ __le32 seq_restarted;
++
++ /* Number of MU Sequences posted */
++ __le32 mu_seq_posted;
++
++ /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
++ __le32 mpdus_sw_flush;
++
++ /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
++ __le32 mpdus_hw_filter;
++
++ /* Num MPDUs truncated by PDG
++ * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
++ */
++ __le32 mpdus_truncated;
++
++ /* Num MPDUs that was tried but didn't receive ACK or BA */
++ __le32 mpdus_ack_failed;
++
++ /* Num MPDUs that was dropped due to expiry. */
++ __le32 mpdus_expired;
++} __packed;
++
+ struct wmi_pdev_stats_rx {
+ /* Cnts any change in ring routing mid-ppdu */
+ __le32 mid_ppdu_route_change;
+@@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
+ struct wmi_pdev_stats_extra extra;
+ } __packed;
+
++struct wmi_10_4_pdev_stats {
++ struct wmi_pdev_stats_base base;
++ struct wmi_10_4_pdev_stats_tx tx;
++ struct wmi_pdev_stats_rx rx;
++ __le32 rx_ovfl_errs;
++ struct wmi_pdev_stats_mem mem;
++ __le32 sram_free_size;
++ struct wmi_pdev_stats_extra extra;
++} __packed;
++
+ /*
+ * VDEV statistics
+ * TODO: add all VDEV stats here
+@@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
+ __le32 unknown_value; /* FIXME: what is this word? */
+ } __packed;
+
++struct wmi_10_4_peer_stats {
++ struct wmi_mac_addr peer_macaddr;
++ __le32 peer_rssi;
++ __le32 peer_rssi_seq_num;
++ __le32 peer_tx_rate;
++ __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];
++ __le32 peer_rssi_changed;
++} __packed;
++
+ struct wmi_10_2_pdev_ext_stats {
+ __le32 rx_rssi_comb;
+ __le32 rx_rssi[4];
+@@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str
+ char *buf);
+ size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
+ size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
++void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
++ struct ath10k_fw_stats *fw_stats,
++ char *buf);
+
+ #endif /* _WMI_H_ */
diff --git a/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch
new file mode 100644
index 0000000..58db2b2
--- /dev/null
+++ b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch
@@ -0,0 +1,60 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Fri, 23 Oct 2015 18:01:03 +0530
+Subject: [PATCH] ath10k: use local memory instead of shadow descriptor
+ in ce_send
+
+Currently to avoid uncached memory access while filling up copy engine
+descriptors, shadow descriptors are used. This can be optimized further
+by removing shadow descriptors. To achieve that first shadow ring
+dependency in ce_send is removed by creating local copy of the
+descriptor on stack and make a one-shot copy into the "uncached"
+descriptor.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/ce.c
++++ b/drivers/net/wireless/ath/ath10k/ce.c
+@@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_
+ {
+ struct ath10k *ar = ce_state->ar;
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
+- struct ce_desc *desc, *sdesc;
++ struct ce_desc *desc, sdesc;
+ unsigned int nentries_mask = src_ring->nentries_mask;
+ unsigned int sw_index = src_ring->sw_index;
+ unsigned int write_index = src_ring->write_index;
+@@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_
+
+ desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
+ write_index);
+- sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index);
+
+ desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
+
+@@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_
+ if (flags & CE_SEND_FLAG_BYTE_SWAP)
+ desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
+
+- sdesc->addr = __cpu_to_le32(buffer);
+- sdesc->nbytes = __cpu_to_le16(nbytes);
+- sdesc->flags = __cpu_to_le16(desc_flags);
++ sdesc.addr = __cpu_to_le32(buffer);
++ sdesc.nbytes = __cpu_to_le16(nbytes);
++ sdesc.flags = __cpu_to_le16(desc_flags);
+
+- *desc = *sdesc;
++ *desc = sdesc;
+
+ src_ring->per_transfer_context[write_index] = per_transfer_context;
+
+@@ -614,7 +613,7 @@ int ath10k_ce_completed_send_next_nolock
+ if (read_index == sw_index)
+ return -EIO;
+
+- sbase = src_ring->shadow_base;
++ sbase = src_ring->base_addr_owner_space;
+ sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
+
+ /* Return data from completed source descriptor */
diff --git a/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch
new file mode 100644
index 0000000..a61a334
--- /dev/null
+++ b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch
@@ -0,0 +1,49 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Fri, 23 Oct 2015 18:01:04 +0530
+Subject: [PATCH] ath10k: remove send completion validation in diag
+ read/write
+
+CE diag window access is serialized (it has to be by design) so
+there's no way to get a different send completion. so there's no
+need for post completion validation.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -920,16 +920,6 @@ static int ath10k_pci_diag_read_mem(stru
+ }
+ }
+
+- if (nbytes != completed_nbytes) {
+- ret = -EIO;
+- goto done;
+- }
+-
+- if (buf != (u32)address) {
+- ret = -EIO;
+- goto done;
+- }
+-
+ i = 0;
+ while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+ &completed_nbytes,
+@@ -1094,16 +1084,6 @@ static int ath10k_pci_diag_write_mem(str
+ }
+ }
+
+- if (nbytes != completed_nbytes) {
+- ret = -EIO;
+- goto done;
+- }
+-
+- if (buf != ce_data) {
+- ret = -EIO;
+- goto done;
+- }
+-
+ i = 0;
+ while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
+ &completed_nbytes,
diff --git a/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch
new file mode 100644
index 0000000..e758665
--- /dev/null
+++ b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch
@@ -0,0 +1,165 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Fri, 23 Oct 2015 18:01:05 +0530
+Subject: [PATCH] ath10k: cleanup copy engine send completion
+
+The physical address necessary to unmap DMA ('bufferp') is stored
+in ath10k_skb_cb as 'paddr'. ath10k doesn't rely on the meta/transfer_id
+when handling send completion (htc ep id is stored in sk_buff control
+buffer). So the unused output arguments {bufferp, nbytesp and transfer_idp}
+are removed from CE send completion. This change is needed before removing
+the shadow copy of copy engine (CE) descriptors in follow up patch.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/ce.c
++++ b/drivers/net/wireless/ath/ath10k/ce.c
+@@ -578,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct at
+ * The caller takes responsibility for any necessary locking.
+ */
+ 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)
++ void **per_transfer_contextp)
+ {
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
+ u32 ctrl_addr = ce_state->ctrl_addr;
+ struct ath10k *ar = ce_state->ar;
+ unsigned int nentries_mask = src_ring->nentries_mask;
+ unsigned int sw_index = src_ring->sw_index;
+- struct ce_desc *sdesc, *sbase;
+ unsigned int read_index;
+
+ if (src_ring->hw_index == sw_index) {
+@@ -613,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock
+ if (read_index == sw_index)
+ return -EIO;
+
+- sbase = src_ring->base_addr_owner_space;
+- sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
+-
+- /* Return data from completed source descriptor */
+- *bufferp = __le32_to_cpu(sdesc->addr);
+- *nbytesp = __le16_to_cpu(sdesc->nbytes);
+- *transfer_idp = MS(__le16_to_cpu(sdesc->flags),
+- CE_DESC_FLAGS_META_DATA);
+-
+ if (per_transfer_contextp)
+ *per_transfer_contextp =
+ src_ring->per_transfer_context[sw_index];
+@@ -696,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct at
+ }
+
+ 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)
+ {
+ struct ath10k *ar = ce_state->ar;
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+@@ -707,9 +691,7 @@ int ath10k_ce_completed_send_next(struct
+
+ spin_lock_bh(&ar_pci->ce_lock);
+ ret = ath10k_ce_completed_send_next_nolock(ce_state,
+- per_transfer_contextp,
+- bufferp, nbytesp,
+- transfer_idp);
++ per_transfer_contextp);
+ spin_unlock_bh(&ar_pci->ce_lock);
+
+ return ret;
+--- a/drivers/net/wireless/ath/ath10k/ce.h
++++ b/drivers/net/wireless/ath/ath10k/ce.h
+@@ -192,16 +192,10 @@ 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);
+
+ 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);
++ void **per_transfer_contextp);
+
+ /*==================CE Engine Initialization=======================*/
+
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -910,9 +910,8 @@ static int ath10k_pci_diag_read_mem(stru
+ goto done;
+
+ i = 0;
+- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+- &completed_nbytes,
+- &id) != 0) {
++ while (ath10k_ce_completed_send_next_nolock(ce_diag,
++ NULL) != 0) {
+ mdelay(1);
+ if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+ ret = -EBUSY;
+@@ -1073,9 +1072,8 @@ static int ath10k_pci_diag_write_mem(str
+ goto done;
+
+ i = 0;
+- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
+- &completed_nbytes,
+- &id) != 0) {
++ while (ath10k_ce_completed_send_next_nolock(ce_diag,
++ NULL) != 0) {
+ mdelay(1);
+
+ if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
+@@ -1139,13 +1137,9 @@ static void ath10k_pci_htc_tx_cb(struct
+ struct ath10k *ar = ce_state->ar;
+ struct sk_buff_head list;
+ struct sk_buff *skb;
+- u32 ce_data;
+- unsigned int nbytes;
+- unsigned int transfer_id;
+
+ __skb_queue_head_init(&list);
+- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
+- &nbytes, &transfer_id) == 0) {
++ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
+ /* no need to call tx completion for NULL pointers */
+ if (skb == NULL)
+ continue;
+@@ -1215,12 +1209,8 @@ static void ath10k_pci_htt_tx_cb(struct
+ {
+ struct ath10k *ar = ce_state->ar;
+ struct sk_buff *skb;
+- u32 ce_data;
+- unsigned int nbytes;
+- unsigned int transfer_id;
+
+- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
+- &nbytes, &transfer_id) == 0) {
++ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
+ /* no need to call tx completion for NULL pointers */
+ if (!skb)
+ continue;
+@@ -1796,12 +1786,8 @@ err_dma:
+ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
+ {
+ struct bmi_xfer *xfer;
+- u32 ce_data;
+- unsigned int nbytes;
+- unsigned int transfer_id;
+
+- if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data,
+- &nbytes, &transfer_id))
++ if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer))
+ return;
+
+ xfer->tx_done = true;
diff --git a/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch
new file mode 100644
index 0000000..5bd8833
--- /dev/null
+++ b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch
@@ -0,0 +1,90 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Fri, 23 Oct 2015 18:01:06 +0530
+Subject: [PATCH] ath10k: remove shadow copy of CE descriptors for source
+ ring
+
+For the messages from host to target, shadow copy of CE descriptors
+are maintained in source ring. Before writing actual CE descriptor,
+first shadow copy is filled and then it is copied to CE address space.
+To optimize in download path and to reduce d-cache pressure, removing
+shadow copy of CE descriptors. This will also reduce driver memory
+consumption by 33KB during on device probing.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/ce.c
++++ b/drivers/net/wireless/ath/ath10k/ce.c
+@@ -921,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *
+ src_ring->base_addr_ce_space_unaligned,
+ CE_DESC_RING_ALIGN);
+
+- /*
+- * Also allocate a shadow src ring in regular
+- * mem to use for faster access.
+- */
+- src_ring->shadow_base_unaligned =
+- kmalloc((nentries * sizeof(struct ce_desc) +
+- CE_DESC_RING_ALIGN), GFP_KERNEL);
+- if (!src_ring->shadow_base_unaligned) {
+- dma_free_coherent(ar->dev,
+- (nentries * sizeof(struct ce_desc) +
+- CE_DESC_RING_ALIGN),
+- src_ring->base_addr_owner_space,
+- src_ring->base_addr_ce_space);
+- kfree(src_ring);
+- return ERR_PTR(-ENOMEM);
+- }
+-
+- src_ring->shadow_base = PTR_ALIGN(
+- src_ring->shadow_base_unaligned,
+- CE_DESC_RING_ALIGN);
+-
+ return src_ring;
+ }
+
+@@ -1120,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *
+ struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
+
+ if (ce_state->src_ring) {
+- kfree(ce_state->src_ring->shadow_base_unaligned);
+ dma_free_coherent(ar->dev,
+ (ce_state->src_ring->nentries *
+ sizeof(struct ce_desc) +
+--- a/drivers/net/wireless/ath/ath10k/ce.h
++++ b/drivers/net/wireless/ath/ath10k/ce.h
+@@ -100,12 +100,6 @@ struct ath10k_ce_ring {
+
+ /* CE address space */
+ u32 base_addr_ce_space;
+- /*
+- * Start of shadow copy of descriptors, within regular memory.
+- * Aligned to descriptor-size boundary.
+- */
+- void *shadow_base_unaligned;
+- struct ce_desc *shadow_base;
+
+ /* keep last */
+ void *per_transfer_context[0];
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -1594,7 +1594,6 @@ static void ath10k_pci_tx_pipe_cleanup(s
+ struct ath10k_pci *ar_pci;
+ struct ath10k_ce_pipe *ce_pipe;
+ struct ath10k_ce_ring *ce_ring;
+- struct ce_desc *ce_desc;
+ struct sk_buff *skb;
+ int i;
+
+@@ -1609,10 +1608,6 @@ static void ath10k_pci_tx_pipe_cleanup(s
+ if (!pci_pipe->buf_sz)
+ return;
+
+- ce_desc = ce_ring->shadow_base;
+- if (WARN_ON(!ce_desc))
+- return;
+-
+ for (i = 0; i < ce_ring->nentries; i++) {
+ skb = ce_ring->per_transfer_context[i];
+ if (!skb)
diff --git a/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch
new file mode 100644
index 0000000..cc79dd7
--- /dev/null
+++ b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch
@@ -0,0 +1,77 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Tue, 27 Oct 2015 17:51:11 +0530
+Subject: [PATCH] ath10k: remove supported chain mask
+
+Removing supported chainmask fields as it can be always derived
+from num_rf_chains.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -745,8 +745,6 @@ struct ath10k {
+ int num_started_vdevs;
+
+ /* Protected by conf-mutex */
+- u8 supp_tx_chainmask;
+- u8 supp_rx_chainmask;
+ u8 cfg_tx_chainmask;
+ u8 cfg_rx_chainmask;
+
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct iee
+
+ 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;
+- }
++ *tx_ant = ar->cfg_tx_chainmask;
++ *rx_ant = ar->cfg_rx_chainmask;
+
+ mutex_unlock(&ar->conf_mutex);
+
+@@ -3884,9 +3879,7 @@ static int ath10k_start(struct ieee80211
+ }
+ }
+
+- if (ar->cfg_tx_chainmask)
+- __ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
+- ar->cfg_rx_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
+@@ -7169,8 +7162,8 @@ int ath10k_mac_register(struct ath10k *a
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+- ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
+- ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
++ ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask;
++ ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask;
+
+ if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
+ ar->hw->wiphy->interface_modes |=
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -4460,8 +4460,10 @@ static void ath10k_wmi_event_service_rea
+ ar->num_rf_chains = ar->max_spatial_stream;
+ }
+
+- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
+- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
++ if (!ar->cfg_tx_chainmask) {
++ ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1;
++ ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1;
++ }
+
+ if (strlen(ar->hw->wiphy->fw_version) == 0) {
+ snprintf(ar->hw->wiphy->fw_version,
diff --git a/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch
new file mode 100644
index 0000000..b4ca9ca
--- /dev/null
+++ b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch
@@ -0,0 +1,37 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Tue, 27 Oct 2015 17:51:12 +0530
+Subject: [PATCH] ath10k: fill HT/VHT MCS rateset only for configured
+ chainmask
+
+HT/VHT MCS rateset should be filled only for configured chainmask
+rather that max supported chainmask. Fix that by checking configured
+chainmask while filling HT/VHT MCS rate map.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -6984,7 +6984,7 @@ static struct ieee80211_sta_vht_cap ath1
+
+ mcs_map = 0;
+ for (i = 0; i < 8; i++) {
+- if (i < ar->num_rf_chains)
++ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
+ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
+ else
+ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
+@@ -7051,8 +7051,10 @@ static struct ieee80211_sta_ht_cap ath10
+ if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
+ ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+- for (i = 0; i < ar->num_rf_chains; i++)
+- ht_cap.mcs.rx_mask[i] = 0xFF;
++ for (i = 0; i < ar->num_rf_chains; i++) {
++ if (ar->cfg_rx_chainmask & BIT(i))
++ ht_cap.mcs.rx_mask[i] = 0xFF;
++ }
+
+ ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+
diff --git a/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch
new file mode 100644
index 0000000..ea79b1a
--- /dev/null
+++ b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch
@@ -0,0 +1,314 @@
+From: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Tue, 27 Oct 2015 17:51:13 +0530
+Subject: [PATCH] ath10k: move static HT/VHT capability setup functions
+
+Move HT and VHT capabiltity setup static functions to avoid
+forward declaration.
+
+Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -3757,6 +3757,146 @@ static void ath10k_check_chain_mask(stru
+ dbg, cm);
+ }
+
++static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
++{
++ int nsts = ar->vht_cap_info;
++
++ nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
++ nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
++
++ /* If firmware does not deliver to host number of space-time
++ * streams supported, assume it support up to 4 BF STS and return
++ * the value for VHT CAP: nsts-1)
++ */
++ if (nsts == 0)
++ return 3;
++
++ return nsts;
++}
++
++static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
++{
++ int sound_dim = ar->vht_cap_info;
++
++ sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
++ sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
++
++ /* If the sounding dimension is not advertised by the firmware,
++ * let's use a default value of 1
++ */
++ if (sound_dim == 0)
++ return 1;
++
++ return sound_dim;
++}
++
++static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
++{
++ struct ieee80211_sta_vht_cap vht_cap = {0};
++ u16 mcs_map;
++ u32 val;
++ int i;
++
++ vht_cap.vht_supported = 1;
++ vht_cap.cap = ar->vht_cap_info;
++
++ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
++ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
++ val = ath10k_mac_get_vht_cap_bf_sts(ar);
++ val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
++ val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
++
++ vht_cap.cap |= val;
++ }
++
++ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
++ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
++ val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
++ val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
++ val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
++
++ vht_cap.cap |= val;
++ }
++
++ mcs_map = 0;
++ for (i = 0; i < 8; i++) {
++ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
++ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
++ else
++ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
++ }
++
++ vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
++ vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
++
++ return vht_cap;
++}
++
++static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
++{
++ int i;
++ struct ieee80211_sta_ht_cap ht_cap = {0};
++
++ if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
++ return ht_cap;
++
++ ht_cap.ht_supported = 1;
++ ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
++ ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
++ ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
++ ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
++ ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
++
++ if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
++ ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
++
++ if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
++ ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
++
++ if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
++ u32 smps;
++
++ smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
++ smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
++
++ ht_cap.cap |= smps;
++ }
++
++ if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
++ ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
++
++ if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
++ u32 stbc;
++
++ stbc = ar->ht_cap_info;
++ stbc &= WMI_HT_CAP_RX_STBC;
++ stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
++ stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
++ stbc &= IEEE80211_HT_CAP_RX_STBC;
++
++ ht_cap.cap |= stbc;
++ }
++
++ if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
++ ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
++
++ if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
++ ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
++
++ /* max AMSDU is implicitly taken from vht_cap_info */
++ if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
++ ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
++
++ for (i = 0; i < ar->num_rf_chains; i++) {
++ if (ar->cfg_rx_chainmask & BIT(i))
++ ht_cap.mcs.rx_mask[i] = 0xFF;
++ }
++
++ ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
++
++ return ht_cap;
++}
++
+ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
+ {
+ int ret;
+@@ -4068,39 +4208,6 @@ static u32 get_nss_from_chainmask(u16 ch
+ return 1;
+ }
+
+-static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
+-{
+- int nsts = ar->vht_cap_info;
+-
+- nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
+- nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
+-
+- /* If firmware does not deliver to host number of space-time
+- * streams supported, assume it support up to 4 BF STS and return
+- * the value for VHT CAP: nsts-1)
+- * */
+- if (nsts == 0)
+- return 3;
+-
+- return nsts;
+-}
+-
+-static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
+-{
+- int sound_dim = ar->vht_cap_info;
+-
+- sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
+- sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
+-
+- /* If the sounding dimension is not advertised by the firmware,
+- * let's use a default value of 1
+- */
+- if (sound_dim == 0)
+- return 1;
+-
+- return sound_dim;
+-}
+-
+ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
+ {
+ u32 value = 0;
+@@ -6954,113 +7061,6 @@ static const struct ieee80211_iface_comb
+ },
+ };
+
+-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
+-{
+- struct ieee80211_sta_vht_cap vht_cap = {0};
+- u16 mcs_map;
+- u32 val;
+- int i;
+-
+- vht_cap.vht_supported = 1;
+- vht_cap.cap = ar->vht_cap_info;
+-
+- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
+- val = ath10k_mac_get_vht_cap_bf_sts(ar);
+- val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
+- val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
+-
+- vht_cap.cap |= val;
+- }
+-
+- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
+- IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
+- val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
+- val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
+- val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
+-
+- vht_cap.cap |= val;
+- }
+-
+- mcs_map = 0;
+- for (i = 0; i < 8; i++) {
+- if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
+- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
+- else
+- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
+- }
+-
+- vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+- vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+-
+- return vht_cap;
+-}
+-
+-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
+-{
+- int i;
+- struct ieee80211_sta_ht_cap ht_cap = {0};
+-
+- if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
+- return ht_cap;
+-
+- ht_cap.ht_supported = 1;
+- ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+- ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
+- ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+- ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+- ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
+- ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
+- ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
+- u32 smps;
+-
+- smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
+- smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
+-
+- ht_cap.cap |= smps;
+- }
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+- ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
+- u32 stbc;
+-
+- stbc = ar->ht_cap_info;
+- stbc &= WMI_HT_CAP_RX_STBC;
+- stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
+- stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
+- stbc &= IEEE80211_HT_CAP_RX_STBC;
+-
+- ht_cap.cap |= stbc;
+- }
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
+- ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
+-
+- if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
+- ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
+-
+- /* max AMSDU is implicitly taken from vht_cap_info */
+- if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
+- ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+-
+- for (i = 0; i < ar->num_rf_chains; i++) {
+- if (ar->cfg_rx_chainmask & BIT(i))
+- ht_cap.mcs.rx_mask[i] = 0xFF;
+- }
+-
+- ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
+-
+- return ht_cap;
+-}
+-
+ static void ath10k_get_arvif_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+ {
diff --git a/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch b/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch
new file mode 100644
index 0000000..7424ca4
--- /dev/null
+++ b/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch
@@ -0,0 +1,42 @@
+From: Matthias Schiffer <mschiffer@universe-factory.net>
+Date: Sat, 24 Oct 2015 21:25:51 +0200
+Subject: [PATCH] mac80211: fix crash on mesh local link ID generation with
+ VIFs
+
+llid_in_use needs to be limited to stations of the same VIF, otherwise it
+will cause a NULL deref as the sta_info of non-mesh-VIFs don't have
+sta->mesh set.
+
+Steps to reproduce:
+
+ modprobe mac80211_hwsim channels=2
+ iw phy phy0 interface add ibss0 type ibss
+ iw phy phy0 interface add mesh0 type mp
+ iw phy phy1 interface add ibss1 type ibss
+ iw phy phy1 interface add mesh1 type mp
+ ip link set ibss0 up
+ ip link set mesh0 up
+ ip link set ibss1 up
+ ip link set mesh1 up
+ iw dev ibss0 ibss join foo 2412
+ iw dev ibss1 ibss join foo 2412
+ # Ensure that ibss0 and ibss1 are actually associated; I often need to
+ # leave and join the cell on ibss1 a second time.
+ iw dev mesh0 mesh join bar
+ iw dev mesh1 mesh join bar # crash
+
+Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
+---
+
+--- a/net/mac80211/mesh_plink.c
++++ b/net/mac80211/mesh_plink.c
+@@ -686,6 +686,9 @@ static bool llid_in_use(struct ieee80211
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
++ if (sdata != sta->sdata)
++ continue;
++
+ if (!memcmp(&sta->mesh->llid, &llid, sizeof(llid))) {
+ in_use = true;
+ break;
diff --git a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch
new file mode 100644
index 0000000..72e9a41
--- /dev/null
+++ b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch
@@ -0,0 +1,30 @@
+--- a/drivers/net/wireless/ath/Makefile
++++ b/drivers/net/wireless/ath/Makefile
+@@ -13,10 +13,10 @@ ath-objs := main.o \
+ regd.o \
+ hw.o \
+ key.o \
++ debug.o \
+ dfs_pattern_detector.o \
+ dfs_pri_detector.o
+
+-ath-$(CPTCFG_ATH_DEBUG) += debug.o
+ ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
+
+ ccflags-y += -D__CHECK_ENDIAN__
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -318,13 +318,6 @@ void _ath_dbg(struct ath_common *common,
+ #endif /* CPTCFG_ATH_DEBUG */
+
+ /** Returns string describing opmode, or NULL if unknown mode. */
+-#ifdef CPTCFG_ATH_DEBUG
+ const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+-#else
+-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+-{
+- return "UNKNOWN";
+-}
+-#endif
+
+ #endif /* ATH_H */
diff --git a/package/kernel/mac80211/patches/401-ath9k_blink_default.patch b/package/kernel/mac80211/patches/401-ath9k_blink_default.patch
new file mode 100644
index 0000000..4a997f1
--- /dev/null
+++ b/package/kernel/mac80211/patches/401-ath9k_blink_default.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -45,7 +45,7 @@ int ath9k_modparam_nohwcrypt;
+ module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+-int ath9k_led_blink;
++int ath9k_led_blink = 1;
+ module_param_named(blink, ath9k_led_blink, int, 0444);
+ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
diff --git a/package/kernel/mac80211/patches/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/402-ath_regd_optional.patch
new file mode 100644
index 0000000..1000cd8
--- /dev/null
+++ b/package/kernel/mac80211/patches/402-ath_regd_optional.patch
@@ -0,0 +1,69 @@
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -341,6 +341,10 @@ ath_reg_apply_beaconing_flags(struct wip
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++#ifdef CPTCFG_ATH_USER_REGD
++ return;
++#endif
++
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!wiphy->bands[band])
+ continue;
+@@ -374,6 +378,10 @@ ath_reg_apply_ir_flags(struct wiphy *wip
+ {
+ struct ieee80211_supported_band *sband;
+
++#ifdef CPTCFG_ATH_USER_REGD
++ return;
++#endif
++
+ sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+ if (!sband)
+ return;
+@@ -402,6 +410,10 @@ static void ath_reg_apply_radar_flags(st
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++#ifdef CPTCFG_ATH_USER_REGD
++ return;
++#endif
++
+ if (!wiphy->bands[IEEE80211_BAND_5GHZ])
+ return;
+
+@@ -633,6 +645,11 @@ ath_regd_init_wiphy(struct ath_regulator
+ const struct ieee80211_regdomain *regd;
+
+ wiphy->reg_notifier = reg_notifier;
++
++#ifdef CPTCFG_ATH_USER_REGD
++ return 0;
++#endif
++
+ wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+ REGULATORY_CUSTOM_REG;
+
+--- a/drivers/net/wireless/ath/Kconfig
++++ b/drivers/net/wireless/ath/Kconfig
+@@ -22,6 +22,9 @@ menuconfig ATH_CARDS
+
+ if ATH_CARDS
+
++config ATH_USER_REGD
++ bool "Do not enforce EEPROM regulatory restrictions"
++
+ config ATH_DEBUG
+ bool "Atheros wireless debugging"
+ ---help---
+--- a/.local-symbols
++++ b/.local-symbols
+@@ -140,6 +140,7 @@ RTL8187_LEDS=
+ ATH_COMMON=
+ ATH_CARDS=
+ ATH_DEBUG=
++ATH_USER_REGD=
+ ATH_TRACEPOINTS=
+ ATH_REG_DYNAMIC_USER_REG_HINTS=
+ ATH_REG_DYNAMIC_USER_CERT_TESTING=
diff --git a/package/kernel/mac80211/patches/403-world_regd_fixup.patch b/package/kernel/mac80211/patches/403-world_regd_fixup.patch
new file mode 100644
index 0000000..2b04309
--- /dev/null
+++ b/package/kernel/mac80211/patches/403-world_regd_fixup.patch
@@ -0,0 +1,84 @@
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -43,7 +43,8 @@ static int __ath_regd_init(struct ath_re
+ NL80211_RRF_NO_OFDM)
+
+ /* We allow IBSS on these on a case by case basis by regulatory domain */
+-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
++#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
++ REG_RULE(5260-10, 5350+10, 80, 0, 30,\
+ NL80211_RRF_NO_IR)
+ #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
+ NL80211_RRF_NO_IR)
+@@ -61,57 +62,56 @@ static int __ath_regd_init(struct ath_re
+ #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
+ ATH9K_5GHZ_5725_5850
+
++#define REGD_RULES(...) \
++ .reg_rules = { __VA_ARGS__ }, \
++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
++
+ /* Can be used for:
+ * 0x60, 0x61, 0x62 */
+ static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+- .n_reg_rules = 5,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_ALL,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x63 and 0x65 */
+ static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x64 only */
+ static const struct ieee80211_regdomain ath_world_regdom_64 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x66 and 0x69 */
+ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
diff --git a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch
new file mode 100644
index 0000000..ca11199
--- /dev/null
+++ b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch
@@ -0,0 +1,19 @@
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -2480,6 +2480,8 @@ void regulatory_hint_country_ie(struct w
+ enum environment_cap env = ENVIRON_ANY;
+ struct regulatory_request *request = NULL, *lr;
+
++ return;
++
+ /* IE len must be evenly divisible by 2 */
+ if (country_ie_len & 0x01)
+ return;
+@@ -2686,6 +2688,7 @@ static void restore_regulatory_settings(
+
+ void regulatory_hint_disconnect(void)
+ {
++ return;
+ REG_DBG_PRINT("All devices are disconnected, going to restore regulatory settings\n");
+ restore_regulatory_settings(false);
+ }
diff --git a/package/kernel/mac80211/patches/405-ath_regd_us.patch b/package/kernel/mac80211/patches/405-ath_regd_us.patch
new file mode 100644
index 0000000..cc55877
--- /dev/null
+++ b/package/kernel/mac80211/patches/405-ath_regd_us.patch
@@ -0,0 +1,26 @@
+--- a/drivers/net/wireless/ath/regd_common.h
++++ b/drivers/net/wireless/ath/regd_common.h
+@@ -32,6 +32,7 @@ enum EnumRd {
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
++ FCC3_FCCA_2 = 0x2A,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo
+ {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+ {FCC3_FCCA, CTL_FCC, CTL_FCC},
++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
+ {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC4_FCCA, CTL_FCC, CTL_FCC},
+ {FCC5_FCCA, CTL_FCC, CTL_FCC},
+@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al
+ {CTRY_UAE, NULL1_WORLD, "AE"},
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
+ /* This "PS" is for US public safety actually... to support this we
+ * would need to assign new special alpha2 to CRDA db as with the world
+ * regdomain and use another alpha2 */
diff --git a/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch
new file mode 100644
index 0000000..6336f1f
--- /dev/null
+++ b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch
@@ -0,0 +1,47 @@
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -114,10 +114,22 @@ static const struct ieee80211_regdomain
+ )
+ };
+
++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
++{
++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
++}
++
++static bool is_default_regd(struct ath_regulatory *reg)
++{
++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT;
++}
++
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+ {
+ if (config_enabled(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+ return true;
++ if (is_default_regd(reg))
++ return true;
+
+ switch (reg->country_code) {
+ case CTRY_UNITED_STATES:
+@@ -202,11 +214,6 @@ static inline bool is_wwr_sku(u16 regd)
+ (regd == WORLD));
+ }
+
+-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
+-{
+- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
+-}
+-
+ bool ath_is_world_regd(struct ath_regulatory *reg)
+ {
+ return is_wwr_sku(ath_regd_get_eepromRD(reg));
+@@ -650,6 +657,9 @@ ath_regd_init_wiphy(struct ath_regulator
+ return 0;
+ #endif
+
++ if (is_default_regd(reg))
++ return 0;
++
+ wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+ REGULATORY_CUSTOM_REG;
+
diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
new file mode 100644
index 0000000..1a62484
--- /dev/null
+++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -722,6 +722,7 @@ static const struct ieee80211_iface_limi
+ BIT(NL80211_IFTYPE_AP) },
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ static const struct ieee80211_iface_limit wds_limits[] = {
diff --git a/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
new file mode 100644
index 0000000..2a5ab3d
--- /dev/null
+++ b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
@@ -0,0 +1,46 @@
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw
+ goto end;
+ }
+
+- /* Don't allow other interfaces if one ad-hoc is configured.
+- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+- * We would need to operate the HW in ad-hoc mode to allow TSF updates
+- * for the IBSS, but this breaks with additional AP or STA interfaces
+- * at the moment. */
+- if (ah->num_adhoc_vifs ||
+- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
++ /* Don't allow more than one ad-hoc interface */
++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1965,7 +1965,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+ }
+
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+- ah->num_mesh_vifs > 1) ||
++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+@@ -2051,7 +2051,7 @@ ath5k_beacon_update_timers(struct ath5k_
+
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+- + ah->num_mesh_vifs > 1) {
++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
+@@ -2518,6 +2518,7 @@ static const struct ieee80211_iface_limi
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
+ BIT(NL80211_IFTYPE_AP) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ static const struct ieee80211_iface_combination if_comb = {
diff --git a/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch b/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch
new file mode 100644
index 0000000..414f495
--- /dev/null
+++ b/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch
@@ -0,0 +1,18 @@
+--- a/drivers/net/wireless/ath/ath5k/reset.c
++++ b/drivers/net/wireless/ath/ath5k/reset.c
+@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ tsf_lo = 0;
+ mode = 0;
+
++#if 0
+ /*
+ * Sanity check for fast flag
+ * Fast channel change only available
+@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ */
+ if (fast && (ah->ah_radio != AR5K_RF2413) &&
+ (ah->ah_radio != AR5K_RF5413))
++#endif
+ fast = false;
+
+ /* Disable sleep clock operation
diff --git a/package/kernel/mac80211/patches/430-add_ath5k_platform.patch b/package/kernel/mac80211/patches/430-add_ath5k_platform.patch
new file mode 100644
index 0000000..b213e2a
--- /dev/null
+++ b/package/kernel/mac80211/patches/430-add_ath5k_platform.patch
@@ -0,0 +1,33 @@
+--- /dev/null
++++ b/include/linux/ath5k_platform.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2008 Atheros Communications Inc.
++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _LINUX_ATH5K_PLATFORM_H
++#define _LINUX_ATH5K_PLATFORM_H
++
++#define ATH5K_PLAT_EEP_MAX_WORDS 2048
++
++struct ath5k_platform_data {
++ u16 *eeprom_data;
++ u8 *macaddr;
++};
++
++#endif /* _LINUX_ATH5K_PLATFORM_H */
diff --git a/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch b/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
new file mode 100644
index 0000000..cdc9315
--- /dev/null
+++ b/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
@@ -0,0 +1,56 @@
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -21,6 +21,7 @@
+ #include <linux/pci-aspm.h>
+ #include <linux/etherdevice.h>
+ #include <linux/module.h>
++#include <linux/ath5k_platform.h>
+ #include "../ath.h"
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -72,7 +73,7 @@ static void ath5k_pci_read_cachesize(str
+ }
+
+ /*
+- * Read from eeprom
++ * Read from eeprom or platform_data
+ */
+ static bool
+ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+@@ -80,6 +81,19 @@ ath5k_pci_eeprom_read(struct ath_common
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
+ u32 status, timeout;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) {
++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
++ return false;
++
++ *data = pdata->eeprom_data[offset];
++ return true;
++ }
++
+ /*
+ * Initialize EEPROM access
+ */
+@@ -123,6 +137,16 @@ static int ath5k_pci_eeprom_read_mac(str
+ u16 data;
+ int octet;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->macaddr) {
++ memcpy(mac, pdata->macaddr, ETH_ALEN);
++ return 0;
++ }
++
+ AR5K_EEPROM_READ(0x20, data);
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
diff --git a/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch b/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch
new file mode 100644
index 0000000..d82f800
--- /dev/null
+++ b/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -48,6 +48,8 @@ static const struct pci_device_id ath5k_
+ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
+ { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
+ { 0 }
+ };
diff --git a/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
new file mode 100644
index 0000000..924b62e
--- /dev/null
+++ b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch
@@ -0,0 +1,143 @@
+This adds a bwmode debugfs file which can be used to set alternate
+channel operating bandwidths. Only tested with AR5413 and only at
+5 and 20 mhz channels.
+
+Signed-off-by: Pat Erley <pat-lkml at erley.org>
+---
+Other devices will need to be added to the switch in write_file_bwmode
+
+drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
+ 1 files changed, 86 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath5k/debug.c
++++ b/drivers/net/wireless/ath/ath5k/debug.c
+@@ -823,6 +823,97 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++/* debugfs: bwmode */
++
++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[15];
++ unsigned int len = 0;
++
++ int cur_ah_bwmode = ah->ah_bwmode_debug;
++
++#define print_selected(MODE, LABEL) \
++ if (cur_ah_bwmode == MODE) \
++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
++ else \
++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
++ len += snprintf(buf+len, sizeof(buf)-len, " ");
++
++ print_selected(AR5K_BWMODE_5MHZ, "5");
++ print_selected(AR5K_BWMODE_10MHZ, "10");
++ print_selected(AR5K_BWMODE_DEFAULT, "20");
++ print_selected(AR5K_BWMODE_40MHZ, "40");
++#undef print_selected
++
++ len += snprintf(buf+len, sizeof(buf)-len, "\n");
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_bwmode(struct file *file,
++ const char __user *userbuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[3];
++ int bw = 20;
++ int tobwmode = AR5K_BWMODE_DEFAULT;
++
++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
++ return -EFAULT;
++
++ /* TODO: Add check for active interface */
++
++ if(strncmp(buf, "5", 1) == 0 ) {
++ tobwmode = AR5K_BWMODE_5MHZ;
++ bw = 5;
++ } else if ( strncmp(buf, "10", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_10MHZ;
++ bw = 10;
++ } else if ( strncmp(buf, "20", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_DEFAULT;
++ bw = 20;
++ } else if ( strncmp(buf, "40", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_40MHZ;
++ bw = 40;
++ } else
++ return -EINVAL;
++
++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
++ bw, tobwmode);
++
++ switch (ah->ah_radio) {
++ /* TODO: only define radios that actually support 5/10mhz channels */
++ case AR5K_RF5413:
++ case AR5K_RF5110:
++ case AR5K_RF5111:
++ case AR5K_RF5112:
++ case AR5K_RF2413:
++ case AR5K_RF2316:
++ case AR5K_RF2317:
++ case AR5K_RF2425:
++ if(ah->ah_bwmode_debug != tobwmode) {
++ mutex_lock(&ah->lock);
++ ah->ah_bwmode = tobwmode;
++ ah->ah_bwmode_debug = tobwmode;
++ mutex_unlock(&ah->lock);
++ }
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return count;
++}
++
++static const struct file_operations fops_bwmode = {
++ .read = read_file_bwmode,
++ .write = write_file_bwmode,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
+
+ /* debugfs: queues etc */
+
+@@ -1010,6 +1101,9 @@ ath5k_debug_init_device(struct ath5k_hw
+ debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
+ &fops_beacon);
+
++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
++ &fops_bwmode);
++
+ debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
+
+ debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1372,6 +1372,7 @@ struct ath5k_hw {
+ u8 ah_coverage_class;
+ bool ah_ack_bitrate_high;
+ u8 ah_bwmode;
++ u8 ah_bwmode_debug;
+ bool ah_short_slot;
+
+ /* Antenna Control */
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru
+ return -EINVAL;
+ }
+
++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
++ ah->ah_bwmode = ah->ah_bwmode_debug;
++
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
new file mode 100644
index 0000000..a7f9d9f
--- /dev/null
+++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch
@@ -0,0 +1,65 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1301,6 +1301,53 @@ void ath9k_deinit_debug(struct ath_softc
+ ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
+ }
+
++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
++ int bytes = 0;
++ int pos = *ppos;
++ int size = 4096;
++ u16 val;
++ int i;
++
++ if (AR_SREV_9300_20_OR_LATER(ah))
++ size = 16384;
++
++ if (*ppos < 0)
++ return -EINVAL;
++
++ if (count > size - *ppos)
++ count = size - *ppos;
++
++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
++ void *from = &val;
++
++ if (!common->bus_ops->eeprom_read(common, i, &val))
++ val = 0xffff;
++
++ if (*ppos % 2) {
++ from++;
++ bytes = 1;
++ } else if (count == 1) {
++ bytes = 1;
++ } else {
++ bytes = 2;
++ }
++ copy_to_user(user_buf, from, bytes);
++ user_buf += bytes;
++ }
++ return *ppos - pos;
++}
++
++static const struct file_operations fops_eeprom = {
++ .read = read_file_eeprom,
++ .open = simple_open,
++ .owner = THIS_MODULE
++};
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1320,6 +1367,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ ath9k_tx99_init_debug(sc);
+ ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
+
++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
++ &fops_eeprom);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
new file mode 100644
index 0000000..143545c
--- /dev/null
+++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch
@@ -0,0 +1,32 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -1038,23 +1038,23 @@ static int __init ath9k_init(void)
+ {
+ int error;
+
+- error = ath_pci_init();
++ error = ath_ahb_init();
+ if (error < 0) {
+- pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+ goto err_out;
+ }
+
+- error = ath_ahb_init();
++ error = ath_pci_init();
+ if (error < 0) {
++ pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+- goto err_pci_exit;
++ goto err_ahb_exit;
+ }
+
+ return 0;
+
+- err_pci_exit:
+- ath_pci_exit();
++ err_ahb_exit:
++ ath_ahb_exit();
+ err_out:
+ return error;
+ }
diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
new file mode 100644
index 0000000..d2a3b96
--- /dev/null
+++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
@@ -0,0 +1,18 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct
+
+ ah->config.rx_intr_mitigation = true;
+
+- if (AR_SREV_9300_20_OR_LATER(ah)) {
+- ah->config.rimt_last = 500;
+- ah->config.rimt_first = 2000;
+- } else {
+- ah->config.rimt_last = 250;
+- ah->config.rimt_first = 700;
+- }
++ ah->config.rimt_last = 250;
++ ah->config.rimt_first = 500;
+
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+ ah->config.pll_pwrsave = 7;
diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
new file mode 100644
index 0000000..d4104f0
--- /dev/null
+++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -87,7 +87,7 @@ int ath_descdma_setup(struct ath_softc *
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+-#define ATH_RXBUF 512
++#define ATH_RXBUF 256
+ #define ATH_TXBUF 512
+ #define ATH_TXBUF_RESERVE 5
+ #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
new file mode 100644
index 0000000..5ecf528
--- /dev/null
+++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch
@@ -0,0 +1,125 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1348,6 +1348,52 @@ static const struct file_operations fops
+ .owner = THIS_MODULE
+ };
+
++
++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08x\n", common->chan_bw);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ unsigned long chan_bw;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &chan_bw))
++ return -EINVAL;
++
++ common->chan_bw = chan_bw;
++ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
++ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++
++ return count;
++}
++
++static const struct file_operations fops_chanbw = {
++ .read = read_file_chan_bw,
++ .write = write_file_chan_bw,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1369,6 +1415,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+
+ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_eeprom);
++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_chanbw);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -151,6 +151,7 @@ struct ath_common {
+ int debug_mask;
+ enum ath_device_state state;
+ unsigned long op_flags;
++ u32 chan_bw;
+
+ struct ath_ani ani;
+
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -296,11 +296,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
+ /*
+ * Update internal channel flags.
+ */
+-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++static void ath9k_cmn_update_ichannel(struct ath_common *common,
++ struct ath9k_channel *ichan,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *chan = chandef->chan;
+ u16 flags = 0;
++ int width;
+
+ ichan->channel = chan->center_freq;
+ ichan->chan = chan;
+@@ -308,7 +310,19 @@ static void ath9k_cmn_update_ichannel(st
+ if (chan->band == IEEE80211_BAND_5GHZ)
+ flags |= CHANNEL_5GHZ;
+
+- switch (chandef->width) {
++ switch (common->chan_bw) {
++ case 5:
++ width = NL80211_CHAN_WIDTH_5;
++ break;
++ case 10:
++ width = NL80211_CHAN_WIDTH_10;
++ break;
++ default:
++ width = chandef->width;
++ break;
++ }
++
++ switch (width) {
+ case NL80211_CHAN_WIDTH_5:
+ flags |= CHANNEL_QUARTER;
+ break;
+@@ -341,10 +355,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *curchan = chandef->chan;
++ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *channel;
+
+ channel = &ah->channels[curchan->hw_value];
+- ath9k_cmn_update_ichannel(channel, chandef);
++ ath9k_cmn_update_ichannel(common, channel, chandef);
+
+ return channel;
+ }
diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
new file mode 100644
index 0000000..c84d1bc
--- /dev/null
+++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch
@@ -0,0 +1,30 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -651,6 +651,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+
+ /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
+ switch (ah->hw_version.devid) {
++ case AR9300_DEVID_INVALID:
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR5416_AR9100_DEVID:
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -36,6 +36,7 @@
+
+ #define ATHEROS_VENDOR_ID 0x168c
+
++#define AR9300_DEVID_INVALID 0xabcd
+ #define AR5416_DEVID_PCI 0x0023
+ #define AR5416_DEVID_PCIE 0x0024
+ #define AR9160_DEVID_PCI 0x0027
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -751,6 +751,7 @@ static const struct pci_device_id ath_pc
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
+ #endif
+
++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
+ { 0 }
+ };
+
diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
new file mode 100644
index 0000000..be7bd58
--- /dev/null
+++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch
@@ -0,0 +1,160 @@
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2361,6 +2361,7 @@ struct cfg80211_qos_map {
+ * (as advertised by the nl80211 feature flag.)
+ * @get_tx_power: store the current TX power into the dbm variable;
+ * return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+ *
+ * @set_wds_peer: set the WDS peer for a WDS interface
+ *
+@@ -2617,6 +2618,7 @@ struct cfg80211_ops {
+ enum nl80211_tx_power_setting type, int mbm);
+ int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ int *dbm);
++ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1250,6 +1250,7 @@ enum ieee80211_smps_mode {
+ *
+ * @power_level: requested transmit power (in dBm), backward compatibility
+ * value only that is set to the minimum of all interfaces
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+ *
+ * @chandef: the channel definition to tune to
+ * @radar_enabled: whether radar detection is enabled
+@@ -1270,6 +1271,7 @@ enum ieee80211_smps_mode {
+ struct ieee80211_conf {
+ u32 flags;
+ int power_level, dynamic_ps_timeout;
++ int max_antenna_gain;
+
+ u16 listen_interval;
+ u8 ps_dtim_period;
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -1783,6 +1783,9 @@ enum nl80211_commands {
+ * between scans. The scan plans are executed sequentially.
+ * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan.
+ *
++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
++ * transmit power to stay within regulatory limits. u32, dBi.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -2157,6 +2160,8 @@ enum nl80211_attrs {
+ NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
+ NL80211_ATTR_SCHED_SCAN_PLANS,
+
++ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2206,6 +2206,19 @@ static int ieee80211_get_tx_power(struct
+ return 0;
+ }
+
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++ struct ieee80211_local *local = wiphy_priv(wiphy);
++
++ if (dbi < 0)
++ return -EINVAL;
++
++ local->user_antenna_gain = dbi;
++ ieee80211_hw_config(local, 0);
++
++ return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr)
+ {
+@@ -3849,6 +3862,7 @@ const struct cfg80211_ops mac80211_confi
+ .set_wiphy_params = ieee80211_set_wiphy_params,
+ .set_tx_power = ieee80211_set_tx_power,
+ .get_tx_power = ieee80211_get_tx_power,
++ .set_antenna_gain = ieee80211_set_antenna_gain,
+ .set_wds_peer = ieee80211_set_wds_peer,
+ .rfkill_poll = ieee80211_rfkill_poll,
+ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1321,6 +1321,7 @@ struct ieee80211_local {
+ int dynamic_ps_forced_timeout;
+
+ int user_power_level; /* in dBm, for all interfaces */
++ int user_antenna_gain; /* in dBi */
+
+ enum ieee80211_smps_mode smps_mode;
+
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct
+ struct ieee80211_sub_if_data *sdata;
+ struct cfg80211_chan_def chandef = {};
+ u32 changed = 0;
+- int power;
++ int power, max_power;
+ u32 offchannel_flag;
+
+ offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct
+ }
+ rcu_read_unlock();
+
++ max_power = chandef.chan->max_reg_power;
++ if (local->user_antenna_gain > 0) {
++ max_power -= local->user_antenna_gain;
++ power = min(power, max_power);
++ }
++
+ if (local->hw.conf.power_level != power) {
+ changed |= IEEE80211_CONF_CHANGE_POWER;
+ local->hw.conf.power_level = power;
+@@ -580,6 +586,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+ IEEE80211_RADIOTAP_MCS_HAVE_BW;
+ local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
++ local->user_antenna_gain = 0;
+ local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -403,6 +403,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
+ [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+
+ /* policy for the key attributes */
+@@ -2220,6 +2221,20 @@ static int nl80211_set_wiphy(struct sk_b
+ if (result)
+ return result;
+ }
++
++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++ int idx, dbi = 0;
++
++ if (!rdev->ops->set_antenna_gain)
++ return -EOPNOTSUPP;
++
++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++ dbi = nla_get_u32(info->attrs[idx]);
++
++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++ if (result)
++ return result;
++ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+ info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
new file mode 100644
index 0000000..89e3c97
--- /dev/null
+++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch
@@ -0,0 +1,251 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -813,6 +813,9 @@ static inline int ath9k_dump_btcoex(stru
+ void ath_init_leds(struct ath_softc *sc);
+ void ath_deinit_leds(struct ath_softc *sc);
+ void ath_fill_led_pin(struct ath_softc *sc);
++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
++ const char *trigger, bool active_low);
++
+ #else
+ static inline void ath_init_leds(struct ath_softc *sc)
+ {
+@@ -952,6 +955,13 @@ void ath_ant_comb_scan(struct ath_softc
+
+ #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
+
++struct ath_led {
++ struct list_head list;
++ struct ath_softc *sc;
++ const struct gpio_led *gpio;
++ struct led_classdev cdev;
++};
++
+ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+@@ -1003,9 +1013,8 @@ struct ath_softc {
+ spinlock_t chan_lock;
+
+ #ifdef CPTCFG_MAC80211_LEDS
+- bool led_registered;
+- char led_name[32];
+- struct led_classdev led_cdev;
++ const char *led_default_trigger;
++ struct list_head leds;
+ #endif
+
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -24,45 +24,102 @@
+ static void ath_led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+ {
+- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+- u32 val = (brightness == LED_OFF);
++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
++ struct ath_softc *sc = led->sc;
+
+- if (sc->sc_ah->config.led_active_high)
+- val = !val;
++ ath9k_ps_wakeup(sc);
++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
++ (brightness != LED_OFF) ^ led->gpio->active_low);
++ ath9k_ps_restore(sc);
++}
++
++static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
++{
++ const struct gpio_led *gpio = led->gpio;
++ int ret;
++
++ led->cdev.name = gpio->name;
++ led->cdev.default_trigger = gpio->default_trigger;
++ led->cdev.brightness_set = ath_led_brightness;
+
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
++ if (ret < 0)
++ return ret;
++
++ led->sc = sc;
++ list_add(&led->list, &sc->leds);
++
++ /* Configure gpio for output */
++ ath9k_hw_cfg_output(sc->sc_ah, gpio->gpio,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++
++ /* LED off */
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++
++ return 0;
++}
++
++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
++ const char *trigger, bool active_low)
++{
++ struct ath_led *led;
++ struct gpio_led *gpio;
++ char *_name;
++ int ret;
++
++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
++ GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio = (struct gpio_led *) (led + 1);
++ _name = (char *) (led->gpio + 1);
++
++ strcpy(_name, name);
++ gpio->name = _name;
++ gpio->gpio = gpio_num;
++ gpio->active_low = active_low;
++ gpio->default_trigger = trigger;
++
++ ret = ath_add_led(sc, led);
++ if (unlikely(ret < 0))
++ kfree(led);
++
++ return ret;
+ }
+
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+- if (!sc->led_registered)
+- return;
++ struct ath_led *led;
+
+- ath_led_brightness(&sc->led_cdev, LED_OFF);
+- led_classdev_unregister(&sc->led_cdev);
++ while (!list_empty(&sc->leds)) {
++ led = list_first_entry(&sc->leds, struct ath_led, list);
++ list_del(&led->list);
++ ath_led_brightness(&led->cdev, LED_OFF);
++ led_classdev_unregister(&led->cdev);
++ kfree(led);
++ }
+ }
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
+- int ret;
++ char led_name[32];
++ const char *trigger;
++
++ INIT_LIST_HEAD(&sc->leds);
+
+ if (AR_SREV_9100(sc->sc_ah))
+ return;
+
+- if (!ath9k_led_blink)
+- sc->led_cdev.default_trigger =
+- ieee80211_get_radio_led_name(sc->hw);
+-
+- snprintf(sc->led_name, sizeof(sc->led_name),
+- "ath9k-%s", wiphy_name(sc->hw->wiphy));
+- sc->led_cdev.name = sc->led_name;
+- sc->led_cdev.brightness_set = ath_led_brightness;
++ snprintf(led_name, sizeof(led_name), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
+
+- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+- if (ret < 0)
+- return;
++ if (ath9k_led_blink)
++ trigger = sc->led_default_trigger;
++ else
++ trigger = ieee80211_get_radio_led_name(sc->hw);
+
+- sc->led_registered = true;
++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
+ }
+
+ void ath_fill_led_pin(struct ath_softc *sc)
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -950,7 +950,7 @@ int ath9k_init_device(u16 devid, struct
+
+ #ifdef CPTCFG_MAC80211_LEDS
+ /* must be initialized before ieee80211_register_hw */
+- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1393,6 +1393,61 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++#ifdef CONFIG_MAC80211_LEDS
++
++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32], *str, *name, *c;
++ ssize_t len;
++ unsigned int gpio;
++ bool active_low = false;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, ubuf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ name = strchr(buf, ',');
++ if (!name)
++ return -EINVAL;
++
++ *(name++) = 0;
++ if (!*name)
++ return -EINVAL;
++
++ c = strchr(name, '\n');
++ if (c)
++ *c = 0;
++
++ str = buf;
++ if (*str == '!') {
++ str++;
++ active_low = true;
++ }
++
++ if (kstrtouint(str, 0, &gpio) < 0)
++ return -EINVAL;
++
++ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
++ return -EINVAL;
++
++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
++ return -EINVAL;
++
++ return count;
++}
++
++static const struct file_operations fops_gpio_led = {
++ .write = write_file_gpio_led,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++#endif
++
+
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+@@ -1417,6 +1472,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+ &fops_eeprom);
+ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+ sc, &fops_chanbw);
++#ifdef CONFIG_MAC80211_LEDS
++ debugfs_create_file("gpio_led", S_IWUSR,
++ sc->debug.debugfs_phy, sc, &fops_gpio_led);
++#endif
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
diff --git a/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch
new file mode 100644
index 0000000..dc33cd0
--- /dev/null
+++ b/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch
@@ -0,0 +1,71 @@
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -41,6 +41,9 @@ struct ath9k_platform_data {
+ int (*external_reset)(void);
+
+ bool use_eeprom;
++
++ int num_leds;
++ const struct gpio_led *leds;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -15,6 +15,7 @@
+ */
+
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
+
+ /********************************/
+ /* LED functions */
+@@ -88,6 +89,24 @@ int ath_create_gpio_led(struct ath_softc
+ return ret;
+ }
+
++static int ath_create_platform_led(struct ath_softc *sc,
++ const struct gpio_led *gpio)
++{
++ struct ath_led *led;
++ int ret;
++
++ led = kzalloc(sizeof(*led), GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio;
++ ret = ath_add_led(sc, led);
++ if (ret < 0)
++ kfree(led);
++
++ return ret;
++}
++
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+ struct ath_led *led;
+@@ -103,8 +122,10 @@ void ath_deinit_leds(struct ath_softc *s
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+ char led_name[32];
+ const char *trigger;
++ int i;
+
+ INIT_LIST_HEAD(&sc->leds);
+
+@@ -120,6 +141,12 @@ void ath_init_leds(struct ath_softc *sc)
+ trigger = ieee80211_get_radio_led_name(sc->hw);
+
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
++
++ if (!pdata)
++ return;
++
++ for (i = 0; i < pdata->num_leds; i++)
++ ath_create_platform_led(sc, &pdata->leds[i]);
+ }
+
+ void ath_fill_led_pin(struct ath_softc *sc)
diff --git a/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch b/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch
new file mode 100644
index 0000000..e899903
--- /dev/null
+++ b/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -42,7 +42,7 @@
+ #define ATH9K_ANI_PERIOD 300
+
+ /* in ms */
+-#define ATH9K_ANI_POLLINTERVAL 1000
++#define ATH9K_ANI_POLLINTERVAL 300
+
+ #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
+ #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
diff --git a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
new file mode 100644
index 0000000..3c5e9f5
--- /dev/null
+++ b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
@@ -0,0 +1,28 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -695,7 +695,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+ {
+ #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
+ struct ath_common *common = ath9k_hw_common(ah);
+- u32 mac_status, last_mac_status = 0;
++ u32 mac_status = 0, last_mac_status = 0;
+ int i;
+
+ /* Enable access to the DMA observation bus */
+@@ -725,6 +725,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw
+ }
+
+ if (i == 0) {
++ if (!AR_SREV_9300_20_OR_LATER(ah) &&
++ (mac_status & 0x700) == 0) {
++ /*
++ * DMA is idle but the MAC is still stuck
++ * processing events
++ */
++ *reset = true;
++ return true;
++ }
++
+ ath_err(common,
+ "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
+ AH_RX_STOP_DMA_TIMEOUT / 1000,
diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
new file mode 100644
index 0000000..9758d5f
--- /dev/null
+++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch
@@ -0,0 +1,139 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1449,6 +1449,50 @@ static const struct file_operations fops
+ #endif
+
+
++static ssize_t read_file_diag(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08lx\n", ah->diag);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ unsigned long diag;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &diag))
++ return -EINVAL;
++
++ ah->diag = diag;
++ ath9k_hw_update_diag(ah);
++
++ return count;
++}
++
++static const struct file_operations fops_diag = {
++ .read = read_file_diag,
++ .write = write_file_diag,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1476,6 +1520,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ debugfs_create_file("gpio_led", S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_gpio_led);
+ #endif
++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_diag);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -519,6 +519,12 @@ enum {
+ ATH9K_RESET_COLD,
+ };
+
++enum {
++ ATH_DIAG_DISABLE_RX,
++ ATH_DIAG_DISABLE_TX,
++ ATH_DIAG_TRIGGER_ERROR,
++};
++
+ struct ath9k_hw_version {
+ u32 magic;
+ u16 devid;
+@@ -804,6 +810,8 @@ struct ath_hw {
+ u32 rfkill_polarity;
+ u32 ah_flags;
+
++ unsigned long diag;
++
+ bool reset_power_on;
+ bool htc_reset_init;
+
+@@ -1066,6 +1074,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+ bool ath9k_hw_check_alive(struct ath_hw *ah);
+
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
++void ath9k_hw_update_diag(struct ath_hw *ah);
+
+ /* Generic hw timer primitives */
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1809,6 +1809,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
+ }
+ EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+
++void ath9k_hw_update_diag(struct ath_hw *ah)
++{
++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++
++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++}
++EXPORT_SYMBOL(ath9k_hw_update_diag);
++
+ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+@@ -2017,6 +2031,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ ar9003_hw_disable_phy_restart(ah);
+
+ ath9k_hw_apply_gpio_override(ah);
++ ath9k_hw_update_diag(ah);
+
+ if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -533,6 +533,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+ return IRQ_HANDLED;
+
++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
++ status |= ATH9K_INT_FATAL;
++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
++ }
++
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
new file mode 100644
index 0000000..fa8eca5
--- /dev/null
+++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch
@@ -0,0 +1,186 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -720,6 +720,7 @@ struct ath_spec_scan {
+ * @config_pci_powersave:
+ * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ *
++ * @get_adc_entropy: get entropy from the raw ADC I/Q output
+ * @spectral_scan_config: set parameters for spectral scan and enable/disable it
+ * @spectral_scan_trigger: trigger a spectral scan run
+ * @spectral_scan_wait: wait for a spectral scan run to finish
+@@ -742,6 +743,7 @@ struct ath_hw_ops {
+ struct ath_hw_antcomb_conf *antconf);
+ void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
+ void (*spectral_scan_config)(struct ath_hw *ah,
+ struct ath_spec_scan *param);
+ void (*spectral_scan_trigger)(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -1998,6 +1998,26 @@ void ar9003_hw_init_rate_txpower(struct
+ }
+ }
+
++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
++ udelay(1);
++ }
++ }
++}
++
+ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+@@ -2034,6 +2054,7 @@ void ar9003_hw_attach_phy_ops(struct ath
+ priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+ priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
+
++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
+ ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+ ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+ ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -710,7 +710,8 @@ static void ath9k_init_txpower_limits(st
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+- ah->curchan = curchan;
++ if (curchan)
++ ah->curchan = curchan;
+ }
+
+ static const struct ieee80211_iface_limit if_limits[] = {
+@@ -910,6 +911,18 @@ static void ath9k_set_hw_capab(struct at
+ SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+ }
+
++static void ath_get_initial_entropy(struct ath_softc *sc)
++{
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[256];
++
++ /* reuse last channel initialized by the tx power test */
++ ath9k_hw_reset(ah, ah->curchan, NULL, false);
++
++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
++ add_device_randomness(buf, sizeof(buf));
++}
++
+ int ath9k_init_device(u16 devid, struct ath_softc *sc,
+ const struct ath_bus_ops *bus_ops)
+ {
+@@ -955,6 +968,8 @@ int ath9k_init_device(u16 devid, struct
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+
++ ath_get_initial_entropy(sc);
++
+ /* Register with mac80211 */
+ error = ieee80211_register_hw(hw);
+ if (error)
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp
+ ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
+ }
+
++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
++ u8 *buf, size_t len)
++{
++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
++}
++
+ #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
+
+ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -1327,9 +1327,30 @@ void ar5008_hw_init_rate_txpower(struct
+ }
+ }
+
++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
++ udelay(1);
++ }
++ }
++}
++
+ int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
++ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+ static const u32 ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+@@ -1344,6 +1365,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
+ if (ret)
+ return ret;
+
++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
++
+ priv_ops->rf_set_freq = ar5008_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+
+--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+@@ -20,6 +20,12 @@
+ #define PHY_AGC_CLR 0x10000000
+ #define RFSILENT_BB 0x00002000
+
++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
++#define AR_PHY_TEST_BBB_OBS_SEL_S 19
++
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
++
+ #define AR_PHY_TURBO 0x9804
+ #define AR_PHY_FC_TURBO_MODE 0x00000001
+ #define AR_PHY_FC_TURBO_SHORT 0x00000002
+@@ -36,6 +42,9 @@
+
+ #define AR_PHY_TEST2 0x9808
+
++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00
++#define AR_PHY_TEST2_RX_OBS_SEL_S 10
++
+ #define AR_PHY_TIMING2 0x9810
+ #define AR_PHY_TIMING3 0x9814
+ #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+@@ -390,6 +399,8 @@
+ #define AR_PHY_RFBUS_GRANT 0x9C20
+ #define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
++#define AR_PHY_TST_ADC 0x9C24
++
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
diff --git a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
new file mode 100644
index 0000000..3f46226
--- /dev/null
+++ b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch
@@ -0,0 +1,79 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct
+ centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ }
+
++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
++{
++ /* On AR9330 and AR9340 devices, some PHY registers must be
++ * tuned to gain better stability/performance. These registers
++ * might be changed while doing wlan reset so the registers must
++ * be reprogrammed after each reset.
++ */
++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
++ REG_RMW(ah, AR_PHY_USB_CTRL2,
++ (1 << 21) | (0xf << 22),
++ (1 << 21) | (0x3 << 22));
++}
++
+ /******************/
+ /* Chip Revisions */
+ /******************/
+@@ -1387,6 +1400,9 @@ static bool ath9k_hw_set_reset(struct at
+ if (AR_SREV_9100(ah))
+ udelay(50);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return true;
+ }
+
+@@ -1486,6 +1502,9 @@ static bool ath9k_hw_chip_reset(struct a
+ ar9003_hw_internal_regulator_apply(ah);
+ ath9k_hw_init_pll(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return true;
+ }
+
+@@ -1787,8 +1806,14 @@ static int ath9k_hw_do_fastcc(struct ath
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ fail:
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return -EINVAL;
+ }
+
+@@ -2042,6 +2067,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ ath9k_hw_set_radar_params(ah);
+ }
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(ath9k_hw_reset);
+--- a/drivers/net/wireless/ath/ath9k/phy.h
++++ b/drivers/net/wireless/ath/ath9k/phy.h
+@@ -48,6 +48,9 @@
+ #define AR_PHY_PLL_CONTROL 0x16180
+ #define AR_PHY_PLL_MODE 0x16184
+
++#define AR_PHY_USB_CTRL1 0x16c84
++#define AR_PHY_USB_CTRL2 0x16c88
++
+ enum ath9k_ant_div_comb_lna_conf {
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+ ATH_ANT_DIV_COMB_LNA2,
diff --git a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch
new file mode 100644
index 0000000..3d24ccd
--- /dev/null
+++ b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch
@@ -0,0 +1,155 @@
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -956,55 +956,6 @@ static bool ar5008_hw_ani_control_new(st
+ * on == 0 means more noise imm
+ */
+ u32 on = param ? 1 : 0;
+- /*
+- * make register setting for default
+- * (weak sig detect ON) come from INI file
+- */
+- int m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- int m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- int m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- int m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- int m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- int m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- int m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- int m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- int m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- int m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -41,20 +41,6 @@ static const int cycpwrThr1_table[] =
+ /* level: 0 1 2 3 4 5 6 7 8 */
+ { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+
+-/*
+- * register values to turn OFDM weak signal detection OFF
+- */
+-static const int m1ThreshLow_off = 127;
+-static const int m2ThreshLow_off = 127;
+-static const int m1Thresh_off = 127;
+-static const int m2Thresh_off = 127;
+-static const int m2CountThr_off = 31;
+-static const int m2CountThrLow_off = 63;
+-static const int m1ThreshLowExt_off = 127;
+-static const int m2ThreshLowExt_off = 127;
+-static const int m1ThreshExt_off = 127;
+-static const int m2ThreshExt_off = 127;
+-
+ static const u8 ofdm2pwr[] = {
+ ALL_TARGET_LEGACY_6_24,
+ ALL_TARGET_LEGACY_6_24,
+@@ -1089,11 +1075,6 @@ static bool ar9003_hw_ani_control(struct
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &ah->ani;
+- int m1ThreshLow, m2ThreshLow;
+- int m1Thresh, m2Thresh;
+- int m2CountThr, m2CountThrLow;
+- int m1ThreshLowExt, m2ThreshLowExt;
+- int m1ThreshExt, m2ThreshExt;
+ s32 value, value2;
+
+ switch (cmd & ah->ani_function) {
+@@ -1107,61 +1088,6 @@ static bool ar9003_hw_ani_control(struct
+ */
+ u32 on = param ? 1 : 0;
+
+- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+- goto skip_ws_det;
+-
+- m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH,
+- m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH,
+- m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR,
+- m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+- m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+- m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH,
+- m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH,
+- m2ThreshExt);
+-skip_ws_det:
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
diff --git a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
new file mode 100644
index 0000000..15863a6
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
@@ -0,0 +1,66 @@
+From 7a69da907de668fb22a30ae218062d6f081864ea Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 17 Aug 2013 19:31:41 +0200
+Subject: [PATCH] rt2x00: rt2800lib: move rt2800_drv_data declaration into
+ rt2800lib.h
+
+The rt2800_drv_data structure contains driver specific
+information. Move the declaration into the rt2800lib.h
+header which is a more logical place for it. Also fix
+the comment style to avoid checkpatch warning.
+
+The patch contains no functional changes, it is in
+preparation for the next patch.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+Changes since v1: ---
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 13 -------------
+ drivers/net/wireless/rt2x00/rt2800lib.h | 11 +++++++++++
+ 2 files changed, 11 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -20,6 +20,20 @@
+ #ifndef RT2800LIB_H
+ #define RT2800LIB_H
+
++#include "rt2800.h"
++
++/* RT2800 driver data structure */
++struct rt2800_drv_data {
++ u8 calibration_bw20;
++ u8 calibration_bw40;
++ u8 bbp25;
++ u8 bbp26;
++ u8 txmixer_gain_24g;
++ u8 txmixer_gain_5g;
++ unsigned int tbtt_tick;
++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
++};
++
+ struct rt2800_ops {
+ void (*register_read)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset, u32 *value);
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -2969,18 +2969,4 @@ enum rt2800_eeprom_word {
+ #define WCID_END 222
+ #define STA_IDS_SIZE (WCID_END - WCID_START + 2)
+
+-/*
+- * RT2800 driver data structure
+- */
+-struct rt2800_drv_data {
+- u8 calibration_bw20;
+- u8 calibration_bw40;
+- u8 bbp25;
+- u8 bbp26;
+- u8 txmixer_gain_24g;
+- u8 txmixer_gain_5g;
+- unsigned int tbtt_tick;
+- DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+-};
+-
+ #endif /* RT2800_H */
diff --git a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
new file mode 100644
index 0000000..9165eec
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
@@ -0,0 +1,80 @@
+From a7f268af31dddf763fe3dbe9cbf96ea77e0540e0 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 17 Aug 2013 19:31:41 +0200
+Subject: [PATCH] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
+
+Some chipsets have more than 16KB of shared memory.
+Introduce a new rt2800 specific flag to indicate that
+and add a helper function which helps to check the
+presence of the new flag.
+
+Also enable the new flag for the RT3593 chipset which
+has 24KB of shared memory. The flag can also be used
+for other chipsets, but none of those has been tested
+yet.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+Changes since v1:
+ - don't enable the new flag for RT3071 and RT5592
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++++
+ drivers/net/wireless/rt2x00/rt2800lib.h | 13 +++++++++++++
+ 2 files changed, 17 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7721,6 +7721,7 @@ static int rt2800_probe_rt(struct rt2x00
+
+ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
+ {
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ int retval;
+ u32 reg;
+
+@@ -7728,6 +7729,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ if (retval)
+ return retval;
+
++ if (rt2x00_rt(rt2x00dev, RT3593))
++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
++
+ /*
+ * Allocate eeprom data.
+ */
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -22,6 +22,10 @@
+
+ #include "rt2800.h"
+
++enum rt2800_flag {
++ RT2800_HAS_HIGH_SHARED_MEM,
++};
++
+ /* RT2800 driver data structure */
+ struct rt2800_drv_data {
+ u8 calibration_bw20;
+@@ -32,6 +36,8 @@ struct rt2800_drv_data {
+ u8 txmixer_gain_5g;
+ unsigned int tbtt_tick;
+ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
++
++ unsigned long rt2800_flags;
+ };
+
+ struct rt2800_ops {
+@@ -64,6 +70,13 @@ struct rt2800_ops {
+ __le32 *(*drv_get_txwi)(struct queue_entry *entry);
+ };
+
++static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
++}
++
+ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
new file mode 100644
index 0000000..5671515
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
@@ -0,0 +1,531 @@
+From 250a1b520cd7fdc0df4fc3fedea9066913f49ecf Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 17 Aug 2013 19:31:42 +0200
+Subject: [PATCH] rt2x00: rt2800: serialize shared memory access
+
+The shared memory of the rt2800 devices is accessible
+through the register offset range between 0x4000 and
+0x8000. The size of this range is 16KB only and on
+devices which have more than 16KB of shared memory either
+the low or the high part of the memory is accessible at a
+time.
+
+Serialize all accesses to the shared memory by a mutex,
+in order to avoid concurrent use of that.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+Changes since v1: ---
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 55 +++++++++++++++++++++++++++++-
+ drivers/net/wireless/rt2x00/rt2800lib.h | 32 +++++++++++++++++
+ drivers/net/wireless/rt2x00/rt2800mmio.c | 26 ++++++++++++++
+ drivers/net/wireless/rt2x00/rt2800mmio.h | 4 +++
+ drivers/net/wireless/rt2x00/rt2800pci.c | 14 ++++++++
+ drivers/net/wireless/rt2x00/rt2800soc.c | 3 ++
+ drivers/net/wireless/rt2x00/rt2800usb.c | 31 +++++++++++++++++
+ 7 files changed, 164 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_de
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+ reg = 0;
+ rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+ rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_d
+ * Wait for device to stabilize.
+ */
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
+ break;
+ msleep(1);
+@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_d
+ /*
+ * Initialize firmware.
+ */
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
++
+ if (rt2x00_is_usb(rt2x00dev)) {
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
++
+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+ }
+ msleep(1);
+@@ -1035,8 +1045,10 @@ void rt2800_write_beacon(struct queue_en
+
+ beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
+ entry->skb->len + padding_len);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+ /*
+@@ -1066,6 +1078,8 @@ static inline void rt2800_clear_beacon_r
+
+ beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
+
++ rt2800_shared_mem_lock(rt2x00dev);
++
+ /*
+ * For the Beacon base registers we only need to clear
+ * the whole TXWI which (when set to 0) will invalidate
+@@ -1073,6 +1087,8 @@ static inline void rt2800_clear_beacon_r
+ */
+ for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
+ rt2800_register_write(rt2x00dev, beacon_base + i, 0);
++
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ void rt2800_clear_beacon(struct queue_entry *entry)
+@@ -1261,7 +1277,9 @@ static void rt2800_delete_wcid_attr(stru
+ {
+ u32 offset;
+ offset = MAC_WCID_ATTR_ENTRY(wcid);
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, offset, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
+@@ -1274,11 +1292,13 @@ static void rt2800_config_wcid_attr_bssi
+ * The BSS Idx numbers is split in a main value of 3 bits,
+ * and a extended field for adding one additional bit to the value.
+ */
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
+ (bssidx & 0x8) >> 3);
+ rt2800_register_write(rt2x00dev, offset, reg);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
+@@ -1291,6 +1311,7 @@ static void rt2800_config_wcid_attr_ciph
+
+ offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ if (crypto->cmd == SET_KEY) {
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
+@@ -1315,6 +1336,7 @@ static void rt2800_config_wcid_attr_ciph
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
+ rt2800_register_write(rt2x00dev, offset, reg);
+ }
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+
+@@ -1324,8 +1346,11 @@ static void rt2800_config_wcid_attr_ciph
+ (crypto->cipher == CIPHER_AES))
+ iveiv_entry.iv[3] |= 0x20;
+ iveiv_entry.iv[3] |= key->keyidx << 6;
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
+@@ -1348,8 +1373,11 @@ int rt2800_config_shared_key(struct rt2x
+ sizeof(key_entry.rx_mic));
+
+ offset = SHARED_KEY_ENTRY(key->hw_key_idx);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &key_entry, sizeof(key_entry));
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ /*
+@@ -1364,10 +1392,12 @@ int rt2800_config_shared_key(struct rt2x
+
+ offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, field,
+ (crypto->cmd == SET_KEY) * crypto->cipher);
+ rt2800_register_write(rt2x00dev, offset, reg);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ /*
+ * Update WCID information
+@@ -1405,8 +1435,11 @@ int rt2800_config_pairwise_key(struct rt
+ sizeof(key_entry.rx_mic));
+
+ offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &key_entry, sizeof(key_entry));
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ /*
+@@ -4884,14 +4917,19 @@ static int rt2800_init_registers(struct
+ /*
+ * ASIC will keep garbage value after boot, clear encryption keys.
+ */
++ rt2800_shared_mem_lock(rt2x00dev);
+ for (i = 0; i < 4; i++)
+ rt2800_register_write(rt2x00dev,
+ SHARED_KEY_MODE_ENTRY(i), 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ for (i = 0; i < 256; i++) {
+ rt2800_config_wcid(rt2x00dev, NULL, i);
+ rt2800_delete_wcid_attr(rt2x00dev, i);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ /*
+@@ -5017,8 +5055,10 @@ static int rt2800_wait_bbp_ready(struct
+ * BBP was enabled after firmware was loaded,
+ * but we need to reactivate it now.
+ */
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ msleep(1);
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+@@ -6714,11 +6754,19 @@ int rt2800_enable_radio(struct rt2x00_de
+ /*
+ * Send signal during boot time to initialize firmware.
+ */
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+- if (rt2x00_is_usb(rt2x00dev))
++ rt2800_shared_mem_unlock(rt2x00dev);
++
++ if (rt2x00_is_usb(rt2x00dev)) {
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
++ }
++
+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
++
+ msleep(1);
+
+ /*
+@@ -7725,6 +7773,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ int retval;
+ u32 reg;
+
++ rt2800_shared_mem_init_lock(rt2x00dev);
++
+ retval = rt2800_probe_rt(rt2x00dev);
+ if (retval)
+ return retval;
+@@ -7808,8 +7858,11 @@ void rt2800_get_key_seq(struct ieee80211
+ return;
+
+ offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2);
+ memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4);
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -38,6 +38,11 @@ struct rt2800_drv_data {
+ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+
+ unsigned long rt2800_flags;
++
++ union {
++ spinlock_t spin;
++ struct mutex mutex;
++ } shmem_lock;
+ };
+
+ struct rt2800_ops {
+@@ -68,6 +73,10 @@ struct rt2800_ops {
+ const u8 *data, const size_t len);
+ int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+ __le32 *(*drv_get_txwi)(struct queue_entry *entry);
++
++ void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev);
++ void (*shmem_lock)(struct rt2x00_dev *rt2x00dev);
++ void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev);
+ };
+
+ static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
+@@ -77,6 +86,29 @@ static inline bool rt2800_has_high_share
+ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+ }
+
++static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ rt2800ops->shmem_init_lock(rt2x00dev);
++}
++
++static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ if (rt2800_has_high_shared_mem(rt2x00dev))
++ rt2800ops->shmem_lock(rt2x00dev);
++}
++
++static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev)
++{
++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++
++ if (rt2800_has_high_shared_mem(rt2x00dev))
++ rt2800ops->shmem_unlock(rt2x00dev);
++}
++
+ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
+--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
+@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2
+ rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
+ rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ if (rt2x00_is_pcie(rt2x00dev) &&
+ (rt2x00_rt(rt2x00dev, RT3090) ||
+@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x0
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
+
++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ spin_lock_init(&drv_data->shmem_lock.spin);
++}
++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock);
++
++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ spin_lock_bh(&drv_data->shmem_lock.spin);
++}
++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock);
++
++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ spin_unlock_bh(&drv_data->shmem_lock.spin);
++}
++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock);
++
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+ MODULE_DESCRIPTION("rt2800 MMIO library");
+--- a/drivers/net/wireless/rt2x00/rt2800mmio.h
++++ b/drivers/net/wireless/rt2x00/rt2800mmio.h
+@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2
+ /* Device state switch handlers. */
+ int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
+
++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev);
++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev);
++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev);
++
+ #endif /* RT2800MMIO_H */
+--- a/drivers/net/wireless/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
+@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct
+ return;
+
+ for (i = 0; i < 200; i++) {
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
+ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
+@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct
+ if (i == 200)
+ rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
+ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(stru
+ */
+ reg = 0;
+ rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+
+ /*
+@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(stru
+
+ rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ return 0;
+ }
+@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct
+ return retval;
+
+ /* After resume MCU_BOOT_SIGNAL will trash these. */
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
+ rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
+@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt
+ 0, 0x02);
+ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
+ } else if (state == STATE_SLEEP) {
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+ 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
+ 0xffffffff);
++ rt2800_shared_mem_unlock(rt2x00dev);
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
+ 0xff, 0x01);
+ }
+@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci
+ .drv_write_firmware = rt2800pci_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+ .drv_get_txwi = rt2800mmio_get_txwi,
++ .shmem_init_lock = rt2800mmio_shmem_init_lock,
++ .shmem_lock = rt2800mmio_shmem_lock,
++ .shmem_unlock = rt2800mmio_shmem_unlock,
+ };
+
+ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc
+ .drv_write_firmware = rt2800soc_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+ .drv_get_txwi = rt2800mmio_get_txwi,
++ .shmem_init_lock = rt2800mmio_shmem_init_lock,
++ .shmem_lock = rt2800mmio_shmem_lock,
++ .shmem_unlock = rt2800mmio_shmem_unlock,
+ };
+
+ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
+--- a/drivers/net/wireless/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/rt2x00/rt2800usb.c
+@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(s
+ return modparam_nohwcrypt;
+ }
+
++static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ mutex_init(&drv_data->shmem_lock.mutex);
++}
++
++static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ mutex_lock(&drv_data->shmem_lock.mutex);
++}
++
++static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ mutex_unlock(&drv_data->shmem_lock.mutex);
++}
++
+ /*
+ * Queue handlers.
+ */
+@@ -299,8 +320,10 @@ static int rt2800usb_write_firmware(stru
+ data + offset, length);
+ }
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ /*
+ * Send firmware request to device to load firmware,
+@@ -315,7 +338,10 @@ static int rt2800usb_write_firmware(stru
+ }
+
+ msleep(10);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ return 0;
+ }
+@@ -333,8 +359,10 @@ static int rt2800usb_init_registers(stru
+ if (rt2800_wait_csr_ready(rt2x00dev))
+ return -EBUSY;
+
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ reg = 0;
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+@@ -863,6 +891,9 @@ static const struct rt2800_ops rt2800usb
+ .drv_write_firmware = rt2800usb_write_firmware,
+ .drv_init_registers = rt2800usb_init_registers,
+ .drv_get_txwi = rt2800usb_get_txwi,
++ .shmem_init_lock = rt2800usb_shmem_init_lock,
++ .shmem_lock = rt2800usb_shmem_lock,
++ .shmem_unlock = rt2800usb_shmem_unlock,
+ };
+
+ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
diff --git a/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
new file mode 100644
index 0000000..b8c1914
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
@@ -0,0 +1,131 @@
+From dcfe3dd46242050f100162dce2bcad24d2c942c6 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 17 Aug 2013 19:31:42 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix beacon generation on RT3593
+
+On the RT3593 chipset, the beacon registers are located
+in the high 8KB part of the shared memory.
+
+The high part of the shared memory is only accessible
+if it is explicitly selected. Add a helper function
+in order to be able to control the SHR_MSEL bit in
+the PBF_SYS_CTRL register. Also add a few more helper
+functions and use those to select the correct part of
+the shared memory before and after accessing the beacon
+registers.
+
+The base addresses of the beacon registers are also
+different from the actually used values, so fix the
+'rt2800_hw_beacon_base' function to return the correct
+values.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+Changes since v1: ---
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 3 +++
+ drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
+ 2 files changed, 47 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -574,6 +574,7 @@
+ #define PBF_SYS_CTRL 0x0400
+ #define PBF_SYS_CTRL_READY FIELD32(0x00000080)
+ #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
++#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000)
+
+ /*
+ * HOST-MCU shared memory
+@@ -2026,6 +2027,8 @@ struct mac_iveiv_entry {
+ (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
+ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
+
++#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512)
++
+ #define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64)
+
+ /*
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st
+ return false;
+ }
+
++static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev,
++ bool high)
++{
++ u32 reg;
++
++ if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev)))
++ return;
++
++ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
++ rt2x00_set_field32(&reg, PBF_SYS_CTRL_SHR_MSEL, high);
++ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
++}
++
++static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2x00_rt(rt2x00dev, RT3593))
++ return true;
++
++ return false;
++}
++
++static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2800_beacon_uses_high_mem(rt2x00dev))
++ rt2800_shared_mem_select(rt2x00dev, true);
++}
++
++static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev)
++{
++ if (rt2800_beacon_uses_high_mem(rt2x00dev))
++ rt2800_shared_mem_select(rt2x00dev, false);
++}
++
+ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, const u8 value)
+ {
+@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+ unsigned int index)
+ {
++ if (rt2x00_rt(rt2x00dev, RT3593))
++ return HW_BEACON_BASE_HIGH(index);
++
+ return HW_BEACON_BASE(index);
+ }
+
+@@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_en
+ beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
+
+ rt2800_shared_mem_lock(rt2x00dev);
++
++ rt2800_select_beacon_mem(rt2x00dev);
+ rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
+ entry->skb->len + padding_len);
++ rt2800_deselect_beacon_mem(rt2x00dev);
++
+ rt2800_shared_mem_unlock(rt2x00dev);
+ __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+@@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_r
+
+ rt2800_shared_mem_lock(rt2x00dev);
+
++ rt2800_select_beacon_mem(rt2x00dev);
++
+ /*
+ * For the Beacon base registers we only need to clear
+ * the whole TXWI which (when set to 0) will invalidate
+@@ -1088,6 +1130,8 @@ static inline void rt2800_clear_beacon_r
+ for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
+ rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+
++ rt2800_deselect_beacon_mem(rt2x00dev);
++
+ rt2800_shared_mem_unlock(rt2x00dev);
+ }
+
diff --git a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
new file mode 100644
index 0000000..d04998a
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
@@ -0,0 +1,62 @@
+From a058825fa7b53fab3b003d8928b60e5b686b3421 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 4 Aug 2013 14:36:11 +0200
+Subject: [PATCH] rt2x00: rt2800lib: add hw_beacon_count field to struct
+ rt2800_drv_data
+
+Some chipsets can handle more than 8 beacons at once.
+Add a new field to the rt2800_drv_data structure which
+will hold the number of supported beacons of the given
+chipset.
+
+Update the rt2x00_init_registers function to get the
+beacon count from the new field instead of using a
+hardcoded value.
+
+In order to keep the current behaviour, initialize the
+new field with the actually used value.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++-
+ drivers/net/wireless/rt2x00/rt2800lib.h | 1 +
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4614,6 +4614,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
+ */
+ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+ {
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u32 reg;
+ u16 eeprom;
+ unsigned int i;
+@@ -4979,7 +4980,7 @@ static int rt2800_init_registers(struct
+ /*
+ * Clear all beacons
+ */
+- for (i = 0; i < 8; i++)
++ for (i = 0; i < drv_data->hw_beacon_count; i++)
+ rt2800_clear_beacon_register(rt2x00dev, i);
+
+ if (rt2x00_is_usb(rt2x00dev)) {
+@@ -7826,6 +7827,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
++ drv_data->hw_beacon_count = 8;
++
+ /*
+ * Allocate eeprom data.
+ */
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -35,6 +35,7 @@ struct rt2800_drv_data {
+ u8 txmixer_gain_24g;
+ u8 txmixer_gain_5g;
+ unsigned int tbtt_tick;
++ unsigned int hw_beacon_count;
+ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+
+ unsigned long rt2800_flags;
diff --git a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
new file mode 100644
index 0000000..f5231f0
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
@@ -0,0 +1,67 @@
+From 1bfa43ca8f30be53ce4fa79cfc3e219642a812b6 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 2 Sep 2013 10:58:32 +0200
+Subject: [PATCH] rt2x00: rt2800lib: init additional beacon offset registers
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++
+ drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -629,6 +629,20 @@
+ */
+ #define PBF_DBG 0x043c
+
++/* BCN_OFFSET2 */
++#define BCN_OFFSET2 0x0444
++#define BCN_OFFSET2_BCN8 FIELD32(0x000000ff)
++#define BCN_OFFSET2_BCN9 FIELD32(0x0000ff00)
++#define BCN_OFFSET2_BCN10 FIELD32(0x00ff0000)
++#define BCN_OFFSET2_BCN11 FIELD32(0xff000000)
++
++/* BCN_OFFSET3 */
++#define BCN_OFFSET3 0x0448
++#define BCN_OFFSET3_BCN12 FIELD32(0x000000ff)
++#define BCN_OFFSET3_BCN13 FIELD32(0x0000ff00)
++#define BCN_OFFSET3_BCN14 FIELD32(0x00ff0000)
++#define BCN_OFFSET3_BCN15 FIELD32(0xff000000)
++
+ /*
+ * RF registers
+ */
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4626,6 +4626,30 @@ static int rt2800_init_registers(struct
+ if (ret)
+ return ret;
+
++ if (drv_data->hw_beacon_count == 16) {
++ rt2800_register_read(rt2x00dev, BCN_OFFSET2, &reg);
++ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN8,
++ rt2800_get_beacon_offset(rt2x00dev, 8));
++ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN9,
++ rt2800_get_beacon_offset(rt2x00dev, 9));
++ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN10,
++ rt2800_get_beacon_offset(rt2x00dev, 10));
++ rt2x00_set_field32(&reg, BCN_OFFSET2_BCN11,
++ rt2800_get_beacon_offset(rt2x00dev, 11));
++ rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg);
++
++ rt2800_register_read(rt2x00dev, BCN_OFFSET3, &reg);
++ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN12,
++ rt2800_get_beacon_offset(rt2x00dev, 12));
++ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN13,
++ rt2800_get_beacon_offset(rt2x00dev, 13));
++ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN14,
++ rt2800_get_beacon_offset(rt2x00dev, 14));
++ rt2x00_set_field32(&reg, BCN_OFFSET3_BCN15,
++ rt2800_get_beacon_offset(rt2x00dev, 15));
++ rt2800_register_write(rt2x00dev, BCN_OFFSET3, reg);
++ }
++
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
diff --git a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
new file mode 100644
index 0000000..4b21eae
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
@@ -0,0 +1,24 @@
+From 9bea8b61f6025cd633bd5ac71be258620b49bcb3 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 2 Sep 2013 11:00:06 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix max supported beacon count for RT3593
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7851,7 +7851,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
+- drv_data->hw_beacon_count = 8;
++ if (rt2x00_rt(rt2x00dev, RT3593))
++ drv_data->hw_beacon_count = 16;
++ else
++ drv_data->hw_beacon_count = 8;
+
+ /*
+ * Allocate eeprom data.
diff --git a/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch
new file mode 100644
index 0000000..8a10c6e
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch
@@ -0,0 +1,30 @@
+From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -210,7 +210,7 @@ endif
+ config RT2800SOC
+ tristate "Ralink WiSoC support"
+ depends on m
+- depends on SOC_RT288X || SOC_RT305X
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
+ select RT2X00_LIB_SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI
+
+ config RT2X00_LIB_SOC
+ tristate "RT2x00 SoC support"
+- depends on SOC_RT288X || SOC_RT305X
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
+ depends on m
+ select RT2X00_LIB
+
diff --git a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
new file mode 100644
index 0000000..e77cd86
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
@@ -0,0 +1,20 @@
+From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7821,6 +7821,7 @@ static int rt2800_probe_rt(struct rt2x00
+ case RT3390:
+ case RT3572:
+ case RT3593:
++ case RT3883:
+ case RT5390:
+ case RT5392:
+ case RT5592:
diff --git a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
new file mode 100644
index 0000000..780c1dd
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
@@ -0,0 +1,112 @@
+From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 4 +-
+ drivers/net/wireless/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -48,7 +48,8 @@
+ * RF2853 2.4G/5G 3T3R
+ * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
+ * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
+- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
++ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593)
++ * RF3853 2.4G/5G 3T3R(RT3883/RT3662)
+ * RF5592 2.4G/5G 2T2R
+ * RF3070 2.4G 1T1R
+ * RF5360 2.4G 1T1R
+@@ -72,6 +73,7 @@
+ #define RF5592 0x000f
+ #define RF3070 0x3070
+ #define RF3290 0x3290
++#define RF3853 0x3853
+ #define RF5360 0x5360
+ #define RF5362 0x5362
+ #define RF5370 0x5370
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7441,6 +7441,66 @@ static const struct rf_channel rf_vals_3
+ {173, 0x61, 0, 9},
+ };
+
++static const struct rf_channel rf_vals_3853[] = {
++ {1, 241, 6, 2},
++ {2, 241, 6, 7},
++ {3, 242, 6, 2},
++ {4, 242, 6, 7},
++ {5, 243, 6, 2},
++ {6, 243, 6, 7},
++ {7, 244, 6, 2},
++ {8, 244, 6, 7},
++ {9, 245, 6, 2},
++ {10, 245, 6, 7},
++ {11, 246, 6, 2},
++ {12, 246, 6, 7},
++ {13, 247, 6, 2},
++ {14, 248, 6, 4},
++
++ {36, 0x56, 8, 4},
++ {38, 0x56, 8, 6},
++ {40, 0x56, 8, 8},
++ {44, 0x57, 8, 0},
++ {46, 0x57, 8, 2},
++ {48, 0x57, 8, 4},
++ {52, 0x57, 8, 8},
++ {54, 0x57, 8, 10},
++ {56, 0x58, 8, 0},
++ {60, 0x58, 8, 4},
++ {62, 0x58, 8, 6},
++ {64, 0x58, 8, 8},
++
++ {100, 0x5b, 8, 8},
++ {102, 0x5b, 8, 10},
++ {104, 0x5c, 8, 0},
++ {108, 0x5c, 8, 4},
++ {110, 0x5c, 8, 6},
++ {112, 0x5c, 8, 8},
++ {114, 0x5c, 8, 10},
++ {116, 0x5d, 8, 0},
++ {118, 0x5d, 8, 2},
++ {120, 0x5d, 8, 4},
++ {124, 0x5d, 8, 8},
++ {126, 0x5d, 8, 10},
++ {128, 0x5e, 8, 0},
++ {132, 0x5e, 8, 4},
++ {134, 0x5e, 8, 6},
++ {136, 0x5e, 8, 8},
++ {140, 0x5f, 8, 0},
++
++ {149, 0x5f, 8, 9},
++ {151, 0x5f, 8, 11},
++ {153, 0x60, 8, 1},
++ {157, 0x60, 8, 5},
++ {159, 0x60, 8, 7},
++ {161, 0x60, 8, 9},
++ {165, 0x61, 8, 1},
++ {167, 0x61, 8, 3},
++ {169, 0x61, 8, 5},
++ {171, 0x61, 8, 7},
++ {173, 0x61, 8, 9},
++};
++
+ static const struct rf_channel rf_vals_5592_xtal20[] = {
+ /* Channel, N, K, mod, R */
+ {1, 482, 4, 10, 3},
+@@ -7668,6 +7728,11 @@ static int rt2800_probe_hw_mode(struct r
+ spec->channels = rf_vals_3x;
+ break;
+
++ case RF3853:
++ spec->num_channels = ARRAY_SIZE(rf_vals_3853);
++ spec->channels = rf_vals_3853;
++ break;
++
+ case RF5592:
+ rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
+ if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
diff --git a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
new file mode 100644
index 0000000..858dece
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
@@ -0,0 +1,28 @@
+From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:40:44 +0200
+Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4378,6 +4378,7 @@ void rt2800_vco_calibration(struct rt2x0
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -7847,6 +7848,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5360:
+ case RF5362:
+ case RF5370:
diff --git a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
new file mode 100644
index 0000000..ed82e44
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
@@ -0,0 +1,235 @@
+From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for
+ RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++
+ 1 file changed, 208 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -2625,6 +2625,211 @@ static void rt2800_config_channel_rf3053
+ }
+ }
+
++static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_conf *conf,
++ struct rf_channel *rf,
++ struct channel_info *info)
++{
++ u8 rfcsr;
++ u8 bbp;
++ u8 pwr1, pwr2, pwr3;
++
++ const bool txbf_enabled = false; /* TODO */
++
++ /* TODO: add band selection */
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++ else if (rf->channel < 132)
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++
++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
++
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
++
++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
++
++ switch (rt2x00dev->default_ant.tx_chain_num) {
++ case 3:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
++ /* fallthrough */
++ case 2:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
++ /* fallthrough */
++ case 1:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
++ break;
++ }
++
++ switch (rt2x00dev->default_ant.rx_chain_num) {
++ case 3:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
++ /* fallthrough */
++ case 2:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
++ /* fallthrough */
++ case 1:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
++ break;
++ }
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rt2800_adjust_freq_offset(rt2x00dev);
++
++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
++ if (!conf_is_ht40(conf))
++ rfcsr &= ~(0x06);
++ else
++ rfcsr |= 0x06;
++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++
++ if (conf_is_ht40(conf))
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
++
++ /* loopback RF_BS */
++ rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
++ if (rf->channel <= 14)
++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
++ else
++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
++ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
++
++ if (rf->channel <= 14)
++ rfcsr = 0x23;
++ else if (rf->channel < 100)
++ rfcsr = 0x36;
++ else if (rf->channel < 132)
++ rfcsr = 0x32;
++ else
++ rfcsr = 0x30;
++
++ if (txbf_enabled)
++ rfcsr |= 0x40;
++
++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
++
++ if (rf->channel <= 14)
++ rfcsr = 0xbb;
++ else if (rf->channel < 100)
++ rfcsr = 0xeb;
++ else if (rf->channel < 132)
++ rfcsr = 0xb3;
++ else
++ rfcsr = 0x9b;
++ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
++
++ if (rf->channel <= 14)
++ rfcsr = 0x8e;
++ else
++ rfcsr = 0x8a;
++
++ if (txbf_enabled)
++ rfcsr |= 0x20;
++
++ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
++
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
++
++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
++
++ rt2800_rfcsr_read(rt2x00dev, 52, &rfcsr);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
++
++ if (rf->channel <= 14) {
++ pwr1 = info->default_power1 & 0x1f;
++ pwr2 = info->default_power2 & 0x1f;
++ pwr3 = info->default_power3 & 0x1f;
++ } else {
++ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
++ (info->default_power1 & 0x7);
++ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
++ (info->default_power2 & 0x7);
++ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
++ (info->default_power3 & 0x7);
++ }
++
++ rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
++ rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
++ rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
++
++ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
++ rf->channel, pwr1, pwr2, pwr3);
++
++ bbp = (info->default_power1 >> 5) |
++ ((info->default_power2 & 0xe0) >> 1);
++ rt2800_bbp_write(rt2x00dev, 109, bbp);
++
++ rt2800_bbp_read(rt2x00dev, 110, &bbp);
++ bbp &= 0x0f;
++ bbp |= (info->default_power3 & 0xe0) >> 1;
++ rt2800_bbp_write(rt2x00dev, 110, bbp);
++
++ rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
++
++ /* Enable RF tuning */
++ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
++
++ udelay(2000);
++
++ rt2800_bbp_read(rt2x00dev, 49, &bbp);
++ /* clear update flag */
++ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
++ rt2800_bbp_write(rt2x00dev, 49, bbp);
++
++ /* TODO: add calibration for TxBF */
++}
++
+ #define POWER_BOUND 0x27
+ #define POWER_BOUND_5G 0x2b
+
+@@ -3237,6 +3442,9 @@ static void rt2800_config_channel(struct
+ case RF3322:
+ rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
+ break;
++ case RF3853:
++ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
++ break;
+ case RF3070:
+ case RF5360:
+ case RF5362:
diff --git a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
new file mode 100644
index 0000000..33cbc4c
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
@@ -0,0 +1,20 @@
+From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:42:05 +0200
+Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7406,6 +7406,7 @@ static int rt2800_init_eeprom(struct rt2
+ case RF3290:
+ case RF3320:
+ case RF3322:
++ case RF3853:
+ case RF5360:
+ case RF5362:
+ case RF5370:
diff --git a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
new file mode 100644
index 0000000..c3a4798
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
@@ -0,0 +1,77 @@
+From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++
+ drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++---
+ 2 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -1588,6 +1588,20 @@
+ #define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00)
+
+ /*
++ * TX_TXBF_CFG:
++ */
++#define TX_TXBF_CFG_0 0x138c
++#define TX_TXBF_CFG_1 0x13a4
++#define TX_TXBF_CFG_2 0x13a8
++#define TX_TXBF_CFG_3 0x13ac
++
++/*
++ * TX_FBK_CFG_3S:
++ */
++#define TX_FBK_CFG_3S_0 0x13c4
++#define TX_FBK_CFG_3S_1 0x13c8
++
++/*
+ * RX_FILTER_CFG: RX configuration register.
+ */
+ #define RX_FILTER_CFG 0x1400
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4981,6 +4981,12 @@ static int rt2800_init_registers(struct
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+ 0x00000000);
+ }
++ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
+ } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -5011,9 +5017,11 @@ static int rt2800_init_registers(struct
+
+ rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
+- if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
+- rt2x00_rt(rt2x00dev, RT2883) ||
+- rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
++ if (rt2x00_rt(rt2x00dev, RT3883))
++ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 3);
++ else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
++ rt2x00_rt(rt2x00dev, RT2883) ||
++ rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
+ else
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
+@@ -5166,6 +5174,11 @@ static int rt2800_init_registers(struct
+ reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+ rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
+
++ if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
++ }
++
+ rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
diff --git a/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch b/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch
new file mode 100644
index 0000000..837c025
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch
@@ -0,0 +1,30 @@
+From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800soc.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s
+
+ static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
++ u32 reg;
++
+ rt2800_disable_radio(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
++
++ reg = 0;
++ if (rt2x00_rt(rt2x00dev, RT3883))
++ rt2x00_set_field32(&reg, TX_PIN_CFG_RFTR_EN, 1);
++
++ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
+ }
+
+ static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
diff --git a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
new file mode 100644
index 0000000..e647777
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
@@ -0,0 +1,71 @@
+From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -5784,6 +5784,47 @@ static void rt2800_init_bbp_3593(struct
+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+ }
+
++static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev)
++{
++ rt2800_init_bbp_early(rt2x00dev);
++
++ rt2800_bbp_write(rt2x00dev, 4, 0x50);
++ rt2800_bbp_write(rt2x00dev, 47, 0x48);
++
++ rt2800_bbp_write(rt2x00dev, 86, 0x46);
++ rt2800_bbp_write(rt2x00dev, 88, 0x90);
++
++ rt2800_bbp_write(rt2x00dev, 92, 0x02);
++
++ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
++ rt2800_bbp_write(rt2x00dev, 104, 0x92);
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
++ rt2800_bbp_write(rt2x00dev, 106, 0x12);
++ rt2800_bbp_write(rt2x00dev, 120, 0x50);
++ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
++ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
++
++ /* Set ITxBF timeout to 0x9C40=1000msec */
++ rt2800_bbp_write(rt2x00dev, 179, 0x02);
++ rt2800_bbp_write(rt2x00dev, 180, 0x00);
++ rt2800_bbp_write(rt2x00dev, 182, 0x40);
++ rt2800_bbp_write(rt2x00dev, 180, 0x01);
++ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x00);
++
++ /* Reprogram the inband interface to put right values in RXWI */
++ rt2800_bbp_write(rt2x00dev, 142, 0x04);
++ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
++ rt2800_bbp_write(rt2x00dev, 142, 0x06);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
++ rt2800_bbp_write(rt2x00dev, 142, 0x07);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
++ rt2800_bbp_write(rt2x00dev, 142, 0x08);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
++ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++}
++
+ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
+ {
+ int ant, div_mode;
+@@ -6002,6 +6043,9 @@ static void rt2800_init_bbp(struct rt2x0
+ case RT3593:
+ rt2800_init_bbp_3593(rt2x00dev);
+ return;
++ case RT3883:
++ rt2800_init_bbp_3883(rt2x00dev);
++ return;
+ case RT5390:
+ case RT5392:
+ rt2800_init_bbp_53xx(rt2x00dev);
diff --git a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
new file mode 100644
index 0000000..0fec3cd
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
@@ -0,0 +1,178 @@
+From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 29 Apr 2013 13:21:48 +0200
+Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800.h | 1 +
+ drivers/net/wireless/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++
+ 2 files changed, 142 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -2171,6 +2171,7 @@ struct mac_iveiv_entry {
+ /*
+ * RFCSR 2:
+ */
++#define RFCSR2_RESCAL_BP FIELD8(0x40)
+ #define RFCSR2_RESCAL_EN FIELD8(0x80)
+
+ /*
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -6819,6 +6819,144 @@ static void rt2800_init_rfcsr_3593(struc
+ /* TODO: enable stream mode support */
+ }
+
++static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev)
++{
++ u8 rfcsr;
++
++ /* TODO: get the actual ECO value from the SoC */
++ const unsigned int eco = 5;
++
++ rt2800_rf_init_calibration(rt2x00dev, 2);
++
++ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0);
++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 3, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b);
++ rt2800_rfcsr_write(rt2x00dev, 9, 0x08);
++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
++
++ /* RFCSR 17 will be initialized later based on the
++ * frequency offset stored in the EEPROM
++ */
++
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 41, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
++ rt2800_rfcsr_write(rt2x00dev, 53, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 54, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 55, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
++ rt2800_rfcsr_write(rt2x00dev, 58, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
++
++ /* TODO: rx filter calibration? */
++
++ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
++
++ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
++
++ rt2800_bbp_write(rt2x00dev, 105, 0x05);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x02);
++ rt2800_bbp_write(rt2x00dev, 180, 0x00);
++ rt2800_bbp_write(rt2x00dev, 182, 0x40);
++ rt2800_bbp_write(rt2x00dev, 180, 0x01);
++ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x00);
++
++ rt2800_bbp_write(rt2x00dev, 142, 0x04);
++ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
++ rt2800_bbp_write(rt2x00dev, 142, 0x06);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
++ rt2800_bbp_write(rt2x00dev, 142, 0x07);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
++ rt2800_bbp_write(rt2x00dev, 142, 0x08);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
++ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++
++ if (eco == 5) {
++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x32);
++ }
++
++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
++ msleep(1);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
++ rfcsr |= 0xc0;
++ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
++ rfcsr |= 0x20;
++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 46, &rfcsr);
++ rfcsr |= 0x20;
++ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
++ rfcsr &= ~0xee;
++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
++}
++
+ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+ {
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+@@ -7050,6 +7188,9 @@ static void rt2800_init_rfcsr(struct rt2
+ case RT3390:
+ rt2800_init_rfcsr_3390(rt2x00dev);
+ break;
++ case RT3883:
++ rt2800_init_rfcsr_3883(rt2x00dev);
++ break;
+ case RT3572:
+ rt2800_init_rfcsr_3572(rt2x00dev);
+ break;
diff --git a/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch b/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch
new file mode 100644
index 0000000..57af961
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch
@@ -0,0 +1,22 @@
+From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 8 May 2013 19:35:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -342,7 +342,8 @@ static unsigned int rt2800_eeprom_word_i
+ wiphy_name(rt2x00dev->hw->wiphy), word))
+ return 0;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ map = rt2800_eeprom_map_ext;
+ else
+ map = rt2800_eeprom_map;
diff --git a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
new file mode 100644
index 0000000..c9d1e06
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
@@ -0,0 +1,21 @@
+From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:48:21 +0200
+Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7587,6 +7587,8 @@ static int rt2800_init_eeprom(struct rt2
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
++ else if (rt2x00_rt(rt2x00dev, RT3883))
++ rf = RF3853;
+ else
+ rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
+
diff --git a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
new file mode 100644
index 0000000..12b9c33
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
@@ -0,0 +1,136 @@
+From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:28 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++--
+ 1 file changed, 69 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3405,6 +3405,36 @@ static char rt2800_txpower_to_dev(struct
+ return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+ }
+
++static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev,
++ struct rf_channel *rf)
++{
++ u8 bbp;
++
++ bbp = (rf->channel > 14) ? 0x48 : 0x38;
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
++
++ rt2800_bbp_write(rt2x00dev, 69, 0x12);
++
++ if (rf->channel <= 14) {
++ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
++ } else {
++ /* Disable CCK packet detection */
++ rt2800_bbp_write(rt2x00dev, 70, 0x00);
++ }
++
++ rt2800_bbp_write(rt2x00dev, 73, 0x10);
++
++ if (rf->channel > 14) {
++ rt2800_bbp_write(rt2x00dev, 62, 0x1d);
++ rt2800_bbp_write(rt2x00dev, 63, 0x1d);
++ rt2800_bbp_write(rt2x00dev, 64, 0x1d);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 62, 0x2d);
++ rt2800_bbp_write(rt2x00dev, 63, 0x2d);
++ rt2800_bbp_write(rt2x00dev, 64, 0x2d);
++ }
++}
++
+ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+@@ -3423,6 +3453,12 @@ static void rt2800_config_channel(struct
+ rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+ info->default_power3);
+
++ switch (rt2x00dev->chip.rt) {
++ case RT3883:
++ rt3883_bbp_adjust(rt2x00dev, rf);
++ break;
++ }
++
+ switch (rt2x00dev->chip.rf) {
+ case RF2020:
+ case RF3020:
+@@ -3506,6 +3542,15 @@ static void rt2800_config_channel(struct
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 77, 0x98);
++ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
++
++ if (rt2x00dev->default_ant.rx_chain_num > 1)
++ rt2800_bbp_write(rt2x00dev, 86, 0x46);
++ else
++ rt2800_bbp_write(rt2x00dev, 86, 0);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+@@ -3518,6 +3563,7 @@ static void rt2800_config_channel(struct
+ !rt2x00_rt(rt2x00dev, RT5392)) {
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
++ rt2800_bbp_write(rt2x00dev, 82, 0x62);
+ rt2800_bbp_write(rt2x00dev, 75, 0x46);
+ } else {
+ if (rt2x00_rt(rt2x00dev, RT3593))
+@@ -3526,19 +3572,22 @@ static void rt2800_config_channel(struct
+ rt2800_bbp_write(rt2x00dev, 82, 0x84);
+ rt2800_bbp_write(rt2x00dev, 75, 0x50);
+ }
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 83, 0x8a);
+ }
+
+ } else {
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_bbp_write(rt2x00dev, 82, 0x94);
+- else if (rt2x00_rt(rt2x00dev, RT3593))
++ else if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 82, 0x82);
+ else
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+
+ if (rt2x00_has_cap_external_lna_a(rt2x00dev))
+@@ -3660,6 +3709,23 @@ static void rt2800_config_channel(struct
+
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
++ usleep_range(1000, 1500);
++ }
++
++ if (rt2x00_rt(rt2x00dev, RT3883)) {
++ if (!conf_is_ht40(conf))
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
++ else
++ rt2800_bbp_write(rt2x00dev, 105, 0x04);
++
++ /* AGC init */
++ if (rf->channel <= 14)
++ reg = 0x2e + rt2x00dev->lna_gain;
++ else
++ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3);
++
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
++
+ usleep_range(1000, 1500);
+ }
+
diff --git a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
new file mode 100644
index 0000000..3f40b4e
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
@@ -0,0 +1,30 @@
+From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 13:57:26 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3392,13 +3392,15 @@ static char rt2800_txpower_to_dev(struct
+ unsigned int channel,
+ char txpower)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
+
+ if (channel <= 14)
+ return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
+ MAX_A_TXPOWER_3593);
+ else
diff --git a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
new file mode 100644
index 0000000..52baeec
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
@@ -0,0 +1,23 @@
+From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:29 +0100
+Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function
+ for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4611,7 +4611,8 @@ static void rt2800_config_txpower(struct
+ struct ieee80211_channel *chan,
+ int power_level)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
+ else
+ rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
diff --git a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
new file mode 100644
index 0000000..b9dafc6
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
@@ -0,0 +1,33 @@
+From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 24 Aug 2013 11:49:55 +0200
+Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7469,7 +7469,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
+ {
+ u16 word;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return 0;
+
+ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+@@ -7483,7 +7484,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
+ {
+ u16 word;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return 0;
+
+ rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
diff --git a/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch b/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch
new file mode 100644
index 0000000..53435aa
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch
@@ -0,0 +1,20 @@
+From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 18 Apr 2013 14:33:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -558,6 +558,7 @@ void rt2800_get_txwi_rxwi_size(struct rt
+ {
+ switch (rt2x00dev->chip.rt) {
+ case RT3593:
++ case RT3883:
+ *txwi_size = TXWI_DESC_SIZE_4WORDS;
+ *rxwi_size = RXWI_DESC_SIZE_5WORDS;
+ break;
diff --git a/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch b/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch
new file mode 100644
index 0000000..08f3f88
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch
@@ -0,0 +1,22 @@
+From b403bdfa00665ce6b53583bdb837ffad0b91c09f Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:29 +0100
+Subject: [PATCH] rt2x00: rt2800lib: use correct beacon base for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -983,7 +983,8 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+ unsigned int index)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return HW_BEACON_BASE_HIGH(index);
+
+ return HW_BEACON_BASE(index);
diff --git a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
new file mode 100644
index 0000000..f09f803
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
@@ -0,0 +1,22 @@
+From 74b7eaf75fc6eb86292056ef705e543f9cd6086b Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 18 Aug 2013 09:57:58 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use correct beacon count for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -8402,7 +8402,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ drv_data->hw_beacon_count = 16;
+ else
+ drv_data->hw_beacon_count = 8;
diff --git a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
new file mode 100644
index 0000000..f7d23fc
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
@@ -0,0 +1,22 @@
+From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 16:53:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -1937,7 +1937,8 @@ void rt2800_config_ant(struct rt2x00_dev
+ rt2800_bbp_write(rt2x00dev, 3, r3);
+ rt2800_bbp_write(rt2x00dev, 1, r1);
+
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ if (ant->rx_chain_num == 1)
+ rt2800_bbp_write(rt2x00dev, 86, 0x00);
+ else
diff --git a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
new file mode 100644
index 0000000..4da750e
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
@@ -0,0 +1,32 @@
+From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 16:58:23 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -1960,7 +1960,8 @@ static void rt2800_config_lna_gain(struc
+ rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
+ } else if (libconf->rf.channel <= 128) {
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom,
+ EEPROM_EXT_LNA2_A1);
+@@ -1970,7 +1971,8 @@ static void rt2800_config_lna_gain(struc
+ EEPROM_RSSI_BG2_LNA_A1);
+ }
+ } else {
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom,
+ EEPROM_EXT_LNA2_A2);
diff --git a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
new file mode 100644
index 0000000..628b237
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
@@ -0,0 +1,44 @@
+From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Tue, 1 Oct 2013 15:40:08 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -4811,7 +4811,8 @@ static u8 rt2800_get_default_vgc(struct
+ else
+ vgc = 0x2e + rt2x00dev->lna_gain;
+ } else { /* 5GHZ band */
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
+ else if (rt2x00_rt(rt2x00dev, RT5592))
+ vgc = 0x24 + (2 * rt2x00dev->lna_gain);
+@@ -4831,7 +4832,8 @@ static inline void rt2800_set_vgc(struct
+ {
+ if (qual->vgc_level != vgc_level) {
+ if (rt2x00_rt(rt2x00dev, RT3572) ||
+- rt2x00_rt(rt2x00dev, RT3593)) {
++ rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
+ vgc_level);
+ } else if (rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -4878,6 +4880,11 @@ void rt2800_link_tuner(struct rt2x00_dev
+ }
+ break;
+
++ case RT3883:
++ if (qual->rssi > -65)
++ vgc += 0x10;
++ break;
++
+ case RT5592:
+ if (qual->rssi > -65)
+ vgc += 0x20;
diff --git a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
new file mode 100644
index 0000000..216b8b6
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
@@ -0,0 +1,42 @@
+From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Tue, 1 Oct 2013 17:27:57 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7606,7 +7606,8 @@ static int rt2800_validate_eeprom(struct
+ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
+ rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
+- if (!rt2x00_rt(rt2x00dev, RT3593)) {
++ if (!rt2x00_rt(rt2x00dev, RT3593) &&
++ !rt2x00_rt(rt2x00dev, RT3883)) {
+ if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+ rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+ rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+@@ -7626,7 +7627,8 @@ static int rt2800_validate_eeprom(struct
+ rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
+ rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
+- if (!rt2x00_rt(rt2x00dev, RT3593)) {
++ if (!rt2x00_rt(rt2x00dev, RT3593) &&
++ !rt2x00_rt(rt2x00dev, RT3883)) {
+ if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+ rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+ rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+@@ -7634,7 +7636,8 @@ static int rt2800_validate_eeprom(struct
+ }
+ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word);
+ if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
+ rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
diff --git a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
new file mode 100644
index 0000000..515086f
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
@@ -0,0 +1,22 @@
+From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 2 Oct 2013 10:11:59 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3981,6 +3981,9 @@ static u8 rt2800_compensate_txpower(stru
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return min_t(u8, txpower, 0xc);
+
++ if (rt2x00_rt(rt2x00dev, RT3883))
++ return min_t(u8, txpower, 0xf);
++
+ if (rt2x00_has_cap_power_limit(rt2x00dev)) {
+ /*
+ * Check if eirp txpower exceed txpower_limit.
diff --git a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
new file mode 100644
index 0000000..77e3f1b
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
@@ -0,0 +1,23 @@
+From f6734ec72da936989a8ce4186b3ede28fbc47836 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 18 Aug 2013 21:57:34 +0200
+Subject: [PATCH] rt2x00: rt2800lib: enable RT2800_HAS_HIGH_SHARED_MEM for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -8415,7 +8415,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ if (retval)
+ return retval;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
diff --git a/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch b/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch
new file mode 100644
index 0000000..dc06e6a
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch
@@ -0,0 +1,22 @@
+From f1acfc2f397e86548ae1b479c198d4bef57050f6 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 29 Sep 2013 18:10:34 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use high memory for beacons on RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -97,7 +97,8 @@ static inline void rt2800_shared_mem_sel
+
+ static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return true;
+
+ return false;
diff --git a/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch b/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch
new file mode 100644
index 0000000..71f7bba
--- /dev/null
+++ b/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch
@@ -0,0 +1,136 @@
+From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious
+ TX_FIFO_STATUS interrupts
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++-----
+ drivers/net/wireless/rt2x00/rt2x00.h | 5 +++
+ 2 files changed, 65 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c
+@@ -415,9 +415,9 @@ void rt2800mmio_autowake_tasklet(unsigne
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+
+-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
++static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev,
++ u32 status)
+ {
+- u32 status;
+ int i;
+
+ /*
+@@ -438,29 +438,77 @@ static void rt2800mmio_txstatus_interrup
+ * Since we have only one producer and one consumer we don't
+ * need to lock the kfifo.
+ */
+- for (i = 0; i < rt2x00dev->tx->limit; i++) {
+- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
+-
+- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+- break;
+-
++ i = 0;
++ do {
+ if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
+- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
++ rt2x00_warn(rt2x00dev,
++ "TX status FIFO overrun, drop TX status report\n");
+ break;
+ }
+- }
++
++ if (++i >= rt2x00dev->tx->limit)
++ break;
++
++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
++ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID));
+
+ /* Schedule the tasklet for processing the tx status. */
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+ }
+
++#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4
++
++static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev,
++ u32 txstatus)
++{
++ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) {
++ rt2x00dev->txstatus_irq_retries = 0;
++ return false;
++ }
++
++ rt2x00dev->txstatus_irq_retries++;
++
++ /* Ensure that we don't go into an infinite IRQ loop. */
++ if (rt2x00dev->txstatus_irq_retries >=
++ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) {
++ rt2x00_warn(rt2x00dev,
++ "%u spurious TX_FIFO_STATUS interrupt(s)\n",
++ rt2x00dev->txstatus_irq_retries);
++ rt2x00dev->txstatus_irq_retries = 0;
++ return false;
++ }
++
++ return true;
++}
++
+ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
+ {
+ struct rt2x00_dev *rt2x00dev = dev_instance;
+ u32 reg, mask;
++ u32 txstatus = 0;
+
+- /* Read status and ACK all interrupts */
++ /* Read status */
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
++
++ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
++ /* Due to unknown reason the hardware generates a
++ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
++ * register contain valid data. Read the TX status
++ * here to see if we have to process the actual
++ * request.
++ */
++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus);
++ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
++ /* Remove the TX_FIFO_STATUS bit so it won't be
++ * processed in this turn. The hardware will
++ * generate another IRQ for us.
++ */
++ rt2x00_set_field32(&reg,
++ INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
++ }
++ }
++
++ /* ACK interrupts */
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+ if (!reg)
+@@ -477,7 +525,7 @@ irqreturn_t rt2800mmio_interrupt(int irq
+ mask = ~reg;
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+- rt2800mmio_txstatus_interrupt(rt2x00dev);
++ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus);
+ /*
+ * Never disable the TX_FIFO_STATUS interrupt.
+ */
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -989,6 +989,11 @@ struct rt2x00_dev {
+ int rf_channel;
+
+ /*
++ * Counter for tx status irq retries (rt2800pci).
++ */
++ unsigned int txstatus_irq_retries;
++
++ /*
+ * Protect the interrupt mask register.
+ */
+ spinlock_t irqmask_lock;
diff --git a/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch b/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch
new file mode 100644
index 0000000..08c8fa6
--- /dev/null
+++ b/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch
@@ -0,0 +1,13 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -94,8 +94,10 @@ int rt2x00pci_probe(struct pci_dev *pci_
+
+ pci_set_master(pci_dev);
+
++#ifdef CONFIG_PCI_SET_MWI
+ if (pci_set_mwi(pci_dev))
+ rt2x00_probe_err("MWI not available\n");
++#endif
+
+ if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
+ rt2x00_probe_err("PCI DMA not supported\n");
diff --git a/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
new file mode 100644
index 0000000..8c71075
--- /dev/null
+++ b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
@@ -0,0 +1,32 @@
+--- /dev/null
++++ b/include/linux/rt2x00_platform.h
+@@ -0,0 +1,19 @@
++/*
++ * Platform data definition for the rt2x00 driver
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ */
++
++#ifndef _RT2X00_PLATFORM_H
++#define _RT2X00_PLATFORM_H
++
++struct rt2x00_platform_data {
++ char *eeprom_file_name;
++};
++
++#endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -38,6 +38,7 @@
+ #include <linux/kfifo.h>
+ #include <linux/hrtimer.h>
+ #include <linux/average.h>
++#include <linux/rt2x00_platform.h>
+
+ #include <net/mac80211.h>
+
diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
new file mode 100644
index 0000000..1255d75
--- /dev/null
+++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
@@ -0,0 +1,301 @@
+--- a/.local-symbols
++++ b/.local-symbols
+@@ -314,6 +314,7 @@ RT2X00_LIB_FIRMWARE=
+ RT2X00_LIB_CRYPTO=
+ RT2X00_LIB_LEDS=
+ RT2X00_LIB_DEBUGFS=
++RT2X00_LIB_EEPROM=
+ RT2X00_DEBUG=
+ WL_MEDIATEK=
+ MT7601U=
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -69,6 +69,7 @@ config RT2800PCI
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_PCI
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2X00_LIB_CRYPTO
+ depends on CRC_CCITT
+ depends on EEPROM_93CX6
+@@ -215,6 +216,7 @@ config RT2800SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
+ ---help---
+@@ -265,6 +267,9 @@ config RT2X00_LIB_FIRMWARE
+ config RT2X00_LIB_CRYPTO
+ bool
+
++config RT2X00_LIB_EEPROM
++ boolean
++
+ config RT2X00_LIB_LEDS
+ bool
+ default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+--- a/drivers/net/wireless/rt2x00/Makefile
++++ b/drivers/net/wireless/rt2x00/Makefile
+@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o
++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
+
+ obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o
+ obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -46,6 +46,8 @@ struct rt2800_drv_data {
+ } shmem_lock;
+ };
+
++#include "rt2800.h"
++
+ struct rt2800_ops {
+ void (*register_read)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset, u32 *value);
+@@ -179,6 +181,15 @@ static inline int rt2800_read_eeprom(str
+ {
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
++ if (rt2x00dev->eeprom_file) {
++ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data,
++ EEPROM_SIZE);
++ return 0;
++ }
++
++ if (!rt2800ops->read_eeprom)
++ return -EINVAL;
++
+ return rt2800ops->read_eeprom(rt2x00dev);
+ }
+
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st
+ return retval;
+ }
+
+-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+-{
+- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+-
+- if (!base_addr)
+- return -ENOMEM;
+-
+- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+-
+- iounmap(base_addr);
+- return 0;
+-}
+-
+ /* Firmware functions */
+ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
+- .read_eeprom = rt2800soc_read_eeprom,
+ .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
+ .drv_write_firmware = rt2800soc_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -697,6 +697,7 @@ enum rt2x00_capability_flags {
+ REQUIRE_HT_TX_DESC,
+ REQUIRE_PS_AUTOWAKE,
+ REQUIRE_DELAYED_RFKILL,
++ REQUIRE_EEPROM_FILE,
+
+ /*
+ * Capabilities
+@@ -966,6 +967,11 @@ struct rt2x00_dev {
+ const struct firmware *fw;
+
+ /*
++ * EEPROM image.
++ */
++ const struct firmware *eeprom_file;
++
++ /*
+ * FIFO for storing tx status reports between isr and tasklet.
+ */
+ DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1334,6 +1334,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+ INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+ INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
+
++ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
++ if (retval)
++ goto exit;
++
+ /*
+ * Let the driver probe the device to detect the capabilities.
+ */
+@@ -1474,6 +1478,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+ * Free the driver data.
+ */
+ kfree(rt2x00dev->drv_data);
++
++ /*
++ * Free EEPROM image.
++ */
++ rt2x00lib_free_eeprom_file(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+
+--- /dev/null
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -0,0 +1,111 @@
++/*
++ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
++ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 eeprom file loading routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++static const char *
++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++
++ if (pdata && pdata->eeprom_file_name)
++ return pdata->eeprom_file_name;
++
++ return NULL
++}
++
++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ const struct firmware *ee;
++ const char *ee_name;
++ int retval;
++
++ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
++ if (!ee_name) {
++ rt2x00_err(rt2x00dev,
++ "Invalid EEPROM filename.\n"
++ "Please file bug report to %s.\n", DRV_PROJECT);
++ return -EINVAL;
++ }
++
++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
++
++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
++ if (retval) {
++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
++ return retval;
++ }
++
++ if (!ee || !ee->size || !ee->data) {
++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
++ retval = -ENOENT;
++ goto err_exit;
++ }
++
++ if (ee->size != rt2x00dev->ops->eeprom_size) {
++ rt2x00_err(rt2x00dev,
++ "EEPROM file size is invalid, it should be %d bytes\n",
++ rt2x00dev->ops->eeprom_size);
++ retval = -EINVAL;
++ goto err_release_ee;
++ }
++
++ rt2x00dev->eeprom_file = ee;
++ return 0;
++
++err_release_ee:
++ release_firmware(ee);
++err_exit:
++ return retval;
++}
++
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ int retval;
++
++ if (!rt2x00lib_get_eeprom_file_name(rt2x00dev))
++ return 0;
++
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
++
++ if (!rt2x00dev->eeprom_file) {
++ retval = rt2x00lib_request_eeprom_file(rt2x00dev);
++ if (retval)
++ return retval;
++ }
++
++ return 0;
++}
++
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ release_firmware(rt2x00dev->eeprom_file);
++ rt2x00dev->eeprom_file = NULL;
++}
+--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
+@@ -320,6 +320,22 @@ static inline void rt2x00lib_free_firmwa
+ #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */
+
+ /*
++ * EEPROM file handlers.
++ */
++#ifdef CPTCFG_RT2X00_LIB_EEPROM
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev);
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev);
++#else
++static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ return 0;
++}
++static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++}
++#endif /* CPTCFG_RT2X00_LIB_EEPROM */
++
++/*
+ * Debugfs handlers.
+ */
+ #ifdef CPTCFG_RT2X00_LIB_DEBUGFS
+--- a/drivers/net/wireless/rt2x00/rt2x00soc.c
++++ b/drivers/net/wireless/rt2x00/rt2x00soc.c
+@@ -92,6 +92,7 @@ int rt2x00soc_probe(struct platform_devi
+ rt2x00dev->hw = hw;
+ rt2x00dev->irq = platform_get_irq(pdev, 0);
+ rt2x00dev->name = pdev->dev.driver->name;
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
+
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
diff --git a/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch b/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch
new file mode 100644
index 0000000..4bc6f37
--- /dev/null
+++ b/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch
@@ -0,0 +1,33 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -26,6 +26,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+@@ -34,11 +35,21 @@ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++#ifdef CONFIG_OF
++ struct device_node *np;
++ const char *eep;
++#endif
+
+ if (pdata && pdata->eeprom_file_name)
+ return pdata->eeprom_file_name;
+
+- return NULL
++#ifdef CONFIG_OF
++ np = rt2x00dev->dev->of_node;
++ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0)
++ return eep;
++#endif
++
++ return NULL;
+ }
+
+ static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
diff --git a/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch
new file mode 100644
index 0000000..75f0415
--- /dev/null
+++ b/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch
@@ -0,0 +1,101 @@
+From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 17 Mar 2013 00:55:04 +0100
+Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
+ OF
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/Kconfig | 1 +
+ drivers/net/wireless/rt2x00/rt2800pci.c | 44 ++++++++++++++++++++++++++-----
+ 2 files changed, 39 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -219,6 +219,7 @@ config RT2800SOC
+ select RT2X00_LIB_EEPROM
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
++ select MTD if SOC_RT288X || SOC_RT305X
+ ---help---
+ This adds support for Ralink WiSoC devices.
+ Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -26,11 +26,66 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
+ #include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+
++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
++{
++ int ret = -EINVAL;
++#ifdef CONFIG_OF
++ static struct firmware mtd_fw;
++ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
++ size_t retlen, len = rt2x00dev->ops->eeprom_size;
++ int size, offset = 0;
++ struct mtd_info *mtd;
++ const char *part;
++ const __be32 *list;
++ phandle phandle;
++
++ list = of_get_property(np, "ralink,mtd-eeprom", &size);
++ if (!list) {
++ dev_err(rt2x00dev->dev, "failed to load eeprom property\n");
++ return -ENOENT;
++ }
++
++ phandle = be32_to_cpup(list++);
++ if (phandle)
++ mtd_np = of_find_node_by_phandle(phandle);
++ if (!mtd_np) {
++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
++ return -EINVAL;
++ }
++
++ part = of_get_property(mtd_np, "label", NULL);
++ if (!part)
++ part = mtd_np->name;
++
++ mtd = get_mtd_device_nm(part);
++ if (IS_ERR(mtd)) {
++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
++ return PTR_ERR(mtd);
++ }
++
++ if (size > sizeof(*list))
++ offset = be32_to_cpup(list);
++
++ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
++ put_mtd_device(mtd);
++
++ if (!ret) {
++ rt2x00dev->eeprom_file = &mtd_fw;
++ mtd_fw.size = len;
++ mtd_fw.data = rt2x00dev->eeprom;
++ }
++#endif
++
++ return ret;
++}
++
+ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -58,6 +113,9 @@ static int rt2x00lib_request_eeprom_file
+ const char *ee_name;
+ int retval;
+
++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
++ return 0;
++
+ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
+ if (!ee_name) {
+ rt2x00_err(rt2x00dev,
diff --git a/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
new file mode 100644
index 0000000..76269f2
--- /dev/null
+++ b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
@@ -0,0 +1,47 @@
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,9 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++
++ int disable_2ghz;
++ int disable_5ghz;
+ };
+
+ #endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -940,6 +940,22 @@ static int rt2x00lib_probe_hw_modes(stru
+ unsigned int num_rates;
+ unsigned int i;
+
++ if (rt2x00dev->dev->platform_data) {
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata->disable_2ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (pdata->disable_5ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++ }
++
++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
++ rt2x00_err(rt2x00dev, "No supported bands\n");
++ return -EINVAL;
++ }
++
++
+ num_rates = 0;
+ if (spec->supported_rates & SUPPORT_RATE_CCK)
+ num_rates += 4;
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -405,6 +405,7 @@ struct hw_mode_spec {
+ unsigned int supported_bands;
+ #define SUPPORT_BAND_2GHZ 0x00000001
+ #define SUPPORT_BAND_5GHZ 0x00000002
++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
+
+ unsigned int supported_rates;
+ #define SUPPORT_RATE_CCK 0x00000001
diff --git a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch
new file mode 100644
index 0000000..0177c80
--- /dev/null
+++ b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch
@@ -0,0 +1,63 @@
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,7 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++ const u8 *mac_address;
+
+ int disable_2ghz;
+ int disable_5ghz;
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -931,6 +931,18 @@ static void rt2x00lib_rate(struct ieee80
+ entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
+ }
+
++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (!pdata)
++ return NULL;
++
++ return pdata->mac_address;
++}
++EXPORT_SYMBOL_GPL(rt2x00lib_get_mac_address);
++
+ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+ struct hw_mode_spec *spec)
+ {
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -1412,6 +1412,7 @@ static inline void rt2x00debug_dump_fram
+ */
+ u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_vif *vif);
++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev);
+
+ /*
+ * Interrupt context handlers.
+--- a/drivers/net/wireless/rt2x00/rt61pci.c
++++ b/drivers/net/wireless/rt2x00/rt61pci.c
+@@ -2390,6 +2390,7 @@ static int rt61pci_validate_eeprom(struc
+ u32 reg;
+ u16 word;
+ u8 *mac;
++ const u8 *pdata_mac;
+ s8 value;
+
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+@@ -2410,7 +2411,11 @@ static int rt61pci_validate_eeprom(struc
+ /*
+ * Start validation of the data that has been read.
+ */
++ pdata_mac = rt2x00lib_get_mac_address(rt2x00dev);
+ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
++ if (pdata_mac)
++ memcpy(mac, pdata_mac, 6);
++
+ if (!is_valid_ether_addr(mac)) {
+ eth_random_addr(mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
diff --git a/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch
new file mode 100644
index 0000000..63a8641
--- /dev/null
+++ b/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -26,6 +26,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/log2.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+@@ -951,6 +952,16 @@ static int rt2x00lib_probe_hw_modes(stru
+ struct ieee80211_rate *rates;
+ unsigned int num_rates;
+ unsigned int i;
++#ifdef CONFIG_OF
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int enabled;
++ if (!of_property_read_u32(np, "ralink,2ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (!of_property_read_u32(np, "ralink,5ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++#endif /* CONFIG_OF */
+
+ if (rt2x00dev->dev->platform_data) {
+ struct rt2x00_platform_data *pdata;
diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
new file mode 100644
index 0000000..d6ea384
--- /dev/null
+++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
@@ -0,0 +1,211 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3528,11 +3528,18 @@ static void rt2800_config_channel(struct
+ /*
+ * Change BBP settings
+ */
++
+ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
++
+ rt2800_bbp_write(rt2x00dev, 27, 0x0);
+ rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 27, 0x20);
+ rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 86, 0x38);
++ rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+ } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+ if (rf->channel > 14) {
+ /* Disable CCK Packet detection on 5GHz */
+@@ -6594,6 +6601,12 @@ static void rt2800_init_rfcsr_3290(struc
+
+ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
+ {
++ int tx0_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX0,
++ &rt2x00dev->cap_flags);
++ int tx1_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX1,
++ &rt2x00dev->cap_flags);
++ u8 rfcsr;
++
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
+ rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
+@@ -6629,15 +6642,30 @@ static void rt2800_init_rfcsr_3352(struc
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 34, 0x01);
++ rfcsr = 0x01;
++ if (!tx0_int_pa)
++ rt2x00_set_field8(&rfcsr, RFCSR34_TX0_EXT_PA, 1);
++ if (!tx1_int_pa)
++ rt2x00_set_field8(&rfcsr, RFCSR34_TX1_EXT_PA, 1);
++ rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
+ rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
+ rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
+- rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
+- rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
++ rfcsr = 0x52;
++ if (tx0_int_pa) {
++ rt2x00_set_field8(&rfcsr, RFCSR41_BIT1, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR41_BIT4, 1);
++ }
++ rt2800_rfcsr_write(rt2x00dev, 41, rfcsr);
++ rfcsr = 0x52;
++ if (tx1_int_pa) {
++ rt2x00_set_field8(&rfcsr, RFCSR42_BIT1, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR42_BIT4, 1);
++ }
++ rt2800_rfcsr_write(rt2x00dev, 42, rfcsr);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
+ rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
+@@ -6645,15 +6673,20 @@ static void rt2800_init_rfcsr_3352(struc
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
+- rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
+- rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
+- rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
+- rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
+- rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
+- rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
+- rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
++ rfcsr = 0x2d;
++ if (!tx0_int_pa)
++ rt2x00_set_field8(&rfcsr, RFCSR50_TX0_EXT_PA, 1);
++ if (!tx1_int_pa)
++ rt2x00_set_field8(&rfcsr, RFCSR50_TX1_EXT_PA, 1);
++ rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
++ rt2800_rfcsr_write(rt2x00dev, 51, (tx0_int_pa ? 0x7f : 0x52));
++ rt2800_rfcsr_write(rt2x00dev, 52, (tx0_int_pa ? 0x00 : 0xc0));
++ rt2800_rfcsr_write(rt2x00dev, 53, (tx0_int_pa ? 0x52 : 0xd2));
++ rt2800_rfcsr_write(rt2x00dev, 54, (tx0_int_pa ? 0x1b : 0xc0));
++ rt2800_rfcsr_write(rt2x00dev, 55, (tx1_int_pa ? 0x7f : 0x52));
++ rt2800_rfcsr_write(rt2x00dev, 56, (tx1_int_pa ? 0x00 : 0xc0));
++ rt2800_rfcsr_write(rt2x00dev, 57, (tx0_int_pa ? 0x52 : 0x49));
++ rt2800_rfcsr_write(rt2x00dev, 58, (tx1_int_pa ? 0x1b : 0xc0));
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
+@@ -7674,6 +7707,7 @@ static int rt2800_init_eeprom(struct rt2
+ * RT53xx: defined in "EEPROM_CHIP_ID" field
+ */
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
++ rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+@@ -7769,7 +7803,8 @@ static int rt2800_init_eeprom(struct rt2
+ /*
+ * Detect if this device has Bluetooth co-existence.
+ */
+- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
++ if (!rt2x00_rt(rt2x00dev, RT3352) &&
++ rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
+ __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
+
+ /*
+@@ -7798,6 +7833,22 @@ static int rt2800_init_eeprom(struct rt2
+ EIRP_MAX_TX_POWER_LIMIT)
+ __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
+
++ /*
++ * Detect if device uses internal or external PA
++ */
++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
++
++ if (rt2x00_rt(rt2x00dev, RT3352)) {
++ if (!rt2x00_get_field16(eeprom,
++ EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
++ __set_bit(CAPABILITY_INTERNAL_PA_TX0,
++ &rt2x00dev->cap_flags);
++ if (!rt2x00_get_field16(eeprom,
++ EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352))
++ __set_bit(CAPABILITY_INTERNAL_PA_TX1,
++ &rt2x00dev->cap_flags);
++ }
++
+ return 0;
+ }
+
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -2335,6 +2335,12 @@ struct mac_iveiv_entry {
+ #define RFCSR36_RF_BS FIELD8(0x80)
+
+ /*
++ * RFCSR 34:
++ */
++#define RFCSR34_TX0_EXT_PA FIELD8(0x04)
++#define RFCSR34_TX1_EXT_PA FIELD8(0x08)
++
++/*
+ * RFCSR 38:
+ */
+ #define RFCSR38_RX_LO1_EN FIELD8(0x20)
+@@ -2346,6 +2352,18 @@ struct mac_iveiv_entry {
+ #define RFCSR39_RX_LO2_EN FIELD8(0x80)
+
+ /*
++ * RFCSR 41:
++ */
++#define RFCSR41_BIT1 FIELD8(0x01)
++#define RFCSR41_BIT4 FIELD8(0x08)
++
++/*
++ * RFCSR 42:
++ */
++#define RFCSR42_BIT1 FIELD8(0x01)
++#define RFCSR42_BIT4 FIELD8(0x08)
++
++/*
+ * RFCSR 49:
+ */
+ #define RFCSR49_TX FIELD8(0x3f)
+@@ -2358,6 +2376,8 @@ struct mac_iveiv_entry {
+ * RFCSR 50:
+ */
+ #define RFCSR50_TX FIELD8(0x3f)
++#define RFCSR50_TX0_EXT_PA FIELD8(0x02)
++#define RFCSR50_TX1_EXT_PA FIELD8(0x10)
+ #define RFCSR50_EP FIELD8(0xc0)
+ /* bits for RT3593 */
+ #define RFCSR50_TX_LO1_EN FIELD8(0x20)
+@@ -2505,6 +2525,8 @@ enum rt2800_eeprom_word {
+ * INTERNAL_TX_ALC: 0: disable, 1: enable
+ * BT_COEXIST: 0: disable, 1: enable
+ * DAC_TEST: 0: disable, 1: enable
++ * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352)
++ * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352)
+ */
+ #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001)
+ #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002)
+@@ -2521,6 +2543,8 @@ enum rt2800_eeprom_word {
+ #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000)
+ #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000)
+ #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000)
++#define EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352 FIELD16(0x4000)
++#define EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352 FIELD16(0x8000)
+
+ /*
+ * EEPROM frequency
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -717,6 +717,8 @@ enum rt2x00_capability_flags {
+ CAPABILITY_DOUBLE_ANTENNA,
+ CAPABILITY_BT_COEXIST,
+ CAPABILITY_VCO_RECALIBRATION,
++ CAPABILITY_INTERNAL_PA_TX0,
++ CAPABILITY_INTERNAL_PA_TX1,
+ };
+
+ /*
diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
new file mode 100644
index 0000000..41a8294
--- /dev/null
+++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
@@ -0,0 +1,106 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -8185,6 +8185,27 @@ static const struct rf_channel rf_vals_5
+ {196, 83, 0, 12, 1},
+ };
+
++/*
++ * RF value list for rt3xxx with Xtal20MHz
++ * Supports: 2.4 GHz (all) (RF3322)
++ */
++static const struct rf_channel rf_vals_xtal20mhz_3x[] = {
++ {1, 0xE2, 2, 0x14},
++ {2, 0xE3, 2, 0x14},
++ {3, 0xE4, 2, 0x14},
++ {4, 0xE5, 2, 0x14},
++ {5, 0xE6, 2, 0x14},
++ {6, 0xE7, 2, 0x14},
++ {7, 0xE8, 2, 0x14},
++ {8, 0xE9, 2, 0x14},
++ {9, 0xEA, 2, 0x14},
++ {10, 0xEB, 2, 0x14},
++ {11, 0xEC, 2, 0x14},
++ {12, 0xED, 2, 0x14},
++ {13, 0xEE, 2, 0x14},
++ {14, 0xF0, 2, 0x18},
++};
++
+ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+ {
+ struct hw_mode_spec *spec = &rt2x00dev->spec;
+@@ -8271,7 +8292,10 @@ static int rt2800_probe_hw_mode(struct r
+ case RF5390:
+ case RF5392:
+ spec->num_channels = 14;
+- spec->channels = rf_vals_3x;
++ if (spec->clk_is_20mhz)
++ spec->channels = rf_vals_xtal20mhz_3x;
++ else
++ spec->channels = rf_vals_3x;
+ break;
+
+ case RF3052:
+@@ -8455,6 +8479,19 @@ static int rt2800_probe_rt(struct rt2x00
+ return 0;
+ }
+
++int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++ struct hw_mode_spec *spec = &rt2x00dev->spec;
++
++ if (!pdata)
++ return -EINVAL;
++
++ spec->clk_is_20mhz = pdata->clk_is_20mhz;
++
++ return 0;
++}
++
+ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
+ {
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+@@ -8497,6 +8534,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+
+ /*
++ * Probe SoC clock.
++ */
++ if (rt2x00_is_soc(rt2x00dev)) {
++ retval = rt2800_probe_clk(rt2x00dev);
++ if (retval)
++ return retval;
++ }
++
++ /*
+ * Initialize hw specifications.
+ */
+ retval = rt2800_probe_hw_mode(rt2x00dev);
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -400,6 +400,7 @@ static inline struct rt2x00_intf* vif_to
+ * @channels: Device/chipset specific channel values (See &struct rf_channel).
+ * @channels_info: Additional information for channels (See &struct channel_info).
+ * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
++ * @clk_is_20mhz: External crystal of WiSoC is 20MHz instead of 40MHz
+ */
+ struct hw_mode_spec {
+ unsigned int supported_bands;
+@@ -416,6 +417,7 @@ struct hw_mode_spec {
+ const struct channel_info *channels_info;
+
+ struct ieee80211_sta_ht_cap ht;
++ int clk_is_20mhz;
+ };
+
+ /*
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -18,6 +18,7 @@ struct rt2x00_platform_data {
+
+ int disable_2ghz;
+ int disable_5ghz;
++ int clk_is_20mhz;
+ };
+
+ #endif /* _RT2X00_PLATFORM_H */
diff --git a/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
new file mode 100644
index 0000000..1970efc
--- /dev/null
+++ b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
@@ -0,0 +1,33 @@
+From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 17 Mar 2013 00:03:31 +0100
+Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC
+
+This patch ads the match table to allow loading the wmac support from a
+devicetree.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/rt2800pci.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -237,10 +237,17 @@ static int rt2800soc_probe(struct platfo
+ return rt2x00soc_probe(pdev, &rt2800soc_ops);
+ }
+
++static const struct of_device_id rt2880_wmac_match[] = {
++ { .compatible = "ralink,rt2880-wmac" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
++
+ static struct platform_driver rt2800soc_driver = {
+ .driver = {
+ .name = "rt2800_wmac",
+ .mod_name = KBUILD_MODNAME,
++ .of_match_table = rt2880_wmac_match,
+ },
+ .probe = rt2800soc_probe,
+ .remove = rt2x00soc_remove,
diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
new file mode 100644
index 0000000..9f11862
--- /dev/null
+++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
@@ -0,0 +1,29 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -36,6 +36,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/clk.h>
+
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -8481,13 +8482,14 @@ static int rt2800_probe_rt(struct rt2x00
+
+ int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev)
+ {
+- struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
+ struct hw_mode_spec *spec = &rt2x00dev->spec;
++ struct clk *clk = clk_get(rt2x00dev->dev, NULL);
+
+- if (!pdata)
+- return -EINVAL;
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
+
+- spec->clk_is_20mhz = pdata->clk_is_20mhz;
++ if (clk_get_rate(clk) == 20000000)
++ spec->clk_is_20mhz = 1;
+
+ return 0;
+ }
diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
new file mode 100644
index 0000000..9679d71
--- /dev/null
+++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch
@@ -0,0 +1,276 @@
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -74,6 +74,7 @@
+ #define RF3070 0x3070
+ #define RF3290 0x3290
+ #define RF3853 0x3853
++#define RF5350 0x5350
+ #define RF5360 0x5360
+ #define RF5362 0x5362
+ #define RF5370 0x5370
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3014,6 +3014,13 @@ static void rt2800_config_channel_rf53xx
+
+ rt2800_rfcsr_write(rt2x00dev, 59,
+ r59_non_bt[idx]);
++ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
++ static const char r59_non_bt[] = {0x0b, 0x0b,
++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
++ 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
++
++ rt2800_rfcsr_write(rt2x00dev, 59,
++ r59_non_bt[idx]);
+ }
+ }
+ }
+@@ -3492,6 +3499,7 @@ static void rt2800_config_channel(struct
+ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
+ break;
+ case RF3070:
++ case RF5350:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -3510,6 +3518,7 @@ static void rt2800_config_channel(struct
+ if (rt2x00_rf(rt2x00dev, RF3070) ||
+ rt2x00_rf(rt2x00dev, RF3290) ||
+ rt2x00_rf(rt2x00dev, RF3322) ||
++ rt2x00_rf(rt2x00dev, RF5350) ||
+ rt2x00_rf(rt2x00dev, RF5360) ||
+ rt2x00_rf(rt2x00dev, RF5362) ||
+ rt2x00_rf(rt2x00dev, RF5370) ||
+@@ -3788,7 +3797,8 @@ static void rt2800_config_channel(struct
+ /*
+ * Clear update flag
+ */
+- if (rt2x00_rt(rt2x00dev, RT3352)) {
++ if (rt2x00_rt(rt2x00dev, RT3352) ||
++ rt2x00_rt(rt2x00dev, RT5350)) {
+ rt2800_bbp_read(rt2x00dev, 49, &bbp);
+ rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
+ rt2800_bbp_write(rt2x00dev, 49, bbp);
+@@ -4674,6 +4684,7 @@ void rt2800_vco_calibration(struct rt2x0
+ case RF3070:
+ case RF3290:
+ case RF3853:
++ case RF5350:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -5087,6 +5098,8 @@ static int rt2800_init_registers(struct
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
++ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+ } else {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+@@ -5742,9 +5755,13 @@ static void rt2800_init_bbp_3352(struct
+
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+- rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+-
+- rt2800_bbp_write(rt2x00dev, 84, 0x99);
++ if (rt2x00_rt(rt2x00dev, RT5350)) {
++ rt2800_bbp_write(rt2x00dev, 83, 0x7a);
++ rt2800_bbp_write(rt2x00dev, 84, 0x9a);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 83, 0x6a);
++ rt2800_bbp_write(rt2x00dev, 84, 0x99);
++ }
+
+ rt2800_bbp_write(rt2x00dev, 86, 0x38);
+
+@@ -5758,9 +5775,13 @@ static void rt2800_init_bbp_3352(struct
+
+ rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
+- rt2800_bbp_write(rt2x00dev, 105, 0x34);
+-
+- rt2800_bbp_write(rt2x00dev, 106, 0x05);
++ if (rt2x00_rt(rt2x00dev, RT5350)) {
++ rt2800_bbp_write(rt2x00dev, 105, 0x3c);
++ rt2800_bbp_write(rt2x00dev, 106, 0x03);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
++ rt2800_bbp_write(rt2x00dev, 106, 0x05);
++ }
+
+ rt2800_bbp_write(rt2x00dev, 120, 0x50);
+
+@@ -5785,6 +5806,13 @@ static void rt2800_init_bbp_3352(struct
+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
+
+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++
++ if (rt2x00_rt(rt2x00dev, RT5350)) {
++ rt2800_bbp_write(rt2x00dev, 150, 0x40); /* Antenna Software OFDM */
++ rt2800_bbp_write(rt2x00dev, 151, 0x30); /* Antenna Software CCK */
++ rt2800_bbp_write(rt2x00dev, 152, 0xa3);
++ rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */
++ }
+ }
+
+ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
+@@ -6126,6 +6154,7 @@ static void rt2800_init_bbp(struct rt2x0
+ rt2800_init_bbp_3290(rt2x00dev);
+ break;
+ case RT3352:
++ case RT5350:
+ rt2800_init_bbp_3352(rt2x00dev);
+ break;
+ case RT3390:
+@@ -7077,6 +7106,76 @@ static void rt2800_init_rfcsr_3883(struc
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+ }
+
++static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev)
++{
++ rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
++ rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x49);
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
++ rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
++ rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
++ if(rt2x00dev->spec.clk_is_20mhz)
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x1f);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0xc0);
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0xd0);
++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
++ rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
++ rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
++ rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
++ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x0c);
++ rt2800_rfcsr_write(rt2x00dev, 45, 0xa6);
++ rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 49, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
++ rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
++ rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
++ rt2800_rfcsr_write(rt2x00dev, 56, 0x82);
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
++ rt2800_rfcsr_write(rt2x00dev, 59, 0x0b);
++ rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
++ rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
++}
++
+ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+ {
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+@@ -7317,6 +7416,9 @@ static void rt2800_init_rfcsr(struct rt2
+ case RT3593:
+ rt2800_init_rfcsr_3593(rt2x00dev);
+ break;
++ case RT5350:
++ rt2800_init_rfcsr_5350(rt2x00dev);
++ break;
+ case RT5390:
+ rt2800_init_rfcsr_5390(rt2x00dev);
+ break;
+@@ -7576,6 +7678,12 @@ static int rt2800_validate_eeprom(struct
+ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
+ rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
++ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1);
++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF3320);
++ rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
++ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+ } else if (rt2x00_rt(rt2x00dev, RT2860) ||
+ rt2x00_rt(rt2x00dev, RT2872)) {
+ /*
+@@ -7714,6 +7822,8 @@ static int rt2800_init_eeprom(struct rt2
+ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+ else if (rt2x00_rt(rt2x00dev, RT3883))
+ rf = RF3853;
++ else if (rt2x00_rt(rt2x00dev, RT5350))
++ rf = RF5350;
+ else
+ rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
+
+@@ -7733,6 +7843,7 @@ static int rt2800_init_eeprom(struct rt2
+ case RF3320:
+ case RF3322:
+ case RF3853:
++ case RF5350:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -8286,6 +8397,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF3290:
+ case RF3320:
+ case RF3322:
++ case RF5350:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -8425,6 +8537,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF3070:
+ case RF3290:
+ case RF3853:
++ case RF5350:
+ case RF5360:
+ case RF5362:
+ case RF5370:
+@@ -8465,6 +8578,7 @@ static int rt2800_probe_rt(struct rt2x00
+ case RT3572:
+ case RT3593:
+ case RT3883:
++ case RT5350:
+ case RT5390:
+ case RT5392:
+ case RT5592:
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -169,6 +169,7 @@ struct rt2x00_chip {
+ #define RT3572 0x3572
+ #define RT3593 0x3593
+ #define RT3883 0x3883 /* WSOC */
++#define RT5350 0x5350 /* WSOC 2.4GHz */
+ #define RT5390 0x5390 /* 2.4GHz */
+ #define RT5392 0x5392 /* 2.4GHz */
+ #define RT5592 0x5592
diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
new file mode 100644
index 0000000..b085c5e
--- /dev/null
+++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
@@ -0,0 +1,40 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -37,6 +37,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/clk.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -7933,6 +7934,17 @@ static int rt2800_init_eeprom(struct rt2
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
++ {
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int led_polarity;
++
++ /* Allow overriding polarity from OF */
++ if (!of_property_read_u32(np, "ralink,led-polarity",
++ &led_polarity))
++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
++ led_polarity);
++ }
++
+ rt2x00dev->led_mcu_reg = eeprom;
+ #endif /* CPTCFG_RT2X00_LIB_LEDS */
+
+--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
+@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc
+ led->led_dev.name = name;
+ led->led_dev.brightness = LED_OFF;
+
++ if (rt2x00_is_soc(rt2x00dev))
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++
+ retval = led_classdev_register(device, &led->led_dev);
+ if (retval) {
+ rt2x00_err(rt2x00dev, "Failed to register led handler\n");
diff --git a/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
new file mode 100644
index 0000000..2dbfd10
--- /dev/null
+++ b/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1283,7 +1283,7 @@ static inline void rt2x00lib_set_if_comb
+ */
+ if_limit = &rt2x00dev->if_limits_ap;
+ if_limit->max = rt2x00dev->ops->max_ap_intf;
+- if_limit->types = BIT(NL80211_IFTYPE_AP);
++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
+ #ifdef CPTCFG_MAC80211_MESH
+ if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+ #endif
diff --git a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
new file mode 100644
index 0000000..259cb1f
--- /dev/null
+++ b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
@@ -0,0 +1,15 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7817,10 +7817,11 @@ static int rt2800_init_eeprom(struct rt2
+ * RT53xx: defined in "EEPROM_CHIP_ID" field
+ */
+ if (rt2x00_rt(rt2x00dev, RT3290) ||
+- rt2x00_rt(rt2x00dev, RT3352) ||
+ rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392))
+ rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
++ else if (rt2x00_rt(rt2x00dev, RT3352))
++ rf = RF3322;
+ else if (rt2x00_rt(rt2x00dev, RT3883))
+ rf = RF3853;
+ else if (rt2x00_rt(rt2x00dev, RT5350))
diff --git a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch
new file mode 100644
index 0000000..77d63fe
--- /dev/null
+++ b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch
@@ -0,0 +1,29 @@
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -2321,6 +2321,8 @@ struct mac_iveiv_entry {
+ #define RFCSR30_RX_H20M FIELD8(0x04)
+ #define RFCSR30_RX_VCM FIELD8(0x18)
+ #define RFCSR30_RF_CALIBRATION FIELD8(0x80)
++#define RF3322_RFCSR30_TX_H20M FIELD8(0x01)
++#define RF3322_RFCSR30_RX_H20M FIELD8(0x02)
+
+ /*
+ * RFCSR 31:
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -3527,8 +3527,13 @@ static void rt2800_config_channel(struct
+ rt2x00_rf(rt2x00dev, RF5390) ||
+ rt2x00_rf(rt2x00dev, RF5392)) {
+ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+- rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+- rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
++ if(rt2x00_rf(rt2x00dev, RF3322)) {
++ rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M, conf_is_ht40(conf));
++ rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_RX_H20M, conf_is_ht40(conf));
++ } else {
++ rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, conf_is_ht40(conf));
++ rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, conf_is_ht40(conf));
++ }
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
diff --git a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
new file mode 100644
index 0000000..9903aa5
--- /dev/null
+++ b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -5679,6 +5679,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+ MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
+
+ static const struct pci_device_id mwl8k_pci_id_table[] = {
++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
diff --git a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch
new file mode 100644
index 0000000..3b8b756
--- /dev/null
+++ b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch
@@ -0,0 +1,21 @@
+--- a/drivers/net/wireless/libertas/cfg.c
++++ b/drivers/net/wireless/libertas/cfg.c
+@@ -2083,6 +2083,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
+ goto err_wiphy_new;
+ }
+
++ set_wiphy_dev(wdev->wiphy, dev);
++
+ lbs_deb_leave(LBS_DEB_CFG80211);
+ return wdev;
+
+--- a/drivers/net/wireless/libertas/main.c
++++ b/drivers/net/wireless/libertas/main.c
+@@ -987,6 +987,7 @@ struct lbs_private *lbs_add_card(void *c
+ goto err_adapter;
+ }
+
++ dev_net_set(dev, wiphy_net(wdev->wiphy));
+ dev->ieee80211_ptr = wdev;
+ dev->ml_priv = priv;
+ SET_NETDEV_DEV(dev, dmdev);
diff --git a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch
new file mode 100644
index 0000000..dace56b
--- /dev/null
+++ b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/libertas/cfg.c
++++ b/drivers/net/wireless/libertas/cfg.c
+@@ -2173,6 +2173,8 @@ int lbs_cfg_register(struct lbs_private
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+ wdev->wiphy->reg_notifier = lbs_reg_notifier;
+
++ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN);
++
+ ret = wiphy_register(wdev->wiphy);
+ if (ret < 0)
+ pr_err("cannot register wiphy device\n");
diff --git a/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch
new file mode 100644
index 0000000..3993c6e
--- /dev/null
+++ b/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -839,6 +839,7 @@ struct b43_wldev {
+ bool qos_enabled; /* TRUE, if QoS is used. */
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
++ int gpiomask; /* GPIO LED mask as a module parameter */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+ MODULE_FIRMWARE("b43/ucode5.fw");
+ MODULE_FIRMWARE("b43/ucode9.fw");
+
++static int modparam_gpiomask = 0x000F;
++module_param_named(gpiomask, modparam_gpiomask, int, 0444);
++MODULE_PARM_DESC(gpiomask,
++ "GPIO mask for LED control (default 0x000F)");
++
+ static int modparam_bad_frames_preempt;
+ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+ MODULE_PARM_DESC(bad_frames_preempt,
+@@ -2883,10 +2888,10 @@ static int b43_gpio_init(struct b43_wlde
+ u32 mask, set;
+
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask);
+
+ mask = 0x0000001F;
+- set = 0x0000000F;
++ set = modparam_gpiomask;
+ if (dev->dev->chip_id == 0x4301) {
+ mask |= 0x0060;
+ set |= 0x0060;
diff --git a/package/kernel/mac80211/patches/810-b43_no_pio.patch b/package/kernel/mac80211/patches/810-b43_no_pio.patch
new file mode 100644
index 0000000..d99f3ce
--- /dev/null
+++ b/package/kernel/mac80211/patches/810-b43_no_pio.patch
@@ -0,0 +1,86 @@
+--- a/drivers/net/wireless/b43/Makefile
++++ b/drivers/net/wireless/b43/Makefile
+@@ -17,7 +17,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o
+ b43-y += sysfs.o
+ b43-y += xmit.o
+ b43-y += dma.o
+-b43-y += pio.o
++b43-$(CPTCFG_B43_PIO) += pio.o
+ b43-y += rfkill.o
+ b43-y += ppr.o
+ b43-$(CPTCFG_B43_LEDS) += leds.o
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -2009,10 +2009,12 @@ static void b43_do_interrupt_thread(stru
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3],
+ dma_reason[4], dma_reason[5]);
++#ifdef CPTCFG_B43_PIO
+ b43err(dev->wl, "This device does not support DMA "
+ "on your system. It will now be switched to PIO.\n");
+ /* Fall back to PIO transfers if we get fatal DMA errors! */
+ dev->use_pio = true;
++#endif
+ b43_controller_restart(dev, "DMA error");
+ return;
+ }
+--- a/drivers/net/wireless/b43/pio.h
++++ b/drivers/net/wireless/b43/pio.h
+@@ -150,7 +150,7 @@ static inline void b43_piorx_write32(str
+ b43_write32(q->dev, q->mmio_base + offset, value);
+ }
+
+-
++#ifdef CPTCFG_B43_PIO
+ int b43_pio_init(struct b43_wldev *dev);
+ void b43_pio_free(struct b43_wldev *dev);
+
+@@ -161,5 +161,37 @@ void b43_pio_rx(struct b43_pio_rxqueue *
+
+ void b43_pio_tx_suspend(struct b43_wldev *dev);
+ void b43_pio_tx_resume(struct b43_wldev *dev);
++#else
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++ return 0;
++}
++
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++
++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
++{
++ return 0;
++}
++
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status)
++{
++}
++
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++#endif /* CPTCFG_B43_PIO */
+
+ #endif /* B43_PIO_H_ */
+--- a/drivers/net/wireless/b43/Kconfig
++++ b/drivers/net/wireless/b43/Kconfig
+@@ -118,7 +118,7 @@ config B43_BCMA_PIO
+ default y
+
+ config B43_PIO
+- bool
++ bool "Broadcom 43xx PIO support"
+ depends on B43 && B43_SSB
+ select SSB_BLOCKIO
+ default y
diff --git a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
new file mode 100644
index 0000000..4f06d8e
--- /dev/null
+++ b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch
@@ -0,0 +1,131 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -1649,7 +1649,7 @@ static void b43_write_beacon_template(st
+ len, ram_offset, shm_size_offset, rate);
+
+ /* Write the PHY TX control parameters. */
+- antenna = B43_ANTENNA_DEFAULT;
++ antenna = dev->tx_antenna;
+ antenna = b43_antenna_to_phyctl(antenna);
+ ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+ /* We can't send beacons with short preamble. Would get PHY errors. */
+@@ -3301,8 +3301,8 @@ static int b43_chip_init(struct b43_wlde
+
+ /* Select the antennae */
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+
+ if (phy->type == B43_PHYTYPE_B) {
+ value16 = b43_read16(dev, 0x005E);
+@@ -4002,7 +4002,6 @@ static int b43_op_config(struct ieee8021
+ struct b43_wldev *dev = wl->current_dev;
+ struct b43_phy *phy = &dev->phy;
+ struct ieee80211_conf *conf = &hw->conf;
+- int antenna;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+@@ -4045,11 +4044,9 @@ static int b43_op_config(struct ieee8021
+ }
+
+ /* Antennas for RX and management frame TX. */
+- antenna = B43_ANTENNA_DEFAULT;
+- b43_mgmtframe_txantenna(dev, antenna);
+- antenna = B43_ANTENNA_DEFAULT;
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, antenna);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+
+ if (wl->radio_enabled != phy->radio_on) {
+ if (wl->radio_enabled) {
+@@ -5210,6 +5207,47 @@ static int b43_op_get_survey(struct ieee
+ return 0;
+ }
+
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ if (tx_ant == 1 && rx_ant == 1) {
++ dev->tx_antenna = B43_ANTENNA0;
++ dev->rx_antenna = B43_ANTENNA0;
++ }
++ else if (tx_ant == 2 && rx_ant == 2) {
++ dev->tx_antenna = B43_ANTENNA1;
++ dev->rx_antenna = B43_ANTENNA1;
++ }
++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++ dev->tx_antenna = B43_ANTENNA_DEFAULT;
++ dev->rx_antenna = B43_ANTENNA_DEFAULT;
++ }
++ else {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ switch (dev->tx_antenna) {
++ case B43_ANTENNA0:
++ *tx_ant = 1; *rx_ant = 1; break;
++ case B43_ANTENNA1:
++ *tx_ant = 2; *rx_ant = 2; break;
++ case B43_ANTENNA_DEFAULT:
++ *tx_ant = 3; *rx_ant = 3; break;
++ }
++ return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+@@ -5231,6 +5269,8 @@ static const struct ieee80211_ops b43_hw
+ .sw_scan_complete = b43_op_sw_scan_complete_notifier,
+ .get_survey = b43_op_get_survey,
+ .rfkill_poll = b43_rfkill_poll,
++ .set_antenna = b43_op_set_antenna,
++ .get_antenna = b43_op_get_antenna,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5539,6 +5579,8 @@ static int b43_one_core_attach(struct b4
+ if (!wldev)
+ goto out;
+
++ wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++ wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ wldev->use_pio = b43_modparam_pio;
+ wldev->dev = dev;
+ wldev->wl = wl;
+@@ -5629,6 +5671,9 @@ static struct b43_wl *b43_wireless_init(
+
+ hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
++ hw->wiphy->available_antennas_rx = 0x3;
++ hw->wiphy->available_antennas_tx = 0x3;
++
+ wl->hw_registred = false;
+ hw->max_rates = 2;
+ SET_IEEE80211_DEV(hw, dev->dev);
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -840,6 +840,8 @@ struct b43_wldev {
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
+ int gpiomask; /* GPIO LED mask as a module parameter */
++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */
++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
diff --git a/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch b/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch
new file mode 100644
index 0000000..9c51ac6
--- /dev/null
+++ b/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/b43/dma.h
++++ b/drivers/net/wireless/b43/dma.h
+@@ -169,7 +169,7 @@ struct b43_dmadesc_generic {
+
+ /* DMA engine tuning knobs */
+ #define B43_TXRING_SLOTS 256
+-#define B43_RXRING_SLOTS 256
++#define B43_RXRING_SLOTS 32
+ #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+ #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
+
diff --git a/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
new file mode 100644
index 0000000..ab06b6e
--- /dev/null
+++ b/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
@@ -0,0 +1,17 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -2900,6 +2900,14 @@ static int b43_gpio_init(struct b43_wlde
+ } else if (dev->dev->chip_id == 0x5354) {
+ /* Don't allow overtaking buttons GPIOs */
+ set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
++ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) {
++ /* just use gpio 0 and 1 for 2.4 GHz wifi led */
++ set &= 0x3;
++ mask &= 0x3;
+ }
+
+ if (0 /* FIXME: conditional unknown */ ) {
diff --git a/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch b/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch
new file mode 100644
index 0000000..9d1d419
--- /dev/null
+++ b/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -118,7 +118,7 @@ static int b43_modparam_pio = 0;
+ module_param_named(pio, b43_modparam_pio, int, 0644);
+ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+
+-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC);
++static int modparam_allhwsupport = 1;
+ module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
+ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
+
diff --git a/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch b/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch
new file mode 100644
index 0000000..185c427
--- /dev/null
+++ b/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+@@ -58,19 +58,12 @@
+ (((c) < 149) ? 3 : 4))))
+
+ #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+-#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+- NL80211_RRF_NO_IR)
++#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0)
+
+-#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+- NL80211_RRF_DFS | \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+- NL80211_RRF_DFS | \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+- NL80211_RRF_NO_IR)
++#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0)
+
+ static const struct ieee80211_regdomain brcms_regdom_x2 = {
+ .n_reg_rules = 6,
diff --git a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
new file mode 100644
index 0000000..d60d3fa
--- /dev/null
+++ b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch
@@ -0,0 +1,97 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Mon, 8 Jun 2015 16:11:40 +0200
+Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is needed by OpenWrt which expects all PHYs to be created after
+module loads successfully.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
+@@ -1236,6 +1236,7 @@ static int __init brcmfmac_module_init(v
+ #endif
+ if (!schedule_work(&brcmf_driver_work))
+ return -EBUSY;
++ flush_work(&brcmf_driver_work);
+
+ return 0;
+ }
+--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+@@ -420,6 +420,7 @@ struct brcmf_fw {
+ u16 bus_nr;
+ void (*done)(struct device *dev, const struct firmware *fw,
+ void *nvram_image, u32 nvram_len);
++ struct completion *completion;
+ };
+
+ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
+@@ -455,6 +456,8 @@ static void brcmf_fw_request_nvram_done(
+ goto fail;
+
+ fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
++ if (fwctx->completion)
++ complete(fwctx->completion);
+ kfree(fwctx);
+ return;
+
+@@ -462,6 +465,8 @@ fail:
+ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+ release_firmware(fwctx->code);
+ device_release_driver(fwctx->dev);
++ if (fwctx->completion)
++ complete(fwctx->completion);
+ kfree(fwctx);
+ }
+
+@@ -477,6 +482,8 @@ static void brcmf_fw_request_code_done(c
+ /* only requested code so done here */
+ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
+ fwctx->done(fwctx->dev, fw, NULL, 0);
++ if (fwctx->completion)
++ complete(fwctx->completion);
+ kfree(fwctx);
+ return;
+ }
+@@ -494,6 +501,8 @@ static void brcmf_fw_request_code_done(c
+ fail:
+ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+ device_release_driver(fwctx->dev);
++ if (fwctx->completion)
++ complete(fwctx->completion);
+ kfree(fwctx);
+ }
+
+@@ -505,6 +514,8 @@ int brcmf_fw_get_firmwares_pcie(struct d
+ u16 domain_nr, u16 bus_nr)
+ {
+ struct brcmf_fw *fwctx;
++ struct completion completion;
++ int err;
+
+ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+ if (!fw_cb || !code)
+@@ -525,9 +536,17 @@ int brcmf_fw_get_firmwares_pcie(struct d
+ fwctx->domain_nr = domain_nr;
+ fwctx->bus_nr = bus_nr;
+
+- return request_firmware_nowait(THIS_MODULE, true, code, dev,
++ init_completion(&completion);
++ fwctx->completion = &completion;
++
++ err = request_firmware_nowait(THIS_MODULE, true, code, dev,
+ GFP_KERNEL, fwctx,
+ brcmf_fw_request_code_done);
++ if (!err)
++ wait_for_completion_timeout(fwctx->completion,
++ msecs_to_jiffies(5000));
++ fwctx->completion = NULL;
++ return err;
+ }
+
+ int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
new file mode 100644
index 0000000..43582f6
--- /dev/null
+++ b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch
@@ -0,0 +1,50 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 9 Jul 2015 00:07:59 +0200
+Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+@@ -609,9 +609,37 @@ static struct wireless_dev *brcmf_cfg802
+ u32 *flags,
+ struct vif_params *params)
+ {
++ struct net_device *dev;
+ struct wireless_dev *wdev;
+ int err;
+
++ /*
++ * There is a bug with in-firmware BSS management. When adding virtual
++ * interface brcmfmac first tells firmware to create new BSS and then
++ * it creates new struct net_device.
++ *
++ * If creating/registering netdev(ice) fails, BSS remains in some bugged
++ * state. It conflicts with existing BSSes by overtaking their auth
++ * requests.
++ *
++ * It results in one BSS (addresss X) sending beacons and another BSS
++ * (address Y) replying to authentication requests. This makes interface
++ * unusable as AP.
++ *
++ * To workaround this bug we may try to guess if register_netdev(ice)
++ * will fail. The most obvious case is using interface name that already
++ * exists. This is actually quite likely with brcmfmac & some user space
++ * scripts as brcmfmac doesn't allow deleting virtual interfaces.
++ * So this bug can be triggered even by something trivial like:
++ * iw dev wlan0 delete
++ * iw phy phy0 interface add wlan0 type __ap
++ */
++ dev = dev_get_by_name(&init_net, name);
++ if (dev) {
++ dev_put(dev);
++ return ERR_PTR(-EEXIST);
++ }
++
+ brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+ if (err) {
diff --git a/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch b/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch
new file mode 100644
index 0000000..e6b2d7b
--- /dev/null
+++ b/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch
@@ -0,0 +1,20 @@
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -211,7 +211,7 @@ endif
+ config RT2800SOC
+ tristate "Ralink WiSoC support"
+ depends on m
+- depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ select RT2X00_LIB_SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+@@ -248,7 +248,7 @@ config RT2X00_LIB_PCI
+
+ config RT2X00_LIB_SOC
+ tristate "RT2x00 SoC support"
+- depends on SOC_RT288X || SOC_RT305X || SOC_RT3883
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ depends on m
+ select RT2X00_LIB
+
diff --git a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
new file mode 100644
index 0000000..b0536ce
--- /dev/null
+++ b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch
@@ -0,0 +1,1202 @@
+--- a/drivers/net/wireless/rt2x00/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -81,6 +81,7 @@
+ #define RF5372 0x5372
+ #define RF5390 0x5390
+ #define RF5392 0x5392
++#define RF7620 0x7620
+
+ /*
+ * Chipset revisions.
+@@ -656,6 +657,14 @@
+ #define RF_CSR_CFG_BUSY FIELD32(0x00020000)
+
+ /*
++ * mt7620 RF registers (reversed order)
++ */
++#define RF_CSR_CFG_DATA_MT7620 FIELD32(0x0000ff00)
++#define RF_CSR_CFG_REGNUM_MT7620 FIELD32(0x03ff0000)
++#define RF_CSR_CFG_WRITE_MT7620 FIELD32(0x00000010)
++#define RF_CSR_CFG_BUSY_MT7620 FIELD32(0x00000001)
++
++/*
+ * EFUSE_CSR: RT30x0 EEPROM
+ */
+ #define EFUSE_CTRL 0x0580
+@@ -1039,6 +1048,11 @@
+ #define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000)
+
+ /*
++ * mt7620
++ */
++#define MIMO_PS_CFG 0x1210
++
++/*
+ * EDCA_AC0_CFG:
+ */
+ #define EDCA_AC0_CFG 0x1300
+@@ -1218,6 +1232,8 @@
+ #define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000)
+ #define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000)
+ #define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000)
++#define TX_PIN_CFG_RFRX_EN FIELD32(0x00100000) /* mt7620 */
++#define TX_PIN_CFG_RFRX_POL FIELD32(0x00200000) /* mt7620 */
+ #define TX_PIN_CFG_PA_PE_A2_EN FIELD32(0x01000000)
+ #define TX_PIN_CFG_PA_PE_G2_EN FIELD32(0x02000000)
+ #define TX_PIN_CFG_PA_PE_A2_POL FIELD32(0x04000000)
+@@ -1564,6 +1580,17 @@
+ #define TX_PWR_CFG_4_EXT_STBC4_CH2 FIELD32(0x0000000f)
+ #define TX_PWR_CFG_4_EXT_STBC6_CH2 FIELD32(0x00000f00)
+
++/* mt7620 */
++#define TX0_RF_GAIN_CORRECT 0x13a0
++#define TX1_RF_GAIN_CORRECT 0x13a4
++#define TX0_RF_GAIN_ATTEN 0x13a8
++#define TX1_RF_GAIN_ATTEN 0x13ac
++#define TX_ALG_CFG_0 0x13b0
++#define TX_ALG_CFG_1 0x13b4
++#define TX0_BB_GAIN_ATTEN 0x13c0
++#define TX1_BB_GAIN_ATTEN 0x13c4
++#define TX_ALC_VGA3 0x13c8
++
+ /* TX_PWR_CFG_7 */
+ #define TX_PWR_CFG_7 0x13d4
+ #define TX_PWR_CFG_7_OFDM54_CH0 FIELD32(0x0000000f)
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -61,6 +61,8 @@
+ rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
+ #define WAIT_FOR_RFCSR(__dev, __reg) \
+ rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
++#define WAIT_FOR_RFCSR_MT7620(__dev, __reg) \
++ rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY_MT7620, (__reg))
+ #define WAIT_FOR_RF(__dev, __reg) \
+ rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
+ #define WAIT_FOR_MCU(__dev, __reg) \
+@@ -186,19 +188,55 @@ static void rt2800_rfcsr_write(struct rt
+ * Wait until the RFCSR becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+- reg = 0;
+- rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
+- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
+- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
++ switch (rt2x00dev->chip.rf) {
++ case RF7620:
++ if (WAIT_FOR_RFCSR_MT7620(rt2x00dev, &reg)) {
++ reg = 0;
++ rt2x00_set_field32(&reg, RF_CSR_CFG_DATA_MT7620, value);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM_MT7620, word);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE_MT7620, 1);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY_MT7620, 1);
++
++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
++ }
++ break;
++
++ default:
++ if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
++ reg = 0;
++ rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+- rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
++ }
++ break;
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+ }
+
++static void rt2800_rfcsr_write_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
++ const unsigned int reg, const u8 value)
++{
++ rt2800_rfcsr_write(rt2x00dev, (reg | (bank << 6)), value);
++}
++
++static void rt2800_rfcsr_write_chanreg(struct rt2x00_dev *rt2x00dev,
++ const unsigned int reg, const u8 value)
++{
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, reg, value);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, reg, value);
++}
++
++static void rt2800_rfcsr_write_dccal(struct rt2x00_dev *rt2x00dev,
++ const unsigned int reg, const u8 value)
++{
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, reg, value);
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, reg, value);
++}
++
+ static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, u8 *value)
+ {
+@@ -214,22 +252,47 @@ static void rt2800_rfcsr_read(struct rt2
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
+ */
+- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+- reg = 0;
+- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
+- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
++ switch (rt2x00dev->chip.rf) {
++ case RF7620:
++ if (WAIT_FOR_RFCSR_MT7620(rt2x00dev, &reg)) {
++ reg = 0;
++ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM_MT7620, word);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE_MT7620, 0);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY_MT7620, 1);
+
+- rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+
+- WAIT_FOR_RFCSR(rt2x00dev, &reg);
+- }
++ WAIT_FOR_RFCSR_MT7620(rt2x00dev, &reg);
++ }
+
+- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
++ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620);
++ break;
++
++ default:
++ if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
++ reg = 0;
++ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
++ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
++
++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
++
++ WAIT_FOR_RFCSR(rt2x00dev, &reg);
++ }
++
++ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
++ break;
++ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+ }
+
++static void rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank,
++ const unsigned int reg, u8 *value)
++{
++ rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)), value);
++}
++
+ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, const u32 value)
+ {
+@@ -566,6 +629,16 @@ void rt2800_get_txwi_rxwi_size(struct rt
+ *rxwi_size = RXWI_DESC_SIZE_5WORDS;
+ break;
+
++ case RT5390:
++ if ( rt2x00dev->chip.rf == RF7620 ) {
++ *txwi_size = TXWI_DESC_SIZE_5WORDS;
++ *rxwi_size = RXWI_DESC_SIZE_6WORDS;
++ } else {
++ *txwi_size = TXWI_DESC_SIZE_4WORDS;
++ *rxwi_size = RXWI_DESC_SIZE_4WORDS;
++ }
++ break;
++
+ case RT5592:
+ *txwi_size = TXWI_DESC_SIZE_5WORDS;
+ *rxwi_size = RXWI_DESC_SIZE_6WORDS;
+@@ -3302,6 +3375,312 @@ static void rt2800_config_channel_rf55xx
+ rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);
+ }
+
++typedef struct mt7620_freqconfig {
++ u8 Channel;
++ u8 Rdiv;
++ u16 N;
++ u8 K;
++ u8 D;
++ u32 Ksd;
++} mt7620_freqconfig;
++
++mt7620_freqconfig mt7620_chanconfig[] =
++{
++ /* 2.4 to 2.483 GHz
++ * CH Rdiv N K D Ksd */
++ { 0, 0, 0, 0, 0, 0 },
++ { 1, 3, 0x50, 0, 0, 0x19999 },
++ { 2, 3, 0x50, 0, 0, 0x24444 },
++ { 3, 3, 0x50, 0, 0, 0x2EEEE },
++ { 4, 3, 0x50, 0, 0, 0x39999 },
++ { 5, 3, 0x51, 0, 0, 0x04444 },
++ { 6, 3, 0x51, 0, 0, 0x0EEEE },
++ { 7, 3, 0x51, 0, 0, 0x19999 },
++ { 8, 3, 0x51, 0, 0, 0x24444 },
++ { 9, 3, 0x51, 0, 0, 0x2EEEE },
++ { 10, 3, 0x51, 0, 0, 0x39999 },
++ { 11, 3, 0x52, 0, 0, 0x04444 },
++ { 12, 3, 0x52, 0, 0, 0x0EEEE },
++ { 13, 3, 0x52, 0, 0, 0x19999 },
++ { 14, 3, 0x52, 0, 0, 0x33333 },
++};
++
++static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_conf *conf,
++ struct rf_channel *rf,
++ struct channel_info *info)
++{
++ int i;
++ u8 bbp;
++ u8 rfcsr;
++ u8 txrx_agc_fc;
++ u32 reg;
++ u16 eeprom, target_power;
++ u32 mac_sys_ctrl, mac_status;
++ u32 tx_pin = 0x00150F0F;
++ struct hw_mode_spec *spec = &rt2x00dev->spec;
++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
++
++ /* Frequeny plan setting */
++ /*
++ * Rdiv setting
++ * R13[1:0]
++ */
++ rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
++ rfcsr = rfcsr & (~0x03);
++ if (spec->clk_is_20mhz)
++ rfcsr |= (mt7620_chanconfig[rf->channel].Rdiv & 0x3);
++ rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
++
++ /*
++ * N setting
++ * R21[0], R20[7:0]
++ */
++ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
++ rfcsr = (mt7620_chanconfig[rf->channel].N & 0x00ff);
++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
++ rfcsr = rfcsr & (~0x01);
++ rfcsr |= ((mt7620_chanconfig[rf->channel].N & 0x0100) >> 8);
++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
++
++ /*
++ * K setting
++ * R16[3:0] (RF PLL freq selection)
++ */
++ rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
++ rfcsr = rfcsr & (~0x0f);
++ rfcsr |= (mt7620_chanconfig[rf->channel].K & 0x0f);
++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
++
++ /*
++ * D setting
++ * R22[2:0] (D=15, R22[2:0]=<111>)
++ */
++ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
++ rfcsr = rfcsr & (~0x07);
++ rfcsr |= (mt7620_chanconfig[rf->channel].D & 0x07);
++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
++
++ /*
++ * Ksd setting
++ * Ksd: R19<1:0>,R18<7:0>,R17<7:0>
++ */
++ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
++ rfcsr = (mt7620_chanconfig[rf->channel].Ksd & 0x000000ff);
++ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
++ rfcsr = ((mt7620_chanconfig[rf->channel].Ksd & 0x0000ff00) >> 8);
++ rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 19, &rfcsr);
++ rfcsr = rfcsr & (~0x03);
++ rfcsr |= ((mt7620_chanconfig[rf->channel].Ksd & 0x00030000) >> 16);
++ rt2800_rfcsr_write(rt2x00dev, 19, rfcsr);
++
++ /* Default: XO=20MHz , SDM mode */
++ rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr);
++ rfcsr = rfcsr & (~0xE0);
++ rfcsr |= 0x80;
++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
++ rfcsr |= 0x80;
++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
++ if (rt2x00dev->default_ant.tx_chain_num == 1)
++ rfcsr &= (~0x2);
++ else
++ rfcsr |= 0x2;
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
++ if (rt2x00dev->default_ant.tx_chain_num == 1)
++ rfcsr &= (~0x20);
++ else
++ rfcsr |= 0x20;
++ if (rt2x00dev->default_ant.rx_chain_num == 1)
++ rfcsr &= (~0x02);
++ else
++ rfcsr |= 0x02;
++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
++
++ rt2800_rfcsr_read(rt2x00dev, 42, &rfcsr);
++ if (rt2x00dev->default_ant.tx_chain_num == 1)
++ rfcsr &= (~0x40);
++ else
++ rfcsr |= 0x40;
++ rt2800_rfcsr_write(rt2x00dev, 42, rfcsr);
++
++ /* RF for DC Cal BW */
++ if (conf_is_ht40(conf)) {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x04);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x10);
++ } else {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20);
++ }
++
++ if (conf_is_ht40(conf)) {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08);
++ } else {
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28);
++ }
++
++ rt2800_rfcsr_read(rt2x00dev, 28, &rfcsr);
++ if (conf_is_ht40(conf) && (rf->channel == 11))
++ rfcsr |= 0x4;
++ else
++ rfcsr &= (~0x4);
++ rt2800_rfcsr_write(rt2x00dev, 28, rfcsr);
++
++ /*if (bScan == FALSE)*/
++ if (conf_is_ht40(conf)) {
++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
++ RFCSR24_TX_AGC_FC);
++ } else {
++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20,
++ RFCSR24_TX_AGC_FC);
++ }
++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 6, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 6, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 7, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 7, rfcsr);
++
++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 58, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 58, rfcsr);
++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 59, &rfcsr);
++ rfcsr &= (~0x3F);
++ rfcsr |= txrx_agc_fc;
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
++
++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_0, &reg);
++ reg = reg & (~0x3F3F);
++ reg |= info->default_power1;
++ reg |= (info->default_power2 << 8);
++ reg |= (0x2F << 16);
++ reg |= (0x2F << 24);
++
++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
++ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
++ /* init base power by e2p target power */
++ rt2800_eeprom_read(rt2x00dev, 0xD0, &target_power);
++ target_power &= 0x3F;
++ reg = reg & (~0x3F3F);
++ reg |= target_power;
++ reg |= (target_power << 8);
++ }
++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_0, reg);
++
++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_1, &reg);
++ reg = reg & (~0x3F);
++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_1, reg);
++
++ /*if (bScan == FALSE)*/
++ /* Save MAC SYS CTRL registers */
++ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &mac_sys_ctrl);
++ /* Disable Tx/Rx */
++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
++ /* Check MAC Tx/Rx idle */
++ for (i = 0; i < 10000; i++) {
++ rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &mac_status);
++ if (mac_status & 0x3)
++ udelay(50);
++ else
++ break;
++ }
++
++ if (i == 10000)
++ rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n");
++
++ if (rf->channel > 10) {
++ rt2800_bbp_read(rt2x00dev, 30, &bbp);
++ bbp = 0x40;
++ rt2800_bbp_write(rt2x00dev, 30, bbp);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x7b);
++ } else {
++ rt2800_bbp_read(rt2x00dev, 30, &bbp);
++ bbp = 0x1f;
++ rt2800_bbp_write(rt2x00dev, 30, bbp);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
++ }
++
++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl);
++
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x0C);
++
++ /* vcocal_en (initiate VCO calibration (reset after completion)) */
++ rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr);
++ rfcsr = ((rfcsr & ~0x80) | 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 4, rfcsr);
++ mdelay(2);
++
++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
++
++ if (rt2x00dev->default_ant.tx_chain_num == 1) {
++ rt2800_bbp_write(rt2x00dev, 91, 0x07);
++ rt2800_bbp_write(rt2x00dev, 95, 0x1A);
++ rt2800_bbp_write(rt2x00dev, 195, 128);
++ rt2800_bbp_write(rt2x00dev, 196, 0xA0);
++ rt2800_bbp_write(rt2x00dev, 195, 170);
++ rt2800_bbp_write(rt2x00dev, 196, 0x12);
++ rt2800_bbp_write(rt2x00dev, 195, 171);
++ rt2800_bbp_write(rt2x00dev, 196, 0x10);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 91, 0x06);
++ rt2800_bbp_write(rt2x00dev, 95, 0x9A);
++ rt2800_bbp_write(rt2x00dev, 195, 128);
++ rt2800_bbp_write(rt2x00dev, 196, 0xE0);
++ rt2800_bbp_write(rt2x00dev, 195, 170);
++ rt2800_bbp_write(rt2x00dev, 196, 0x30);
++ rt2800_bbp_write(rt2x00dev, 195, 171);
++ rt2800_bbp_write(rt2x00dev, 196, 0x30);
++ }
++
++ /* On 11A, We should delay and wait RF/BBP to be stable*/
++ /* and the appropriate time should be 1000 micro seconds */
++ /* 2005/06/05 - On 11G, We also need this delay time.
++ * Otherwise it's difficult to pass the WHQL.*/
++ udelay(1000);
++}
++
++
+ static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word,
+ const u8 value)
+@@ -3458,7 +3837,7 @@ static void rt2800_config_channel(struct
+ struct channel_info *info)
+ {
+ u32 reg;
+- unsigned int tx_pin;
++ u32 tx_pin;
+ u8 bbp, rfcsr;
+
+ info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+@@ -3512,6 +3891,9 @@ static void rt2800_config_channel(struct
+ case RF5592:
+ rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);
+ break;
++ case RF7620:
++ rt2800_config_channel_rf7620(rt2x00dev, conf, rf, info);
++ break;
+ default:
+ rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
+ }
+@@ -3614,7 +3996,7 @@ static void rt2800_config_channel(struct
+ else if (rt2x00_rt(rt2x00dev, RT3593) ||
+ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 82, 0x82);
+- else
++ else if (rt2x00dev->chip.rf != RF7620)
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+
+ if (rt2x00_rt(rt2x00dev, RT3593) ||
+@@ -3636,7 +4018,7 @@ static void rt2800_config_channel(struct
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
+- tx_pin = 0;
++ rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+
+ switch (rt2x00dev->default_ant.tx_chain_num) {
+ case 3:
+@@ -3685,6 +4067,7 @@ static void rt2800_config_channel(struct
+
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); /* mt7620 */
+
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+@@ -4701,6 +5084,14 @@ void rt2800_vco_calibration(struct rt2x0
+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+ break;
++ case RF7620:
++ rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr);
++ /* vcocal_en (initiate VCO calibration (reset after completion))
++ * It should be at the end of RF configuration. */
++ rfcsr = ((rfcsr & ~0x80) | 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 4, rfcsr);
++ mdelay(1);
++ break;
+ default:
+ return;
+ }
+@@ -5101,9 +5492,42 @@ static int rt2800_init_registers(struct
+ } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT5592)) {
+- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
++ if (rt2x00dev->chip.rf == RF7620) {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0,
++ 0x00000401);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1,
++ 0x000C0000);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
++ 0x00000000);
++ rt2800_register_write(rt2x00dev, MIMO_PS_CFG,
++ 0x00000002);
++ rt2800_register_write(rt2x00dev, TX_PIN_CFG,
++ 0x00150F0F);
++ rt2800_register_write(rt2x00dev, TX_ALC_VGA3,
++ 0x06060606);
++ rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN,
++ 0x0);
++ rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN,
++ 0x0);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
++ 0x6C6C666C);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
++ 0x6C6C666C);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
++ 0x3630363A);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT,
++ 0x3630363A);
++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_1, &reg);
++ reg = reg & (~0x80000000);
++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_1, reg);
++ } else {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0,
++ 0x00000404);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1,
++ 0x00080606);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
++ 0x00000000);
++ }
+ } else if (rt2x00_rt(rt2x00dev, RT5350)) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+ } else {
+@@ -6135,6 +6559,225 @@ static void rt2800_init_bbp_5592(struct
+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+ }
+
++static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev,
++ const u8 reg, const u8 value)
++{
++ rt2800_bbp_write(rt2x00dev, 195, reg);
++ rt2800_bbp_write(rt2x00dev, 196, value);
++}
++
++static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
++ const u8 reg, const u8 value)
++{
++ rt2800_bbp_write(rt2x00dev, 158, reg);
++ rt2800_bbp_write(rt2x00dev, 159, value);
++}
++
++static void rt2800_init_bbp_7620(struct rt2x00_dev *rt2x00dev)
++{
++ u8 bbp;
++
++ /* Apply Maximum Likelihood Detection (MLD) for 2 stream case */
++ rt2800_bbp_read(rt2x00dev, 105, &bbp);
++ rt2x00_set_field8(&bbp, BBP105_MLD,
++ rt2x00dev->default_ant.rx_chain_num == 2);
++ rt2800_bbp_write(rt2x00dev, 105, bbp);
++
++ /* Avoid data loss and CRC errors */
++ /* MAC interface control (MAC_IF_80M, 1: 80 MHz) */
++ rt2800_bbp4_mac_if_ctrl(rt2x00dev);
++
++ /* Fix I/Q swap issue */
++ rt2800_bbp_read(rt2x00dev, 1, &bbp);
++ bbp |= 0x04;
++ rt2800_bbp_write(rt2x00dev, 1, bbp);
++
++ /* BBP for G band */
++ rt2800_bbp_write(rt2x00dev, 3, 0x08);
++ rt2800_bbp_write(rt2x00dev, 4, 0x00); /* rt2800_bbp4_mac_if_ctrl? */
++ rt2800_bbp_write(rt2x00dev, 6, 0x08);
++ rt2800_bbp_write(rt2x00dev, 14, 0x09);
++ rt2800_bbp_write(rt2x00dev, 15, 0xFF);
++ rt2800_bbp_write(rt2x00dev, 16, 0x01);
++ rt2800_bbp_write(rt2x00dev, 20, 0x06);
++ rt2800_bbp_write(rt2x00dev, 21, 0x00);
++ rt2800_bbp_write(rt2x00dev, 22, 0x00);
++ rt2800_bbp_write(rt2x00dev, 27, 0x00);
++ rt2800_bbp_write(rt2x00dev, 28, 0x00);
++ rt2800_bbp_write(rt2x00dev, 30, 0x00);
++ rt2800_bbp_write(rt2x00dev, 31, 0x48);
++ rt2800_bbp_write(rt2x00dev, 47, 0x40);
++ rt2800_bbp_write(rt2x00dev, 62, 0x00);
++ rt2800_bbp_write(rt2x00dev, 63, 0x00);
++ rt2800_bbp_write(rt2x00dev, 64, 0x00);
++ rt2800_bbp_write(rt2x00dev, 65, 0x2C);
++ rt2800_bbp_write(rt2x00dev, 66, 0x1C);
++ rt2800_bbp_write(rt2x00dev, 67, 0x20);
++ rt2800_bbp_write(rt2x00dev, 68, 0xDD);
++ rt2800_bbp_write(rt2x00dev, 69, 0x10);
++ rt2800_bbp_write(rt2x00dev, 70, 0x05);
++ rt2800_bbp_write(rt2x00dev, 73, 0x18);
++ rt2800_bbp_write(rt2x00dev, 74, 0x0F);
++ rt2800_bbp_write(rt2x00dev, 75, 0x60);
++ rt2800_bbp_write(rt2x00dev, 76, 0x44);
++ rt2800_bbp_write(rt2x00dev, 77, 0x59);
++ rt2800_bbp_write(rt2x00dev, 78, 0x1E);
++ rt2800_bbp_write(rt2x00dev, 79, 0x1C);
++ rt2800_bbp_write(rt2x00dev, 80, 0x0C);
++ rt2800_bbp_write(rt2x00dev, 81, 0x3A);
++ rt2800_bbp_write(rt2x00dev, 82, 0xB6);
++ rt2800_bbp_write(rt2x00dev, 83, 0x9A);
++ rt2800_bbp_write(rt2x00dev, 84, 0x9A);
++ rt2800_bbp_write(rt2x00dev, 86, 0x38);
++ rt2800_bbp_write(rt2x00dev, 88, 0x90);
++ rt2800_bbp_write(rt2x00dev, 91, 0x04);
++ rt2800_bbp_write(rt2x00dev, 92, 0x02);
++ rt2800_bbp_write(rt2x00dev, 95, 0x9A);
++ rt2800_bbp_write(rt2x00dev, 96, 0x00);
++ rt2800_bbp_write(rt2x00dev, 103, 0xC0);
++ rt2800_bbp_write(rt2x00dev, 104, 0x92);
++ /* FIXME BBP105 owerwrite */
++ rt2800_bbp_write(rt2x00dev, 105, 0x3C);
++ rt2800_bbp_write(rt2x00dev, 106, 0x12);
++ rt2800_bbp_write(rt2x00dev, 109, 0x00);
++ rt2800_bbp_write(rt2x00dev, 134, 0x10);
++ rt2800_bbp_write(rt2x00dev, 135, 0xA6);
++ rt2800_bbp_write(rt2x00dev, 137, 0x04);
++ rt2800_bbp_write(rt2x00dev, 142, 0x30);
++ rt2800_bbp_write(rt2x00dev, 143, 0xF7);
++ rt2800_bbp_write(rt2x00dev, 160, 0xEC);
++ rt2800_bbp_write(rt2x00dev, 161, 0xC4);
++ rt2800_bbp_write(rt2x00dev, 162, 0x77);
++ rt2800_bbp_write(rt2x00dev, 163, 0xF9);
++ rt2800_bbp_write(rt2x00dev, 164, 0x00);
++ rt2800_bbp_write(rt2x00dev, 165, 0x00);
++ rt2800_bbp_write(rt2x00dev, 186, 0x00);
++ rt2800_bbp_write(rt2x00dev, 187, 0x00);
++ rt2800_bbp_write(rt2x00dev, 188, 0x00);
++ rt2800_bbp_write(rt2x00dev, 186, 0x00);
++ rt2800_bbp_write(rt2x00dev, 187, 0x01);
++ rt2800_bbp_write(rt2x00dev, 188, 0x00);
++ rt2800_bbp_write(rt2x00dev, 189, 0x00);
++
++ rt2800_bbp_write(rt2x00dev, 91, 0x06);
++ rt2800_bbp_write(rt2x00dev, 92, 0x04);
++ rt2800_bbp_write(rt2x00dev, 93, 0x54);
++ rt2800_bbp_write(rt2x00dev, 99, 0x50);
++ rt2800_bbp_write(rt2x00dev, 148, 0x84);
++ rt2800_bbp_write(rt2x00dev, 167, 0x80);
++ rt2800_bbp_write(rt2x00dev, 178, 0xFF);
++ rt2800_bbp_write(rt2x00dev, 106, 0x13);
++
++ /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */
++ rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00);
++ rt2800_bbp_glrt_write(rt2x00dev, 1, 0x14); /* ? see above */
++ rt2800_bbp_glrt_write(rt2x00dev, 2, 0x20);
++ rt2800_bbp_glrt_write(rt2x00dev, 3, 0x0A);
++ rt2800_bbp_glrt_write(rt2x00dev, 10, 0x16);
++ rt2800_bbp_glrt_write(rt2x00dev, 11, 0x06);
++ rt2800_bbp_glrt_write(rt2x00dev, 12, 0x02);
++ rt2800_bbp_glrt_write(rt2x00dev, 13, 0x07);
++ rt2800_bbp_glrt_write(rt2x00dev, 14, 0x05);
++ rt2800_bbp_glrt_write(rt2x00dev, 15, 0x09);
++ rt2800_bbp_glrt_write(rt2x00dev, 16, 0x20);
++ rt2800_bbp_glrt_write(rt2x00dev, 17, 0x08);
++ rt2800_bbp_glrt_write(rt2x00dev, 18, 0x4A);
++ rt2800_bbp_glrt_write(rt2x00dev, 19, 0x00);
++ rt2800_bbp_glrt_write(rt2x00dev, 20, 0x00);
++ rt2800_bbp_glrt_write(rt2x00dev, 128, 0xE0);
++ rt2800_bbp_glrt_write(rt2x00dev, 129, 0x1F);
++ rt2800_bbp_glrt_write(rt2x00dev, 130, 0x4F);
++ rt2800_bbp_glrt_write(rt2x00dev, 131, 0x32);
++ rt2800_bbp_glrt_write(rt2x00dev, 132, 0x08);
++ rt2800_bbp_glrt_write(rt2x00dev, 133, 0x28);
++ rt2800_bbp_glrt_write(rt2x00dev, 134, 0x19);
++ rt2800_bbp_glrt_write(rt2x00dev, 135, 0x0A);
++ rt2800_bbp_glrt_write(rt2x00dev, 138, 0x16);
++ rt2800_bbp_glrt_write(rt2x00dev, 139, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 140, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1A);
++ rt2800_bbp_glrt_write(rt2x00dev, 142, 0x36);
++ rt2800_bbp_glrt_write(rt2x00dev, 143, 0x2C);
++ rt2800_bbp_glrt_write(rt2x00dev, 144, 0x26);
++ rt2800_bbp_glrt_write(rt2x00dev, 145, 0x24);
++ rt2800_bbp_glrt_write(rt2x00dev, 146, 0x42);
++ rt2800_bbp_glrt_write(rt2x00dev, 147, 0x40);
++ rt2800_bbp_glrt_write(rt2x00dev, 148, 0x30);
++ rt2800_bbp_glrt_write(rt2x00dev, 149, 0x29);
++ rt2800_bbp_glrt_write(rt2x00dev, 150, 0x4C);
++ rt2800_bbp_glrt_write(rt2x00dev, 151, 0x46);
++ rt2800_bbp_glrt_write(rt2x00dev, 152, 0x3D);
++ rt2800_bbp_glrt_write(rt2x00dev, 153, 0x40);
++ rt2800_bbp_glrt_write(rt2x00dev, 154, 0x3E);
++ rt2800_bbp_glrt_write(rt2x00dev, 155, 0x38);
++ rt2800_bbp_glrt_write(rt2x00dev, 156, 0x3D);
++ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2F);
++ rt2800_bbp_glrt_write(rt2x00dev, 158, 0x3C);
++ rt2800_bbp_glrt_write(rt2x00dev, 159, 0x34);
++ rt2800_bbp_glrt_write(rt2x00dev, 160, 0x2C);
++ rt2800_bbp_glrt_write(rt2x00dev, 161, 0x2F);
++ rt2800_bbp_glrt_write(rt2x00dev, 162, 0x3C);
++ rt2800_bbp_glrt_write(rt2x00dev, 163, 0x35);
++ rt2800_bbp_glrt_write(rt2x00dev, 164, 0x2E);
++ rt2800_bbp_glrt_write(rt2x00dev, 165, 0x2F);
++ rt2800_bbp_glrt_write(rt2x00dev, 166, 0x49);
++ rt2800_bbp_glrt_write(rt2x00dev, 167, 0x41);
++ rt2800_bbp_glrt_write(rt2x00dev, 168, 0x36);
++ rt2800_bbp_glrt_write(rt2x00dev, 169, 0x39);
++ rt2800_bbp_glrt_write(rt2x00dev, 170, 0x30);
++ rt2800_bbp_glrt_write(rt2x00dev, 171, 0x30);
++ rt2800_bbp_glrt_write(rt2x00dev, 172, 0x0E);
++ rt2800_bbp_glrt_write(rt2x00dev, 173, 0x0D);
++ rt2800_bbp_glrt_write(rt2x00dev, 174, 0x28);
++ rt2800_bbp_glrt_write(rt2x00dev, 175, 0x21);
++ rt2800_bbp_glrt_write(rt2x00dev, 176, 0x1C);
++ rt2800_bbp_glrt_write(rt2x00dev, 177, 0x16);
++ rt2800_bbp_glrt_write(rt2x00dev, 178, 0x50);
++ rt2800_bbp_glrt_write(rt2x00dev, 179, 0x4A);
++ rt2800_bbp_glrt_write(rt2x00dev, 180, 0x43);
++ rt2800_bbp_glrt_write(rt2x00dev, 181, 0x50);
++ rt2800_bbp_glrt_write(rt2x00dev, 182, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 183, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 184, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 185, 0x10);
++ rt2800_bbp_glrt_write(rt2x00dev, 200, 0x7D);
++ rt2800_bbp_glrt_write(rt2x00dev, 201, 0x14);
++ rt2800_bbp_glrt_write(rt2x00dev, 202, 0x32);
++ rt2800_bbp_glrt_write(rt2x00dev, 203, 0x2C);
++ rt2800_bbp_glrt_write(rt2x00dev, 204, 0x36);
++ rt2800_bbp_glrt_write(rt2x00dev, 205, 0x4C);
++ rt2800_bbp_glrt_write(rt2x00dev, 206, 0x43);
++ rt2800_bbp_glrt_write(rt2x00dev, 207, 0x2C);
++ rt2800_bbp_glrt_write(rt2x00dev, 208, 0x2E);
++ rt2800_bbp_glrt_write(rt2x00dev, 209, 0x36);
++ rt2800_bbp_glrt_write(rt2x00dev, 210, 0x30);
++ rt2800_bbp_glrt_write(rt2x00dev, 211, 0x6E);
++
++ /* BBP for G band DCOC function */
++ rt2800_bbp_dcoc_write(rt2x00dev, 140, 0x0C);
++ rt2800_bbp_dcoc_write(rt2x00dev, 141, 0x00);
++ rt2800_bbp_dcoc_write(rt2x00dev, 142, 0x10);
++ rt2800_bbp_dcoc_write(rt2x00dev, 143, 0x10);
++ rt2800_bbp_dcoc_write(rt2x00dev, 144, 0x10);
++ rt2800_bbp_dcoc_write(rt2x00dev, 145, 0x10);
++ rt2800_bbp_dcoc_write(rt2x00dev, 146, 0x08);
++ rt2800_bbp_dcoc_write(rt2x00dev, 147, 0x40);
++ rt2800_bbp_dcoc_write(rt2x00dev, 148, 0x04);
++ rt2800_bbp_dcoc_write(rt2x00dev, 149, 0x04);
++ rt2800_bbp_dcoc_write(rt2x00dev, 150, 0x08);
++ rt2800_bbp_dcoc_write(rt2x00dev, 151, 0x08);
++ rt2800_bbp_dcoc_write(rt2x00dev, 152, 0x03);
++ rt2800_bbp_dcoc_write(rt2x00dev, 153, 0x03);
++ rt2800_bbp_dcoc_write(rt2x00dev, 154, 0x03);
++ rt2800_bbp_dcoc_write(rt2x00dev, 155, 0x02);
++ rt2800_bbp_dcoc_write(rt2x00dev, 156, 0x40);
++ rt2800_bbp_dcoc_write(rt2x00dev, 157, 0x40);
++ rt2800_bbp_dcoc_write(rt2x00dev, 158, 0x64);
++ rt2800_bbp_dcoc_write(rt2x00dev, 159, 0x64);
++
++ rt2800_bbp4_mac_if_ctrl(rt2x00dev);
++}
++
+ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+ {
+ unsigned int i;
+@@ -6177,7 +6820,10 @@ static void rt2800_init_bbp(struct rt2x0
+ return;
+ case RT5390:
+ case RT5392:
+- rt2800_init_bbp_53xx(rt2x00dev);
++ if (rt2x00dev->chip.rf == RF7620)
++ rt2800_init_bbp_7620(rt2x00dev);
++ else
++ rt2800_init_bbp_53xx(rt2x00dev);
+ break;
+ case RT5592:
+ rt2800_init_bbp_5592(rt2x00dev);
+@@ -7391,6 +8037,296 @@ static void rt2800_init_rfcsr_5592(struc
+ rt2800_led_open_drain_enable(rt2x00dev);
+ }
+
++static void rt2800_init_rfcsr_7620(struct rt2x00_dev *rt2x00dev)
++{
++ u16 freq;
++ u8 rfvalue;
++ struct hw_mode_spec *spec = &rt2x00dev->spec;
++
++ /* Initialize RF central register to default value */
++ rt2800_rfcsr_write(rt2x00dev, 0, 0x02);
++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 2, 0x33);
++ rt2800_rfcsr_write(rt2x00dev, 3, 0xFF);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x0C);
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x40); /* Read only */
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 8, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 9, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 10, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
++ /* rt2800_rfcsr_write(rt2x00dev, 12, 0x43); *//* EEPROM */
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 15, 0x22);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x4C);
++ rt2800_rfcsr_write(rt2x00dev, 17, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0xA0);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0x12);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x07);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0x13);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0xFE);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x24);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x7A);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0x05);
++ rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 38, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 41, 0xD0);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5B);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
++
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
++ if (spec->clk_is_20mhz)
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x03);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x7C);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 17, 0x99);
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x99);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x09);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0xB0);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0x06);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x5D);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x61);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0xB5);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x02);
++
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x62);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0xAD);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80);
++ /* RTMP_TEMPERATURE_CALIBRATION */
++ /* rt2800_rfcsr_write(rt2x00dev, 34, 0x23); */
++ /* rt2800_rfcsr_write(rt2x00dev, 35, 0x01); */
++
++ /* use rt2800_adjust_freq_offset ? */
++ rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &freq);
++ rfvalue = freq & 0xff;
++ rt2800_rfcsr_write(rt2x00dev, 12, rfvalue);
++
++ /* Initialize RF channel register to default value */
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 1, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 2, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 3, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 4, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 5, 0x08);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 6, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 7, 0x51);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x16);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x61);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 12, 0x22);
++ /* rt2800_rfcsr_write_chanreg(rt2x00dev, 13, 0x3D); */ /* fails */
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 15, 0x13);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 16, 0x22);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x01);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x52);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 22, 0x80);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 23, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 25, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x5C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0x6B);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 30, 0x6B);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 31, 0x31);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x5D);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xE6);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 35, 0x55);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 37, 0xBB);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 39, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 40, 0x03);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 41, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 42, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xD3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x07);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x68);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xEF);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x07);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xA8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0x85);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x10);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x07);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6A);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0x85);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x10);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 62, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 63, 0x00);
++
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5);
++
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x69);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09);
++
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16);
++
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B);
++
++ /* Initialize RF channel register for DRQFN */
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7);
++
++ /* reduce power consumption */
++/* rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x53);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x64);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0x4F);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0x4F);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x02);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x64);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0x4F);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x02);
++*/
++ /* Initialize RF DC calibration register to default value */
++ rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 1, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 2, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x04);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 9, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 10, 0x07);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 11, 0x01);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 12, 0x07);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 13, 0x07);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 14, 0x07);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 15, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 16, 0x22);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 18, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 19, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 20, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 21, 0xF1);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 22, 0x11);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 23, 0x02);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 24, 0x41);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 25, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 27, 0xD7);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 28, 0xA2);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 29, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 30, 0x49);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 31, 0x20);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 32, 0x04);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 33, 0xF1);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 34, 0xA1);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 35, 0x01);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 41, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 42, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 43, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 44, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 45, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 46, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 47, 0x3E);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 48, 0x3D);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 49, 0x3E);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 50, 0x3D);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 51, 0x3E);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 52, 0x3D);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 53, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 54, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 55, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 56, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 57, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x10);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 60, 0x0A);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 61, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00);
++
++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20);
++
++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
++}
++
+ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+ {
+ if (rt2800_is_305x_soc(rt2x00dev)) {
+@@ -7426,7 +8362,10 @@ static void rt2800_init_rfcsr(struct rt2
+ rt2800_init_rfcsr_5350(rt2x00dev);
+ break;
+ case RT5390:
+- rt2800_init_rfcsr_5390(rt2x00dev);
++ if (rt2x00dev->chip.rf == RF7620)
++ rt2800_init_rfcsr_7620(rt2x00dev);
++ else
++ rt2800_init_rfcsr_5390(rt2x00dev);
+ break;
+ case RT5392:
+ rt2800_init_rfcsr_5392(rt2x00dev);
+@@ -7858,6 +8797,7 @@ static int rt2800_init_eeprom(struct rt2
+ case RF5390:
+ case RF5392:
+ case RF5592:
++ case RF7620:
+ break;
+ default:
+ rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
+@@ -8422,6 +9362,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF5372:
+ case RF5390:
+ case RF5392:
++ case RF7620:
+ spec->num_channels = 14;
+ if (spec->clk_is_20mhz)
+ spec->channels = rf_vals_xtal20mhz_3x;
+@@ -8562,6 +9503,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF5372:
+ case RF5390:
+ case RF5392:
++ case RF7620:
+ __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
+ break;
+ }
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..af35560
--- /dev/null
+++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch
@@ -0,0 +1,33 @@
+From: Sven Eckelmann <sven@open-mesh.com>
+Date: Tue, 18 Nov 2014 12:29:28 +0100
+Subject: [PATCH] ath10k: Don't initialize devices asynchronously
+
+OpenWrt requires all PHYs to be initialized to create the configuration files
+during bootup. ath10k violates this because it delays the creation of the PHY
+to a not well defined point in the future.
+
+Forcing the work to be done immediately works around this problem but may also
+delay the boot when firmware images cannot be found.
+
+Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -1844,6 +1844,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..f2718c7
--- /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
+@@ -7092,6 +7092,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)
+ {
+ static const u32 cipher_suites[] = {
+@@ -7317,6 +7332,12 @@ int ath10k_mac_register(struct ath10k *a
+ ar->hw->wiphy->cipher_suites = cipher_suites;
+ ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
++#if CPTCFG_MAC80211_LEDS
++ 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/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch
new file mode 100644
index 0000000..d487504
--- /dev/null
+++ b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch
@@ -0,0 +1,20 @@
+--- a/drivers/net/wireless/mwl8k.c
++++ b/drivers/net/wireless/mwl8k.c
+@@ -6262,6 +6262,8 @@ static int mwl8k_probe(struct pci_dev *p
+
+ priv->running_bsses = 0;
+
++ wait_for_completion(&priv->firmware_loading_complete);
++
+ return rc;
+
+ err_stop_firmware:
+@@ -6295,8 +6297,6 @@ static void mwl8k_remove(struct pci_dev
+ return;
+ priv = hw->priv;
+
+- wait_for_completion(&priv->firmware_loading_complete);
+-
+ if (priv->fw_state == FW_STATE_ERROR) {
+ mwl8k_hw_reset(priv);
+ goto unmap;
diff --git a/package/kernel/mac80211/scripts/import-backports.sh b/package/kernel/mac80211/scripts/import-backports.sh
new file mode 100755
index 0000000..d056eb6
--- /dev/null
+++ b/package/kernel/mac80211/scripts/import-backports.sh
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+BASE=$1; shift
+
+usage() {
+ echo "Usage: $0 NNN <file>..."
+ exit 1
+}
+
+check_number() {
+ case "$1" in
+ [0-9][0-9][0-9]) return 0;;
+ esac
+ return 1;
+}
+
+patch_header()
+{
+ awk '
+ /^(---|\*\*\*|Index:)[ \t][^ \t]|^diff -/ \
+ { exit }
+ { print }
+ '
+}
+
+strip_diffstat()
+{
+ awk '
+ /#? .* \| / \
+ { eat = eat $0 "\n"
+ next }
+ /^#? .* files? changed(, .* insertions?\(\+\))?(, .* deletions?\(-\))?/ \
+ { eat = ""
+ next }
+ { print eat $0
+ eat = "" }
+ '
+}
+
+strip_trailing_whitespace() {
+ sed -e 's:[ '$'\t'']*$::'
+}
+
+fixup_header() {
+ awk '
+ /^From / { next }
+ /^Subject: / {
+ sub("Subject: \\[[^\]]*\\]", "Subject: [PATCH]")
+ }
+ { print }
+ '
+}
+
+check_number "$BASE" || usage
+
+quilt series > /dev/null || {
+ echo "Not in quilt directory"
+ exit 2
+}
+
+get_next() {
+ NEW=$BASE
+ quilt series | while read CUR; do
+ [ -n "$CUR" ] || break
+ CUR=${CUR%%-*}
+ check_number "$CUR" || continue
+ [ "$CUR" -lt "$NEW" ] && continue
+ [ "$CUR" -ge "$(($BASE + 100))" ] && continue
+ NEW="$(($CUR + 1))"
+ echo $NEW
+ done | tail -n1
+}
+
+CUR=`get_next`
+CUR="${CUR:-$BASE}"
+
+while [ -n "$1" ]; do
+ FILE="$1"; shift
+ NAME="$(basename $FILE)"
+ NAME="${NAME#[0-9]*-}"
+ echo -n "Processing patch $NAME: "
+
+ [ -e "$FILE" ] || {
+ echo "file $FILE not found"
+ exit 1
+ }
+
+ grep -qE "$NAME$" patches/series && {
+ echo "already applied"
+ continue
+ }
+
+ quilt new "$CUR-$NAME" || exit 1
+ patch_header < "$FILE" |
+ strip_diffstat |
+ strip_trailing_whitespace |
+ fixup_header > "patches/$CUR-$NAME"
+
+ quilt fold < "$FILE" || {
+ cp "$FILE" ./cur_patch
+ echo "patch $FILE failed to apply, copied to ./cur_patch"
+ exit 1
+ }
+
+ quilt refresh -p ab --no-index --no-timestamps
+
+ CUR="$(($CUR + 1))"
+done
+
+exit 0