gluon/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r41029.patch
2014-06-06 09:17:55 +02:00

14824 lines
508 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Mon, 19 May 2014 15:59:37 +0200
Subject: Backport mac80211 from Barrier Breaker (r41029)
diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile
index 9a7093c..c286b0f 100644
--- a/package/mac80211/Makefile
+++ b/package/mac80211/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2007-2013 OpenWrt.org
+# Copyright (C) 2007-2014 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mac80211
-PKG_VERSION:=2014-01-23.1
+PKG_VERSION:=2014-05-22
PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
PKG_BACKPORT_VERSION:=
-PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6
+PKG_MD5SUM:=367937d4f8c05cb36ca989ee26abc3df
PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -105,12 +105,12 @@ Generic IEEE 802.11 Networking Stack (mac80211)
endef
PKG_LINUX_FIRMWARE_NAME:=linux-firmware
-PKG_LINUX_FIRMWARE_VERSION:=7d0c7a8cfd78388d90cc784a185b19dcbdbce824
+PKG_LINUX_FIRMWARE_VERSION:=f8c22c692bdee57a20b092e647464ff6176df3ed
PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION).tar.bz2
PKG_LINUX_FIRMWARE_PROTO:=git
PKG_LINUX_FIRMWARE_SOURCE_URL:=git://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:=837a1a9456c1ec8b428cc0b2b08a331b
+PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=e219333f01835c6e556875a9e0deb3f9
define Download/linux-firmware
FILE:=$(PKG_LINUX_FIRMWARE_SOURCE)
@@ -124,7 +124,7 @@ endef
$(eval $(call Download,linux-firmware))
PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
-PKG_ATH10K_LINUX_FIRMWARE_VERSION:=d86e78e5c6be34329936c8bd73a212700437be2e
+PKG_ATH10K_LINUX_FIRMWARE_VERSION:=38eeda3ae6f90fde5546bdd48ee4ff3090f238c0
PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git
PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git
@@ -363,8 +363,8 @@ define KernelPackage/rtl8180
$(call KernelPackage/rtl818x/Default)
DEPENDS+= @PCI_SUPPORT
TITLE+= (RTL8180 PCI)
- FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl8180.ko
- AUTOLOAD:=$(call AutoLoad,27,rtl8180)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl818x_pci.ko
+ AUTOLOAD:=$(call AutoLoad,27,rtl818x_pci)
endef
define KernelPackage/rtl8187
@@ -606,6 +606,19 @@ Atheros IEEE 802.11ac family of chipsets. For now only
PCI is supported.
endef
+define KernelPackage/ath10k/config
+ if PACKAGE_kmod-ath10k
+
+ config ATH10K_STA_FW
+ bool "Firmware optimized for STA operation"
+ default n
+ help
+ Use the ath10k firmware optimized for wireless client instead
+ of access point operation.
+
+ endif
+endef
+
define KernelPackage/carl9170
$(call KernelPackage/mac80211/Default)
TITLE:=Driver for Atheros AR9170 USB sticks
@@ -844,6 +857,13 @@ define KernelPackage/iwlagn/config
Download and install firmware for:
Intel Centrino Advanced-N 6230, Wireless-N 1030, Wireless-N 130 and Advanced-N 6235
+ 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 IWL100_FW
bool "Intel 100 Firmware"
default y
@@ -1639,8 +1659,7 @@ define KernelPackage/wl18xx/install
$(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-conf.bin \
- $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw.bin \
- $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-2.bin \
+ $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-3.bin \
$(1)/lib/firmware/ti-connectivity
endef
@@ -1664,10 +1683,19 @@ endef
define KernelPackage/ath10k/install
$(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0
+ifeq ($(CONFIG_ATH10K_STA_FW),y)
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
+ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \
+ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin
+else
$(INSTALL_DATA) \
$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
$(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/firmware-2.bin \
$(1)/lib/firmware/ath10k/QCA988X/hw2.0/
+endif
endef
define KernelPackage/mwl8k/install
@@ -1714,6 +1742,9 @@ endif
ifneq ($(CONFIG_IWL6030_FW),)
$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-6000g2b-6.ucode $(1)/lib/firmware
endif
+ifneq ($(CONFIG_IWL7260_FW),)
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-7260-7.ucode $(1)/lib/firmware
+endif
ifneq ($(CONFIG_IWL100_FW),)
$(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/iwlwifi-100-5.ucode $(1)/lib/firmware
endif
diff --git a/package/mac80211/files/regdb.txt b/package/mac80211/files/regdb.txt
index 2badb21..fcab208 100644
--- a/package/mac80211/files/regdb.txt
+++ b/package/mac80211/files/regdb.txt
@@ -1,211 +1,216 @@
# This is the world regulatory domain
country 00:
- (2402 - 2472 @ 40), (3, 20)
+ (2402 - 2472 @ 40), (20)
# Channel 12 - 13.
- (2457 - 2482 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+ (2457 - 2482 @ 40), (20), NO-IR
# Channel 14. Only JP enables this and for 802.11b only
- (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
+ (2474 - 2494 @ 20), (20), NO-IR
# Channel 36 - 48
- (5170 - 5250 @ 80), (3, 20)
+ (5170 - 5250 @ 80), (20), NO-IR
# NB: 5260 MHz - 5700 MHz requies DFS
# Channel 149 - 165
- (5735 - 5835 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
+ (5735 - 5835 @ 80), (20), NO-IR
# IEEE 802.11ad (60GHz), channels 1..3
- (57240 - 63720 @ 2160), (N/A, 0)
+ (57240 - 63720 @ 2160), (0)
country AD:
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country AE:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country AL:
- (2402 - 2482 @ 20), (N/A, 20)
-
-country AM:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (N/A, 18)
- (5250 - 5330 @ 20), (N/A, 18), DFS
-
-country AN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
-
-country AR:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country AE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20.00)
+ (5250 - 5330 @ 80), (20.00), DFS
+ (5490 - 5710 @ 80), (27.00), DFS
+
+country AM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18)
+ (5250 - 5330 @ 80), (18), DFS
+
+country AN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country AR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country AT: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country AU:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country AW:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
-
-country AZ:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
- (5250 - 5330 @ 40), (N/A, 18), DFS
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5710 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country AZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18)
+ (5250 - 5330 @ 80), (18), DFS
country BA: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country BB:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 23)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
+country BB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
-country BD:
- (2402 - 2482 @ 40), (N/A, 20)
+country BD: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
country BE: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country BG: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 23)
- (5250 - 5290 @ 40), (N/A, 23), DFS
- (5490 - 5710 @ 40), (N/A, 30), DFS
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country BH:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (N/A, 20)
- (5250 - 5330 @ 20), (N/A, 20), DFS
- (5735 - 5835 @ 20), (N/A, 20)
+country BH: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
country BL:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
- (5250 - 5330 @ 40), (N/A, 18), DFS
-
-country BN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5735 - 5835 @ 40), (N/A, 30)
-
-country BO:
- (2402 - 2482 @ 40), (N/A, 30)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country BR:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country BY:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
-
-country BZ:
- (2402 - 2482 @ 40), (N/A, 30)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country CA:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (18)
+ (5250 - 5330 @ 40), (18), DFS
+
+country BN: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
+
+country BO: DFS-JP
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5835 @ 80), (30)
+
+country BR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BY: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (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)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country CH: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country CL:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5735 - 5835 @ 40), (N/A, 20)
-
-country CN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 80), (N/A, 30)
+ (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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country CL: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
+
+country CN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5250 - 5330 @ 80), (23), DFS
+ (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), (N/A, 28)
- (59400 - 63720 @ 2160), (N/A, 44)
- (63720 - 65880 @ 2160), (N/A, 28)
-
-country CO:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country CR:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (57240 - 59400 @ 2160), (28)
+ (59400 - 63720 @ 2160), (44)
+ (63720 - 65880 @ 2160), (28)
+
+country CO: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country CY: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
# 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), (N/A, 100 mW)
- (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR
- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
- (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR
+ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR
+ (5470 - 5725 @ 80), (500 mW), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
@@ -221,542 +226,555 @@ country CZ: DFS-ETSI
country DE: DFS-ETSI
# entries 279004 and 280006
- (2400 - 2483.5 @ 40), (N/A, 100 mW)
- # entry 303005
- (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR
- # entries 304002 and 305002
- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
+ (2400 - 2483.5 @ 40), (100 mW)
+ # entry 303005, 304002 and 305002
+ (5150 - 5350 @ 80), (100 mW), NO-OUTDOOR
# entries 308002, 309001 and 310003
- (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+ (5470 - 5725 @ 80), (500 mW), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country DK: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country DO:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country DZ:
- (2402 - 2482 @ 40), (N/A, 20)
-
-country EC:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country DO: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
+
+country DZ: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170.000 - 5250.000 @ 80.000), (23.00)
+ (5250.000 - 5330.000 @ 80.000), (23.00), DFS
+ (5490.000 - 5670.000 @ 80.000), (23.00), DFS
+
+country EC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country EE: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country EG:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (N/A, 20)
- (5250 - 5330 @ 20), (N/A, 20), DFS
+country EG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
country ES: DFS-ETSI
- (2400 - 2483.5 @ 40), (N/A, 100 mW)
- (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR
- (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
- (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+ (2400 - 2483.5 @ 40), (100 mW)
+ (5150 - 5250 @ 80), (100 mW), NO-OUTDOOR
+ (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR
+ (5470 - 5725 @ 80), (500 mW), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country FI: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country FR: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country GE:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
- (5250 - 5330 @ 40), (N/A, 18), DFS
+country GE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18)
+ (5250 - 5330 @ 80), (18), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country GB: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country GD:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
+country GD: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country GR: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country GL: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (N/A, 20)
- (5250 - 5330 @ 20), (N/A, 20), DFS
- (5490 - 5710 @ 20), (N/A, 27), DFS
-
-country GT:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country GU:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country HN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country GT: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GU: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country HK:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5710 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country HR: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country HT:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+country HT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
country HU: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country ID:
+country ID: DFS-JP
# ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5815 @ 80), (N/A, 20)
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5815 @ 80), (23)
country IE: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country IL:
- (2402 - 2482 @ 40), (N/A, 20)
- (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR
- (5250 - 5350 @ 80), (N/A, 200 mW), NO-OUTDOOR, DFS
+country IL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5150 - 5350 @ 80), (200 mW), NO-OUTDOOR
-country IN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5735 - 5835 @ 40), (N/A, 20)
+country IN: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
country IS: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country IR:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
+country IR: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
country IT: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country JM:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country JP:
- (2402 - 2482 @ 40), (N/A, 20)
- (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
- (4910 - 4990 @ 40), (N/A, 23)
- (5030 - 5090 @ 40), (N/A, 23)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 160), (N/A, 23), DFS
-
-country JO:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
-
-country KE:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country KH:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
-
-country KP:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5330 @ 40), (3, 20)
- (5160 - 5250 @ 40), (3, 20), DFS
- (5490 - 5630 @ 40), (3, 30), DFS
- (5735 - 5815 @ 40), (3, 30)
-
-country KR:
- (2402 - 2482 @ 20), (N/A, 20)
- (5170 - 5250 @ 80), (3, 20)
- (5250 - 5330 @ 80), (3, 20), DFS
- (5490 - 5630 @ 80), (3, 30), DFS
- (5735 - 5815 @ 80), (3, 30)
-
-country KW:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
+ (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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country JM: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+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)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 160), (23), DFS
+
+country JO: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5735 - 5835 @ 80), (23)
+
+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)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country KP: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5630 @ 80), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country KR: DFS-JP
+ (2402 - 2482 @ 20), (20)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country KW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
country KZ:
- (2402 - 2482 @ 40), (N/A, 20)
+ (2402 - 2482 @ 40), (20)
-country LB:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
+country LB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country LI: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
-
-country LK:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (3, 17)
- (5250 - 5330 @ 20), (3, 20), DFS
- (5490 - 5710 @ 20), (3, 20), DFS
- (5735 - 5835 @ 20), (3, 30)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country LK: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country LT: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country LU: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country LV: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country MC: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 18)
- (5250 - 5330 @ 40), (N/A, 18), DFS
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
-country MA:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 23)
- (5735 - 5835 @ 80), (N/A, 23)
+country MA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
country MO:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 23)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (23)
+ (5250 - 5330 @ 40), (23), DFS
+ (5735 - 5835 @ 40), (30)
country MK: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country MT: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country MY:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 17)
- (5250 - 5330 @ 80), (N/A, 23), DFS
- (5735 - 5835 @ 80), (N/A, 30)
-
-country MX:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country MY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MX: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country NL: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20), NO-OUTDOOR
- (5250 - 5330 @ 80), (N/A, 20), NO-OUTDOOR, DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 80), (20), NO-OUTDOOR
+ (5490 - 5710 @ 80), (27), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country NO: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country NP:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country NZ:
- (2402 - 2482 @ 40), (N/A, 30)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country OM:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country PA:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country PE:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country PG:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 23), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country PH:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country PK:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
+ (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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country NP: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
+
+country NZ: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country OM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country PA: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (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), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country PT: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country PR:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+country PR: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
-country QA:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
+country QA: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
country RO: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
# Source:
# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
-country RS:
- (2400 - 2483.5 @ 40), (N/A, 100 mW)
- (5150 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR
- (5470 - 5725 @ 20), (3, 1000 mW), DFS
- # 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
-country RU:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5330 @ 40), (N/A, 20)
- (5650 - 5710 @ 40), (N/A, 30)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country RW:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5835 @ 40), (N/A, 30)
-
-country SA:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+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
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country RU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5650 - 5730 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country RW: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
country SE: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country SG:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+country SG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
country SI: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (N/A, 20)
- (5250 - 5330 @ 40), (N/A, 20), DFS
- (5490 - 5710 @ 40), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country SK: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country SV:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (3, 17)
- (5250 - 5330 @ 20), (3, 23), DFS
- (5735 - 5835 @ 20), (3, 30)
+country SV: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), DFS
+ (5735 - 5835 @ 80), (30)
country SY:
- (2402 - 2482 @ 40), (N/A, 20)
-
-country TW:
- (2402 - 2472 @ 40), (3, 27)
- (5270 - 5330 @ 40), (3, 17), DFS
- (5490 - 5710 @ 80), (3, 30), DFS
- (5735 - 5815 @ 80), (3, 30)
-
-country TH:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country TT:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country TN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 20), (N/A, 20)
- (5250 - 5330 @ 20), (N/A, 20), DFS
+ (2402 - 2482 @ 40), (20)
+
+country TW: DFS-JP
+ (2402 - 2472 @ 40), (30)
+ (5270 - 5330 @ 40), (17), DFS
+ (5490 - 5590 @ 80), (30), DFS
+ (5650 - 5710 @ 40), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TT: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
country TR: DFS-ETSI
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (N/A, 20)
- (5250 - 5330 @ 80), (N/A, 20), DFS
- (5490 - 5710 @ 80), (N/A, 27), DFS
+ (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
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
# Source:
# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
@@ -765,59 +783,63 @@ country TR: DFS-ETSI
# 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:
- (2400 - 2483.5 @ 40), (N/A, 20), NO-OUTDOOR
- (5150 - 5350 @ 40), (N/A, 20), NO-OUTDOOR
+country UA: DFS-ETSI
+ (2400 - 2483.5 @ 40), (20), NO-OUTDOOR
+ (5150 - 5350 @ 40), (20), NO-OUTDOOR
+ (5490 - 5670 @ 80), (20), DFS
+ (5735 - 5835 @ 80), (20)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
country US: DFS-FCC
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5600 @ 80), (3, 24), DFS
- (5650 - 5710 @ 40), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (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), (N/A, 40)
-
-country UY:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country UZ:
- (2402 - 2472 @ 40), (3, 27)
- (5170 - 5250 @ 40), (3, 17)
- (5250 - 5330 @ 40), (3, 20), DFS
- (5490 - 5710 @ 40), (3, 20), DFS
- (5735 - 5835 @ 40), (3, 30)
-
-country VE:
- (2402 - 2482 @ 40), (N/A, 20)
- (5735 - 5815 @ 40), (N/A, 23)
-
-country VN:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
+ (57240 - 63720 @ 2160), (40)
+
+country UY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country UZ: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (24), DFS
+ (5490 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country VE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (17)
+ (5250 - 5330 @ 80), (23), 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)
country YE:
- (2402 - 2482 @ 40), (N/A, 20)
-
-country ZA:
- (2402 - 2482 @ 40), (N/A, 20)
- (5170 - 5250 @ 80), (3, 17)
- (5250 - 5330 @ 80), (3, 24), DFS
- (5490 - 5710 @ 80), (3, 24), DFS
- (5735 - 5835 @ 80), (3, 30)
-
-country ZW:
- (2402 - 2482 @ 40), (N/A, 20)
+ (2402 - 2482 @ 40), (20)
+
+country ZA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
+
+country ZW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5710 @ 80), (27), DFS
diff --git a/package/mac80211/patches/001-fix_build.patch b/package/mac80211/patches/001-fix_build.patch
index 26b327a..99ef50e 100644
--- a/package/mac80211/patches/001-fix_build.patch
+++ b/package/mac80211/patches/001-fix_build.patch
@@ -131,7 +131,7 @@
.PHONY: defconfig-help
--- a/Makefile.real
+++ b/Makefile.real
-@@ -54,7 +54,7 @@ defconfig-%::
+@@ -59,7 +59,7 @@ defconfig-%::
backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
@$(MAKE) oldconfig
@@ -140,7 +140,7 @@
@grep -f .local-symbols .config | ( \
echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
-@@ -75,7 +75,12 @@ backport-include/backport/autoconf.h: .c
+@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
esac ;\
done ;\
echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
diff --git a/package/mac80211/patches/003-remove_bogus_modparams.patch b/package/mac80211/patches/003-remove_bogus_modparams.patch
index c969b19..ffb730b 100644
--- a/package/mac80211/patches/003-remove_bogus_modparams.patch
+++ b/package/mac80211/patches/003-remove_bogus_modparams.patch
@@ -1,6 +1,6 @@
--- a/compat/main.c
+++ b/compat/main.c
-@@ -21,31 +21,6 @@ MODULE_LICENSE("GPL");
+@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
#error "You need a BACKPORTS_VERSION"
#endif
diff --git a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
index 584fb05..8d97224 100644
--- a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
+++ b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
@@ -18,8 +18,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/backport-include/backport/leds-disabled.h
+++ b/backport-include/backport/leds-disabled.h
-@@ -163,6 +163,19 @@ static inline void led_trigger_event(str
- enum led_brightness event)
+@@ -176,6 +176,19 @@ static inline void led_trigger_blink_one
+ int invert)
{
}
+
diff --git a/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch b/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch
new file mode 100644
index 0000000..55bffbc
--- /dev/null
+++ b/package/mac80211/patches/005-make-genregdb.awk-skip-antenna-gain.patch
@@ -0,0 +1,44 @@
+From: Luis R. Rodriguez <mcgrof@do-not-panic.com>
+Date: Wed, 23 Oct 2013 14:55:36 -0400
+Subject: [RFC] cfg80211: make genregdb.awk skip antenna gain
+
+Now that wireless-regdb doesn't include
+antenna gain lets skip parsing it completely
+for when CONFIG_CFG80211_INTERNAL_REGDB is
+enabled.
+
+Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
+---
+ net/wireless/genregdb.awk | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+ mode change 100644 => 100755 net/wireless/genregdb.awk
+
+--- a/net/wireless/genregdb.awk
++++ b/net/wireless/genregdb.awk
+@@ -56,14 +56,11 @@ function parse_reg_rule()
+ end = $3
+ bw = $5
+ sub(/\),/, "", bw)
+- gain = $6
+- sub(/\(/, "", gain)
+- sub(/,/, "", gain)
+- power = $7
+- sub(/\)/, "", power)
++ power = $6
++ sub(/\(/, "", power)
+ sub(/,/, "", power)
+ # power might be in mW...
+- units = $8
++ units = $7
+ sub(/\)/, "", units)
+ sub(/,/, "", units)
+ dfs_cac = $9
+@@ -86,7 +83,7 @@ function parse_reg_rule()
+ sub(/\(/, "", dfs_cac)
+ sub(/\)/, "", dfs_cac)
+ flagstr = ""
+- for (i=8; i<=NF; i++)
++ for (i=7; i<=NF; i++)
+ flagstr = flagstr $i
+ split(flagstr, flagarray, ",")
+ flags = ""
diff --git a/package/mac80211/patches/007-select_queue.patch b/package/mac80211/patches/007-select_queue.patch
new file mode 100644
index 0000000..0a1d292
--- /dev/null
+++ b/package/mac80211/patches/007-select_queue.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/mwifiex/main.c
++++ b/drivers/net/wireless/mwifiex/main.c
+@@ -745,7 +745,7 @@ static struct net_device_stats *mwifiex_
+ return &priv->stats;
+ }
+
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+ static u16
+ mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
diff --git a/package/mac80211/patches/020-disable_tty_set_termios.patch b/package/mac80211/patches/020-disable_tty_set_termios.patch
deleted file mode 100644
index e6d4ff6..0000000
--- a/package/mac80211/patches/020-disable_tty_set_termios.patch
+++ /dev/null
@@ -1,16 +0,0 @@
---- a/compat/compat-2.6.39.c
-+++ b/compat/compat-2.6.39.c
-@@ -13,6 +13,7 @@
- #include <linux/sched.h>
- #include <linux/module.h>
-
-+#ifdef CONFIG_COMPAT_BLUETOOTH
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
- #ifdef CONFIG_TTY
- /*
-@@ -114,4 +115,4 @@ int tty_set_termios(struct tty_struct *t
- EXPORT_SYMBOL_GPL(tty_set_termios);
- #endif /* CONFIG_TTY */
- #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) */
--
-+#endif
diff --git a/package/mac80211/patches/050-lib80211_option.patch b/package/mac80211/patches/050-lib80211_option.patch
index 5372114..168871a 100644
--- a/package/mac80211/patches/050-lib80211_option.patch
+++ b/package/mac80211/patches/050-lib80211_option.patch
@@ -1,6 +1,6 @@
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
-@@ -123,7 +123,7 @@ config CFG80211_WEXT
+@@ -160,7 +160,7 @@ config CFG80211_WEXT
extensions with cfg80211-based drivers.
config LIB80211
@@ -9,7 +9,7 @@
depends on m
default n
help
-@@ -133,15 +133,15 @@ config LIB80211
+@@ -170,15 +170,15 @@ config LIB80211
Drivers should select this themselves if needed.
config LIB80211_CRYPT_WEP
diff --git a/package/mac80211/patches/060-no_local_ssb_bcma.patch b/package/mac80211/patches/060-no_local_ssb_bcma.patch
index f4b9470..93197ae 100644
--- a/package/mac80211/patches/060-no_local_ssb_bcma.patch
+++ b/package/mac80211/patches/060-no_local_ssb_bcma.patch
@@ -1,6 +1,6 @@
--- a/.local-symbols
+++ b/.local-symbols
-@@ -379,42 +379,6 @@ USB_CDC_PHONET=
+@@ -403,42 +403,6 @@ USB_CDC_PHONET=
USB_IPHETH=
USB_SIERRA_NET=
USB_VL600=
@@ -68,7 +68,7 @@
obj-$(CPTCFG_NFC) += net/nfc/
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -2734,7 +2734,7 @@ static struct ssb_device *b43_ssb_gpio_d
+@@ -2733,7 +2733,7 @@ static struct ssb_device *b43_ssb_gpio_d
{
struct ssb_bus *bus = dev->dev->sdev->bus;
@@ -77,12 +77,12 @@
return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
#else
return bus->chipco.dev;
-@@ -4751,7 +4751,7 @@ static int b43_wireless_core_init(struct
+@@ -4698,7 +4698,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. */
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
+-#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)
diff --git a/package/mac80211/patches/070-add-missing-header.patch b/package/mac80211/patches/070-add-missing-header.patch
new file mode 100644
index 0000000..e3ec780
--- /dev/null
+++ b/package/mac80211/patches/070-add-missing-header.patch
@@ -0,0 +1,10 @@
+--- a/compat/backport-3.15.c
++++ b/compat/backport-3.15.c
+@@ -12,6 +12,7 @@
+ #include <linux/kernel.h>
+ #include <linux/device.h>
+ #include <linux/of.h>
++#include <linux/string.h>
+ #include <net/net_namespace.h>
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
diff --git a/package/mac80211/patches/100-revert_aes_ccm_port.patch b/package/mac80211/patches/100-revert_aes_ccm_port.patch
index 4654bc8..640d34e 100644
--- a/package/mac80211/patches/100-revert_aes_ccm_port.patch
+++ b/package/mac80211/patches/100-revert_aes_ccm_port.patch
@@ -4,7 +4,7 @@
depends on CRYPTO
depends on CRYPTO_ARC4
depends on CRYPTO_AES
-- depends on CRYPTO_CCM
+- select BACKPORT_CRYPTO_CCM
depends on CRC32
select BACKPORT_AVERAGE
---help---
@@ -19,35 +19,17 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
-@@ -19,75 +17,134 @@
+@@ -19,76 +17,134 @@
#include "key.h"
#include "aes_ccm.h"
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
- u8 *data, size_t data_len, u8 *mic)
+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
- {
-- struct scatterlist assoc, pt, ct[2];
-- struct {
-- struct aead_request req;
-- u8 priv[crypto_aead_reqsize(tfm)];
-- } aead_req;
--
-- memset(&aead_req, 0, sizeof(aead_req));
--
-- sg_init_one(&pt, data, data_len);
-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
-- sg_init_table(ct, 2);
-- sg_set_buf(&ct[0], data, data_len);
-- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
--
-- aead_request_set_tfm(&aead_req.req, tfm);
-- aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
-- aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
++{
+ int i;
+ u8 *b_0, *aad, *b, *s_0;
-
-- crypto_aead_encrypt(&aead_req.req);
++
+ b_0 = scratch + 3 * AES_BLOCK_SIZE;
+ aad = scratch + 4 * AES_BLOCK_SIZE;
+ b = scratch;
@@ -73,22 +55,23 @@
+ b_0[14] = 0;
+ b_0[15] = 0;
+ crypto_cipher_encrypt_one(tfm, s_0, b_0);
- }
-
--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-- u8 *data, size_t data_len, u8 *mic)
++}
++
+
+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
+ u8 *data, size_t data_len,
+ u8 *cdata, u8 *mic)
{
- struct scatterlist assoc, pt, ct[2];
-- struct {
-- struct aead_request req;
-- u8 priv[crypto_aead_reqsize(tfm)];
-- } aead_req;
++ int i, j, last_len, num_blocks;
++ u8 *pos, *cpos, *b, *s_0, *e, *b_0;
+
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
-
-- memset(&aead_req, 0, sizeof(aead_req));
+- memset(aead_req, 0, sizeof(aead_req_data));
-
- sg_init_one(&pt, data, data_len);
- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
@@ -96,13 +79,9 @@
- sg_set_buf(&ct[0], data, data_len);
- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
-
-- aead_request_set_tfm(&aead_req.req, tfm);
-- aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
-- aead_request_set_crypt(&aead_req.req, ct, &pt,
-- data_len + IEEE80211_CCMP_MIC_LEN, b_0);
-+ int i, j, last_len, num_blocks;
-+ u8 *pos, *cpos, *b, *s_0, *e, *b_0;
-+
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_assoc(aead_req, &assoc, assoc.length);
+- aead_request_set_crypt(aead_req, &pt, ct, data_len, b_0);
+ b = scratch;
+ s_0 = scratch + AES_BLOCK_SIZE;
+ e = scratch + 2 * AES_BLOCK_SIZE;
@@ -131,30 +110,38 @@
+ *cpos++ = *pos++ ^ e[i];
+ }
-- return crypto_aead_decrypt(&aead_req.req);
+- crypto_aead_encrypt(aead_req);
+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
+ mic[i] = b[i] ^ s_0[i];
}
--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+- u8 *data, size_t data_len, u8 *mic)
+
+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
+ u8 *cdata, size_t data_len, u8 *mic, u8 *data)
{
-- struct crypto_aead *tfm;
-- int err;
+- struct scatterlist assoc, pt, ct[2];
+- char aead_req_data[sizeof(struct aead_request) +
+- crypto_aead_reqsize(tfm)]
+- __aligned(__alignof__(struct aead_request));
+- struct aead_request *aead_req = (void *) aead_req_data;
+-
+- memset(aead_req, 0, sizeof(aead_req_data));
+-
+- sg_init_one(&pt, data, data_len);
+- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+- sg_init_table(ct, 2);
+- sg_set_buf(&ct[0], data, data_len);
+- sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
+-
+- aead_request_set_tfm(aead_req, tfm);
+- aead_request_set_assoc(aead_req, &assoc, assoc.length);
+- aead_request_set_crypt(aead_req, ct, &pt,
+- data_len + IEEE80211_CCMP_MIC_LEN, b_0);
+ int i, j, last_len, num_blocks;
+ u8 *pos, *cpos, *b, *s_0, *a, *b_0;
-
-- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
-- if (IS_ERR(tfm))
-- return tfm;
--
-- err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
-- if (!err)
-- err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
-- if (!err)
-- return tfm;
++
+ b = scratch;
+ s_0 = scratch + AES_BLOCK_SIZE;
+ a = scratch + 2 * AES_BLOCK_SIZE;
@@ -187,24 +174,37 @@
+ return -1;
+ }
-- crypto_free_aead(tfm);
-- return ERR_PTR(err);
+- return crypto_aead_decrypt(aead_req);
+ return 0;
}
--void ieee80211_aes_key_free(struct crypto_aead *tfm)
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
+
+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
-+{
+ {
+- struct crypto_aead *tfm;
+- int err;
+ struct crypto_cipher *tfm;
-+
+
+- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
+- if (IS_ERR(tfm))
+- return tfm;
+-
+- err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
+- if (!err)
+- err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
+- if (!err)
+- return tfm;
+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+ if (!IS_ERR(tfm))
+ crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
-+
+
+- crypto_free_aead(tfm);
+- return ERR_PTR(err);
+ return tfm;
-+}
-+
+ }
+
+-void ieee80211_aes_key_free(struct crypto_aead *tfm)
+
+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
{
@@ -246,13 +246,13 @@
struct {
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
-@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
+@@ -301,15 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
}
--static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
+-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
- int encrypted)
++ int encrypted)
{
__le16 mask_fc;
int a4_included, mgmt;
@@ -271,7 +271,7 @@
/*
* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
* Retry, PwrMgt, MoreData; set Protected
-@@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s
+@@ -331,21 +338,20 @@ static void ccmp_special_blocks(struct s
else
qos_tid = 0;
@@ -300,7 +300,7 @@
/* AAD (extra authenticate-only data) / masked 802.11 header
* FC | A1 | A2 | A3 | SC | [A4] | [QC] */
-@@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
+@@ -401,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
u8 *pos;
u8 pn[6];
u64 pn64;
@@ -310,11 +310,11 @@
if (info->control.hw_key &&
!(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
-@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
+@@ -458,9 +463,9 @@ static int ccmp_encrypt_skb(struct ieee8
return 0;
pos += IEEE80211_CCMP_HDR_LEN;
-- ccmp_special_blocks(skb, pn, b_0, aad, 0);
+- ccmp_special_blocks(skb, pn, b_0, aad);
- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
- skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+ ccmp_special_blocks(skb, pn, scratch, 0);
@@ -323,7 +323,7 @@
return 0;
}
-@@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+@@ -523,16 +528,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
}
if (!(status->flag & RX_FLAG_DECRYPTED)) {
@@ -331,7 +331,7 @@
- u8 b_0[AES_BLOCK_SIZE];
+ u8 scratch[6 * AES_BLOCK_SIZE];
/* hardware didn't decrypt/verify MIC */
-- ccmp_special_blocks(skb, pn, b_0, aad, 1);
+- ccmp_special_blocks(skb, pn, b_0, aad);
+ ccmp_special_blocks(skb, pn, scratch, 1);
if (ieee80211_aes_ccm_decrypt(
diff --git a/package/mac80211/patches/150-disable_addr_notifier.patch b/package/mac80211/patches/150-disable_addr_notifier.patch
index 7b50154..6a7f5c1 100644
--- a/package/mac80211/patches/150-disable_addr_notifier.patch
+++ b/package/mac80211/patches/150-disable_addr_notifier.patch
@@ -1,6 +1,6 @@
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -287,7 +287,7 @@ void ieee80211_restart_hw(struct ieee802
+@@ -285,7 +285,7 @@ void ieee80211_restart_hw(struct ieee802
}
EXPORT_SYMBOL(ieee80211_restart_hw);
@@ -9,7 +9,7 @@
static int ieee80211_ifa_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
-@@ -346,7 +346,7 @@ static int ieee80211_ifa_changed(struct
+@@ -344,7 +344,7 @@ static int ieee80211_ifa_changed(struct
}
#endif
@@ -18,7 +18,7 @@
static int ieee80211_ifa6_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
-@@ -1031,14 +1031,14 @@ int ieee80211_register_hw(struct ieee802
+@@ -1036,14 +1036,14 @@ int ieee80211_register_hw(struct ieee802
goto fail_pm_qos;
}
@@ -35,7 +35,7 @@
local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
result = register_inet6addr_notifier(&local->ifa6_notifier);
if (result)
-@@ -1047,13 +1047,13 @@ int ieee80211_register_hw(struct ieee802
+@@ -1052,13 +1052,13 @@ int ieee80211_register_hw(struct ieee802
return 0;
@@ -52,7 +52,7 @@
fail_ifa:
pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
&local->network_latency_notifier);
-@@ -1086,10 +1086,10 @@ void ieee80211_unregister_hw(struct ieee
+@@ -1103,10 +1103,10 @@ void ieee80211_unregister_hw(struct ieee
pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
&local->network_latency_notifier);
diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch
index a1af6c2..3305388 100644
--- a/package/mac80211/patches/300-pending_work.patch
+++ b/package/mac80211/patches/300-pending_work.patch
@@ -1,4153 +1,2752 @@
-commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Apr 6 23:35:28 2014 +0200
-
- ath9k_hw: reduce ANI firstep range for older chips
-
- Use 0-8 instead of 0-16, which is closer to the old implementation.
- Also drop the overwrite of the firstep_low parameter to improve
- stability.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14
-Author: Helmut Schaa <helmut.schaa@googlemail.com>
-Date: Wed Mar 12 10:37:55 2014 +0100
-
- ath9k: Fix sequence number assignment for non-data frames
-
- Since commit 558ff225de80ac95b132d3a115ddadcd64498b4f (ath9k: fix
- ps-poll responses under a-mpdu sessions) non-data frames would have
- gotten a sequence number from a TIDs sequence counter instead of
- using the global sequence counter.
-
- This can lead to instable connections.
-
- To fix this only select the correct TID if we are processing a
- data frame. Furthermore, prevent non-data frames to get a sequence
- number from a TID sequence counter by adding a check to
- ath_tx_setup_buffer.
-
- Cc: Felix Fietkau <nbd@openwrt.org>
- Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
-
-commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Tue Mar 11 14:03:32 2014 +0100
-
- ath9k_hw: set ANI firstep as absolute values instead of relative
-
- On older chips, the INI value differ in similar ways as cycpwr_thr1, so
- convert it to absolute values as well.
-
- Since the ANI algorithm is different here compared to the old
- implementation (fewer steps, controlled at a different point in time),
- it makes sense to use values similar to what would be applied for newer
- chips, just without relying on INI defaults.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 91d70d40400c569b49605b78fd7c43e9405694f4
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Tue Mar 11 14:00:37 2014 +0100
+commit d3a58df87a2e4c2301ac843604202d290a48440b
+Author: Avraham Stern <avraham.stern@intel.com>
+Date: Thu May 22 12:17:47 2014 +0300
- ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative
-
- The table was copied from the ANI implementation of AR9300. It assumes
- that the INI values contain a baseline value that is usable as reference
- from which to increase/decrease based on the noise immunity value.
+ mac80211: set new interfaces as idle upon init
- On older chips, the differences are bigger and especially AR5008/AR9001
- are configured to much more sensitive values than what is useful.
+ Mark new interfaces as idle to allow operations that require that
+ interfaces are idle to take place. Interface types that are always
+ not idle (like AP interfaces) will be set as not idle when they are
+ assigned a channel context.
- Improve ANI behavior by reverting to the absolute values used in the
- previous implementation (expressed as a simple formula instead of the
- old table).
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ Signed-off-by: Avraham Stern <avraham.stern@intel.com>
+ Signed-off-by: Emmanuel Grumbach<emmanuel.grumbach@intel.com>
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit c977493766310a825f406836636ffd66e1447783
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Mon Mar 10 19:52:56 2014 +0100
+commit 923eaf367206e01f22c97aee22300e332d071916
+Author: Arik Nemtsov <arik@wizery.com>
+Date: Mon May 26 14:40:51 2014 +0300
- ath9k_hw: remove ANI function restrictions for AP mode
+ mac80211: don't check netdev state for debugfs read/write
- The primary purpose of this piece of code was to selectively disable
- OFDM weak signal detection. The checks for this are elsewhere, and an
- earlier commit relaxed the restrictions for older chips, which are more
- sensitive to interference.
+ Doing so will lead to an oops for a p2p-dev interface, since it has
+ no netdev.
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 8d804f1af11e4e058b1e8453327777d73a585cb8
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Mar 9 11:25:43 2014 +0100
+ Cc: stable@vger.kernel.org
+ Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
+ Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
- ath9k: clean up and enhance ANI debugfs file
-
- Unify scnprintf calls and include the current OFDM/CCK immunity level.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+commit a9fb54169b197f31aff24c8d6270dd1e56cde395
+Author: chaitanya.mgit@gmail.com <chaitanya.mgit@gmail.com>
+Date: Mon May 26 18:01:44 2014 +0530
+
+ regdb: Generalize the mW to dBm power conversion
+
+ Generalize the power conversion from mW to dBm
+ using log. This should fix the below compilation
+ error for country NO which adds a new power value
+ 2000mW which is not handled earlier.
+
+ CC [M] net/wireless/wext-sme.o
+ CC [M] net/wireless/regdb.o
+ net/wireless/regdb.c:1130:1: error: Unknown undeclared here (not in
+ a function)
+ net/wireless/regdb.c:1130:9: error: expected } before power
+ make[2]: *** [net/wireless/regdb.o] Error 1
+ make[1]: *** [net/wireless] Error 2
+ make: *** [net] Error 2
+
+ Reported-By: John Walker <john@x109.net>
+ Signed-off-by: Chaitanya T K <chaitanya.mgit@gmail.com>
+ Acked-by: John W. Linville <linville@tuxdriver.com>
+ [remove unneeded parentheses, fix rounding by using %.0f]
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 22e298b5a3a8a49e33805d4e351965123dede35b
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Mar 9 10:58:47 2014 +0100
+commit c7d37a66e345df2fdf1aa7b2c9a6d3d53846ca5b
+Author: Krzysztof Hałasa <khalasa@piap.pl>
+Date: Mon May 26 14:14:46 2014 +0200
- ath9k: fix ready time of the multicast buffer queue
-
- qi->tqi_readyTime is written directly to registers that expect
- microseconds as unit instead of TU.
- When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so
- convert it to microseconds before passing it to ath9k_hw.
+ mac80211: fix IBSS join by initializing last_scan_completed
- This should hopefully fix some Tx DMA issues with buffered multicast
- frames in AP mode.
+ Without this fix, freshly rebooted Linux creates a new IBSS
+ instead of joining an existing one. Only when jiffies counter
+ overflows after 5 minutes the IBSS can be successfully joined.
+ Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
+ [edit commit message slightly]
Cc: stable@vger.kernel.org
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit fcb064fdd5a27bec8d24099bc0172468f34c97cb
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sun Mar 9 09:43:09 2014 +0100
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
- ath9k_hw: fix unreachable code in baseband hang detection code
-
- The commit "ath9k: reduce baseband hang detection false positive rate"
- added a delay in the loop checking the baseband state, however it was
- unreachable due to previous 'continue' statements.
-
- Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+commit 34171dc0d623be2c1032416bf7d3819f388ed70d
+Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date: Sun May 25 15:35:41 2014 +0300
+
+ mac80211: fix virtual monitor interface addition
+
+ Since the commit below, cfg80211_chandef_dfs_required()
+ will warn if it gets a an NL80211_IFTYPE_UNSPECIFIED iftype
+ as explicitely written in the commit log.
+ When an virtual monitor interface is added, its type is set
+ in ieee80211_sub_if_data.vif.type, but not in
+ ieee80211_sub_if_data.wdev.iftype which is passed to
+ cfg80211_chandef_dfs_required() hence resulting in the
+ following warning:
+
+ WARNING: CPU: 1 PID: 21265 at net/wireless/chan.c:376 cfg80211_chandef_dfs_required+0xbc/0x130 [cfg80211]()
+ Modules linked in: [...]
+ CPU: 1 PID: 21265 Comm: ifconfig Tainted: G W O 3.13.11+ #12
+ Hardware name: Dell Inc. Latitude E6410/0667CC, BIOS A01 03/05/2010
+ 0000000000000009 ffff88008f5fdb08 ffffffff817d4219 ffff88008f5fdb50
+ ffff88008f5fdb40 ffffffff8106f57d 0000000000000000 0000000000000000
+ ffff880081062fb8 ffff8800810604e0 0000000000000001 ffff88008f5fdba0
+ Call Trace:
+ [<ffffffff817d4219>] dump_stack+0x4d/0x66
+ [<ffffffff8106f57d>] warn_slowpath_common+0x7d/0xa0
+ [<ffffffff8106f5ec>] warn_slowpath_fmt+0x4c/0x50
+ [<ffffffffa04ea4ec>] cfg80211_chandef_dfs_required+0xbc/0x130 [cfg80211]
+ [<ffffffffa06b1024>] ieee80211_vif_use_channel+0x94/0x500 [mac80211]
+ [<ffffffffa0684e6b>] ieee80211_add_virtual_monitor+0x1ab/0x5c0 [mac80211]
+ [<ffffffffa0686ae5>] ieee80211_do_open+0xe75/0x1580 [mac80211]
+ [<ffffffffa0687259>] ieee80211_open+0x69/0x70 [mac80211]
+ [snip]
+
+ Fixes: 00ec75fc5a64 ("cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required()")
+ Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+ Acked-by: Luciano Coelho <luciano.coelho@intel.com>
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 31959d8df39319e32c6d5ba9c135727be90cfad7
+commit d93cc72b37b4e2c314e1c499e80e8801907c2fea
Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Fri Mar 7 08:09:38 2014 +0100
+Date: Thu Jun 5 14:21:37 2014 +0200
- mac80211: fix possible NULL dereference
-
- If chanctx is missing on a given vif then the band
- is assumed to be 2GHz. However if hw doesn't
- support 2GHz band then mac80211 ended up with a
- NULL dereference.
-
- This fixes a splat:
+ mac80211: use csa counter offsets instead of csa_active
- [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
- [ 4605.210789] IP: [<ffffffffa07b5635>] ieee80211_parse_bitrates+0x65/0x110 [mac80211]
+ vif->csa_active is protected by mutexes only. This
+ means it is unreliable to depend on it on codeflow
+ in non-sleepable beacon and CSA code. There was no
+ guarantee to have vif->csa_active update be
+ visible before beacons are updated on SMP systems.
- The splat was preceeded by WARN_ON(!chanctx_conf)
- in ieee80211_get_sdata_band().
+ Using csa counter offsets which are embedded in
+ beacon struct (and thus are protected with single
+ RCU assignment) is much safer.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
-
-commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e
-Author: Michael Braun <michael-dev@fami-braun.de>
-Date: Thu Mar 6 15:08:43 2014 +0100
-
- mac80211: fix WPA with VLAN on AP side with ps-sta again
-
- commit de74a1d9032f4d37ea453ad2a647e1aff4cd2591
- "mac80211: fix WPA with VLAN on AP side with ps-sta"
- fixed an issue where queued multicast packets would
- be sent out encrypted with the key of an other bss.
-
- commit "7cbf9d017dbb5e3276de7d527925d42d4c11e732"
- "mac80211: fix oops on mesh PS broadcast forwarding"
- essentially reverted it, because vif.type cannot be AP_VLAN
- due to the check to vif.type in ieee80211_get_buffered_bc before.
-
- As the later commit intended to fix the MESH case, fix it
- by checking for IFTYPE_AP instead of IFTYPE_AP_VLAN.
-
- Fixes: 7cbf9d017dbb
- Cc: <stable@vger.kernel.org> # 3.10.x
- Cc: <stable@vger.kernel.org> # 3.11.x
- Cc: <stable@vger.kernel.org> # 3.12.x
- Cc: <stable@vger.kernel.org> # 3.13.x
- Cc: <linux-wireless@vger.kernel.org>
- Cc: <projekt-wlan@fem.tu-ilmenau.de>
- Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
-
-commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Mon Mar 3 14:19:08 2014 +0100
-
- cfg80211: remove racy beacon_interval assignment
-
- In case of AP mode, the beacon interval is already reset to
- zero inside cfg80211_stop_ap(), and in the other modes it
- isn't relevant. Remove the assignment to remove a potential
- race since the assignment isn't properly locked.
-
- Reported-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Fri Feb 28 18:52:56 2014 +0100
-
- ath9k_hw: tweak noise immunity thresholds for older chipsets
-
- Older chipsets are more sensitive to high PHY error counts, and the
- current noise immunity thresholds were based on tests run at QCA with
- newer chipsets.
-
- This patch brings back the values from the old ANI implementation for
- old chipsets, and it also disables weak signal detection on an earlier
- noise immunity level, to improve overall radio stability on affected
- devices.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 431e506da5953adc3b65af25f4b90873d528c115
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Fri Feb 28 18:44:13 2014 +0100
-
- ath9k_hw: toggle weak signal detection in AP mode on older chipsets
-
- The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode"
- prevented weak signal detection changes from taking effect in AP mode on
- all chipsets, claiming it is "not allowed".
-
- The main reason for not disabling weak signal detection in AP mode is
- that typically beacon RSSI is used to track whether it is needed to
- boost range, and this is unavailable in AP mode for obvious reasons.
-
- The problem with not disabling weak signal detection is that older
- chipsets are very sensitive to high PHY error counts. When faced with
- heavy noise, this can lead to an excessive amount of "Failed to stop
- TX DMA" errors in the field.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 98d1a6c5b14688ed030e81b889f607be308e0df9
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Mon Feb 24 22:20:32 2014 +0100
-
- ath9k: fix invalid descriptor discarding
-
- Only set sc->rx.discard_next to rx_stats->rs_more when actually
- discarding the current descriptor.
-
- Also, fix a detection of broken descriptors:
- First the code checks if the current descriptor is not done.
- Then it checks if the next descriptor is done.
- Add a check that afterwards checks the first descriptor again, because
- it might have been completed in the mean time.
-
- This fixes a regression introduced in
- commit 723e711356b5a8a95728a890e254e8b0d47b55cf
- "ath9k: fix handling of broken descriptors"
-
- Cc: stable@vger.kernel.org
- Reported-by: Marco André Dinis <marcoandredinis@gmail.com>
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 52a46300e782fe6994466523eb2b0b59091ea59f
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Mon Feb 24 11:43:50 2014 +0100
-
- ath9k: reduce baseband hang detection false positive rate
-
- Check if the baseband state remains stable, and add a small delay
- between register reads.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 118945bb12082e9d4edddc868d88143164e0f440
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sat Feb 22 14:55:23 2014 +0100
-
- ath5k: set SURVEY_INFO_IN_USE on get_survey
-
- Only one channel is returned - the one currently being used.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit ee41f72476e1ea44283dfe1cbf75b9543a1e15c8
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sat Feb 22 14:44:52 2014 +0100
-
- ath9k: make some hardware reset log messages debug-only
-
- On some chips, baseband watchdog hangs are more common than others, and
- the driver has support for handling them.
- Interrupts even after a watchdog hang are also quite common, so there's
- not much point in spamming the user's logfiles.
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit b14fbb554fc65a2e0b5c41a319269b0350f187e7
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sat Feb 22 14:35:25 2014 +0100
-
- ath9k: do not set half/quarter channel flags in AR_PHY_MODE
-
- 5/10 MHz channel bandwidth is configured via the PLL clock, instead of
- the AR_PHY_MODE register. Using that register is AR93xx specific, and
- makes the mode incompatible with earlier chipsets.
-
- In some early versions, these flags were apparently applied at the wrong
- point in time and thus did not cause connectivity issues, however now
- they are causing problems, as pointed out in this OpenWrt ticket:
-
- https://dev.openwrt.org/ticket/14916
-
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Sat Feb 22 13:43:29 2014 +0100
+commit d2746694fcdef24e0a7a1947d8c70082cde81a26
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date: Thu Jun 5 14:21:36 2014 +0200
- ath9k: fix ps-poll responses under a-mpdu sessions
-
- When passing tx frames to the U-APSD queue for powersave poll responses,
- the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for
- proper sequence number accounting.
+ mac80211: move csa counters from sdata to beacon/presp
- This fixes high latency and connection stability issues with ath9k
- running as AP and a few kinds of mobile phones as client, when PS-Poll
- is heavily used
-
- Cc: stable@vger.kernel.org
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Fri Feb 21 11:39:59 2014 +0100
-
- ath9k: list more reset causes in debugfs
+ Having csa counters part of beacon and probe_resp
+ structures makes it easier to get rid of possible
+ races between setting a beacon and updating
+ counters on SMP systems by guaranteeing counters
+ are always consistent against given beacon struct.
- Number of MAC hangs and stuck beacons were missing
+ While at it relax WARN_ON into WARN_ON_ONCE to
+ prevent spamming logs and racing.
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit d84856012e0f10fe598a5ad3b7b869397a089e07
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Thu Feb 20 11:19:58 2014 +0100
+commit 5dcb54f3a1a8cd7e0331e773487574f9743615db
+Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+Date: Thu Jun 5 08:12:57 2014 +0200
- mac80211: fix station wakeup powersave race
-
- Consider the following (relatively unlikely) scenario:
- 1) station goes to sleep while frames are buffered in driver
- 2) driver blocks wakeup (until no more frames are buffered)
- 3) station wakes up again
- 4) driver unblocks wakeup
+ mac80211: allow tx via monitor iface when DFS
- In this case, the current mac80211 code will do the following:
- 1) WLAN_STA_PS_STA set
- 2) WLAN_STA_PS_DRIVER set
- 3) - nothing -
- 4) WLAN_STA_PS_DRIVER cleared
+ Allow send frames using monitor interface
+ when DFS chandef and we pass CAC (beaconing
+ allowed).
- As a result, no frames will be delivered to the client, even
- though it is awake, until it sends another frame to us that
- triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end().
-
- Since we now take the PS spinlock, we can fix this while at
- the same time removing the complexity with the pending skb
- queue function. This was broken since my commit 50a9432daeec
- ("mac80211: fix powersaving clients races") due to removing
- the clearing of WLAN_STA_PS_STA in the RX path.
-
- While at it, fix a cleanup path issue when a station is
- removed while the driver is still blocking its wakeup.
+ This fix problem when old kernel and new backports used,
+ in such case hostapd create/use also monitor interface.
+ Before this patch all frames hostapd send using monitor
+ iface were dropped when AP was configured on DFS channel.
+ Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 798f2786602cbe93e6b928299614aa36ebf50692
+commit 6f09a1beb0d2007572248c986780562219bd206f
Author: Johannes Berg <johannes.berg@intel.com>
-Date: Mon Feb 17 20:49:03 2014 +0100
+Date: Wed Jun 4 17:31:56 2014 +0200
- mac80211: insert stations before adding to driver
-
- There's a race condition in mac80211 because we add stations
- to the internal lists after adding them to the driver, which
- means that (for example) the following can happen:
- 1. a station connects and is added
- 2. first, it is added to the driver
- 3. then, it is added to the mac80211 lists
+ cfg80211: make ethtool the driver's responsibility
- If the station goes to sleep between steps 2 and 3, and the
- firmware/hardware records it as being asleep, mac80211 will
- never instruct the driver to wake it up again as it never
- realized it went to sleep since the RX path discarded the
- frame as a "spurious class 3 frame", no station entry was
- present yet.
+ Currently, cfg80211 tries to implement ethtool, but that doesn't
+ really scale well, with all the different operations. Make the
+ lower-level driver responsible for it, which currently only has
+ an effect on mac80211. It will similarly not scale well at that
+ level though, since mac80211 also has many drivers.
- Fix this by adding the station in software first, and only
- then adding it to the driver. That way, any state that the
- driver changes will be reflected properly in mac80211's
- station state. The problematic part is the roll-back if the
- driver fails to add the station, in that case a bit more is
- needed. To not make that overly complex prevent starting BA
- sessions in the meantime.
+ To cleanly implement this in mac80211, introduce a new file and
+ move some code to appropriate places.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date: Thu Feb 20 09:22:11 2014 +0200
+commit 6b0c6f133de8f90caeb1c4a902e6140567c5bf96
+Author: Johannes Berg <johannes.berg@intel.com>
+Date: Wed Jun 4 17:06:23 2014 +0200
- mac80211: fix AP powersave TX vs. wakeup race
-
- There is a race between the TX path and the STA wakeup: while
- a station is sleeping, mac80211 buffers frames until it wakes
- up, then the frames are transmitted. However, the RX and TX
- path are concurrent, so the packet indicating wakeup can be
- processed while a packet is being transmitted.
-
- This can lead to a situation where the buffered frames list
- is emptied on the one side, while a frame is being added on
- the other side, as the station is still seen as sleeping in
- the TX path.
+ mac80211: remove weak WEP IV accounting
- As a result, the newly added frame will not be send anytime
- soon. It might be sent much later (and out of order) when the
- station goes to sleep and wakes up the next time.
+ Since WEP is practically dead, there seems very little
+ point in keeping WEP weak IV accounting.
- Additionally, it can lead to the crash below.
-
- Fix all this by synchronising both paths with a new lock.
- Both path are not fastpath since they handle PS situations.
-
- In a later patch we'll remove the extra skb queue locks to
- reduce locking overhead.
-
- BUG: unable to handle kernel
- NULL pointer dereference at 000000b0
- IP: [<ff6f1791>] ieee80211_report_used_skb+0x11/0x3e0 [mac80211]
- *pde = 00000000
- Oops: 0000 [#1] SMP DEBUG_PAGEALLOC
- EIP: 0060:[<ff6f1791>] EFLAGS: 00210282 CPU: 1
- EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211]
- EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000
- ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0
- DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
- CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0
- DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
- DR6: ffff0ff0 DR7: 00000400
- Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000)
- iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9
- Stack:
- e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0
- ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210
- ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002
- Call Trace:
- [<ff6f1b75>] ieee80211_free_txskb+0x15/0x20 [mac80211]
- [<ff723dc1>] invoke_tx_handlers+0x1661/0x1780 [mac80211]
- [<ff7248a5>] ieee80211_tx+0x75/0x100 [mac80211]
- [<ff7249bf>] ieee80211_xmit+0x8f/0xc0 [mac80211]
- [<ff72550e>] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211]
- [<c149ef70>] dev_hard_start_xmit+0x450/0x950
- [<c14b9aa9>] sch_direct_xmit+0xa9/0x250
- [<c14b9c9b>] __qdisc_run+0x4b/0x150
- [<c149f732>] dev_queue_xmit+0x2c2/0xca0
-
- Cc: stable@vger.kernel.org
- Reported-by: Yaara Rozenblum <yaara.rozenblum@intel.com>
- Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
- Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com>
- [reword commit log, use a separate lock]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 80e419de0dff38436b30d363311c625766193f86
-Author: Inbal Hacohen <Inbal.Hacohen@intel.com>
-Date: Wed Feb 12 09:32:27 2014 +0200
+commit aecdc89fb4664c76baa4bbd46008f220532309ff
+Author: Luciano Coelho <luciano.coelho@intel.com>
+Date: Fri May 23 11:04:50 2014 +0300
- cfg80211: bugfix in regulatory user hint process
+ ath9k/ath10k: remove unnecessary channel_switch_beacon callbacks
- After processing hint_user, we would want to schedule the
- timeout work only if we are actually waiting to CRDA. This happens
- when the status is not "IGNORE" nor "ALREADY_SET".
+ The channel_switch_beacon callback is optional, so it doesn't have to
+ be defined if it's not going to do anything useful with it. Both
+ ath9k and ath10k define the callback and just returns. This commit
+ removes them.
- Signed-off-by: Inbal Hacohen <Inbal.Hacohen@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ Cc: Michal Kazior <michal.kazior@tieto.com>
+ Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+ Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-commit 6514c93afede55284e2cb63359aadedb85884c80
-Author: Jouni Malinen <jouni@qca.qualcomm.com>
-Date: Tue Feb 18 20:41:08 2014 +0200
+commit 60ccc107c9b9fb732fdee1f76bb2dad44f0e1798
+Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+Date: Tue May 27 16:58:02 2014 +0530
- ath9k: Enable U-APSD AP mode support
+ ath9k: Fix deadlock while updating p2p beacon timer
- mac80211 handles the actual operations, so ath9k can just indicate
- support for this. Based on initial tests, this combination seems to
- work fine.
+ pm_lock is taken twice while syncing HW TSF of p2p vif.
+ Fix this by taking the lock at caller side.
- Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
+ Cc: Felix Fietkau <nbd@openwrt.org>
+ Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+ Signed-off-by: John W. Linville <linville@tuxdriver.com>
-commit a63caf0a357ad5c1f08d6b7827dc76c451445017
+commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc
Author: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Wed Feb 19 13:15:17 2014 +0100
+Date: Thu Jun 5 13:52:27 2014 +0200
- ath9k: protect tid->sched check
-
- We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
- is race condition which can result of doing list_del(&tid->list) twice
- (second time with poisoned list node) and cause crash like shown below:
+ rt2x00: do not initialize BCN_OFFSET registers
- [424271.637220] BUG: unable to handle kernel paging request at 00100104
- [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
- ...
- [424271.639953] Call Trace:
- [424271.639998] [<f90f6900>] ? ath9k_get_survey+0x110/0x110 [ath9k]
- [424271.640083] [<f90f6942>] ath9k_sta_notify+0x42/0x50 [ath9k]
- [424271.640177] [<f809cfef>] sta_ps_start+0x8f/0x1c0 [mac80211]
- [424271.640258] [<c10f730e>] ? free_compound_page+0x2e/0x40
- [424271.640346] [<f809e915>] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211]
- [424271.640437] [<c112f048>] ? kmem_cache_free+0x1d8/0x1f0
- [424271.640510] [<c1345a84>] ? kfree_skbmem+0x34/0x90
- [424271.640578] [<c10fc23c>] ? put_page+0x2c/0x40
- [424271.640640] [<c1345a84>] ? kfree_skbmem+0x34/0x90
- [424271.640706] [<c1345a84>] ? kfree_skbmem+0x34/0x90
- [424271.640787] [<f809dde3>] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211]
- [424271.640897] [<f80a07a0>] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211]
- [424271.641009] [<f809e22d>] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211]
- [424271.641104] [<c13846ce>] ? ip_output+0x7e/0xd0
- [424271.641182] [<f80a1057>] ieee80211_rx+0x307/0x7c0 [mac80211]
- [424271.641266] [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
- [424271.641358] [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
- [424271.641445] [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
+ We setup BCN_OFFSET{0,1} registers dynamically, don't have to
+ initialize them.
- Bug report:
- https://bugzilla.kernel.org/show_bug.cgi?id=70551
-
- Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
- Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
-Author: Felix Fietkau <nbd@openwrt.org>
-Date: Tue Feb 11 15:54:13 2014 +0100
-
- mac80211: send control port protocol frames to the VO queue
-
- Improves reliability of wifi connections with WPA, since authentication
- frames are prioritized over normal traffic and also typically exempt
- from aggregation.
-
- Cc: stable@vger.kernel.org
- Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-
-commit d4426800f71e972feaa33e04c5801fc730627bdd
-Author: Stanislaw Gruszka <stf_xl@wp.pl>
-Date: Mon Feb 10 22:38:28 2014 +0100
-
- rtl8187: fix regression on MIPS without coherent DMA
-
- This patch fixes regression caused by commit a16dad77634 "MIPS: Fix
- potencial corruption". That commit fixes one corruption scenario in
- cost of adding another one, which actually start to cause crashes
- on Yeeloong laptop when rtl8187 driver is used.
-
- For correct DMA read operation on machines without DMA coherence, kernel
- have to invalidate cache, such it will refill later with new data that
- device wrote to memory, when that data is needed to process. We can only
- invalidate full cache line. Hence when cache line includes both dma
- buffer and some other data (written in cache, but not yet in main
- memory), the other data can not hit memory due to invalidation. That
- happen on rtl8187 where struct rtl8187_priv fields are located just
- before and after small buffers that are passed to USB layer and DMA
- is performed on them.
-
- To fix the problem we align buffers and reserve space after them to make
- them match cache line.
-
- This patch does not resolve all possible MIPS problems entirely, for
- that we have to assure that we always map cache aligned buffers for DMA,
- what can be complex or even not possible. But patch fixes visible and
- reproducible regression and seems other possible corruptions do not
- happen in practice, since Yeeloong laptop works stable without rtl8187
- driver.
-
- Bug report:
- https://bugzilla.kernel.org/show_bug.cgi?id=54391
-
- Reported-by: Petr Pisar <petr.pisar@atlas.cz>
- Bisected-by: Tom Li <biergaizi2009@gmail.com>
- Reported-and-tested-by: Tom Li <biergaizi2009@gmail.com>
- Cc: stable@vger.kernel.org
- Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
-
-commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:55 2014 +0530
-
- ath9k: Calculate IQ-CAL median
-
- This patch adds a routine to calculate the median IQ correction
- values for AR955x, which is used for outlier detection.
- The normal method which is used for all other chips is
- bypassed for AR955x.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit c52a6fce0820c8d0687443ab86058ae03b478c8f
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:54 2014 +0530
-
- ath9k: Expand the IQ coefficient array
-
- This will be used for storing data for mutiple
- IQ calibration runs, for AR955x.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit 034969ff5c2b6431d10e07c1938f0b916da85cc3
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:53 2014 +0530
-
- ath9k: Modify IQ calibration for AR955x
-
- IQ calibration post-processing for AR955x is different
- from other chips - instead of just doing it as part
- of AGC calibration once, it is triggered 3 times and
- a median is determined. This patch adds initial support
- for changing the calibration behavior for AR955x.
-
- Also, to simplify things, a helper routine to issue/poll
- AGC calibration is used.
-
- For non-AR955x chips, the iqcal_idx (which will be used
- in subsequent patches) is set to zero.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:52 2014 +0530
-
- ath9k: Fix magnitude/phase calculation
-
- Incorrect values are programmed in the registers
- containing the IQ correction coefficients by the IQ-CAL
- post-processing code. Fix this.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit 36f93484f96f79171dcecb67c5ef0c3de22531a6
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:51 2014 +0530
-
- ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes
-
- Use ar9003_hw_tx_iq_cal_outlier_detection instead.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:50 2014 +0530
-
- ath9k: Check explicitly for IQ calibration
-
- In chips like AR955x, the initvals contain the information
- whether IQ calibration is to be done in the HW when an
- AGC calibration is triggered. Check if IQ-CAL is enabled
- in the initvals before flagging 'txiqcal_done' as true.
-
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit cb4969634b93c4643a32cc3fbd27d2b288b25771
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Fri Feb 7 10:29:49 2014 +0530
+commit e5c58ca7a48d4c82f282749a978052c47fd95998
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Thu Jun 5 13:52:26 2014 +0200
- ath9k: Fix IQ cal post processing for SoC
+ rt2x00: change order when stop beaconing
- Calibration data is not reused for SoC chips, so
- call ar9003_hw_tx_iq_cal_post_proc() with the correct
- argument. The 'is_reusable' flag is currently used
- only for PC-OEM chips, but it makes things clearer to
- specify it explicity.
+ When no beaconing is needed, first stop beacon queue (disable beaconing
+ globally) to avoid possible sending of not prepared beacon on short
+ period after clearing beacon and before stop of BCN queue.
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+ Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Mon Feb 3 13:31:37 2014 +0530
+commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Thu Jun 5 13:52:25 2014 +0200
- ath9k: Fix TX power calculation
+ rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM
- The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
- fixed the incorrect values in the eeprom templates, but if
- boards have already been calibrated with incorrect values,
- they would still be using the wrong TX power. Fix this by assigning
- a default value in such cases.
+ We setup MAC_BSSID_DW1_BSS_BCN_NUM dynamically when numbers of active
+ beacons increase. Change default to 0 to tell hardware that we want to
+ send only one beacon as default.
- Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+ Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-commit b9f268b5b01331c3c82179abca551429450e9417
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Wed Jan 29 14:22:27 2014 +0100
+commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Thu Jun 5 13:52:24 2014 +0200
- cfg80211: consider existing DFS interfaces
-
- It was possible to break interface combinations in
- the following way:
-
- combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
- combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
+ rt2x00: change beaconing setup on RT2800
- With the above interface combinations it was
- possible to:
+ As reported by Matthias, on 5572 chip, even if we clear up TXWI
+ of corresponding beacon, hardware still try to send it or do other
+ action that increase power consumption peak up to 1A.
- step 1. start AP on DFS channel by matching combo 2
- step 2. start AP on non-DFS channel by matching combo 1
+ To avoid the issue, setup beaconing dynamically by configuring offsets
+ of currently active beacons and MAC_BSSID_DW1_BSS_BCN_NUM variable,
+ which limit number of beacons that hardware will try to send.
- This was possible beacuse (step 2) did not consider
- if other interfaces require radar detection.
-
- The patch changes how cfg80211 tracks channels -
- instead of channel itself now a complete chandef
- is stored.
-
- Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
+ Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28
-Author: Antonio Quartulli <antonio@open-mesh.com>
-Date: Wed Jan 29 17:53:43 2014 +0100
+commit 916e591b2cc41f7e572992175ca56d866d7bc958
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Thu Jun 5 13:52:23 2014 +0200
- cfg80211: fix channel configuration in IBSS join
-
- When receiving an IBSS_JOINED event select the BSS object
- based on the {bssid, channel} couple rather than the bssid
- only.
- With the current approach if another cell having the same
- BSSID (but using a different channel) exists then cfg80211
- picks up the wrong BSS object.
- The result is a mismatching channel configuration between
- cfg80211 and the driver, that can lead to any sort of
- problem.
-
- The issue can be triggered by having an IBSS sitting on
- given channel and then asking the driver to create a new
- cell using the same BSSID but with a different frequency.
- By passing the channel to cfg80211_get_bss() we can solve
- this ambiguity and retrieve/create the correct BSS object.
- All the users of cfg80211_ibss_joined() have been changed
- accordingly.
+ rt2x00: change beaconing locking
- Moreover WARN when cfg80211_ibss_joined() gets a NULL
- channel as argument and remove a bogus call of the same
- function in ath6kl (it does not make sense to call
- cfg80211_ibss_joined() with a zero BSSID on ibss-leave).
+ This patch is needed for further changes to keep global variables
+ consistent when changing beaconing on diffrent vif's.
- Cc: Kalle Valo <kvalo@qca.qualcomm.com>
- Cc: Arend van Spriel <arend@broadcom.com>
- Cc: Bing Zhao <bzhao@marvell.com>
- Cc: Jussi Kivilinna <jussi.kivilinna@iki.fi>
- Cc: libertas-dev@lists.infradead.org
- Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
- Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
- [minor code cleanup in ath6kl]
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
-commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85
+commit 930b0dffd1731f3f418f9132faea720a23b7af61
Author: Johannes Berg <johannes.berg@intel.com>
-Date: Fri Jan 24 14:41:44 2014 +0100
-
- mac80211: fix bufferable MMPDU RX handling
-
- Action, disassoc and deauth frames are bufferable, and as such don't
- have the PM bit in the frame control field reserved which means we
- need to react to the bit when receiving in such a frame.
-
- Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu()
- and using it for the RX path that currently ignores the PM bit in
- any non-data frames for doze->wake transitions, but listens to it in
- all frames for wake->doze transitions, both of which are wrong.
-
- Also use the new helper in the TX path to clean up the code.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit fc0df6d2343636e3f48a069330d5b972e3d8659d
-Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date: Fri Jan 24 14:29:21 2014 +0100
-
- cfg80211: set preset_chandef after channel switch
-
- Set preset_chandef in channel switch notification.
- In other case we will have old preset_chandef.
-
- Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit cdec895e2344987ff171cece96e25d7407a3ebf6
-Author: Simon Wunderlich <simon@open-mesh.com>
-Date: Fri Jan 24 23:48:29 2014 +0100
-
- mac80211: send ibss probe responses with noack flag
-
- Responding to probe requests for scanning clients will often create
- excessive retries, as it happens quite often that the scanning client
- already left the channel. Therefore do it like hostapd and send probe
- responses for wildcard SSID only once by using the noack flag.
+Date: Tue Jun 3 11:18:47 2014 +0200
+
+ mac80211: fix station/driver powersave race
+
+ It is currently possible to have a race due to the station PS
+ unblock work like this:
+ * station goes to sleep with frames buffered in the driver
+ * driver blocks wakeup
+ * station wakes up again
+ * driver flushes/returns frames, and unblocks, which schedules
+ the unblock work
+ * unblock work starts to run, and checks that the station is
+ awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
+ * we process a received frame with PM=1, setting the flag again
+ * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
+ to the driver, and then clearing the WLAN_STA_PS_DRIVER and
+ WLAN_STA_PS_STA flags
+
+ In this scenario, mac80211 will think that the station is awake,
+ while it really is asleep, and any TX'ed frames should be filtered
+ by the device (it will know that the station is sleeping) but then
+ passed to mac80211 again, which will not buffer it either as it
+ thinks the station is awake, and eventually the packets will be
+ dropped.
+
+ Fix this by moving the clearing of the flags to exactly where we
+ learn about the situation. This creates a problem of reordering,
+ so introduce another flag indicating that delivery is being done,
+ this new flag also queues frames and is cleared only while the
+ spinlock is held (which the queuing code also holds) so that any
+ concurrent delivery/TX is handled correctly.
- Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
- [fix typo & 'wildcard SSID' in commit log]
+ Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b
-Author: Luciano Coelho <luciano.coelho@intel.com>
-Date: Tue Jan 28 17:09:08 2014 +0200
+commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Fri May 23 19:58:14 2014 +0200
- mac80211: ibss: remove unnecessary call to release channel
-
- The ieee80211_vif_use_channel() function calls
- ieee80211_vif_release_channel(), so there's no need to call it
- explicitly in __ieee80211_sta_join_ibss().
+ mac80211: reduce packet loss notifications under load
- Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Wed Jan 29 07:56:21 2014 +0100
-
- mac80211: add missing CSA locking
+ During strong signal fluctuations under high throughput, few consecutive
+ failed A-MPDU transmissions can easily trigger packet loss notification,
+ and thus (in AP mode) client disconnection.
- The patch adds a missing sdata lock and adds a few
- lockdeps for easier maintenance.
+ Reduce the number of false positives by checking the A-MPDU status flag
+ and treating a failed A-MPDU as a single packet.
- Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-commit ad17ba7d14d225b109b73c177cd446afb8050598
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Wed Jan 29 07:56:20 2014 +0100
+commit 7b7843a36fbcc568834404c7430ff895d8502131
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Fri May 23 19:26:32 2014 +0200
- mac80211: fix sdata->radar_required locking
+ mac80211: fix a memory leak on sta rate selection table
- radar_required setting wasn't protected by
- local->mtx in some places. This should prevent
- from scanning/radar detection/roc colliding.
-
- Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ Cc: stable@vger.kernel.org
+ Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Wed Jan 29 07:56:19 2014 +0100
+commit 96892d6aa0a153423070addf3070bc79578b3897
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Mon May 19 21:20:49 2014 +0200
- mac80211: move csa_active setting in STA CSA
+ ath9k: avoid passing buffers to the hardware during flush
- The sdata->vif.csa_active could be left set after,
- e.g. channel context constraints check fail in STA
- mode leaving the interface in a strange state for
- a brief period of time until it is disconnected.
- This was harmless but ugly.
+ The commit "ath9k: fix possible hang on flush" changed the receive code
+ to always link rx descriptors of processed frames, even when flushing.
+ In some cases, this leads to flushed rx buffers being passed to the
+ hardware while rx is already stopped.
- Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
- Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9
-Author: Michal Kazior <michal.kazior@tieto.com>
-Date: Wed Jan 29 07:56:18 2014 +0100
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
- mac80211: fix possible memory leak on AP CSA failure
-
- If CSA for AP interface failed and the interface
- was not stopped afterwards another CSA request
- would leak sdata->u.ap.next_beacon.
-
- Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
- Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 3a77ba08940682bf3d52cf14f980337324af9d4a
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Sat Feb 1 00:33:29 2014 +0100
-
- mac80211: fix fragmentation code, particularly for encryption
-
- The "new" fragmentation code (since my rewrite almost 5 years ago)
- erroneously sets skb->len rather than using skb_trim() to adjust
- the length of the first fragment after copying out all the others.
- This leaves the skb tail pointer pointing to after where the data
- originally ended, and thus causes the encryption MIC to be written
- at that point, rather than where it belongs: immediately after the
- data.
-
- The impact of this is that if software encryption is done, then
- a) encryption doesn't work for the first fragment, the connection
- becomes unusable as the first fragment will never be properly
- verified at the receiver, the MIC is practically guaranteed to
- be wrong
- b) we leak up to 8 bytes of plaintext (!) of the packet out into
- the air
-
- This is only mitigated by the fact that many devices are capable
- of doing encryption in hardware, in which case this can't happen
- as the tail pointer is irrelevant in that case. Additionally,
- fragmentation is not used very frequently and would normally have
- to be configured manually.
-
- Fix this by using skb_trim() properly.
-
- Cc: stable@vger.kernel.org
- Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation")
- Reported-by: Jouni Malinen <j@w1.fi>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit de5f242e0c10e841017e37eb8c38974a642dbca8
-Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-Date: Tue Jan 28 06:21:59 2014 +0530
-
- ath9k: Fix build error on ARM
-
- Use mdelay instead of udelay to fix this error:
-
- ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined!
- make[1]: *** [__modpost] Error 1
- make: *** [modules] Error 2
-
- Reported-by: Josh Boyer <jwboyer@fedoraproject.org>
- Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
-
-commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a
-Author: Geert Uytterhoeven <geert@linux-m68k.org>
-Date: Sun Jan 26 11:53:21 2014 +0100
-
- ath9k: Fix uninitialized variable in ath9k_has_tx_pending()
-
- drivers/net/wireless/ath/ath9k/main.c: In function ath9k_has_tx_pending:
- drivers/net/wireless/ath/ath9k/main.c:1869: warning: npend may be used uninitialized in this function
-
- Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k:
- optimize ath9k_flush").
-
- Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-
-commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date: Mon Jan 27 11:07:42 2014 +0200
-
- mac80211: release the channel in error path in start_ap
-
- When the driver cannot start the AP or when the assignement
- of the beacon goes wrong, we need to unassign the vif.
-
- Cc: stable@vger.kernel.org
- Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit dfb6889a75c601aedb7450b7e606668e77da6679
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Wed Jan 22 11:14:19 2014 +0200
-
- cfg80211: send scan results from work queue
-
- Due to the previous commit, when a scan finishes, it is in theory
- possible to hit the following sequence:
- 1. interface starts being removed
- 2. scan is cancelled by driver and cfg80211 is notified
- 3. scan done work is scheduled
- 4. interface is removed completely, rdev->scan_req is freed,
- event sent to userspace but scan done work remains pending
- 5. new scan is requested on another virtual interface
- 6. scan done work runs, freeing the still-running scan
-
- To fix this situation, hang on to the scan done message and block
- new scans while that is the case, and only send the message from
- the work function, regardless of whether the scan_req is already
- freed from interface removal. This makes step 5 above impossible
- and changes step 6 to be
- 5. scan done work runs, sending the scan done message
-
- As this can't work for wext, so we send the message immediately,
- but this shouldn't be an issue since we still return -EBUSY.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Wed Jan 22 11:14:18 2014 +0200
-
- cfg80211: fix scan done race
-
- When an interface/wdev is removed, any ongoing scan should be
- cancelled by the driver. This will make it call cfg80211, which
- only queues a work struct. If interface/wdev removal is quick
- enough, this can leave the scan request pending and processed
- only after the interface is gone, causing a use-after-free.
-
- Fix this by making sure the scan request is not pending after
- the interface is destroyed. We can't flush or cancel the work
- item due to locking concerns, but when it'll run it shouldn't
- find anything to do. This leaves a potential issue, if a new
- scan gets requested before the work runs, it prematurely stops
- the running scan, potentially causing another crash. I'll fix
- that in the next patch.
-
- This was particularly observed with P2P_DEVICE wdevs, likely
- because freeing them is quicker than freeing netdevs.
-
- Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
- Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans")
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit ae04fa489ab31b5a10d3cc8399f52761175d4321
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date: Thu Jan 23 14:28:16 2014 +0200
-
- mac80211: avoid deadlock revealed by lockdep
-
- sdata->u.ap.request_smps_work cant be flushed synchronously
- under wdev_lock(wdev) since ieee80211_request_smps_ap_work
- itself locks the same lock.
- While at it, reset the driver_smps_mode when the ap is
- stopped to its default: OFF.
-
- This solves:
-
- ======================================================
- [ INFO: possible circular locking dependency detected ]
- 3.12.0-ipeer+ #2 Tainted: G O
- -------------------------------------------------------
- rmmod/2867 is trying to acquire lock:
- ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
-
- but task is already holding lock:
- (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
-
- which lock already depends on the new lock.
-
- the existing dependency chain (in reverse order) is:
-
- -> #1 (&wdev->mtx){+.+.+.}:
- [<c10aefa9>] lock_acquire+0x79/0xe0
- [<c1607a1a>] mutex_lock_nested+0x4a/0x360
- [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211]
- [<c105cdd8>] process_one_work+0x198/0x450
- [<c105d469>] worker_thread+0xf9/0x320
- [<c10669ff>] kthread+0x9f/0xb0
- [<c1613397>] ret_from_kernel_thread+0x1b/0x28
-
- -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}:
- [<c10ae9df>] __lock_acquire+0x183f/0x1910
- [<c10aefa9>] lock_acquire+0x79/0xe0
- [<c105b917>] flush_work+0x47/0x90
- [<c105d867>] __cancel_work_timer+0x67/0xe0
- [<c105d90f>] cancel_work_sync+0xf/0x20
- [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211]
- [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211]
- [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211]
- [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211]
- [<c160f2c9>] notifier_call_chain+0x59/0x130
- [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30
- [<c106c70f>] raw_notifier_call_chain+0x1f/0x30
- [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70
- [<c14f8263>] call_netdevice_notifiers+0x13/0x20
- [<c14f82a4>] __dev_close_many+0x34/0xb0
- [<c14f83fe>] dev_close_many+0x6e/0xc0
- [<c14f9c77>] rollback_registered_many+0xa7/0x1f0
- [<c14f9dd4>] unregister_netdevice_many+0x14/0x60
- [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211]
- [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211]
- [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm]
- [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi]
- [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi]
- [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm]
- [<c10b8bf9>] SyS_delete_module+0x179/0x2b0
- [<c1613421>] sysenter_do_call+0x12/0x32
-
- Fixes: 687da132234f ("mac80211: implement SMPS for AP")
- Cc: <stable@vger.kernel.org> [3.13]
- Reported-by: Ilan Peer <ilan.peer@intel.com>
- Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 178b205e96217164fd7c30113464250d0b6f5eca
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Thu Jan 23 16:32:29 2014 +0100
-
- cfg80211: re-enable 5/10 MHz support
-
- Unfortunately I forgot this during the merge window, but the
- patch seems small enough to go in as a fix. The userspace API
- bug that was the reason for disabling it has long been fixed.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
-Author: Pontus Fuchs <pontus.fuchs@gmail.com>
-Date: Thu Jan 16 15:00:40 2014 +0100
-
- nl80211: Reset split_start when netlink skb is exhausted
-
- When the netlink skb is exhausted split_start is left set. In the
- subsequent retry, with a larger buffer, the dump is continued from the
- failing point instead of from the beginning.
-
- This was causing my rt28xx based USB dongle to now show up when
- running "iw list" with an old iw version without split dump support.
-
- Cc: stable@vger.kernel.org
- Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
- Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
- [avoid the entire workaround when state->split is set]
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
-Author: Eliad Peller <eliad@wizery.com>
-Date: Sun Jan 12 11:06:37 2014 +0200
-
- mac80211: move roc cookie assignment earlier
-
- ieee80211_start_roc_work() might add a new roc
- to existing roc, and tell cfg80211 it has already
- started.
-
- However, this might happen before the roc cookie
- was set, resulting in REMAIN_ON_CHANNEL (started)
- event with null cookie. Consequently, it can make
- wpa_supplicant go out of sync.
-
- Fix it by setting the roc cookie earlier.
-
- Cc: stable@vger.kernel.org
- Signed-off-by: Eliad Peller <eliad@wizery.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Fri Jan 24 14:06:29 2014 +0100
-
- nl80211: send event when AP operation is stopped
-
- There are a few cases, e.g. suspend, where an AP interface is
- stopped by the kernel rather than by userspace request, most
- commonly when suspending. To let userspace know about this,
- send the NL80211_CMD_STOP_AP command as an event every time
- an AP interface is stopped. This also happens when userspace
- did in fact request the AP stop, but that's not a problem.
-
- For full-MAC drivers this may need to be extended to also
- cover cases where the device stopped the AP operation for
- some reason, this a bit more complicated because then all
- cfg80211 state also needs to be reset; such API is not part
- of this patch.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit d5d567eda7704f190379ca852a8f9a4112e3eee3
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Thu Jan 23 16:20:29 2014 +0100
-
- mac80211: add length check in ieee80211_is_robust_mgmt_frame()
-
- A few places weren't checking that the frame passed to the
- function actually has enough data even though the function
- clearly documents it must have a payload byte. Make this
- safer by changing the function to take an skb and checking
- the length inside. The old version is preserved for now as
- the rtl* drivers use it and don't have a correct skb.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit f8f6d212a047fc65c7d3442dfc038f65517236fc
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Fri Jan 24 10:53:53 2014 +0100
-
- nl80211: fix scheduled scan RSSI matchset attribute confusion
-
- The scheduled scan matchsets were intended to be a list of filters,
- with the found BSS having to pass at least one of them to be passed
- to the host. When the RSSI attribute was added, however, this was
- broken and currently wpa_supplicant adds that attribute in its own
- matchset; however, it doesn't intend that to mean that anything
- that passes the RSSI filter should be passed to the host, instead
- it wants it to mean that everything needs to also have higher RSSI.
-
- This is semantically problematic because we have a list of filters
- like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which
- one should be OR'ed and which one AND'ed.
-
- To fix this, move the RSSI filter attribute into each matchset. As
- we need to stay backward compatible, treat a matchset with only the
- RSSI attribute as a "default RSSI filter" for all other matchsets,
- but only if there are other matchsets (an RSSI-only matchset by
- itself is still desirable.)
-
- To make driver implementation easier, keep a global min_rssi_thold
- for the entire request as well. The only affected driver is ath6kl.
-
- I found this when I looked into the code after Raja Mani submitted
- a patch fixing the n_match_sets calculation to disregard the RSSI,
- but that patch didn't address the semantic issue.
-
- Reported-by: Raja Mani <rmani@qti.qualcomm.com>
- Acked-by: Luciano Coelho <luciano.coelho@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit de553e8545e65a6dc4e45f43df7e1443d4291922
-Author: Johannes Berg <johannes.berg@intel.com>
-Date: Fri Jan 24 10:17:47 2014 +0100
-
- nl80211: check nla_parse() return values
-
- If there's a policy, then nla_parse() return values must be
- checked, otherwise the policy is useless and there's nothing
- that ensures the attributes are actually what we expect them
- to be.
-
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-
-commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1
-Author: Karl Beldan <karl.beldan@rivierawaves.com>
-Date: Thu Jan 23 20:06:34 2014 +0100
-
- mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec
-
- ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of
- the BA parameters. In the discussion [1] about this patch, Johannes
- recalled that it fixed some races with the DELBA and indeed this
- behavior was introduced in [2].
- While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on
- their BA params TID AC violates the spec and is more a workaround for
- some drivers. Helmut expressed some concerns wrt such drivers, in
- particular DELBAs in rt2x00.
-
- ATM, DELBAs are sent after a driver has called (hence "purposely")
- ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some
- details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_*
- given to the driver ampdu_action supposed to call this function, which
- could prove handy to people trying to do the right thing in faulty
- drivers (if their fw/hw don't get in their way).
-
- [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com
- [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames")
-
- Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
- Cc: Helmut Schaa <helmut.schaa@googlemail.com>
- Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
- Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
-+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
-@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc
- if (nw_type & ADHOC_NETWORK) {
- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
- nw_type & ADHOC_CREATOR ? "creator" : "joiner");
-- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
-+ cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
- cfg80211_put_bss(ar->wiphy, bss);
- return;
- }
-@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(st
- }
-
- if (vif->nw_type & ADHOC_NETWORK) {
-- if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
-+ if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
- ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
- "%s: ath6k not in ibss mode\n", __func__);
-- return;
-- }
-- memset(bssid, 0, ETH_ALEN);
-- cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
- return;
- }
-
-@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s
- struct ath6kl_vif *vif = netdev_priv(dev);
- u16 interval;
- int ret, rssi_thold;
-+ int n_match_sets = request->n_match_sets;
-+
-+ /*
-+ * If there's a matchset w/o an SSID, then assume it's just for
-+ * the RSSI (nothing else is currently supported) and ignore it.
-+ * The device only supports a global RSSI filter that we set below.
-+ */
-+ if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
-+ n_match_sets = 0;
-
- if (ar->state != ATH6KL_STATE_ON)
- return -EIO;
-@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(s
- ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
- request->n_ssids,
- request->match_sets,
-- request->n_match_sets);
-+ n_match_sets);
- if (ret < 0)
- return ret;
-
-- if (!request->n_match_sets) {
-+ if (!n_match_sets) {
- ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
- ALL_BSS_FILTER, 0);
- if (ret < 0)
-@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(s
-
- if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
- ar->fw_capabilities)) {
-- if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
-+ if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
- rssi_thold = 0;
-- else if (request->rssi_thold < -127)
-+ else if (request->min_rssi_thold < -127)
- rssi_thold = -127;
- else
-- rssi_thold = request->rssi_thold;
-+ rssi_thold = request->min_rssi_thold;
-
- ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
- rssi_thold);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at
- if (AR_SREV_9300_20_OR_LATER(ah))
- udelay(50);
- else if (AR_SREV_9100(ah))
-- udelay(10000);
-+ mdelay(10);
- else
- udelay(100);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
+ * buffer (or rx fifo). This can incorrectly acknowledge packets
+ * to a sender if last desc is self-linked.
+ */
+-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
++ bool flush)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
+ common->rx_bufsize,
+ 0);
+
+- if (sc->rx.rxlink == NULL)
+- ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+- else
++ if (sc->rx.rxlink)
+ *sc->rx.rxlink = bf->bf_daddr;
++ else if (!flush)
++ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
+
+ sc->rx.rxlink = &ds->ds_link;
+ }
-@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
- bool ath9k_hw_check_alive(struct ath_hw *ah)
+-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
++ bool flush)
{
- int count = 50;
-- u32 reg;
-+ u32 reg, last_val;
-
- if (AR_SREV_9300(ah))
- return !ath9k_hw_detect_mac_hang(ah);
-@@ -1542,9 +1542,14 @@ bool ath9k_hw_check_alive(struct ath_hw
- if (AR_SREV_9285_12_OR_LATER(ah))
- return true;
-
-+ last_val = REG_READ(ah, AR_OBS_BUS_1);
- do {
- reg = REG_READ(ah, AR_OBS_BUS_1);
-+ if (reg != last_val)
-+ return true;
-
-+ udelay(1);
-+ last_val = reg;
- if ((reg & 0x7E7FFFEF) == 0x00702400)
- continue;
-
-@@ -2051,9 +2056,8 @@ static bool ath9k_hw_set_power_awake(str
-
- REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
--
- if (AR_SREV_9100(ah))
-- udelay(10000);
-+ mdelay(10);
- else
- udelay(50);
+ if (sc->rx.buf_hold)
+- ath_rx_buf_link(sc, sc->rx.buf_hold);
++ ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -451,7 +451,7 @@ void ath9k_tasklet(unsigned long data)
- * interrupts are enabled in the reset routine.
- */
- atomic_inc(&ah->intr_ref_cnt);
-- ath_dbg(common, ANY, "FATAL: Skipping interrupts\n");
-+ ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
- goto out;
+ sc->rx.buf_hold = bf;
+ }
+@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
+ sc->rx.buf_hold = NULL;
+ sc->rx.rxlink = NULL;
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
+- ath_rx_buf_link(sc, bf);
++ ath_rx_buf_link(sc, bf, false);
}
-@@ -471,7 +471,7 @@ void ath9k_tasklet(unsigned long data)
- * interrupts are enabled in the reset routine.
- */
- atomic_inc(&ah->intr_ref_cnt);
-- ath_dbg(common, ANY,
-+ ath_dbg(common, RESET,
- "BB_WATCHDOG: Skipping interrupts\n");
- goto out;
- }
-@@ -484,7 +484,7 @@ void ath9k_tasklet(unsigned long data)
- type = RESET_TYPE_TX_GTT;
- ath9k_queue_reset(sc, type);
- atomic_inc(&ah->intr_ref_cnt);
-- ath_dbg(common, ANY,
-+ ath_dbg(common, RESET,
- "GTT: Skipping interrupts\n");
- goto out;
+ /* We could have deleted elements so the list may be empty now */
+@@ -1118,12 +1120,12 @@ requeue_drop_frag:
+ requeue:
+ list_add_tail(&bf->list, &sc->rx.rxbuf);
+
+- if (edma) {
+- ath_rx_edma_buf_link(sc, qtype);
+- } else {
+- ath_rx_buf_relink(sc, bf);
++ if (!edma) {
++ ath_rx_buf_relink(sc, bf, flush);
+ if (!flush)
+ ath9k_hw_rxena(ah);
++ } else if (!flush) {
++ ath_rx_edma_buf_link(sc, qtype);
}
-@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
- static bool ath9k_has_tx_pending(struct ath_softc *sc)
- {
-- int i, npend;
-+ int i, npend = 0;
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
---- a/drivers/net/wireless/iwlwifi/mvm/scan.c
-+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
-@@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid(
- * config match list.
- */
- for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
-+ /* skip empty SSID matchsets */
-+ if (!req->match_sets[i].ssid.ssid_len)
-+ continue;
- scan->direct_scan[i].id = WLAN_EID_SSID;
- scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
- memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
---- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
-@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80
- /* During testing, hdr was NULL */
- return false;
- }
-- if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
---- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
-@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80
- /* In testing, hdr was NULL here */
- return false;
- }
-- if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
---- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
-@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80
- /* during testing, hdr was NULL here */
- return false;
- }
-- if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
---- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
-+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
-@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee
- /* during testing, hdr could be NULL here */
- return false;
- }
-- if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
-+ if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
---- a/include/linux/ieee80211.h
-+++ b/include/linux/ieee80211.h
-@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf
- }
+ if (!budget--)
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct
+ struct ps_data *ps;
- /**
-+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
-+ * @fc: frame control field in little-endian byteorder
-+ */
-+static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
-+{
-+ /* IEEE 802.11-2012, definition of "bufferable management frame";
-+ * note that this ignores the IBSS special case. */
-+ return ieee80211_is_mgmt(fc) &&
-+ (ieee80211_is_action(fc) ||
-+ ieee80211_is_disassoc(fc) ||
-+ ieee80211_is_deauth(fc));
-+}
-+
-+/**
- * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
- * @seq_ctrl: frame sequence control bytes in little-endian byteorder
- */
-@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc
- }
+ if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
+- test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
++ test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
++ test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+ ps = &sdata->bss->ps;
+@@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct
- /**
-- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
-+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
- * @hdr: the frame (buffer must include at least the first octet of payload)
- */
--static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
-+static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
- {
- if (ieee80211_is_disassoc(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control))
-@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m
- }
+ clear_sta_flag(sta, WLAN_STA_PS_STA);
+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++ clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
- /**
-+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
-+ * @skb: the skb containing the frame, length will be checked
-+ */
-+static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
-+{
-+ if (skb->len < 25)
-+ return false;
-+ return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
-+}
-+
-+/**
- * ieee80211_is_public_action - check if frame is a public action frame
- * @hdr: the frame
- * @len: length of the frame
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1395,9 +1395,11 @@ struct cfg80211_scan_request {
- * struct cfg80211_match_set - sets of attributes to match
- *
- * @ssid: SSID to be matched
-+ * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
- */
- struct cfg80211_match_set {
- struct cfg80211_ssid ssid;
-+ s32 rssi_thold;
- };
+ atomic_dec(&ps->num_sta_ps);
+ sta_info_recalc_tim(sta);
+@@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ mesh_sta_cleanup(sta);
- /**
-@@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
- * @dev: the interface
- * @scan_start: start time of the scheduled scan
- * @channels: channels to scan
-- * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
-+ * @min_rssi_thold: for drivers only supporting a single threshold, this
-+ * contains the minimum over all matchsets
- */
- struct cfg80211_sched_scan_request {
- struct cfg80211_ssid *ssids;
-@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
- u32 flags;
- struct cfg80211_match_set *match_sets;
- int n_match_sets;
-- s32 rssi_thold;
-+ s32 min_rssi_thold;
-
- /* internal */
- struct wiphy *wiphy;
-@@ -3130,8 +3133,8 @@ struct cfg80211_cached_keys;
- * @identifier: (private) Identifier used in nl80211 to identify this
- * wireless device if it has no netdev
- * @current_bss: (private) Used by the internal configuration code
-- * @channel: (private) Used by the internal configuration code to track
-- * the user-set AP, monitor and WDS channel
-+ * @chandef: (private) Used by the internal configuration code to track
-+ * the user-set channel definition.
- * @preset_chandef: (private) Used by the internal configuration code to
- * track the channel to be used for AP later
- * @bssid: (private) Used by the internal configuration code
-@@ -3195,9 +3198,7 @@ struct wireless_dev {
-
- struct cfg80211_internal_bss *current_bss; /* associated / joined */
- struct cfg80211_chan_def preset_chandef;
--
-- /* for AP and mesh channel tracking */
-- struct ieee80211_channel *channel;
-+ struct cfg80211_chan_def chandef;
+- cancel_work_sync(&sta->drv_unblock_wk);
++ cancel_work_sync(&sta->drv_deliver_wk);
- bool ibss_fixed;
- bool ibss_dfs_possible;
-@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct
- *
- * @dev: network device
- * @bssid: the BSSID of the IBSS joined
-+ * @channel: the channel of the IBSS joined
- * @gfp: allocation flags
- *
- * This function notifies cfg80211 that the device joined an IBSS or
-@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct
- * with the locally generated beacon -- this guarantees that there is
- * always a scan result for this IBSS. cfg80211 will handle the rest.
+ /*
+ * Destroy aggregation state here. It would be nice to wait for the
+@@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
*/
--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+ struct ieee80211_channel *channel, gfp_t gfp);
-
- /**
- * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr {
- * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
- * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
- * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
-- * only report BSS with matching SSID.
-+ * only report BSS with matching SSID.
- * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
-- * BSS in scan results. Filtering is turned off if not specified.
-+ * BSS in scan results. Filtering is turned off if not specified. Note that
-+ * if this attribute is in a match set of its own, then it is treated as
-+ * the default value for all matchsets with an SSID, rather than being a
-+ * matchset of its own without an RSSI filter. This is due to problems with
-+ * how this API was implemented in the past. Also, due to the same problem,
-+ * the only way to create a matchset with only an RSSI filter (with this
-+ * attribute) is if there's only a single matchset with the RSSI attribute.
- * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
- * attribute number currently defined
- * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request
- mgmt->u.action.u.addba_req.start_seq_num =
- cpu_to_le16(start_seq_num << 4);
-
-- ieee80211_tx_skb_tid(sdata, skb, tid);
-+ ieee80211_tx_skb(sdata, skb);
- }
-
- void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wip
- /* TODO: make hostapd tell us what it wants */
- sdata->smps_mode = IEEE80211_SMPS_OFF;
- sdata->needed_rx_chains = sdata->local->rx_chains;
-- sdata->radar_required = params->radar_required;
-
- mutex_lock(&local->mtx);
-+ sdata->radar_required = params->radar_required;
- err = ieee80211_vif_use_channel(sdata, &params->chandef,
- IEEE80211_CHANCTX_SHARED);
- mutex_unlock(&local->mtx);
-@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
- IEEE80211_P2P_OPPPS_ENABLE_BIT;
+ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
+ {
++ struct ieee80211_sta_rates *rates;
+ int i;
- err = ieee80211_assign_beacon(sdata, &params->beacon);
-- if (err < 0)
-+ if (err < 0) {
-+ ieee80211_vif_release_channel(sdata);
- return err;
-+ }
- changed |= err;
-
- err = drv_start_ap(sdata->local, sdata);
-@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip
- if (old)
- kfree_rcu(old, rcu_head);
- RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
-+ ieee80211_vif_release_channel(sdata);
- return err;
+ if (sta->rate_ctrl)
+@@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
+ kfree(sta->tx_lat);
}
-@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc
- int err;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ sdata_assert_lock(sdata);
-
- /* don't allow changing the beacon while CSA is in place - offset
- * of channel switch counter may change
-@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph
- struct probe_resp *old_probe_resp;
- struct cfg80211_chan_def chandef;
-
-+ sdata_assert_lock(sdata);
++ rates = rcu_dereference_protected(sta->sta.rates, true);
++ if (rates)
++ kfree(rates);
+
- old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
- if (!old_beacon)
- return -ENOENT;
-@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
+ sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
-- cancel_work_sync(&sdata->u.ap.request_smps_work);
--
- /* turn off carrier for this interface and dependent VLANs */
- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
- netif_carrier_off(vlan->dev);
-@@ -1103,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiph
- kfree_rcu(old_beacon, rcu_head);
- if (old_probe_resp)
- kfree_rcu(old_probe_resp, rcu_head);
-+ sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
-
- __sta_info_flush(sdata, true);
- ieee80211_free_keys(sdata, true);
-@@ -1988,6 +1993,9 @@ static int ieee80211_change_bss(struct w
-
- band = ieee80211_get_sdata_band(sdata);
-
-+ if (WARN_ON(!wiphy->bands[band]))
-+ return -EINVAL;
-+
- if (params->use_cts_prot >= 0) {
- sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
- changed |= BSS_CHANGED_ERP_CTS_PROT;
-@@ -2638,6 +2646,24 @@ static int ieee80211_start_roc_work(stru
- INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
- INIT_LIST_HEAD(&roc->dependents);
-
-+ /*
-+ * cookie is either the roc cookie (for normal roc)
-+ * or the SKB (for mgmt TX)
-+ */
-+ if (!txskb) {
-+ /* local->mtx protects this */
-+ local->roc_cookie_counter++;
-+ roc->cookie = local->roc_cookie_counter;
-+ /* wow, you wrapped 64 bits ... more likely a bug */
-+ if (WARN_ON(roc->cookie == 0)) {
-+ roc->cookie = 1;
-+ local->roc_cookie_counter++;
-+ }
-+ *cookie = roc->cookie;
-+ } else {
-+ *cookie = (unsigned long)txskb;
-+ }
-+
- /* if there's one pending or we're scanning, queue this one */
- if (!list_empty(&local->roc_list) ||
- local->scanning || local->radar_detect_enabled)
-@@ -2772,24 +2798,6 @@ static int ieee80211_start_roc_work(stru
- if (!queued)
- list_add_tail(&roc->list, &local->roc_list);
-
-- /*
-- * cookie is either the roc cookie (for normal roc)
-- * or the SKB (for mgmt TX)
-- */
-- if (!txskb) {
-- /* local->mtx protects this */
-- local->roc_cookie_counter++;
-- roc->cookie = local->roc_cookie_counter;
-- /* wow, you wrapped 64 bits ... more likely a bug */
-- if (WARN_ON(roc->cookie == 0)) {
-- roc->cookie = 1;
-- local->roc_cookie_counter++;
-- }
-- *cookie = roc->cookie;
-- } else {
-- *cookie = (unsigned long)txskb;
-- }
--
- return 0;
+ kfree(sta);
+@@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
}
-@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct
- if (!ieee80211_sdata_running(sdata))
- goto unlock;
-
-- sdata->radar_required = sdata->csa_radar_required;
-+ sdata_assert_lock(sdata);
-+
- mutex_lock(&local->mtx);
-+ sdata->radar_required = sdata->csa_radar_required;
- err = ieee80211_vif_change_channel(sdata, &changed);
- mutex_unlock(&local->mtx);
- if (WARN_ON(err < 0))
-@@ -3022,13 +3032,13 @@ void ieee80211_csa_finalize_work(struct
- switch (sdata->vif.type) {
- case NL80211_IFTYPE_AP:
- err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
-+ kfree(sdata->u.ap.next_beacon);
-+ sdata->u.ap.next_beacon = NULL;
-+
- if (err < 0)
- goto unlock;
-
- changed |= err;
-- kfree(sdata->u.ap.next_beacon);
-- sdata->u.ap.next_beacon = NULL;
--
- ieee80211_bss_info_change_notify(sdata, err);
- break;
- case NL80211_IFTYPE_ADHOC:
-@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph
- struct ieee80211_if_mesh __maybe_unused *ifmsh;
- int err, num_chanctx;
-
-- lockdep_assert_held(&sdata->wdev.mtx);
-+ sdata_assert_lock(sdata);
-
- if (!list_empty(&local->roc_list) || local->scanning)
- return -EBUSY;
---- a/net/mac80211/ht.c
-+++ b/net/mac80211/ht.c
-@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802
- mgmt->u.action.u.delba.params = cpu_to_le16(params);
- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
-
-- ieee80211_tx_skb_tid(sdata, skb, tid);
-+ ieee80211_tx_skb(sdata, skb);
- }
-
- void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
-@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
- u.ap.request_smps_work);
-
- sdata_lock(sdata);
-- __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
-+ if (sdata_dereference(sdata->u.ap.beacon, sdata))
-+ __ieee80211_request_smps_ap(sdata,
-+ sdata->u.ap.driver_smps_mode);
- sdata_unlock(sdata);
- }
+-static void sta_unblock(struct work_struct *wk)
++static void sta_deliver_ps_frames(struct work_struct *wk)
+ {
+ struct sta_info *sta;
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
+- sta = container_of(wk, struct sta_info, drv_unblock_wk);
++ sta = container_of(wk, struct sta_info, drv_deliver_wk);
- ieee80211_roc_purge(local, sdata);
+ if (sta->dead)
+ return;
-- if (sdata->vif.type == NL80211_IFTYPE_STATION)
-+ switch (sdata->vif.type) {
-+ case NL80211_IFTYPE_STATION:
- ieee80211_mgd_stop(sdata);
+- if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
+- local_bh_disable();
++ local_bh_disable();
++ if (!test_sta_flag(sta, WLAN_STA_PS_STA))
+ ieee80211_sta_ps_deliver_wakeup(sta);
+- local_bh_enable();
+- } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
+- clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-
-- if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ break;
-+ case NL80211_IFTYPE_ADHOC:
- ieee80211_ibss_stop(sdata);
+- local_bh_disable();
++ else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
+ ieee80211_sta_ps_deliver_poll_response(sta);
+- local_bh_enable();
+- } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
+- clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-
-+ break;
-+ case NL80211_IFTYPE_AP:
-+ cancel_work_sync(&sdata->u.ap.request_smps_work);
-+ break;
-+ default:
-+ break;
-+ }
-
- /*
- * Remove all stations associated with this interface.
-@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee
- cancel_work_sync(&local->dynamic_ps_enable_work);
-
- cancel_work_sync(&sdata->recalc_smps);
-+ sdata_lock(sdata);
- sdata->vif.csa_active = false;
-+ sdata_unlock(sdata);
- cancel_work_sync(&sdata->csa_finalize_work);
-
- cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
-- if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
-+ if (is_multicast_ether_addr(hdr->addr1))
- return 0;
-
-- return ieee80211_is_robust_mgmt_frame(hdr);
-+ return ieee80211_is_robust_mgmt_frame(skb);
+- local_bh_disable();
++ else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
+ ieee80211_sta_ps_deliver_uapsd(sta);
+- local_bh_enable();
+- } else
+- clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++ local_bh_enable();
}
+ static int sta_prepare_rate_control(struct ieee80211_local *local,
+@@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
-@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
-- if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
-+ if (!is_multicast_ether_addr(hdr->addr1))
- return 0;
-
-- return ieee80211_is_robust_mgmt_frame(hdr);
-+ return ieee80211_is_robust_mgmt_frame(skb);
- }
-
-
-@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
- if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
- return -1;
-
-- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
-+ if (!ieee80211_is_robust_mgmt_frame(skb))
- return -1; /* not a robust management frame */
-
- mmie = (struct ieee80211_mmie *)
-@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *
- sta->sta.addr, sta->sta.aid);
-
- if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-+ /*
-+ * Clear the flag only if the other one is still set
-+ * so that the TX path won't start TX'ing new frames
-+ * directly ... In the case that the driver flag isn't
-+ * set ieee80211_sta_ps_deliver_wakeup() will clear it.
-+ */
-+ clear_sta_flag(sta, WLAN_STA_PS_STA);
- ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
- sta->sta.addr, sta->sta.aid);
- return;
-@@ -1311,18 +1318,15 @@ ieee80211_rx_h_sta_process(struct ieee80
- !ieee80211_has_morefrags(hdr->frame_control) &&
- !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
- (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
-- rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
-+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-+ /* PM bit is only checked in frames where it isn't reserved,
-+ * in AP mode it's reserved in non-bufferable management frames
-+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
-+ */
-+ (!ieee80211_is_mgmt(hdr->frame_control) ||
-+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
- if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
-- /*
-- * Ignore doze->wake transitions that are
-- * indicated by non-data frames, the standard
-- * is unclear here, but for example going to
-- * PS mode and then scanning would cause a
-- * doze->wake transition for the probe request,
-- * and that is clearly undesirable.
-- */
-- if (ieee80211_is_data(hdr->frame_control) &&
-- !ieee80211_has_pm(hdr->frame_control))
-+ if (!ieee80211_has_pm(hdr->frame_control))
- sta_ps_end(sta);
- } else {
- if (ieee80211_has_pm(hdr->frame_control))
-@@ -1845,8 +1849,7 @@ static int ieee80211_drop_unencrypted_mg
- * having configured keys.
- */
- if (unlikely(ieee80211_is_action(fc) && !rx->key &&
-- ieee80211_is_robust_mgmt_frame(
-- (struct ieee80211_hdr *) rx->skb->data)))
-+ ieee80211_is_robust_mgmt_frame(rx->skb)))
- return -EACCES;
+ spin_lock_init(&sta->lock);
+ spin_lock_init(&sta->ps_lock);
+- INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
++ INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
+ INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
+ mutex_init(&sta->ampdu_mlme.mtx);
+ #ifdef CPTCFG_MAC80211_MESH
+@@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
}
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc,
- if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
- return 0;
-
-- if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
-- skb->data))
-+ if (!ieee80211_is_robust_mgmt_frame(skb))
- return 0;
-
- return 1;
-@@ -478,6 +477,20 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
- sta->sta.addr, sta->sta.aid, ac);
- if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
- purge_old_ps_buffers(tx->local);
+ ieee80211_add_pending_skbs(local, &pending);
+- clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+- clear_sta_flag(sta, WLAN_STA_PS_STA);
+
-+ /* sync with ieee80211_sta_ps_deliver_wakeup */
-+ spin_lock(&sta->ps_lock);
-+ /*
-+ * STA woke up the meantime and all the frames on ps_tx_buf have
-+ * been queued to pending queue. No reordering can happen, go
-+ * ahead and Tx the packet.
-+ */
-+ if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
-+ !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-+ spin_unlock(&sta->ps_lock);
-+ return TX_CONTINUE;
-+ }
++ /* now we're no longer in the deliver code */
++ clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
+
- if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
- struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
- ps_dbg(tx->sdata,
-@@ -492,6 +505,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
- info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
- info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
- skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
-+ spin_unlock(&sta->ps_lock);
-
- if (!timer_pending(&local->sta_cleanup))
- mod_timer(&local->sta_cleanup,
-@@ -525,9 +539,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
-
- /* only deauth, disassoc and action are bufferable MMPDUs */
- if (ieee80211_is_mgmt(hdr->frame_control) &&
-- !ieee80211_is_deauth(hdr->frame_control) &&
-- !ieee80211_is_disassoc(hdr->frame_control) &&
-- !ieee80211_is_action(hdr->frame_control)) {
-+ !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
- if (tx->flags & IEEE80211_TX_UNICAST)
- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
- return TX_CONTINUE;
-@@ -567,7 +579,7 @@ ieee80211_tx_h_select_key(struct ieee802
- tx->key = key;
- else if (ieee80211_is_mgmt(hdr->frame_control) &&
- is_multicast_ether_addr(hdr->addr1) &&
-- ieee80211_is_robust_mgmt_frame(hdr) &&
-+ ieee80211_is_robust_mgmt_frame(tx->skb) &&
- (key = rcu_dereference(tx->sdata->default_mgmt_key)))
- tx->key = key;
- else if (is_multicast_ether_addr(hdr->addr1) &&
-@@ -582,12 +594,12 @@ ieee80211_tx_h_select_key(struct ieee802
- tx->key = NULL;
- else if (tx->skb->protocol == tx->sdata->control_port_protocol)
- tx->key = NULL;
-- else if (ieee80211_is_robust_mgmt_frame(hdr) &&
-+ else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
- !(ieee80211_is_action(hdr->frame_control) &&
- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
- tx->key = NULL;
- else if (ieee80211_is_mgmt(hdr->frame_control) &&
-- !ieee80211_is_robust_mgmt_frame(hdr))
-+ !ieee80211_is_robust_mgmt_frame(tx->skb))
- tx->key = NULL;
- else {
- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
-@@ -878,7 +890,7 @@ static int ieee80211_fragment(struct iee
- }
-
- /* adjust first fragment's length */
-- skb->len = hdrlen + per_fragm;
-+ skb_trim(skb, hdrlen + per_fragm);
- return 0;
- }
-
-@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802
- cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- }
-
-- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+ if (sdata->vif.type == NL80211_IFTYPE_AP)
- sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
- if (!ieee80211_tx_prepare(sdata, &tx, skb))
- break;
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
- if (!ieee80211_is_data(hdr->frame_control) &&
-- !ieee80211_is_robust_mgmt_frame(hdr))
-+ !ieee80211_is_robust_mgmt_frame(skb))
- return RX_CONTINUE;
-
- data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
---- a/net/wireless/ap.c
-+++ b/net/wireless/ap.c
-@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg
- err = rdev_stop_ap(rdev, dev);
- if (!err) {
- wdev->beacon_interval = 0;
-- wdev->channel = NULL;
-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef));
- wdev->ssid_len = 0;
- rdev_set_qos_map(rdev, dev, NULL);
-+ nl80211_send_ap_stopped(wdev);
- }
++ /* The station might have polled and then woken up before we responded,
++ * so clear these flags now to avoid them sticking around.
++ */
++ clear_sta_flag(sta, WLAN_STA_PSPOLL);
++ clear_sta_flag(sta, WLAN_STA_UAPSD);
+ spin_unlock(&sta->ps_lock);
- return err;
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
+ atomic_dec(&ps->num_sta_ps);
+@@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
- rdev->opencount--;
+ trace_api_sta_block_awake(sta->local, pubsta, block);
-- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
-- !rdev->scan_req->notified);
-+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-+ if (WARN_ON(!rdev->scan_req->notified))
-+ rdev->scan_req->aborted = true;
-+ ___cfg80211_scan_done(rdev, false);
+- if (block)
++ if (block) {
+ set_sta_flag(sta, WLAN_STA_PS_DRIVER);
+- else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
+- ieee80211_queue_work(hw, &sta->drv_unblock_wk);
++ return;
++ }
++
++ if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
++ return;
++
++ if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
++ set_sta_flag(sta, WLAN_STA_PS_DELIVER);
++ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++ ieee80211_queue_work(hw, &sta->drv_deliver_wk);
++ } else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
++ test_sta_flag(sta, WLAN_STA_UAPSD)) {
++ /* must be asleep in this case */
++ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++ ieee80211_queue_work(hw, &sta->drv_deliver_wk);
++ } else {
++ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+ }
}
+ EXPORT_SYMBOL(ieee80211_sta_block_awake);
- static int cfg80211_rfkill_set_block(void *data, bool blocked)
-@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
- int i;
- u16 ifmodes = wiphy->interface_modes;
-
-- /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
-- wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
--
- /*
- * There are major locking problems in nl80211/mac80211 for CSA,
- * disable for all drivers until this has been reworked.
-@@ -795,8 +795,6 @@ void cfg80211_leave(struct cfg80211_regi
- default:
- break;
- }
--
-- wdev->beacon_interval = 0;
+@@ -1703,3 +1723,137 @@ u8 sta_info_tx_streams(struct sta_info *
+ return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+ >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
}
-
- static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
-@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call
- break;
- case NETDEV_DOWN:
- cfg80211_update_iface_num(rdev, wdev->iftype, -1);
-- WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
-- !rdev->scan_req->notified);
-+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
-+ if (WARN_ON(!rdev->scan_req->notified))
-+ rdev->scan_req->aborted = true;
-+ ___cfg80211_scan_done(rdev, false);
-+ }
-
- if (WARN_ON(rdev->sched_scan_req &&
- rdev->sched_scan_req->dev == wdev->netdev)) {
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
- struct rb_root bss_tree;
- u32 bss_generation;
- struct cfg80211_scan_request *scan_req; /* protected by RTNL */
-+ struct sk_buff *scan_msg;
- struct cfg80211_sched_scan_request *sched_scan_req;
- unsigned long suspend_at;
- struct work_struct scan_done_wk;
-@@ -210,6 +211,7 @@ struct cfg80211_event {
- } dc;
- struct {
- u8 bssid[ETH_ALEN];
-+ struct ieee80211_channel *channel;
- } ij;
- };
- };
-@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021
- struct net_device *dev, bool nowext);
- int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
- struct net_device *dev, bool nowext);
--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+ struct ieee80211_channel *channel);
- int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev);
-
-@@ -361,7 +364,8 @@ int cfg80211_validate_key_settings(struc
- struct key_params *params, int key_idx,
- bool pairwise, const u8 *mac_addr);
- void __cfg80211_scan_done(struct work_struct *wk);
--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
-+ bool send_message);
- void __cfg80211_sched_scan_results(struct work_struct *wk);
- int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
- bool driver_initiated);
-@@ -441,7 +445,8 @@ static inline unsigned int elapsed_jiffi
- void
- cfg80211_get_chan_state(struct wireless_dev *wdev,
- struct ieee80211_channel **chan,
-- enum cfg80211_chan_mode *chanmode);
-+ enum cfg80211_chan_mode *chanmode,
-+ u8 *radar_detect);
-
- int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
- struct cfg80211_chan_def *chandef);
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_
- * We can then retry with the larger buffer.
- */
- if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
-- !skb->len &&
-+ !skb->len && !state->split &&
- cb->min_dump_alloc < 4096) {
- cb->min_dump_alloc = 4096;
-+ state->split_start = 0;
- rtnl_unlock();
- return 1;
- }
-@@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b
- nla_for_each_nested(nl_txq_params,
- info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
- rem_txq_params) {
-- nla_parse(tb, NL80211_TXQ_ATTR_MAX,
-- nla_data(nl_txq_params),
-- nla_len(nl_txq_params),
-- txq_params_policy);
-+ result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
-+ nla_data(nl_txq_params),
-+ nla_len(nl_txq_params),
-+ txq_params_policy);
-+ if (result)
-+ goto bad_res;
- result = parse_txq_params(tb, &txq_params);
- if (result)
- goto bad_res;
-@@ -3289,7 +3292,7 @@ static int nl80211_start_ap(struct sk_bu
- if (!err) {
- wdev->preset_chandef = params.chandef;
- wdev->beacon_interval = params.beacon_interval;
-- wdev->channel = params.chandef.chan;
-+ wdev->chandef = params.chandef;
- wdev->ssid_len = params.ssid_len;
- memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
- }
-@@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf
-
- nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
- rem_reg_rules) {
-- nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
-- nla_data(nl_reg_rule), nla_len(nl_reg_rule),
-- reg_rule_policy);
-+ r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
-+ nla_data(nl_reg_rule), nla_len(nl_reg_rule),
-+ reg_rule_policy);
-+ if (r)
-+ goto bad_reg;
- r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
- if (r)
- goto bad_reg;
-@@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s
- if (!rdev->ops->scan)
- return -EOPNOTSUPP;
-
-- if (rdev->scan_req) {
-+ if (rdev->scan_req || rdev->scan_msg) {
- err = -EBUSY;
- goto unlock;
- }
-@@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru
- enum ieee80211_band band;
- size_t ie_len;
- struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
-+ s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
-
- if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
- !rdev->ops->sched_scan_start)
-@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
- if (n_ssids > wiphy->max_sched_scan_ssids)
- return -EINVAL;
-
-- if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
-+ /*
-+ * First, count the number of 'real' matchsets. Due to an issue with
-+ * the old implementation, matchsets containing only the RSSI attribute
-+ * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
-+ * RSSI for all matchsets, rather than their own matchset for reporting
-+ * all APs with a strong RSSI. This is needed to be compatible with
-+ * older userspace that treated a matchset with only the RSSI as the
-+ * global RSSI for all other matchsets - if there are other matchsets.
-+ */
-+ if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
- nla_for_each_nested(attr,
- info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
-- tmp)
-- n_match_sets++;
-+ tmp) {
-+ struct nlattr *rssi;
+
-+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-+ nla_data(attr), nla_len(attr),
-+ nl80211_match_policy);
-+ if (err)
-+ return err;
-+ /* add other standalone attributes here */
-+ if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
-+ n_match_sets++;
-+ continue;
-+ }
-+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
-+ if (rssi)
-+ default_match_rssi = nla_get_s32(rssi);
++void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
++{
++ struct ieee80211_sub_if_data *sdata = sta->sdata;
++ struct ieee80211_local *local = sdata->local;
++ struct rate_control_ref *ref = local->rate_ctrl;
++ struct timespec uptime;
++ u64 packets = 0;
++ u32 thr = 0;
++ int i, ac;
++
++ sinfo->generation = sdata->local->sta_generation;
++
++ sinfo->filled = STATION_INFO_INACTIVE_TIME |
++ STATION_INFO_RX_BYTES64 |
++ STATION_INFO_TX_BYTES64 |
++ STATION_INFO_RX_PACKETS |
++ STATION_INFO_TX_PACKETS |
++ STATION_INFO_TX_RETRIES |
++ STATION_INFO_TX_FAILED |
++ STATION_INFO_TX_BITRATE |
++ STATION_INFO_RX_BITRATE |
++ STATION_INFO_RX_DROP_MISC |
++ STATION_INFO_BSS_PARAM |
++ STATION_INFO_CONNECTED_TIME |
++ STATION_INFO_STA_FLAGS |
++ STATION_INFO_BEACON_LOSS_COUNT;
++
++ do_posix_clock_monotonic_gettime(&uptime);
++ sinfo->connected_time = uptime.tv_sec - sta->last_connected;
++
++ sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
++ sinfo->tx_bytes = 0;
++ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
++ sinfo->tx_bytes += sta->tx_bytes[ac];
++ packets += sta->tx_packets[ac];
++ }
++ sinfo->tx_packets = packets;
++ sinfo->rx_bytes = sta->rx_bytes;
++ sinfo->rx_packets = sta->rx_packets;
++ sinfo->tx_retries = sta->tx_retry_count;
++ sinfo->tx_failed = sta->tx_retry_failed;
++ sinfo->rx_dropped_misc = sta->rx_dropped;
++ sinfo->beacon_loss_count = sta->beacon_loss_count;
++
++ if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
++ (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
++ sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
++ if (!local->ops->get_rssi ||
++ drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
++ sinfo->signal = (s8)sta->last_signal;
++ sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
++ }
++ if (sta->chains) {
++ sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
++ STATION_INFO_CHAIN_SIGNAL_AVG;
++
++ sinfo->chains = sta->chains;
++ for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
++ sinfo->chain_signal[i] = sta->chain_signal_last[i];
++ sinfo->chain_signal_avg[i] =
++ (s8) -ewma_read(&sta->chain_signal_avg[i]);
+ }
+ }
+
-+ /* However, if there's no other matchset, add the RSSI one */
-+ if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
-+ n_match_sets = 1;
-
- if (n_match_sets > wiphy->max_match_sets)
- return -EINVAL;
-@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
- tmp) {
- struct nlattr *ssid, *rssi;
-
-- nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-- nla_data(attr), nla_len(attr),
-- nl80211_match_policy);
-+ err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-+ nla_data(attr), nla_len(attr),
-+ nl80211_match_policy);
-+ if (err)
-+ goto out_free;
- ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
- if (ssid) {
-+ if (WARN_ON(i >= n_match_sets)) {
-+ /* this indicates a programming error,
-+ * the loop above should have verified
-+ * things properly
-+ */
-+ err = -EINVAL;
-+ goto out_free;
-+ }
-+
- if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
- err = -EINVAL;
- goto out_free;
-@@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru
- nla_data(ssid), nla_len(ssid));
- request->match_sets[i].ssid.ssid_len =
- nla_len(ssid);
-+ /* special attribute - old implemenation w/a */
-+ request->match_sets[i].rssi_thold =
-+ default_match_rssi;
-+ rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
-+ if (rssi)
-+ request->match_sets[i].rssi_thold =
-+ nla_get_s32(rssi);
- }
-- rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
-- if (rssi)
-- request->rssi_thold = nla_get_u32(rssi);
-- else
-- request->rssi_thold =
-- NL80211_SCAN_RSSI_THOLD_OFF;
- i++;
- }
-+
-+ /* there was no other matchset, so the RSSI one is alone */
-+ if (i == 0)
-+ request->match_sets[0].rssi_thold = default_match_rssi;
++ sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
++ sta_set_rate_info_rx(sta, &sinfo->rxrate);
++
++ if (ieee80211_vif_is_mesh(&sdata->vif)) {
++#ifdef CPTCFG_MAC80211_MESH
++ sinfo->filled |= STATION_INFO_LLID |
++ STATION_INFO_PLID |
++ STATION_INFO_PLINK_STATE |
++ STATION_INFO_LOCAL_PM |
++ STATION_INFO_PEER_PM |
++ STATION_INFO_NONPEER_PM;
++
++ sinfo->llid = sta->llid;
++ sinfo->plid = sta->plid;
++ sinfo->plink_state = sta->plink_state;
++ if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
++ sinfo->filled |= STATION_INFO_T_OFFSET;
++ sinfo->t_offset = sta->t_offset;
++ }
++ sinfo->local_pm = sta->local_pm;
++ sinfo->peer_pm = sta->peer_pm;
++ sinfo->nonpeer_pm = sta->nonpeer_pm;
++#endif
++ }
+
-+ request->min_rssi_thold = INT_MAX;
-+ for (i = 0; i < n_match_sets; i++)
-+ request->min_rssi_thold =
-+ min(request->match_sets[i].rssi_thold,
-+ request->min_rssi_thold);
-+ } else {
-+ request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
- }
-
- if (info->attrs[NL80211_ATTR_IE]) {
-@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection
-
- err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
- if (!err) {
-- wdev->channel = chandef.chan;
-+ wdev->chandef = chandef;
- wdev->cac_started = true;
- wdev->cac_start_time = jiffies;
- }
-@@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s
- * directly to the enum ieee80211_band values used in cfg80211.
- */
- BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
-- nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
-- {
-+ nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
- enum ieee80211_band band = nla_type(tx_rates);
-+ int err;
++ sinfo->bss_param.flags = 0;
++ if (sdata->vif.bss_conf.use_cts_prot)
++ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
++ if (sdata->vif.bss_conf.use_short_preamble)
++ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
++ if (sdata->vif.bss_conf.use_short_slot)
++ sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
++ sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
++ sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
++
++ sinfo->sta_flags.set = 0;
++ sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
++ BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
++ BIT(NL80211_STA_FLAG_WME) |
++ BIT(NL80211_STA_FLAG_MFP) |
++ BIT(NL80211_STA_FLAG_AUTHENTICATED) |
++ BIT(NL80211_STA_FLAG_ASSOCIATED) |
++ BIT(NL80211_STA_FLAG_TDLS_PEER);
++ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
++ if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
++ if (test_sta_flag(sta, WLAN_STA_WME))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
++ if (test_sta_flag(sta, WLAN_STA_MFP))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
++ if (test_sta_flag(sta, WLAN_STA_AUTH))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
++ if (test_sta_flag(sta, WLAN_STA_ASSOC))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
++ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
++
++ /* check if the driver has a SW RC implementation */
++ if (ref && ref->ops->get_expected_throughput)
++ thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
++ else
++ thr = drv_get_expected_throughput(local, &sta->sta);
+
- if (band < 0 || band >= IEEE80211_NUM_BANDS)
- return -EINVAL;
- sband = rdev->wiphy.bands[band];
- if (sband == NULL)
- return -EINVAL;
-- nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
-- nla_len(tx_rates), nl80211_txattr_policy);
-+ err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
-+ nla_len(tx_rates), nl80211_txattr_policy);
-+ if (err)
-+ return err;
- if (tb[NL80211_TXRATE_LEGACY]) {
- mask.control[band].legacy = rateset_to_mask(
- sband,
-@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
- NL80211_MCGRP_SCAN, GFP_KERNEL);
- }
-
--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-- struct wireless_dev *wdev)
-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
-+ struct wireless_dev *wdev, bool aborted)
- {
- struct sk_buff *msg;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
-- return;
-+ return NULL;
-
- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
-- NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
-+ aborted ? NL80211_CMD_SCAN_ABORTED :
-+ NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
- nlmsg_free(msg);
-- return;
-+ return NULL;
- }
-
-- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
-- NL80211_MCGRP_SCAN, GFP_KERNEL);
-+ return msg;
- }
-
--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-- struct wireless_dev *wdev)
-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
-+ struct sk_buff *msg)
- {
-- struct sk_buff *msg;
--
-- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return;
-
-- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
-- NL80211_CMD_SCAN_ABORTED) < 0) {
-- nlmsg_free(msg);
-- return;
-- }
--
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- NL80211_MCGRP_SCAN, GFP_KERNEL);
- }
-@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne
- wdev->iftype != NL80211_IFTYPE_MESH_POINT))
- return;
-
-- wdev->channel = chandef->chan;
-+ wdev->chandef = *chandef;
-+ wdev->preset_chandef = *chandef;
- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
- }
- EXPORT_SYMBOL(cfg80211_ch_switch_notify);
-@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct
- }
- EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
++ if (thr != 0) {
++ sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
++ sinfo->expected_throughput = thr;
++ }
++}
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
+ */
+ #define STA_LOST_PKT_THRESHOLD 50
-+void nl80211_send_ap_stopped(struct wireless_dev *wdev)
++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
+{
-+ struct wiphy *wiphy = wdev->wiphy;
-+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-+ struct sk_buff *msg;
-+ void *hdr;
++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
-+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-+ if (!msg)
++ /* This packet was aggregated but doesn't carry status info */
++ if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
++ !(info->flags & IEEE80211_TX_STAT_AMPDU))
+ return;
+
-+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
-+ if (!hdr)
-+ goto out;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
-+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
-+ goto out;
-+
-+ genlmsg_end(msg, hdr);
++ if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
++ return;
+
-+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
-+ NL80211_MCGRP_MLME, GFP_KERNEL);
-+ return;
-+ out:
-+ nlmsg_free(msg);
++ cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
++ sta->lost_packets, GFP_ATOMIC);
++ sta->lost_packets = 0;
+}
+
- /* initialisation/exit functions */
-
- int nl80211_init(void)
---- a/net/wireless/nl80211.h
-+++ b/net/wireless/nl80211.h
-@@ -8,10 +8,10 @@ void nl80211_exit(void);
- void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
- void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev);
--void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
-- struct wireless_dev *wdev);
--void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
-- struct wireless_dev *wdev);
-+struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
-+ struct wireless_dev *wdev, bool aborted);
-+void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
-+ struct sk_buff *msg);
- void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 cmd);
- void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
-@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg
- enum nl80211_radar_event event,
- struct net_device *netdev, gfp_t gfp);
-
-+void nl80211_send_ap_stopped(struct wireless_dev *wdev);
-+
- void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
-
- #endif /* __NET_WIRELESS_NL80211_H */
---- a/net/wireless/scan.c
-+++ b/net/wireless/scan.c
-@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct
- dev->bss_generation++;
- }
-
--void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
-+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
-+ bool send_message)
+ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- struct cfg80211_scan_request *request;
- struct wireless_dev *wdev;
-+ struct sk_buff *msg;
- #ifdef CPTCFG_CFG80211_WEXT
- union iwreq_data wrqu;
- #endif
-
- ASSERT_RTNL();
-
-- request = rdev->scan_req;
-+ if (rdev->scan_msg) {
-+ nl80211_send_scan_result(rdev, rdev->scan_msg);
-+ rdev->scan_msg = NULL;
-+ return;
-+ }
+ struct sk_buff *skb2;
+@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
+ if (info->flags & IEEE80211_TX_STAT_ACK) {
+ if (sta->lost_packets)
+ sta->lost_packets = 0;
+- } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
+- cfg80211_cqm_pktloss_notify(sta->sdata->dev,
+- sta->sta.addr,
+- sta->lost_packets,
+- GFP_ATOMIC);
+- sta->lost_packets = 0;
++ } else {
++ ieee80211_lost_packet(sta, skb);
+ }
+ }
-+ request = rdev->scan_req;
- if (!request)
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
return;
-
-@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
- if (wdev->netdev)
- cfg80211_sme_scan_done(wdev->netdev);
-
-- if (request->aborted) {
-- nl80211_send_scan_aborted(rdev, wdev);
-- } else {
-- if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
-- /* flush entries from previous scans */
-- spin_lock_bh(&rdev->bss_lock);
-- __cfg80211_bss_expire(rdev, request->scan_start);
-- spin_unlock_bh(&rdev->bss_lock);
-- }
-- nl80211_send_scan_done(rdev, wdev);
-+ if (!request->aborted &&
-+ request->flags & NL80211_SCAN_FLAG_FLUSH) {
-+ /* flush entries from previous scans */
-+ spin_lock_bh(&rdev->bss_lock);
-+ __cfg80211_bss_expire(rdev, request->scan_start);
-+ spin_unlock_bh(&rdev->bss_lock);
}
-+ msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
-+
- #ifdef CPTCFG_CFG80211_WEXT
- if (wdev->netdev && !request->aborted) {
- memset(&wrqu, 0, sizeof(wrqu));
-@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
-
- rdev->scan_req = NULL;
- kfree(request);
-+
-+ if (!send_message)
-+ rdev->scan_msg = msg;
-+ else
-+ nl80211_send_scan_result(rdev, msg);
++ set_sta_flag(sta, WLAN_STA_PS_DELIVER);
++ clear_sta_flag(sta, WLAN_STA_PS_STA);
+ ieee80211_sta_ps_deliver_wakeup(sta);
}
- void __cfg80211_scan_done(struct work_struct *wk)
-@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
- scan_done_wk);
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
+ WLAN_STA_TOFFSET_KNOWN,
+ WLAN_STA_MPSP_OWNER,
+ WLAN_STA_MPSP_RECIPIENT,
++ WLAN_STA_PS_DELIVER,
+ };
- rtnl_lock();
-- ___cfg80211_scan_done(rdev);
-+ ___cfg80211_scan_done(rdev, true);
- rtnl_unlock();
- }
+ #define ADDBA_RESP_INTERVAL HZ
+@@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
+ * @last_rx_rate_vht_nss: rx status nss of last data packet
+ * @lock: used for locking all fields that require locking, see comments
+ * in the header file.
+- * @drv_unblock_wk: used for driver PS unblocking
++ * @drv_deliver_wk: used for delivering frames after driver PS unblocking
+ * @listen_interval: listen interval of this station, when we're acting as AP
+ * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
+ * @ps_lock: used for powersave (when mac80211 is the AP) related locking
+@@ -278,7 +279,6 @@ struct ieee80211_tx_latency_stat {
+ * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
+ * @rx_packets: Number of MSDUs received from this STA
+ * @rx_bytes: Number of bytes received from this STA
+- * @wep_weak_iv_count: number of weak WEP IVs received from this station
+ * @last_rx: time (in jiffies) when last frame was received from this STA
+ * @last_connected: time (in seconds) when a station got connected
+ * @num_duplicates: number of duplicate frames received from this STA
+@@ -345,7 +345,7 @@ struct sta_info {
+ void *rate_ctrl_priv;
+ spinlock_t lock;
+
+- struct work_struct drv_unblock_wk;
++ struct work_struct drv_deliver_wk;
+
+ u16 listen_interval;
+
+@@ -367,7 +367,6 @@ struct sta_info {
+ /* Updated from RX path only, no locking requirements */
+ unsigned long rx_packets;
+ u64 rx_bytes;
+- unsigned long wep_weak_iv_count;
+ unsigned long last_rx;
+ long last_connected;
+ unsigned long num_duplicates;
+@@ -628,6 +627,8 @@ void sta_set_rate_info_tx(struct sta_inf
+ struct rate_info *rinfo);
+ void sta_set_rate_info_rx(struct sta_info *sta,
+ struct rate_info *rinfo);
++void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
++
+ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
+ unsigned long exp_time);
+ u8 sta_info_tx_streams(struct sta_info *sta);
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
+ return TX_CONTINUE;
-@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
+ if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
+- test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
++ test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
++ test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
+ !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
+ int ac = skb_get_queue_mapping(tx->skb);
-- if (rdev->scan_req) {
-+ if (rdev->scan_req || rdev->scan_msg) {
- err = -EBUSY;
- goto out;
- }
-@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
-- if (rdev->scan_req)
-+ if (rdev->scan_req || rdev->scan_msg)
- return -EAGAIN;
-
- res = ieee80211_scan_results(rdev, info, extra, data->length);
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
- ASSERT_RDEV_LOCK(rdev);
- ASSERT_WDEV_LOCK(wdev);
-
-- if (rdev->scan_req)
-+ if (rdev->scan_req || rdev->scan_msg)
- return -EBUSY;
-
- if (wdev->conn->params.channel)
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct
- }
+@@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
+ * ahead and Tx the packet.
+ */
+ if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
+- !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
++ !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
++ !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
+ spin_unlock(&sta->ps_lock);
+ return TX_CONTINUE;
+ }
+@@ -1618,12 +1620,12 @@ netdev_tx_t ieee80211_monitor_start_xmit
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_chanctx_conf *chanctx_conf;
+- struct ieee80211_channel *chan;
+ struct ieee80211_radiotap_header *prthdr =
+ (struct ieee80211_radiotap_header *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr;
+ struct ieee80211_sub_if_data *tmp_sdata, *sdata;
++ struct cfg80211_chan_def *chandef;
+ u16 len_rthdr;
+ int hdrlen;
- ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
-- sdata->vif.csa_active = true;
+@@ -1721,9 +1723,9 @@ netdev_tx_t ieee80211_monitor_start_xmit
+ }
- mutex_lock(&local->chanctx_mtx);
- if (local->use_chanctx) {
-@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct
- mutex_unlock(&local->chanctx_mtx);
+ if (chanctx_conf)
+- chan = chanctx_conf->def.chan;
++ chandef = &chanctx_conf->def;
+ else if (!local->use_chanctx)
+- chan = local->_oper_chandef.chan;
++ chandef = &local->_oper_chandef;
+ else
+ goto fail_rcu;
- sdata->csa_chandef = csa_ie.chandef;
-+ sdata->vif.csa_active = true;
+@@ -1743,10 +1745,11 @@ netdev_tx_t ieee80211_monitor_start_xmit
+ * radar detection by itself. We can do that later by adding a
+ * monitor flag interfaces used for AP support.
+ */
+- if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)))
++ if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
++ sdata->vif.type))
+ goto fail_rcu;
- if (csa_ie.mode)
- ieee80211_stop_queues_by_reason(&local->hw,
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(
- {
- struct ieee80211_sub_if_data *sdata;
+- ieee80211_xmit(sdata, skb, chan->band);
++ ieee80211_xmit(sdata, skb, chandef->chan->band);
+ rcu_read_unlock();
-+ lockdep_assert_held(&local->mtx);
-+
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->radar_required) {
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st
- }
+ return NETDEV_TX_OK;
+@@ -2425,7 +2428,7 @@ static void ieee80211_set_csa(struct iee
+ u8 *beacon_data;
+ size_t beacon_data_len;
+ int i;
+- u8 count = sdata->csa_current_counter;
++ u8 count = beacon->csa_current_counter;
- mutex_lock(&local->mtx);
-- ieee80211_vif_release_channel(sdata);
- if (ieee80211_vif_use_channel(sdata, &chandef,
- ifibss->fixed_channel ?
- IEEE80211_CHANCTX_SHARED :
-@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st
- mutex_unlock(&local->mtx);
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP:
+@@ -2444,46 +2447,54 @@ static void ieee80211_set_csa(struct iee
return;
}
-+ sdata->radar_required = radar_required;
- mutex_unlock(&local->mtx);
-
- memcpy(ifibss->bssid, bssid, ETH_ALEN);
-@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st
- rcu_assign_pointer(ifibss->presp, presp);
- mgmt = (void *)presp->head;
-
-- sdata->radar_required = radar_required;
- sdata->vif.bss_conf.enable_beacon = true;
- sdata->vif.bss_conf.beacon_int = beacon_int;
- sdata->vif.bss_conf.basic_rates = basic_rates;
-@@ -386,7 +385,7 @@ static void __ieee80211_sta_join_ibss(st
- presp->head_len, 0, GFP_KERNEL);
- cfg80211_put_bss(local->hw.wiphy, bss);
- netif_carrier_on(sdata->dev);
-- cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
-+ cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
- }
-
- static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
-@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct
- int err;
- u32 sta_flags;
-+ sdata_assert_lock(sdata);
-+
- sta_flags = IEEE80211_STA_DISABLE_VHT;
- switch (ifibss->chandef.width) {
- case NL80211_CHAN_WIDTH_5:
-@@ -1471,6 +1472,11 @@ static void ieee80211_rx_mgmt_probe_req(
- memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
- ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
- IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
++ rcu_read_lock();
+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
+- u16 counter_offset_beacon =
+- sdata->csa_counter_offset_beacon[i];
+- u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
+-
+- if (counter_offset_beacon) {
+- if (WARN_ON(counter_offset_beacon >= beacon_data_len))
+- return;
+-
+- beacon_data[counter_offset_beacon] = count;
+- }
+-
+- if (sdata->vif.type == NL80211_IFTYPE_AP &&
+- counter_offset_presp) {
+- rcu_read_lock();
+- resp = rcu_dereference(sdata->u.ap.probe_resp);
++ resp = rcu_dereference(sdata->u.ap.probe_resp);
+
+- /* If nl80211 accepted the offset, this should
+- * not happen.
+- */
+- if (WARN_ON(!resp)) {
++ if (beacon->csa_counter_offsets[i]) {
++ if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >=
++ beacon_data_len)) {
+ rcu_read_unlock();
+ return;
+ }
+- resp->data[counter_offset_presp] = count;
+- rcu_read_unlock();
+
-+ /* avoid excessive retries for probe request to wildcard SSIDs */
-+ if (pos[1] == 0)
-+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
++ beacon_data[beacon->csa_counter_offsets[i]] = count;
+ }
+
- ieee80211_tx_skb(sdata, skb);
++ if (sdata->vif.type == NL80211_IFTYPE_AP && resp &&
++ resp->csa_counter_offsets)
++ resp->data[resp->csa_counter_offsets[i]] = count;
+ }
++ rcu_read_unlock();
}
---- a/net/mac80211/mesh.c
-+++ b/net/mac80211/mesh.c
-@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct
- if (!ifmsh->mesh_id)
- return false;
+ u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
+ {
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
++ struct beacon_data *beacon = NULL;
++ u8 count = 0;
++
++ rcu_read_lock();
++
++ if (sdata->vif.type == NL80211_IFTYPE_AP)
++ beacon = rcu_dereference(sdata->u.ap.beacon);
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ beacon = rcu_dereference(sdata->u.ibss.presp);
++ else if (ieee80211_vif_is_mesh(&sdata->vif))
++ beacon = rcu_dereference(sdata->u.mesh.beacon);
++
++ if (!beacon)
++ goto unlock;
+
+- sdata->csa_current_counter--;
++ beacon->csa_current_counter--;
+
+ /* the counter should never reach 0 */
+- WARN_ON(!sdata->csa_current_counter);
++ WARN_ON_ONCE(!beacon->csa_current_counter);
++ count = beacon->csa_current_counter;
+
+- return sdata->csa_current_counter;
++unlock:
++ rcu_read_unlock();
++ return count;
+ }
+ EXPORT_SYMBOL(ieee80211_csa_update_counter);
-+ sdata_assert_lock(sdata);
-+
- sta_flags = IEEE80211_STA_DISABLE_VHT;
- switch (sdata->vif.bss_conf.chandef.width) {
- case NL80211_CHAN_WIDTH_20_NOHT:
---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
-+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
-@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
- struct net_device *ndev = ifp->ndev;
- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
-+ struct ieee80211_channel *chan;
- s32 err = 0;
-
- if (ifp->vif->mode == WL_MODE_AP) {
-@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf
- } else if (brcmf_is_linkup(e)) {
- brcmf_dbg(CONN, "Linkup\n");
- if (brcmf_is_ibssmode(ifp->vif)) {
-+ chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
- memcpy(profile->bssid, e->addr, ETH_ALEN);
- wl_inform_ibss(cfg, ndev, e->addr);
-- cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
-+ cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
- clear_bit(BRCMF_VIF_STATUS_CONNECTING,
- &ifp->vif->sme_state);
- set_bit(BRCMF_VIF_STATUS_CONNECTED,
---- a/drivers/net/wireless/libertas/cfg.c
-+++ b/drivers/net/wireless/libertas/cfg.c
-@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri
- memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
- priv->wdev->ssid_len = params->ssid_len;
-
-- cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
-+ cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
-+ GFP_KERNEL);
-
- /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
- priv->connect_status = LBS_CONNECTED;
---- a/drivers/net/wireless/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/mwifiex/cfg80211.c
-@@ -1881,7 +1881,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy
- params->privacy);
- done:
- if (!ret) {
-- cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
-+ cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
-+ params->chandef.chan, GFP_KERNEL);
- dev_dbg(priv->adapter->dev,
- "info: joined/created adhoc network with bssid"
- " %pM successfully\n", priv->cfg_bssid);
---- a/drivers/net/wireless/rndis_wlan.c
-+++ b/drivers/net/wireless/rndis_wlan.c
-@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(s
- bssid, req_ie, req_ie_len,
- resp_ie, resp_ie_len, GFP_KERNEL);
- } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
-- cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
-+ cfg80211_ibss_joined(usbdev->net, bssid,
-+ get_current_channel(usbdev, NULL),
-+ GFP_KERNEL);
-
- kfree(info);
-
---- a/net/wireless/ibss.c
-+++ b/net/wireless/ibss.c
-@@ -14,7 +14,8 @@
- #include "rdev-ops.h"
+@@ -2493,7 +2504,6 @@ bool ieee80211_csa_is_complete(struct ie
+ struct beacon_data *beacon = NULL;
+ u8 *beacon_data;
+ size_t beacon_data_len;
+- int counter_beacon = sdata->csa_counter_offset_beacon[0];
+ int ret = false;
+ if (!ieee80211_sdata_running(sdata))
+@@ -2531,10 +2541,13 @@ bool ieee80211_csa_is_complete(struct ie
+ goto out;
+ }
--void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
-+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+ struct ieee80211_channel *channel)
- {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_bss *bss;
-@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d
- if (!wdev->ssid_len)
- return;
+- if (WARN_ON(counter_beacon > beacon_data_len))
++ if (!beacon->csa_counter_offsets[0])
++ goto out;
++
++ if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len))
+ goto out;
-- bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
-- wdev->ssid, wdev->ssid_len,
-+ bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
- WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
+- if (beacon_data[counter_beacon] == 1)
++ if (beacon_data[beacon->csa_counter_offsets[0]] == 1)
+ ret = true;
+ out:
+ rcu_read_unlock();
+@@ -2550,6 +2563,7 @@ __ieee80211_beacon_get(struct ieee80211_
+ bool is_template)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
++ struct beacon_data *beacon = NULL;
+ struct sk_buff *skb = NULL;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_sub_if_data *sdata = NULL;
+@@ -2571,10 +2585,10 @@ __ieee80211_beacon_get(struct ieee80211_
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP) {
+ struct ieee80211_if_ap *ap = &sdata->u.ap;
+- struct beacon_data *beacon = rcu_dereference(ap->beacon);
+
++ beacon = rcu_dereference(ap->beacon);
+ if (beacon) {
+- if (sdata->vif.csa_active) {
++ if (beacon->csa_counter_offsets[0]) {
+ if (!is_template)
+ ieee80211_csa_update_counter(vif);
+
+@@ -2615,37 +2629,37 @@ __ieee80211_beacon_get(struct ieee80211_
+ } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ struct ieee80211_hdr *hdr;
+- struct beacon_data *presp = rcu_dereference(ifibss->presp);
+
+- if (!presp)
++ beacon = rcu_dereference(ifibss->presp);
++ if (!beacon)
+ goto out;
- if (WARN_ON(!bss))
-@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d
- #endif
- }
+- if (sdata->vif.csa_active) {
++ if (beacon->csa_counter_offsets[0]) {
+ if (!is_template)
+ ieee80211_csa_update_counter(vif);
--void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
-+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
-+ struct ieee80211_channel *channel, gfp_t gfp)
- {
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
- struct cfg80211_event *ev;
- unsigned long flags;
+- ieee80211_set_csa(sdata, presp);
++ ieee80211_set_csa(sdata, beacon);
+ }
-- trace_cfg80211_ibss_joined(dev, bssid);
-+ trace_cfg80211_ibss_joined(dev, bssid, channel);
-+
-+ if (WARN_ON(!channel))
-+ return;
+- skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
++ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
+ local->hw.extra_beacon_tailroom);
+ if (!skb)
+ goto out;
+ skb_reserve(skb, local->tx_headroom);
+- memcpy(skb_put(skb, presp->head_len), presp->head,
+- presp->head_len);
++ memcpy(skb_put(skb, beacon->head_len), beacon->head,
++ beacon->head_len);
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_BEACON);
+ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+- struct beacon_data *bcn = rcu_dereference(ifmsh->beacon);
+
+- if (!bcn)
++ beacon = rcu_dereference(ifmsh->beacon);
++ if (!beacon)
+ goto out;
- ev = kzalloc(sizeof(*ev), gfp);
- if (!ev)
- return;
+- if (sdata->vif.csa_active) {
++ if (beacon->csa_counter_offsets[0]) {
+ if (!is_template)
+ /* TODO: For mesh csa_counter is in TU, so
+ * decrementing it by one isn't correct, but
+@@ -2654,40 +2668,42 @@ __ieee80211_beacon_get(struct ieee80211_
+ */
+ ieee80211_csa_update_counter(vif);
- ev->type = EVENT_IBSS_JOINED;
-- memcpy(ev->cr.bssid, bssid, ETH_ALEN);
-+ memcpy(ev->ij.bssid, bssid, ETH_ALEN);
-+ ev->ij.channel = channel;
+- ieee80211_set_csa(sdata, bcn);
++ ieee80211_set_csa(sdata, beacon);
+ }
- spin_lock_irqsave(&wdev->event_lock, flags);
- list_add_tail(&ev->list, &wdev->event_list);
-@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211
+ if (ifmsh->sync_ops)
+- ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
++ ifmsh->sync_ops->adjust_tbtt(sdata, beacon);
+
+ skb = dev_alloc_skb(local->tx_headroom +
+- bcn->head_len +
++ beacon->head_len +
+ 256 + /* TIM IE */
+- bcn->tail_len +
++ beacon->tail_len +
+ local->hw.extra_beacon_tailroom);
+ if (!skb)
+ goto out;
+ skb_reserve(skb, local->tx_headroom);
+- memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);
++ memcpy(skb_put(skb, beacon->head_len), beacon->head,
++ beacon->head_len);
+ ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
+
+ if (offs) {
+- offs->tim_offset = bcn->head_len;
+- offs->tim_length = skb->len - bcn->head_len;
++ offs->tim_offset = beacon->head_len;
++ offs->tim_length = skb->len - beacon->head_len;
+ }
- wdev->ibss_fixed = params->channel_fixed;
- wdev->ibss_dfs_possible = params->userspace_handles_dfs;
-+ wdev->chandef = params->chandef;
- #ifdef CPTCFG_CFG80211_WEXT
- wdev->wext.ibss.chandef = params->chandef;
- #endif
-@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct
-
- wdev->current_bss = NULL;
- wdev->ssid_len = 0;
-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef));
- #ifdef CPTCFG_CFG80211_WEXT
- if (!nowext)
- wdev->wext.ibss.ssid_len = 0;
---- a/net/wireless/trace.h
-+++ b/net/wireless/trace.h
-@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
- TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
- );
+- memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);
++ memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
++ beacon->tail_len);
+ } else {
+ WARN_ON(1);
+ goto out;
+ }
--DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
-- TP_PROTO(struct net_device *netdev, const u8 *addr),
-- TP_ARGS(netdev, addr)
--);
--
- DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
- TP_PROTO(struct net_device *netdev, const u8 *addr),
- TP_ARGS(netdev, addr)
-@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r
- TP_ARGS(netdev, addr)
- );
+ /* CSA offsets */
+- if (offs) {
++ if (offs && beacon) {
+ int i;
+
+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
+- u16 csa_off = sdata->csa_counter_offset_beacon[i];
++ u16 csa_off = beacon->csa_counter_offsets[i];
+
+ if (!csa_off)
+ continue;
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offse
+ return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
+ }
-+TRACE_EVENT(cfg80211_ibss_joined,
-+ TP_PROTO(struct net_device *netdev, const u8 *bssid,
-+ struct ieee80211_channel *channel),
-+ TP_ARGS(netdev, bssid, channel),
-+ TP_STRUCT__entry(
-+ NETDEV_ENTRY
-+ MAC_ENTRY(bssid)
-+ CHAN_ENTRY
-+ ),
-+ TP_fast_assign(
-+ NETDEV_ASSIGN;
-+ MAC_ASSIGN(bssid, bssid);
-+ CHAN_ASSIGN(channel);
-+ ),
-+ TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
-+ NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
-+);
++static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
++{
++ struct data_queue *queue = rt2x00dev->bcn;
++ struct queue_entry *entry;
++ int i, bcn_num = 0;
++ u64 off, reg = 0;
++ u32 bssid_dw1;
+
- TRACE_EVENT(cfg80211_probe_status,
- TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
- bool acked),
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct
- ev->dc.reason, true);
- break;
- case EVENT_IBSS_JOINED:
-- __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
-+ __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
-+ ev->ij.channel);
- break;
- }
- wdev_unlock(wdev);
-@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct
- */
- mutex_lock_nested(&wdev_iter->mtx, 1);
- __acquire(wdev_iter->mtx);
-- cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
-+ cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
- wdev_unlock(wdev_iter);
-
- switch (chmode) {
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct
- void
- cfg80211_get_chan_state(struct wireless_dev *wdev,
- struct ieee80211_channel **chan,
-- enum cfg80211_chan_mode *chanmode)
-+ enum cfg80211_chan_mode *chanmode,
-+ u8 *radar_detect)
- {
- *chan = NULL;
- *chanmode = CHAN_MODE_UNDEFINED;
-@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_
- !wdev->ibss_dfs_possible)
- ? CHAN_MODE_SHARED
- : CHAN_MODE_EXCLUSIVE;
++ /*
++ * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
++ */
++ for (i = 0; i < queue->limit; i++) {
++ entry = &queue->entries[i];
++ if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
++ continue;
++ off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
++ reg |= off << (8 * bcn_num);
++ bcn_num++;
++ }
+
-+ /* consider worst-case - IBSS can try to return to the
-+ * original user-specified channel as creator */
-+ if (wdev->ibss_dfs_possible)
-+ *radar_detect |= BIT(wdev->chandef.width);
- return;
- }
- break;
-@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- if (wdev->cac_started) {
-- *chan = wdev->channel;
-+ *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
-+ *radar_detect |= BIT(wdev->chandef.width);
- } else if (wdev->beacon_interval) {
-- *chan = wdev->channel;
-+ *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
++ WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+
-+ if (cfg80211_chandef_dfs_required(wdev->wiphy,
-+ &wdev->chandef))
-+ *radar_detect |= BIT(wdev->chandef.width);
- }
- return;
- case NL80211_IFTYPE_MESH_POINT:
- if (wdev->mesh_id_len) {
-- *chan = wdev->channel;
-+ *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
++ rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
++ rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
++
++ /*
++ * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
++ */
++ rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
++ rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
++ bcn_num > 0 ? bcn_num - 1 : 0);
++ rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
++}
++
+ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
+ {
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+@@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
+
+ rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
+ entry->skb->len + padding_len);
++ __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
-+ if (cfg80211_chandef_dfs_required(wdev->wiphy,
-+ &wdev->chandef))
-+ *radar_detect |= BIT(wdev->chandef.width);
- }
- return;
- case NL80211_IFTYPE_MONITOR:
---- a/net/wireless/mesh.c
-+++ b/net/wireless/mesh.c
-@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211
- if (!err) {
- memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
- wdev->mesh_id_len = setup->mesh_id_len;
-- wdev->channel = setup->chandef.chan;
-+ wdev->chandef = setup->chandef;
- }
++ /*
++ * Change global beacons settings.
++ */
++ rt2800_update_beacons_setup(rt2x00dev);
- return err;
-@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg
- err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
- chandef->chan);
- if (!err)
-- wdev->channel = chandef->chan;
-+ wdev->chandef = *chandef;
+ /*
+ * Restore beaconing state.
+@@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
+ * Clear beacon.
+ */
+ rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
++ __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
- return err;
- }
-@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct
- err = rdev_leave_mesh(rdev, dev);
- if (!err) {
- wdev->mesh_id_len = 0;
-- wdev->channel = NULL;
-+ memset(&wdev->chandef, 0, sizeof(wdev->chandef));
- rdev_set_qos_map(rdev, dev, NULL);
- }
+ /*
++ * Change global beacons settings.
++ */
++ rt2800_update_beacons_setup(rt2x00dev);
++ /*
+ * Restore beaconing state.
+ */
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+@@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_de
+ if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
+ reg = le32_to_cpu(conf->bssid[1]);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
+- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
++ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
+ conf->bssid[1] = cpu_to_le32(reg);
+ }
---- a/net/wireless/mlme.c
-+++ b/net/wireless/mlme.c
-@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic
- if (WARN_ON(!wdev->cac_started))
- return;
+@@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct
+ if (ret)
+ return ret;
+
+- rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
+- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
+- rt2800_get_beacon_offset(rt2x00dev, 0));
+- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
+- rt2800_get_beacon_offset(rt2x00dev, 1));
+- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
+- rt2800_get_beacon_offset(rt2x00dev, 2));
+- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
+- rt2800_get_beacon_offset(rt2x00dev, 3));
+- rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
+-
+- rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
+- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
+- rt2800_get_beacon_offset(rt2x00dev, 4));
+- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
+- rt2800_get_beacon_offset(rt2x00dev, 5));
+- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
+- rt2800_get_beacon_offset(rt2x00dev, 6));
+- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
+- rt2800_get_beacon_offset(rt2x00dev, 7));
+- rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
+-
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-- if (WARN_ON(!wdev->channel))
-+ if (WARN_ON(!wdev->chandef.chan))
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_ite
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- switch (event) {
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(
- break;
- }
- }
-+
-+ if (is2GHz && !twiceMaxEdgePower)
-+ twiceMaxEdgePower = 60;
-+
- return twiceMaxEdgePower;
+- if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
++ if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
++ mutex_lock(&intf->beacon_skb_mutex);
+ rt2x00queue_update_beacon(rt2x00dev, vif);
++ mutex_unlock(&intf->beacon_skb_mutex);
++ }
}
---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-@@ -23,10 +23,11 @@
- #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
- #define MAX_MAG_DELTA 11
- #define MAX_PHS_DELTA 10
-+#define MAXIQCAL 3
-
- struct coeff {
-- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
-- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
-+ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
-+ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
- int iqc_coeff[2];
- };
+ static void rt2x00lib_intf_scheduled(struct work_struct *work)
+@@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(
+ * never be called for USB devices.
+ */
+ WARN_ON(rt2x00_is_usb(rt2x00dev));
+- rt2x00queue_update_beacon_locked(rt2x00dev, vif);
++ rt2x00queue_update_beacon(rt2x00dev, vif);
+ }
-@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc
- if (q_q_coff > 63)
- q_q_coff = 63;
+ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -624,25 +624,24 @@ void rt2x00mac_bss_info_changed(struct i
+ * Start/stop beaconing.
+ */
+ if (changes & BSS_CHANGED_BEACON_ENABLED) {
++ mutex_lock(&intf->beacon_skb_mutex);
+ if (!bss_conf->enable_beacon && intf->enable_beacon) {
+ rt2x00dev->intf_beaconing--;
+ intf->enable_beacon = false;
+- /*
+- * Clear beacon in the H/W for this vif. This is needed
+- * to disable beaconing on this particular interface
+- * and keep it running on other interfaces.
+- */
+- rt2x00queue_clear_beacon(rt2x00dev, vif);
-- iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
-+ iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
+ if (rt2x00dev->intf_beaconing == 0) {
+ /*
+ * Last beaconing interface disabled
+ * -> stop beacon queue.
+ */
+- mutex_lock(&intf->beacon_skb_mutex);
+ rt2x00queue_stop_queue(rt2x00dev->bcn);
+- mutex_unlock(&intf->beacon_skb_mutex);
+ }
++ /*
++ * Clear beacon in the H/W for this vif. This is needed
++ * to disable beaconing on this particular interface
++ * and keep it running on other interfaces.
++ */
++ rt2x00queue_clear_beacon(rt2x00dev, vif);
+ } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
+ rt2x00dev->intf_beaconing++;
+ intf->enable_beacon = true;
+@@ -658,11 +657,10 @@ void rt2x00mac_bss_info_changed(struct i
+ * First beaconing interface enabled
+ * -> start beacon queue.
+ */
+- mutex_lock(&intf->beacon_skb_mutex);
+ rt2x00queue_start_queue(rt2x00dev->bcn);
+- mutex_unlock(&intf->beacon_skb_mutex);
+ }
+ }
++ mutex_unlock(&intf->beacon_skb_mutex);
+ }
- ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
- chain_idx, iqc_coeff[0]);
-@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc
- if (q_q_coff > 63)
- q_q_coff = 63;
+ /*
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x
+ if (unlikely(!intf->beacon))
+ return -ENOBUFS;
-- iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
-+ iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
+- mutex_lock(&intf->beacon_skb_mutex);
+-
+ /*
+ * Clean up the beacon skb.
+ */
+@@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x
+ if (rt2x00dev->ops->lib->clear_beacon)
+ rt2x00dev->ops->lib->clear_beacon(intf->beacon);
- ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
- chain_idx, iqc_coeff[1]);
-@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc
- return true;
+- mutex_unlock(&intf->beacon_skb_mutex);
+-
+ return 0;
}
--static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
-+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
-+ int nmeasurement,
- int max_delta)
+-int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+- struct ieee80211_vif *vif)
++int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_vif *vif)
{
- int mp_max = -64, max_idx = 0;
-@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int
-
- /* find min/max mismatch across all calibrated gains */
- for (i = 0; i < nmeasurement; i++) {
-- if (mp_coeff[i] > mp_max) {
-- mp_max = mp_coeff[i];
-+ if (mp_coeff[i][0] > mp_max) {
-+ mp_max = mp_coeff[i][0];
- max_idx = i;
-- } else if (mp_coeff[i] < mp_min) {
-- mp_min = mp_coeff[i];
-+ } else if (mp_coeff[i][0] < mp_min) {
-+ mp_min = mp_coeff[i][0];
- min_idx = i;
- }
- }
+ struct rt2x00_intf *intf = vif_to_intf(vif);
+ struct skb_frame_desc *skbdesc;
+@@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str
- /* find average (exclude max abs value) */
- for (i = 0; i < nmeasurement; i++) {
-- if ((abs(mp_coeff[i]) < abs(mp_max)) ||
-- (abs(mp_coeff[i]) < abs(mp_min))) {
-- mp_avg += mp_coeff[i];
-+ if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
-+ (abs(mp_coeff[i][0]) < abs(mp_min))) {
-+ mp_avg += mp_coeff[i][0];
- mp_count++;
- }
- }
-@@ -873,7 +875,7 @@ static void ar9003_hw_detect_outlier(int
- if (mp_count)
- mp_avg /= mp_count;
- else
-- mp_avg = mp_coeff[nmeasurement - 1];
-+ mp_avg = mp_coeff[nmeasurement - 1][0];
-
- /* detect outlier */
- if (abs(mp_max - mp_min) > max_delta) {
-@@ -882,15 +884,16 @@ static void ar9003_hw_detect_outlier(int
- else
- outlier_idx = min_idx;
-
-- mp_coeff[outlier_idx] = mp_avg;
-+ mp_coeff[outlier_idx][0] = mp_avg;
- }
}
--static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
-- struct coeff *coeff,
-- bool is_reusable)
-+static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
-+ struct coeff *coeff,
-+ bool is_reusable)
- {
- int i, im, nmeasurement;
-+ int magnitude, phase;
- u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
- struct ath9k_hw_cal_data *caldata = ah->caldata;
-
-@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_
- if (nmeasurement > MAX_MEASUREMENT)
- nmeasurement = MAX_MEASUREMENT;
-
-- /* detect outlier only if nmeasurement > 1 */
-- if (nmeasurement > 1) {
-- /* Detect magnitude outlier */
-- ar9003_hw_detect_outlier(coeff->mag_coeff[i],
-- nmeasurement, MAX_MAG_DELTA);
+-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+- struct ieee80211_vif *vif)
+-{
+- struct rt2x00_intf *intf = vif_to_intf(vif);
+- int ret;
-
-- /* Detect phase outlier */
-- ar9003_hw_detect_outlier(coeff->phs_coeff[i],
-- nmeasurement, MAX_PHS_DELTA);
-+ /*
-+ * Skip normal outlier detection for AR9550.
-+ */
-+ if (!AR_SREV_9550(ah)) {
-+ /* detect outlier only if nmeasurement > 1 */
-+ if (nmeasurement > 1) {
-+ /* Detect magnitude outlier */
-+ ar9003_hw_detect_outlier(coeff->mag_coeff[i],
-+ nmeasurement,
-+ MAX_MAG_DELTA);
-+
-+ /* Detect phase outlier */
-+ ar9003_hw_detect_outlier(coeff->phs_coeff[i],
-+ nmeasurement,
-+ MAX_PHS_DELTA);
-+ }
- }
-
- for (im = 0; im < nmeasurement; im++) {
-+ magnitude = coeff->mag_coeff[i][im][0];
-+ phase = coeff->phs_coeff[i][im][0];
+- mutex_lock(&intf->beacon_skb_mutex);
+- ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
+- mutex_unlock(&intf->beacon_skb_mutex);
+-
+- return ret;
+-}
+-
+ bool rt2x00queue_for_each_entry(struct data_queue *queue,
+ enum queue_index start,
+ enum queue_index end,
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
+@@ -353,6 +353,7 @@ struct txentry_desc {
+ */
+ enum queue_entry_flags {
+ ENTRY_BCN_ASSIGNED,
++ ENTRY_BCN_ENABLED,
+ ENTRY_OWNER_DEVICE_DATA,
+ ENTRY_DATA_PENDING,
+ ENTRY_DATA_IO_FAILED,
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1757,7 +1757,6 @@ out:
+ void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
+ {
+ struct ath_vif *avp = (void *)vif->drv_priv;
+- unsigned long flags;
+ u32 tsf;
-- coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
-- ((coeff->phs_coeff[i][im] & 0x7f) << 7);
-+ coeff->iqc_coeff[0] =
-+ (phase & 0x7f) | ((magnitude & 0x7f) << 7);
+ if (!sc->p2p_ps_timer)
+@@ -1767,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_soft
+ return;
- if ((im % 2) == 0)
- REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
-@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru
- return true;
+ sc->p2p_ps_vif = avp;
+-
+- spin_lock_irqsave(&sc->sc_pm_lock, flags);
+- if (!(sc->ps_flags & PS_BEACON_SYNC)) {
+- tsf = ath9k_hw_gettsf32(sc->sc_ah);
+- ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
+- ath9k_update_p2p_ps_timer(sc, avp);
+- }
+- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
++ tsf = ath9k_hw_gettsf32(sc->sc_ah);
++ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
++ ath9k_update_p2p_ps_timer(sc, avp);
}
--static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
-+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
-+ struct coeff *coeff,
-+ int i, int nmeasurement)
-+{
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ int im, ix, iy, temp;
-+
-+ for (im = 0; im < nmeasurement; im++) {
-+ for (ix = 0; ix < MAXIQCAL - 1; ix++) {
-+ for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
-+ if (coeff->mag_coeff[i][im][iy] <
-+ coeff->mag_coeff[i][im][ix]) {
-+ temp = coeff->mag_coeff[i][im][ix];
-+ coeff->mag_coeff[i][im][ix] =
-+ coeff->mag_coeff[i][im][iy];
-+ coeff->mag_coeff[i][im][iy] = temp;
-+ }
-+ if (coeff->phs_coeff[i][im][iy] <
-+ coeff->phs_coeff[i][im][ix]) {
-+ temp = coeff->phs_coeff[i][im][ix];
-+ coeff->phs_coeff[i][im][ix] =
-+ coeff->phs_coeff[i][im][iy];
-+ coeff->phs_coeff[i][im][iy] = temp;
-+ }
-+ }
-+ }
-+ coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
-+ coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
-+
-+ ath_dbg(common, CALIBRATE,
-+ "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
-+ i, im,
-+ coeff->mag_coeff[i][im][0],
-+ coeff->phs_coeff[i][im][0]);
-+ }
-+}
-+
-+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
-+ struct coeff *coeff,
-+ int iqcal_idx,
-+ int nmeasurement)
-+{
-+ int i;
-+
-+ if ((iqcal_idx + 1) != MAXIQCAL)
-+ return false;
-+
-+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
-+ __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
-+ }
-+
-+ return true;
-+}
-+
-+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
-+ int iqcal_idx,
-+ bool is_reusable)
- {
+ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+@@ -1791,6 +1785,7 @@ static void ath9k_bss_info_changed(struc
+ struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
-@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro
- AR_PHY_CHAN_INFO_TAB_1,
- AR_PHY_CHAN_INFO_TAB_2,
- };
-- struct coeff coeff;
-+ static struct coeff coeff;
- s32 iq_res[6];
- int i, im, j;
-- int nmeasurement;
-+ int nmeasurement = 0;
-+ bool outlier_detect = true;
-
- for (i = 0; i < AR9300_MAX_CHAINS; i++) {
- if (!(ah->txchainmask & (1 << i)))
-@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro
- goto tx_iqcal_fail;
- }
-
-- coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
-- coeff.phs_coeff[i][im] =
-+ coeff.phs_coeff[i][im][iqcal_idx] =
-+ coeff.iqc_coeff[0] & 0x7f;
-+ coeff.mag_coeff[i][im][iqcal_idx] =
- (coeff.iqc_coeff[0] >> 7) & 0x7f;
-
-- if (coeff.mag_coeff[i][im] > 63)
-- coeff.mag_coeff[i][im] -= 128;
-- if (coeff.phs_coeff[i][im] > 63)
-- coeff.phs_coeff[i][im] -= 128;
-+ if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
-+ coeff.mag_coeff[i][im][iqcal_idx] -= 128;
-+ if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
-+ coeff.phs_coeff[i][im][iqcal_idx] -= 128;
- }
+ struct ath_vif *avp = (void *)vif->drv_priv;
++ unsigned long flags;
+ int slottime;
+
+ ath9k_ps_wakeup(sc);
+@@ -1853,7 +1848,10 @@ static void ath9k_bss_info_changed(struc
+
+ if (changed & BSS_CHANGED_P2P_PS) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+- ath9k_update_p2p_ps(sc, vif);
++ spin_lock_irqsave(&sc->sc_pm_lock, flags);
++ if (!(sc->ps_flags & PS_BEACON_SYNC))
++ ath9k_update_p2p_ps(sc, vif);
++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ spin_unlock_bh(&sc->sc_pcu_lock);
}
-- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
-+
-+ if (AR_SREV_9550(ah))
-+ outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
-+ iqcal_idx, nmeasurement);
-+ if (outlier_detect)
-+ ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
-
- return;
-@@ -1409,7 +1484,7 @@ skip_tx_iqcal:
- }
+@@ -2232,14 +2230,6 @@ static void ath9k_sw_scan_complete(struc
+ clear_bit(ATH_OP_SCANNING, &common->op_flags);
+ }
- if (txiqcal_done)
-- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
-+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
- else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
- ar9003_hw_tx_iq_cal_reload(ah);
+-static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
+- struct ieee80211_vif *vif,
+- struct cfg80211_chan_def *chandef)
+-{
+- /* depend on vif->csa_active only */
+- return;
+-}
+-
+ struct ieee80211_ops ath9k_ops = {
+ .tx = ath9k_tx,
+ .start = ath9k_start,
+@@ -2287,5 +2277,4 @@ struct ieee80211_ops ath9k_ops = {
+ #endif
+ .sw_scan_start = ath9k_sw_scan_start,
+ .sw_scan_complete = ath9k_sw_scan_complete,
+- .channel_switch_beacon = ath9k_channel_switch_beacon,
+ };
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -4142,14 +4142,6 @@ static int ath10k_set_bitrate_mask(struc
+ fixed_nss, force_sgi);
+ }
-@@ -1455,14 +1530,38 @@ skip_tx_iqcal:
- return true;
+-static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw,
+- struct ieee80211_vif *vif,
+- struct cfg80211_chan_def *chandef)
+-{
+- /* there's no need to do anything here. vif->csa_active is enough */
+- return;
+-}
+-
+ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+@@ -4256,7 +4248,6 @@ static const struct ieee80211_ops ath10k
+ .restart_complete = ath10k_restart_complete,
+ .get_survey = ath10k_get_survey,
+ .set_bitrate_mask = ath10k_set_bitrate_mask,
+- .channel_switch_beacon = ath10k_channel_switch_beacon,
+ .sta_rc_update = ath10k_sta_rc_update,
+ .get_tsf = ath10k_get_tsf,
+ #ifdef CONFIG_PM
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -468,327 +468,6 @@ void sta_set_rate_info_rx(struct sta_inf
+ rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
}
-+static bool do_ar9003_agc_cal(struct ath_hw *ah)
-+{
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ bool status;
-+
-+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
-+ AR_PHY_AGC_CONTROL_CAL);
-+
-+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-+ AR_PHY_AGC_CONTROL_CAL,
-+ 0, AH_WAIT_TIMEOUT);
-+ if (!status) {
-+ ath_dbg(common, CALIBRATE,
-+ "offset calibration failed to complete in %d ms,"
-+ "noisy environment?\n",
-+ AH_WAIT_TIMEOUT / 1000);
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_cal_data *caldata = ah->caldata;
- bool txiqcal_done = false;
-- bool is_reusable = true, status = true;
-+ bool status = true;
- bool run_agc_cal = false, sep_iq_cal = false;
-+ int i = 0;
-
- /* Use chip chainmask only for calibration */
- ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
-@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc
- * AGC calibration. Specifically, AR9550 in SoC chips.
- */
- if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
-- txiqcal_done = true;
-+ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
-+ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
-+ txiqcal_done = true;
-+ } else {
-+ txiqcal_done = false;
-+ }
- run_agc_cal = true;
- } else {
- sep_iq_cal = true;
-@@ -1512,27 +1616,37 @@ skip_tx_iqcal:
- if (AR_SREV_9330_11(ah))
- ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
-
-- /* Calibrate the AGC */
-- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-- REG_READ(ah, AR_PHY_AGC_CONTROL) |
-- AR_PHY_AGC_CONTROL_CAL);
+-static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
+-{
+- struct ieee80211_sub_if_data *sdata = sta->sdata;
+- struct ieee80211_local *local = sdata->local;
+- struct rate_control_ref *ref = local->rate_ctrl;
+- struct timespec uptime;
+- u64 packets = 0;
+- u32 thr = 0;
+- int i, ac;
+-
+- sinfo->generation = sdata->local->sta_generation;
+-
+- sinfo->filled = STATION_INFO_INACTIVE_TIME |
+- STATION_INFO_RX_BYTES64 |
+- STATION_INFO_TX_BYTES64 |
+- STATION_INFO_RX_PACKETS |
+- STATION_INFO_TX_PACKETS |
+- STATION_INFO_TX_RETRIES |
+- STATION_INFO_TX_FAILED |
+- STATION_INFO_TX_BITRATE |
+- STATION_INFO_RX_BITRATE |
+- STATION_INFO_RX_DROP_MISC |
+- STATION_INFO_BSS_PARAM |
+- STATION_INFO_CONNECTED_TIME |
+- STATION_INFO_STA_FLAGS |
+- STATION_INFO_BEACON_LOSS_COUNT;
-
-- /* Poll for offset calibration complete */
-- status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-- AR_PHY_AGC_CONTROL_CAL,
-- 0, AH_WAIT_TIMEOUT);
+- do_posix_clock_monotonic_gettime(&uptime);
+- sinfo->connected_time = uptime.tv_sec - sta->last_connected;
+-
+- sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
+- sinfo->tx_bytes = 0;
+- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+- sinfo->tx_bytes += sta->tx_bytes[ac];
+- packets += sta->tx_packets[ac];
- }
-+ /*
-+ * For non-AR9550 chips, we just trigger AGC calibration
-+ * in the HW, poll for completion and then process
-+ * the results.
-+ *
-+ * For AR955x, we run it multiple times and use
-+ * median IQ correction.
-+ */
-+ if (!AR_SREV_9550(ah)) {
-+ status = do_ar9003_agc_cal(ah);
-+ if (!status)
-+ return false;
-
-- if (!status) {
-- ath_dbg(common, CALIBRATE,
-- "offset calibration failed to complete in %d ms; noisy environment?\n",
-- AH_WAIT_TIMEOUT / 1000);
-- return false;
-+ if (txiqcal_done)
-+ ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
-+ } else {
-+ if (!txiqcal_done) {
-+ status = do_ar9003_agc_cal(ah);
-+ if (!status)
-+ return false;
-+ } else {
-+ for (i = 0; i < MAXIQCAL; i++) {
-+ status = do_ar9003_agc_cal(ah);
-+ if (!status)
-+ return false;
-+ ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
-+ }
-+ }
-+ }
- }
-
-- if (txiqcal_done)
-- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+- sinfo->tx_packets = packets;
+- sinfo->rx_bytes = sta->rx_bytes;
+- sinfo->rx_packets = sta->rx_packets;
+- sinfo->tx_retries = sta->tx_retry_count;
+- sinfo->tx_failed = sta->tx_retry_failed;
+- sinfo->rx_dropped_misc = sta->rx_dropped;
+- sinfo->beacon_loss_count = sta->beacon_loss_count;
+-
+- if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
+- (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
+- sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
+- if (!local->ops->get_rssi ||
+- drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
+- sinfo->signal = (s8)sta->last_signal;
+- sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
+- }
+- if (sta->chains) {
+- sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
+- STATION_INFO_CHAIN_SIGNAL_AVG;
+-
+- sinfo->chains = sta->chains;
+- for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
+- sinfo->chain_signal[i] = sta->chain_signal_last[i];
+- sinfo->chain_signal_avg[i] =
+- (s8) -ewma_read(&sta->chain_signal_avg[i]);
+- }
+- }
+-
+- sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
+- sta_set_rate_info_rx(sta, &sinfo->rxrate);
+-
+- if (ieee80211_vif_is_mesh(&sdata->vif)) {
+-#ifdef CPTCFG_MAC80211_MESH
+- sinfo->filled |= STATION_INFO_LLID |
+- STATION_INFO_PLID |
+- STATION_INFO_PLINK_STATE |
+- STATION_INFO_LOCAL_PM |
+- STATION_INFO_PEER_PM |
+- STATION_INFO_NONPEER_PM;
+-
+- sinfo->llid = sta->llid;
+- sinfo->plid = sta->plid;
+- sinfo->plink_state = sta->plink_state;
+- if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
+- sinfo->filled |= STATION_INFO_T_OFFSET;
+- sinfo->t_offset = sta->t_offset;
+- }
+- sinfo->local_pm = sta->local_pm;
+- sinfo->peer_pm = sta->peer_pm;
+- sinfo->nonpeer_pm = sta->nonpeer_pm;
+-#endif
+- }
+-
+- sinfo->bss_param.flags = 0;
+- if (sdata->vif.bss_conf.use_cts_prot)
+- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+- if (sdata->vif.bss_conf.use_short_preamble)
+- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+- if (sdata->vif.bss_conf.use_short_slot)
+- sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+- sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
+- sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
+-
+- sinfo->sta_flags.set = 0;
+- sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
+- BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+- BIT(NL80211_STA_FLAG_WME) |
+- BIT(NL80211_STA_FLAG_MFP) |
+- BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+- BIT(NL80211_STA_FLAG_ASSOCIATED) |
+- BIT(NL80211_STA_FLAG_TDLS_PEER);
+- if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+- if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+- if (test_sta_flag(sta, WLAN_STA_WME))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
+- if (test_sta_flag(sta, WLAN_STA_MFP))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
+- if (test_sta_flag(sta, WLAN_STA_AUTH))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+- if (test_sta_flag(sta, WLAN_STA_ASSOC))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+- sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+-
+- /* check if the driver has a SW RC implementation */
+- if (ref && ref->ops->get_expected_throughput)
+- thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
+- else
+- thr = drv_get_expected_throughput(local, &sta->sta);
+-
+- if (thr != 0) {
+- sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
+- sinfo->expected_throughput = thr;
+- }
+-}
+-
+-static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
+- "rx_packets", "rx_bytes", "wep_weak_iv_count",
+- "rx_duplicates", "rx_fragments", "rx_dropped",
+- "tx_packets", "tx_bytes", "tx_fragments",
+- "tx_filtered", "tx_retry_failed", "tx_retries",
+- "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
+- "channel", "noise", "ch_time", "ch_time_busy",
+- "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
+-};
+-#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
+-
+-static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
+- struct net_device *dev,
+- int sset)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int rv = 0;
+-
+- if (sset == ETH_SS_STATS)
+- rv += STA_STATS_LEN;
+-
+- rv += drv_get_et_sset_count(sdata, sset);
+-
+- if (rv == 0)
+- return -EOPNOTSUPP;
+- return rv;
+-}
+-
+-static void ieee80211_get_et_stats(struct wiphy *wiphy,
+- struct net_device *dev,
+- struct ethtool_stats *stats,
+- u64 *data)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- struct ieee80211_chanctx_conf *chanctx_conf;
+- struct ieee80211_channel *channel;
+- struct sta_info *sta;
+- struct ieee80211_local *local = sdata->local;
+- struct station_info sinfo;
+- struct survey_info survey;
+- int i, q;
+-#define STA_STATS_SURVEY_LEN 7
+-
+- memset(data, 0, sizeof(u64) * STA_STATS_LEN);
+-
+-#define ADD_STA_STATS(sta) \
+- do { \
+- data[i++] += sta->rx_packets; \
+- data[i++] += sta->rx_bytes; \
+- data[i++] += sta->wep_weak_iv_count; \
+- data[i++] += sta->num_duplicates; \
+- data[i++] += sta->rx_fragments; \
+- data[i++] += sta->rx_dropped; \
+- \
+- data[i++] += sinfo.tx_packets; \
+- data[i++] += sinfo.tx_bytes; \
+- data[i++] += sta->tx_fragments; \
+- data[i++] += sta->tx_filtered_count; \
+- data[i++] += sta->tx_retry_failed; \
+- data[i++] += sta->tx_retry_count; \
+- data[i++] += sta->beacon_loss_count; \
+- } while (0)
+-
+- /* For Managed stations, find the single station based on BSSID
+- * and use that. For interface types, iterate through all available
+- * stations and add stats for any station that is assigned to this
+- * network device.
+- */
+-
+- mutex_lock(&local->sta_mtx);
+-
+- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+- sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
+-
+- if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
+- goto do_survey;
+-
+- sinfo.filled = 0;
+- sta_set_sinfo(sta, &sinfo);
+-
+- i = 0;
+- ADD_STA_STATS(sta);
+-
+- data[i++] = sta->sta_state;
+-
+-
+- if (sinfo.filled & STATION_INFO_TX_BITRATE)
+- data[i] = 100000 *
+- cfg80211_calculate_bitrate(&sinfo.txrate);
+- i++;
+- if (sinfo.filled & STATION_INFO_RX_BITRATE)
+- data[i] = 100000 *
+- cfg80211_calculate_bitrate(&sinfo.rxrate);
+- i++;
+-
+- if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
+- data[i] = (u8)sinfo.signal_avg;
+- i++;
+- } else {
+- list_for_each_entry(sta, &local->sta_list, list) {
+- /* Make sure this station belongs to the proper dev */
+- if (sta->sdata->dev != dev)
+- continue;
+-
+- sinfo.filled = 0;
+- sta_set_sinfo(sta, &sinfo);
+- i = 0;
+- ADD_STA_STATS(sta);
+- }
+- }
+-
+-do_survey:
+- i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
+- /* Get survey stats for current channel */
+- survey.filled = 0;
+-
+- rcu_read_lock();
+- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+- if (chanctx_conf)
+- channel = chanctx_conf->def.chan;
+- else
+- channel = NULL;
+- rcu_read_unlock();
-
- /* Revert chainmask to runtime parameters */
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+- if (channel) {
+- q = 0;
+- do {
+- survey.filled = 0;
+- if (drv_get_survey(local, q, &survey) != 0) {
+- survey.filled = 0;
+- break;
+- }
+- q++;
+- } while (channel != survey.channel);
+- }
+-
+- if (survey.filled)
+- data[i++] = survey.channel->center_freq;
+- else
+- data[i++] = 0;
+- if (survey.filled & SURVEY_INFO_NOISE_DBM)
+- data[i++] = (u8)survey.noise;
+- else
+- data[i++] = -1LL;
+- if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
+- data[i++] = survey.channel_time;
+- else
+- data[i++] = -1LL;
+- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
+- data[i++] = survey.channel_time_busy;
+- else
+- data[i++] = -1LL;
+- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
+- data[i++] = survey.channel_time_ext_busy;
+- else
+- data[i++] = -1LL;
+- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
+- data[i++] = survey.channel_time_rx;
+- else
+- data[i++] = -1LL;
+- if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
+- data[i++] = survey.channel_time_tx;
+- else
+- data[i++] = -1LL;
+-
+- mutex_unlock(&local->sta_mtx);
+-
+- if (WARN_ON(i != STA_STATS_LEN))
+- return;
+-
+- drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
+-}
+-
+-static void ieee80211_get_et_strings(struct wiphy *wiphy,
+- struct net_device *dev,
+- u32 sset, u8 *data)
+-{
+- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+- int sz_sta_stats = 0;
+-
+- if (sset == ETH_SS_STATS) {
+- sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
+- memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
+- }
+- drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
+-}
+-
+ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *mac, struct station_info *sinfo)
+ {
+@@ -875,7 +554,8 @@ static int ieee80211_set_monitor_channel
+ }
+
+ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
+- const u8 *resp, size_t resp_len)
++ const u8 *resp, size_t resp_len,
++ const struct ieee80211_csa_settings *csa)
+ {
+ struct probe_resp *new, *old;
---- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
-+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
-@@ -15,6 +15,8 @@
- #ifndef RTL8187_H
- #define RTL8187_H
+@@ -891,6 +571,11 @@ static int ieee80211_set_probe_resp(stru
+ new->len = resp_len;
+ memcpy(new->data, resp, resp_len);
-+#include <linux/cache.h>
++ if (csa)
++ memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
++ csa->n_counter_offsets_presp *
++ sizeof(new->csa_counter_offsets[0]));
+
- #include "rtl818x.h"
- #include "leds.h"
-
-@@ -139,7 +141,10 @@ struct rtl8187_priv {
- u8 aifsn[4];
- u8 rfkill_mask;
- struct {
-- __le64 buf;
-+ union {
-+ __le64 buf;
-+ u8 dummy1[L1_CACHE_BYTES];
-+ } ____cacheline_aligned;
- struct sk_buff_head queue;
- } b_tx_status; /* This queue is used by both -b and non-b devices */
- struct mutex io_mutex;
-@@ -147,7 +152,8 @@ struct rtl8187_priv {
- u8 bits8;
- __le16 bits16;
- __le32 bits32;
-- } *io_dmabuf;
-+ u8 dummy2[L1_CACHE_BYTES];
-+ } *io_dmabuf ____cacheline_aligned;
- bool rfkill_off;
- u16 seqno;
- };
---- a/net/mac80211/wme.c
-+++ b/net/mac80211/wme.c
-@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80
- return IEEE80211_AC_BE;
- }
+ rcu_assign_pointer(sdata->u.ap.probe_resp, new);
+ if (old)
+ kfree_rcu(old, rcu_head);
+@@ -899,7 +584,8 @@ static int ieee80211_set_probe_resp(stru
+ }
-+ if (skb->protocol == sdata->control_port_protocol) {
-+ skb->priority = 7;
-+ return ieee80211_downgrade_queue(sdata, skb);
+ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
+- struct cfg80211_beacon_data *params)
++ struct cfg80211_beacon_data *params,
++ const struct ieee80211_csa_settings *csa)
+ {
+ struct beacon_data *new, *old;
+ int new_head_len, new_tail_len;
+@@ -943,6 +629,13 @@ static int ieee80211_assign_beacon(struc
+ new->head_len = new_head_len;
+ new->tail_len = new_tail_len;
+
++ if (csa) {
++ new->csa_current_counter = csa->count;
++ memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
++ csa->n_counter_offsets_beacon *
++ sizeof(new->csa_counter_offsets[0]));
+ }
+
- /* use the data classifier to determine what 802.1d tag the
- * data frame has */
- rcu_read_lock();
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
- for (tidno = 0, tid = &an->tid[tidno];
- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
-
-- if (!tid->sched)
-- continue;
--
- ac = tid->ac;
- txq = ac->txq;
+ /* copy in head */
+ if (params->head)
+ memcpy(new->head, params->head, new_head_len);
+@@ -957,7 +650,7 @@ static int ieee80211_assign_beacon(struc
+ memcpy(new->tail, old->tail, new_tail_len);
- ath_txq_lock(sc, txq);
+ err = ieee80211_set_probe_resp(sdata, params->probe_resp,
+- params->probe_resp_len);
++ params->probe_resp_len, csa);
+ if (err < 0)
+ return err;
+ if (err == 0)
+@@ -1042,7 +735,7 @@ static int ieee80211_start_ap(struct wip
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ IEEE80211_P2P_OPPPS_ENABLE_BIT;
-+ if (!tid->sched) {
-+ ath_txq_unlock(sc, txq);
-+ continue;
-+ }
-+
- buffered = ath_tid_has_buffered(tid);
+- err = ieee80211_assign_beacon(sdata, &params->beacon);
++ err = ieee80211_assign_beacon(sdata, &params->beacon, NULL);
+ if (err < 0) {
+ ieee80211_vif_release_channel(sdata);
+ return err;
+@@ -1090,7 +783,7 @@ static int ieee80211_change_beacon(struc
+ if (!old)
+ return -ENOENT;
- tid->sched = false;
-@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc
+- err = ieee80211_assign_beacon(sdata, params);
++ err = ieee80211_assign_beacon(sdata, params, NULL);
+ if (err < 0)
+ return err;
+ ieee80211_bss_info_change_notify(sdata, err);
+@@ -3073,7 +2766,8 @@ static int ieee80211_set_after_csa_beaco
- ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP:
+- err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
++ err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
++ NULL);
+ kfree(sdata->u.ap.next_beacon);
+ sdata->u.ap.next_beacon = NULL;
+
+@@ -3176,6 +2870,7 @@ static int ieee80211_set_csa_beacon(stru
+ struct cfg80211_csa_settings *params,
+ u32 *changed)
+ {
++ struct ieee80211_csa_settings csa = {};
+ int err;
-- qi.tqi_readyTime = (cur_conf->beacon_interval *
-+ qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
- ATH_CABQ_READY_TIME) / 100;
- ath_txq_update(sc, qnum, &qi);
+ switch (sdata->vif.type) {
+@@ -3210,20 +2905,13 @@ static int ieee80211_set_csa_beacon(stru
+ IEEE80211_MAX_CSA_COUNTERS_NUM))
+ return -EINVAL;
-@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff
+- /* make sure we don't have garbage in other counters */
+- memset(sdata->csa_counter_offset_beacon, 0,
+- sizeof(sdata->csa_counter_offset_beacon));
+- memset(sdata->csa_counter_offset_presp, 0,
+- sizeof(sdata->csa_counter_offset_presp));
+-
+- memcpy(sdata->csa_counter_offset_beacon,
+- params->counter_offsets_beacon,
+- params->n_counter_offsets_beacon * sizeof(u16));
+- memcpy(sdata->csa_counter_offset_presp,
+- params->counter_offsets_presp,
+- params->n_counter_offsets_presp * sizeof(u16));
++ csa.counter_offsets_beacon = params->counter_offsets_beacon;
++ csa.counter_offsets_presp = params->counter_offsets_presp;
++ csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
++ csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
++ csa.count = params->count;
+
+- err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
++ err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa);
+ if (err < 0) {
+ kfree(sdata->u.ap.next_beacon);
+ return err;
+@@ -3367,7 +3055,6 @@ __ieee80211_channel_switch(struct wiphy
+ sdata->csa_radar_required = params->radar_required;
+ sdata->csa_chandef = params->chandef;
+ sdata->csa_block_tx = params->block_tx;
+- sdata->csa_current_counter = params->count;
+ sdata->vif.csa_active = true;
+
+ if (sdata->csa_block_tx)
+@@ -3515,10 +3202,23 @@ static int ieee80211_mgmt_tx(struct wiph
+ sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
+ params->n_csa_offsets) {
+ int i;
+- u8 c = sdata->csa_current_counter;
++ struct beacon_data *beacon = NULL;
++
++ rcu_read_lock();
+
+- for (i = 0; i < params->n_csa_offsets; i++)
+- data[params->csa_offsets[i]] = c;
++ if (sdata->vif.type == NL80211_IFTYPE_AP)
++ beacon = rcu_dereference(sdata->u.ap.beacon);
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ beacon = rcu_dereference(sdata->u.ibss.presp);
++ else if (ieee80211_vif_is_mesh(&sdata->vif))
++ beacon = rcu_dereference(sdata->u.mesh.beacon);
++
++ if (beacon)
++ for (i = 0; i < params->n_csa_offsets; i++)
++ data[params->csa_offsets[i]] =
++ beacon->csa_current_counter;
++
++ rcu_read_unlock();
+ }
- ATH_TXBUF_RESET(bf);
+ IEEE80211_SKB_CB(skb)->flags = flags;
+@@ -3598,21 +3298,6 @@ static int ieee80211_get_antenna(struct
+ return drv_get_antenna(local, tx_ant, rx_ant);
+ }
-- if (tid) {
-+ if (tid && ieee80211_is_data_present(hdr->frame_control)) {
- fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
- seqno = tid->seq_next;
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
-@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw
- txq->stopped = true;
- }
+-static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
+-{
+- struct ieee80211_local *local = wiphy_priv(wiphy);
+-
+- return drv_set_ringparam(local, tx, rx);
+-}
+-
+-static void ieee80211_get_ringparam(struct wiphy *wiphy,
+- u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+-{
+- struct ieee80211_local *local = wiphy_priv(wiphy);
+-
+- drv_get_ringparam(local, tx, tx_max, rx, rx_max);
+-}
+-
+ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_gtk_rekey_data *data)
+@@ -3844,8 +3529,6 @@ const struct cfg80211_ops mac80211_confi
+ .mgmt_frame_register = ieee80211_mgmt_frame_register,
+ .set_antenna = ieee80211_set_antenna,
+ .get_antenna = ieee80211_get_antenna,
+- .set_ringparam = ieee80211_set_ringparam,
+- .get_ringparam = ieee80211_get_ringparam,
+ .set_rekey_data = ieee80211_set_rekey_data,
+ .tdls_oper = ieee80211_tdls_oper,
+ .tdls_mgmt = ieee80211_tdls_mgmt,
+@@ -3854,9 +3537,6 @@ const struct cfg80211_ops mac80211_confi
+ #ifdef CONFIG_PM
+ .set_wakeup = ieee80211_set_wakeup,
+ #endif
+- .get_et_sset_count = ieee80211_get_et_sset_count,
+- .get_et_stats = ieee80211_get_et_stats,
+- .get_et_strings = ieee80211_get_et_strings,
+ .get_channel = ieee80211_cfg_get_channel,
+ .start_radar_detection = ieee80211_start_radar_detection,
+ .channel_switch = ieee80211_channel_switch,
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -587,7 +587,6 @@ void ieee80211_sta_debugfs_add(struct st
+ DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count);
+ DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed);
+ DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count);
+- DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count);
+
+ if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
+ debugfs_create_x32("driver_buffered_tids", 0400,
+--- a/net/mac80211/wep.c
++++ b/net/mac80211/wep.c
+@@ -271,22 +271,6 @@ static int ieee80211_wep_decrypt(struct
+ return ret;
+ }
-+ if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
-+ tid = ath_get_skb_tid(sc, txctl->an, skb);
-+
- if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
- ath_txq_unlock(sc, txq);
- txq = sc->tx.uapsdq;
- ath_txq_lock(sc, txq);
- } else if (txctl->an &&
- ieee80211_is_data_present(hdr->frame_control)) {
-- tid = ath_get_skb_tid(sc, txctl->an, skb);
-
- WARN_ON(tid->ac->txq != txctl->txq);
-
- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -943,6 +943,7 @@ static void ath9k_set_hw_capab(struct at
- hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
- hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
-+ hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-
- hw->queues = 4;
- hw->max_rates = 4;
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1700,14 +1700,8 @@ void ieee80211_stop_queue_by_reason(stru
- void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
- void ieee80211_add_pending_skb(struct ieee80211_local *local,
- struct sk_buff *skb);
--void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
-- struct sk_buff_head *skbs,
-- void (*fn)(void *data), void *data);
--static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
-- struct sk_buff_head *skbs)
+-static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb,
+- struct ieee80211_key *key)
-{
-- ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+- unsigned int hdrlen;
+- u8 *ivpos;
+- u32 iv;
+-
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
+- ivpos = skb->data + hdrlen;
+- iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
+-
+- return ieee80211_wep_weak_iv(iv, key->conf.keylen);
-}
-+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
-+ struct sk_buff_head *skbs);
- void ieee80211_flush_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata);
+-
+ ieee80211_rx_result
+ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
+ {
+@@ -301,16 +285,12 @@ ieee80211_crypto_wep_decrypt(struct ieee
+ if (!(status->flag & RX_FLAG_DECRYPTED)) {
+ if (skb_linearize(rx->skb))
+ return RX_DROP_UNUSABLE;
+- if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+- rx->sta->wep_weak_iv_count++;
+ if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
+ return RX_DROP_UNUSABLE;
+ } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
+ if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
+ IEEE80211_WEP_IV_LEN))
+ return RX_DROP_UNUSABLE;
+- if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
+- rx->sta->wep_weak_iv_count++;
+ ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
+ /* remove ICV */
+ if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2278,16 +2278,6 @@ struct cfg80211_qos_map {
+ *
+ * @set_noack_map: Set the NoAck Map for the TIDs.
+ *
+- * @get_et_sset_count: Ethtool API to get string-set count.
+- * See @ethtool_ops.get_sset_count
+- *
+- * @get_et_stats: Ethtool API to get a set of u64 stats.
+- * See @ethtool_ops.get_ethtool_stats
+- *
+- * @get_et_strings: Ethtool API to get a set of strings to describe stats
+- * and perhaps other supported types of ethtool data-sets.
+- * See @ethtool_ops.get_strings
+- *
+ * @get_channel: Get the current operating channel for the virtual interface.
+ * For monitor interfaces, it should return %NULL unless there's a single
+ * current monitoring channel.
+@@ -2529,13 +2519,6 @@ struct cfg80211_ops {
+ struct net_device *dev,
+ u16 noack_map);
+
+- int (*get_et_sset_count)(struct wiphy *wiphy,
+- struct net_device *dev, int sset);
+- void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
+- struct ethtool_stats *stats, u64 *data);
+- void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
+- u32 sset, u8 *data);
+-
+ int (*get_channel)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef);
+@@ -4846,6 +4829,10 @@ void cfg80211_stop_iface(struct wiphy *w
+ */
+ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee
- return -ENOENT;
- }
++
++/* ethtool helper */
++void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
++
+ /* Logging, debugging and troubleshooting/diagnostic helpers. */
+
+ /* wiphy_printk helpers, similar to dev_printk */
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -17,6 +17,7 @@ mac80211-y := \
+ aes_ccm.o \
+ aes_cmac.o \
+ cfg.o \
++ ethtool.o \
+ rx.o \
+ spectmgmt.o \
+ tx.o \
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -229,16 +229,29 @@ struct ieee80211_rx_data {
+ u16 tkip_iv16;
+ };
+
++struct ieee80211_csa_settings {
++ const u16 *counter_offsets_beacon;
++ const u16 *counter_offsets_presp;
++
++ int n_counter_offsets_beacon;
++ int n_counter_offsets_presp;
++
++ u8 count;
++};
++
+ struct beacon_data {
+ u8 *head, *tail;
+ int head_len, tail_len;
+ struct ieee80211_meshconf_ie *meshconf;
++ u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
++ u8 csa_current_counter;
+ struct rcu_head rcu_head;
+ };
+
+ struct probe_resp {
+ struct rcu_head rcu_head;
+ int len;
++ u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
+ u8 data[0];
+ };
--static void cleanup_single_sta(struct sta_info *sta)
-+static void __cleanup_single_sta(struct sta_info *sta)
- {
- int ac, i;
- struct tid_ampdu_tx *tid_tx;
-@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct st
- struct ieee80211_local *local = sdata->local;
- struct ps_data *ps;
+@@ -754,8 +767,6 @@ struct ieee80211_sub_if_data {
+ struct mac80211_qos_map __rcu *qos_map;
-- if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
-+ if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
-+ test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
- if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
- sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- ps = &sdata->bss->ps;
-@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct st
- return;
+ struct work_struct csa_finalize_work;
+- u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
+- u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
+ bool csa_radar_required;
+ bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
+ struct cfg80211_chan_def csa_chandef;
+@@ -767,7 +778,6 @@ struct ieee80211_sub_if_data {
+ struct ieee80211_chanctx *reserved_chanctx;
+ struct cfg80211_chan_def reserved_chandef;
+ bool reserved_radar_required;
+- u8 csa_current_counter;
- clear_sta_flag(sta, WLAN_STA_PS_STA);
-+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+ /* used to reconfigure hardware SM PS */
+ struct work_struct recalc_smps;
+@@ -1850,6 +1860,8 @@ int ieee80211_tdls_oper(struct wiphy *wi
+ const u8 *peer, enum nl80211_tdls_operation oper);
- atomic_dec(&ps->num_sta_ps);
- sta_info_recalc_tim(sta);
-@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct st
- ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
- kfree(tid_tx);
- }
-+}
-+static void cleanup_single_sta(struct sta_info *sta)
-+{
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+ struct ieee80211_local *local = sdata->local;
++extern const struct ethtool_ops ieee80211_ethtool_ops;
+
-+ __cleanup_single_sta(sta);
- sta_info_free(local, sta);
- }
+ #ifdef CPTCFG_MAC80211_NOINLINE
+ #define debug_noinline noinline
+ #else
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -399,6 +399,7 @@ int ieee80211_add_virtual_monitor(struct
+ sdata->vif.type = NL80211_IFTYPE_MONITOR;
+ snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
+ wiphy_name(local->hw.wiphy));
++ sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
-@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i
- rcu_read_unlock();
+ sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
- spin_lock_init(&sta->lock);
-+ spin_lock_init(&sta->ps_lock);
- INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
- INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
- mutex_init(&sta->ampdu_mlme.mtx);
-@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct
- goto out_err;
- }
+@@ -1303,6 +1304,7 @@ static void ieee80211_setup_sdata(struct
+ sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
+ sdata->control_port_no_encrypt = false;
+ sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
++ sdata->vif.bss_conf.idle = true;
-- /* notify driver */
-- err = sta_info_insert_drv_state(local, sdata, sta);
-- if (err)
-- goto out_err;
--
- local->num_sta++;
- local->sta_generation++;
- smp_mb();
+ sdata->noack_map = 0;
-+ /* simplify things and don't accept BA sessions yet */
-+ set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-+
- /* make the station visible */
- sta_info_hash_add(local, sta);
+@@ -1721,6 +1723,8 @@ int ieee80211_if_add(struct ieee80211_lo
- list_add_rcu(&sta->list, &local->sta_list);
+ ndev->features |= local->hw.netdev_features;
-+ /* notify driver */
-+ err = sta_info_insert_drv_state(local, sdata, sta);
-+ if (err)
-+ goto out_remove;
++ netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
+
- set_sta_flag(sta, WLAN_STA_INSERTED);
-+ /* accept BA sessions now */
-+ clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
+ ret = register_netdevice(ndev);
+ if (ret) {
+ free_netdev(ndev);
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -25,7 +25,6 @@
+ #include "sysfs.h"
+ #include "debugfs.h"
+ #include "wext-compat.h"
+-#include "ethtool.h"
+ #include "rdev-ops.h"
- ieee80211_recalc_min_chandef(sdata);
- ieee80211_sta_debugfs_add(sta);
-@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct
- mesh_accept_plinks_update(sdata);
+ /* name for sysfs, %d is appended */
+@@ -940,8 +939,6 @@ static int cfg80211_netdev_notifier_call
+ /* allow mac80211 to determine the timeout */
+ wdev->ps_timeout = -1;
- return 0;
-+ out_remove:
-+ sta_info_hash_del(local, sta);
-+ list_del_rcu(&sta->list);
-+ local->num_sta--;
-+ synchronize_net();
-+ __cleanup_single_sta(sta);
- out_err:
- mutex_unlock(&local->sta_mtx);
- rcu_read_lock();
-@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta
- }
- EXPORT_SYMBOL(ieee80211_find_sta);
+- netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops);
+-
+ if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+ wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
+ wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
+--- a/net/wireless/ethtool.c
++++ b/net/wireless/ethtool.c
+@@ -1,11 +1,9 @@
+ #include <linux/utsname.h>
+ #include <net/cfg80211.h>
+ #include "core.h"
+-#include "ethtool.h"
+ #include "rdev-ops.h"
--static void clear_sta_ps_flags(void *_sta)
-+/* powersave support code */
-+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
+-static void cfg80211_get_drvinfo(struct net_device *dev,
+- struct ethtool_drvinfo *info)
++void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
-- struct sta_info *sta = _sta;
- struct ieee80211_sub_if_data *sdata = sta->sdata;
-+ struct ieee80211_local *local = sdata->local;
-+ struct sk_buff_head pending;
-+ int filtered = 0, buffered = 0, ac;
-+ unsigned long flags;
- struct ps_data *ps;
-
- if (sdata->vif.type == NL80211_IFTYPE_AP ||
-@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st
- else
- return;
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
-- clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-- if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
-- atomic_dec(&ps->num_sta_ps);
+@@ -23,84 +21,4 @@ static void cfg80211_get_drvinfo(struct
+ strlcpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)),
+ sizeof(info->bus_info));
+ }
+-
+-static int cfg80211_get_regs_len(struct net_device *dev)
+-{
+- /* For now, return 0... */
+- return 0;
-}
-
--/* powersave support code */
--void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
+-static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+- void *data)
-{
-- struct ieee80211_sub_if_data *sdata = sta->sdata;
-- struct ieee80211_local *local = sdata->local;
-- struct sk_buff_head pending;
-- int filtered = 0, buffered = 0, ac;
-- unsigned long flags;
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
- clear_sta_flag(sta, WLAN_STA_SP);
-
- BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
-@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str
+- regs->version = wdev->wiphy->hw_version;
+- regs->len = 0;
+-}
+-
+-static void cfg80211_get_ringparam(struct net_device *dev,
+- struct ethtool_ringparam *rp)
+-{
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+-
+- memset(rp, 0, sizeof(*rp));
+-
+- if (rdev->ops->get_ringparam)
+- rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending,
+- &rp->rx_pending, &rp->rx_max_pending);
+-}
+-
+-static int cfg80211_set_ringparam(struct net_device *dev,
+- struct ethtool_ringparam *rp)
+-{
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+-
+- if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
+- return -EINVAL;
+-
+- if (rdev->ops->set_ringparam)
+- return rdev_set_ringparam(rdev, rp->tx_pending, rp->rx_pending);
+-
+- return -ENOTSUPP;
+-}
+-
+-static int cfg80211_get_sset_count(struct net_device *dev, int sset)
+-{
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+- if (rdev->ops->get_et_sset_count)
+- return rdev_get_et_sset_count(rdev, dev, sset);
+- return -EOPNOTSUPP;
+-}
+-
+-static void cfg80211_get_stats(struct net_device *dev,
+- struct ethtool_stats *stats, u64 *data)
+-{
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+- if (rdev->ops->get_et_stats)
+- rdev_get_et_stats(rdev, dev, stats, data);
+-}
+-
+-static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
+-{
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+- if (rdev->ops->get_et_strings)
+- rdev_get_et_strings(rdev, dev, sset, data);
+-}
+-
+-const struct ethtool_ops cfg80211_ethtool_ops = {
+- .get_drvinfo = cfg80211_get_drvinfo,
+- .get_regs_len = cfg80211_get_regs_len,
+- .get_regs = cfg80211_get_regs,
+- .get_link = ethtool_op_get_link,
+- .get_ringparam = cfg80211_get_ringparam,
+- .set_ringparam = cfg80211_set_ringparam,
+- .get_strings = cfg80211_get_strings,
+- .get_ethtool_stats = cfg80211_get_stats,
+- .get_sset_count = cfg80211_get_sset_count,
+-};
++EXPORT_SYMBOL(cfg80211_get_drvinfo);
+--- a/net/wireless/ethtool.h
++++ /dev/null
+@@ -1,6 +0,0 @@
+-#ifndef __CFG80211_ETHTOOL__
+-#define __CFG80211_ETHTOOL__
+-
+-extern const struct ethtool_ops cfg80211_ethtool_ops;
+-
+-#endif /* __CFG80211_ETHTOOL__ */
+--- a/net/wireless/rdev-ops.h
++++ b/net/wireless/rdev-ops.h
+@@ -714,25 +714,6 @@ static inline int rdev_get_antenna(struc
+ return ret;
+ }
- skb_queue_head_init(&pending);
+-static inline int rdev_set_ringparam(struct cfg80211_registered_device *rdev,
+- u32 tx, u32 rx)
+-{
+- int ret;
+- trace_rdev_set_ringparam(&rdev->wiphy, tx, rx);
+- ret = rdev->ops->set_ringparam(&rdev->wiphy, tx, rx);
+- trace_rdev_return_int(&rdev->wiphy, ret);
+- return ret;
+-}
+-
+-static inline void rdev_get_ringparam(struct cfg80211_registered_device *rdev,
+- u32 *tx, u32 *tx_max, u32 *rx,
+- u32 *rx_max)
+-{
+- trace_rdev_get_ringparam(&rdev->wiphy);
+- rdev->ops->get_ringparam(&rdev->wiphy, tx, tx_max, rx, rx_max);
+- trace_rdev_return_void_tx_rx(&rdev->wiphy, *tx, *tx_max, *rx, *rx_max);
+-}
+-
+ static inline int
+ rdev_sched_scan_start(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+@@ -816,35 +797,6 @@ static inline int rdev_set_noack_map(str
+ }
-+ /* sync with ieee80211_tx_h_unicast_ps_buf */
-+ spin_lock(&sta->ps_lock);
- /* Send all buffered frames to the station */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- int count = skb_queue_len(&pending), tmp;
-@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str
- buffered += tmp - count;
- }
+ static inline int
+-rdev_get_et_sset_count(struct cfg80211_registered_device *rdev,
+- struct net_device *dev, int sset)
+-{
+- int ret;
+- trace_rdev_get_et_sset_count(&rdev->wiphy, dev, sset);
+- ret = rdev->ops->get_et_sset_count(&rdev->wiphy, dev, sset);
+- trace_rdev_return_int(&rdev->wiphy, ret);
+- return ret;
+-}
+-
+-static inline void rdev_get_et_stats(struct cfg80211_registered_device *rdev,
+- struct net_device *dev,
+- struct ethtool_stats *stats, u64 *data)
+-{
+- trace_rdev_get_et_stats(&rdev->wiphy, dev);
+- rdev->ops->get_et_stats(&rdev->wiphy, dev, stats, data);
+- trace_rdev_return_void(&rdev->wiphy);
+-}
+-
+-static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev,
+- struct net_device *dev, u32 sset,
+- u8 *data)
+-{
+- trace_rdev_get_et_strings(&rdev->wiphy, dev, sset);
+- rdev->ops->get_et_strings(&rdev->wiphy, dev, sset, data);
+- trace_rdev_return_void(&rdev->wiphy);
+-}
+-
+-static inline int
+ rdev_get_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_chan_def *chandef)
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -298,11 +298,6 @@ DEFINE_EVENT(wiphy_only_evt, rdev_return
+ TP_ARGS(wiphy)
+ );
-- ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
-+ ieee80211_add_pending_skbs(local, &pending);
-+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-+ clear_sta_flag(sta, WLAN_STA_PS_STA);
-+ spin_unlock(&sta->ps_lock);
-+
-+ atomic_dec(&ps->num_sta_ps);
+-DEFINE_EVENT(wiphy_only_evt, rdev_get_ringparam,
+- TP_PROTO(struct wiphy *wiphy),
+- TP_ARGS(wiphy)
+-);
+-
+ DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna,
+ TP_PROTO(struct wiphy *wiphy),
+ TP_ARGS(wiphy)
+@@ -580,11 +575,6 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_stop
+ TP_ARGS(wiphy, netdev)
+ );
- /* This station just woke up and isn't aware of our SMPS state */
- if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat {
- * @drv_unblock_wk: used for driver PS unblocking
- * @listen_interval: listen interval of this station, when we're acting as AP
- * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
-+ * @ps_lock: used for powersave (when mac80211 is the AP) related locking
- * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
- * when it leaves power saving state or polls
- * @tx_filtered: buffers (per AC) of frames we already tried to
-@@ -356,10 +357,8 @@ struct sta_info {
- /* use the accessors defined below */
- unsigned long _flags;
-
-- /*
-- * STA powersave frame queues, no more than the internal
-- * locking required.
-- */
-+ /* STA powersave lock and frame queues */
-+ spinlock_t ps_lock;
- struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
- struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
- unsigned long driver_buffered_tids;
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- }
+-DEFINE_EVENT(wiphy_netdev_evt, rdev_get_et_stats,
+- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+- TP_ARGS(wiphy, netdev)
+-);
+-
+ DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev)
+@@ -1439,11 +1429,6 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
+ WIPHY_PR_ARG, __entry->tx, __entry->rx)
+ );
--void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
-- struct sk_buff_head *skbs,
-- void (*fn)(void *data), void *data)
-+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
-+ struct sk_buff_head *skbs)
- {
- struct ieee80211_hw *hw = &local->hw;
- struct sk_buff *skb;
-@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc
- __skb_queue_tail(&local->pending[queue], skb);
- }
+-DEFINE_EVENT(tx_rx_evt, rdev_set_ringparam,
+- TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+- TP_ARGS(wiphy, rx, tx)
+-);
+-
+ DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+ TP_ARGS(wiphy, rx, tx)
+@@ -1725,40 +1710,6 @@ TRACE_EVENT(rdev_set_noack_map,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
+ );
-- if (fn)
-- fn(data);
+-TRACE_EVENT(rdev_get_et_sset_count,
+- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int sset),
+- TP_ARGS(wiphy, netdev, sset),
+- TP_STRUCT__entry(
+- WIPHY_ENTRY
+- NETDEV_ENTRY
+- __field(int, sset)
+- ),
+- TP_fast_assign(
+- WIPHY_ASSIGN;
+- NETDEV_ASSIGN;
+- __entry->sset = sset;
+- ),
+- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d",
+- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+-);
-
- for (i = 0; i < hw->queues; i++)
- __ieee80211_wake_queue(hw, i,
- IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regu
- return;
- case NL80211_REGDOM_SET_BY_USER:
- treatment = reg_process_hint_user(reg_request);
-- if (treatment == REG_REQ_OK ||
-+ if (treatment == REG_REQ_IGNORE ||
- treatment == REG_REQ_ALREADY_SET)
- return;
- schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -138,43 +138,41 @@ static ssize_t read_file_ani(struct file
- unsigned int len = 0, size = 1024;
- ssize_t retval = 0;
- char *buf;
-+ int i;
-+ struct {
-+ const char *name;
-+ unsigned int val;
-+ } ani_info[] = {
-+ { "ANI RESET", ah->stats.ast_ani_reset },
-+ { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
-+ { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
-+ { "SPUR UP", ah->stats.ast_ani_spurup },
-+ { "SPUR DOWN", ah->stats.ast_ani_spurup },
-+ { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
-+ { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
-+ { "MRC-CCK ON", ah->stats.ast_ani_ccklow },
-+ { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh },
-+ { "FIR-STEP UP", ah->stats.ast_ani_stepup },
-+ { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown },
-+ { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero },
-+ { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs },
-+ { "CCK ERRORS", ah->stats.ast_ani_cckerrs },
-+ };
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
-- if (common->disable_ani) {
-- len += scnprintf(buf + len, size - len, "%s: %s\n",
-- "ANI", "DISABLED");
-+ len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI",
-+ common->disable_ani ? "DISABLED" : "ENABLED");
+-TRACE_EVENT(rdev_get_et_strings,
+- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 sset),
+- TP_ARGS(wiphy, netdev, sset),
+- TP_STRUCT__entry(
+- WIPHY_ENTRY
+- NETDEV_ENTRY
+- __field(u32, sset)
+- ),
+- TP_fast_assign(
+- WIPHY_ASSIGN;
+- NETDEV_ASSIGN;
+- __entry->sset = sset;
+- ),
+- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u",
+- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
+-);
+-
+ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+--- /dev/null
++++ b/net/mac80211/ethtool.c
+@@ -0,0 +1,244 @@
++/*
++ * mac80211 ethtool hooks for cfg80211
++ *
++ * Copied from cfg.c - originally
++ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
++ * Copyright 2014 Intel Corporation (Author: Johannes Berg)
++ *
++ * This file is GPLv2 as found in COPYING.
++ */
++#include <linux/types.h>
++#include <net/cfg80211.h>
++#include "ieee80211_i.h"
++#include "sta_info.h"
++#include "driver-ops.h"
++
++static int ieee80211_set_ringparam(struct net_device *dev,
++ struct ethtool_ringparam *rp)
++{
++ struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
+
-+ if (common->disable_ani)
- goto exit;
-- }
-
-- len += scnprintf(buf + len, size - len, "%15s: %s\n",
-- "ANI", "ENABLED");
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "ANI RESET", ah->stats.ast_ani_reset);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "SPUR UP", ah->stats.ast_ani_spurup);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "SPUR DOWN", ah->stats.ast_ani_spurup);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "MRC-CCK ON", ah->stats.ast_ani_ccklow);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "FIR-STEP UP", ah->stats.ast_ani_stepup);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
-- len += scnprintf(buf + len, size - len, "%15s: %u\n",
-- "CCK ERRORS", ah->stats.ast_ani_cckerrs);
-+ for (i = 0; i < ARRAY_SIZE(ani_info); i++)
-+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
-+ ani_info[i].name, ani_info[i].val);
++ if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
++ return -EINVAL;
+
- exit:
- if (len > size)
- len = size;
-@@ -866,6 +864,12 @@ static ssize_t read_file_reset(struct fi
- "%17s: %2d\n", "PLL RX Hang",
- sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
- len += scnprintf(buf + len, sizeof(buf) - len,
-+ "%17s: %2d\n", "MAC Hang",
-+ sc->debug.stats.reset[RESET_TYPE_MAC_HANG]);
-+ len += scnprintf(buf + len, sizeof(buf) - len,
-+ "%17s: %2d\n", "Stuck Beacon",
-+ sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]);
-+ len += scnprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "MCI Reset",
- sc->debug.stats.reset[RESET_TYPE_MCI]);
-
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -868,10 +868,6 @@ static void ar9003_hw_set_rfmode(struct
-
- if (IS_CHAN_A_FAST_CLOCK(ah, chan))
- rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-- if (IS_CHAN_QUARTER_RATE(chan))
-- rfMode |= AR_PHY_MODE_QUARTER;
-- if (IS_CHAN_HALF_RATE(chan))
-- rfMode |= AR_PHY_MODE_HALF;
-
- if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF))
- REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-@@ -706,6 +706,7 @@ ath5k_get_survey(struct ieee80211_hw *hw
- survey->channel = conf->chandef.chan;
- survey->noise = ah->ah_noise_floor;
- survey->filled = SURVEY_INFO_NOISE_DBM |
-+ SURVEY_INFO_IN_USE |
- SURVEY_INFO_CHANNEL_TIME |
- SURVEY_INFO_CHANNEL_TIME_BUSY |
- SURVEY_INFO_CHANNEL_TIME_RX |
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx
- return NULL;
-
- /*
-- * mark descriptor as zero-length and set the 'more'
-- * flag to ensure that both buffers get discarded
-+ * Re-check previous descriptor, in case it has been filled
-+ * in the mean time.
- */
-- rs->rs_datalen = 0;
-- rs->rs_more = true;
-+ ret = ath9k_hw_rxprocdesc(ah, ds, rs);
-+ if (ret == -EINPROGRESS) {
-+ /*
-+ * mark descriptor as zero-length and set the 'more'
-+ * flag to ensure that both buffers get discarded
-+ */
-+ rs->rs_datalen = 0;
-+ rs->rs_more = true;
-+ }
- }
-
- list_del(&bf->list);
-@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hdr *hdr;
- bool discard_current = sc->rx.discard_next;
-- int ret = 0;
-
- /*
- * Discard corrupt descriptors which are marked in
- * ath_get_next_rx_buf().
- */
-- sc->rx.discard_next = rx_stats->rs_more;
- if (discard_current)
-- return -EINVAL;
-+ goto corrupt;
++ return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
++}
+
-+ sc->rx.discard_next = false;
-
- /*
- * Discard zero-length packets.
- */
- if (!rx_stats->rs_datalen) {
- RX_STAT_INC(rx_len_err);
-- return -EINVAL;
-+ goto corrupt;
- }
-
-- /*
-- * rs_status follows rs_datalen so if rs_datalen is too large
-- * we can take a hint that hardware corrupted it, so ignore
-- * those frames.
-- */
-+ /*
-+ * rs_status follows rs_datalen so if rs_datalen is too large
-+ * we can take a hint that hardware corrupted it, so ignore
-+ * those frames.
++static void ieee80211_get_ringparam(struct net_device *dev,
++ struct ethtool_ringparam *rp)
++{
++ struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
++
++ memset(rp, 0, sizeof(*rp));
++
++ drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending,
++ &rp->rx_pending, &rp->rx_max_pending);
++}
++
++static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
++ "rx_packets", "rx_bytes",
++ "rx_duplicates", "rx_fragments", "rx_dropped",
++ "tx_packets", "tx_bytes", "tx_fragments",
++ "tx_filtered", "tx_retry_failed", "tx_retries",
++ "beacon_loss", "sta_state", "txrate", "rxrate", "signal",
++ "channel", "noise", "ch_time", "ch_time_busy",
++ "ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
++};
++#define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats)
++
++static int ieee80211_get_sset_count(struct net_device *dev, int sset)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int rv = 0;
++
++ if (sset == ETH_SS_STATS)
++ rv += STA_STATS_LEN;
++
++ rv += drv_get_et_sset_count(sdata, sset);
++
++ if (rv == 0)
++ return -EOPNOTSUPP;
++ return rv;
++}
++
++static void ieee80211_get_stats(struct net_device *dev,
++ struct ethtool_stats *stats,
++ u64 *data)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct ieee80211_chanctx_conf *chanctx_conf;
++ struct ieee80211_channel *channel;
++ struct sta_info *sta;
++ struct ieee80211_local *local = sdata->local;
++ struct station_info sinfo;
++ struct survey_info survey;
++ int i, q;
++#define STA_STATS_SURVEY_LEN 7
++
++ memset(data, 0, sizeof(u64) * STA_STATS_LEN);
++
++#define ADD_STA_STATS(sta) \
++ do { \
++ data[i++] += sta->rx_packets; \
++ data[i++] += sta->rx_bytes; \
++ data[i++] += sta->num_duplicates; \
++ data[i++] += sta->rx_fragments; \
++ data[i++] += sta->rx_dropped; \
++ \
++ data[i++] += sinfo.tx_packets; \
++ data[i++] += sinfo.tx_bytes; \
++ data[i++] += sta->tx_fragments; \
++ data[i++] += sta->tx_filtered_count; \
++ data[i++] += sta->tx_retry_failed; \
++ data[i++] += sta->tx_retry_count; \
++ data[i++] += sta->beacon_loss_count; \
++ } while (0)
++
++ /* For Managed stations, find the single station based on BSSID
++ * and use that. For interface types, iterate through all available
++ * stations and add stats for any station that is assigned to this
++ * network device.
+ */
- if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
- RX_STAT_INC(rx_len_err);
-- return -EINVAL;
-+ goto corrupt;
++
++ mutex_lock(&local->sta_mtx);
++
++ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
++ sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
++
++ if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
++ goto do_survey;
++
++ sinfo.filled = 0;
++ sta_set_sinfo(sta, &sinfo);
++
++ i = 0;
++ ADD_STA_STATS(sta);
++
++ data[i++] = sta->sta_state;
++
++
++ if (sinfo.filled & STATION_INFO_TX_BITRATE)
++ data[i] = 100000 *
++ cfg80211_calculate_bitrate(&sinfo.txrate);
++ i++;
++ if (sinfo.filled & STATION_INFO_RX_BITRATE)
++ data[i] = 100000 *
++ cfg80211_calculate_bitrate(&sinfo.rxrate);
++ i++;
++
++ if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
++ data[i] = (u8)sinfo.signal_avg;
++ i++;
++ } else {
++ list_for_each_entry(sta, &local->sta_list, list) {
++ /* Make sure this station belongs to the proper dev */
++ if (sta->sdata->dev != dev)
++ continue;
++
++ sinfo.filled = 0;
++ sta_set_sinfo(sta, &sinfo);
++ i = 0;
++ ADD_STA_STATS(sta);
++ }
++ }
++
++do_survey:
++ i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
++ /* Get survey stats for current channel */
++ survey.filled = 0;
++
++ rcu_read_lock();
++ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
++ if (chanctx_conf)
++ channel = chanctx_conf->def.chan;
++ else
++ channel = NULL;
++ rcu_read_unlock();
++
++ if (channel) {
++ q = 0;
++ do {
++ survey.filled = 0;
++ if (drv_get_survey(local, q, &survey) != 0) {
++ survey.filled = 0;
++ break;
++ }
++ q++;
++ } while (channel != survey.channel);
++ }
++
++ if (survey.filled)
++ data[i++] = survey.channel->center_freq;
++ else
++ data[i++] = 0;
++ if (survey.filled & SURVEY_INFO_NOISE_DBM)
++ data[i++] = (u8)survey.noise;
++ else
++ data[i++] = -1LL;
++ if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
++ data[i++] = survey.channel_time;
++ else
++ data[i++] = -1LL;
++ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
++ data[i++] = survey.channel_time_busy;
++ else
++ data[i++] = -1LL;
++ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
++ data[i++] = survey.channel_time_ext_busy;
++ else
++ data[i++] = -1LL;
++ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
++ data[i++] = survey.channel_time_rx;
++ else
++ data[i++] = -1LL;
++ if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
++ data[i++] = survey.channel_time_tx;
++ else
++ data[i++] = -1LL;
++
++ mutex_unlock(&local->sta_mtx);
++
++ if (WARN_ON(i != STA_STATS_LEN))
++ return;
++
++ drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
++}
++
++static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
++{
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ int sz_sta_stats = 0;
++
++ if (sset == ETH_SS_STATS) {
++ sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
++ memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
++ }
++ drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
++}
++
++static int ieee80211_get_regs_len(struct net_device *dev)
++{
++ return 0;
++}
++
++static void ieee80211_get_regs(struct net_device *dev,
++ struct ethtool_regs *regs,
++ void *data)
++{
++ struct wireless_dev *wdev = dev->ieee80211_ptr;
++
++ regs->version = wdev->wiphy->hw_version;
++ regs->len = 0;
++}
++
++const struct ethtool_ops ieee80211_ethtool_ops = {
++ .get_drvinfo = cfg80211_get_drvinfo,
++ .get_regs_len = ieee80211_get_regs_len,
++ .get_regs = ieee80211_get_regs,
++ .get_link = ethtool_op_get_link,
++ .get_ringparam = ieee80211_get_ringparam,
++ .set_ringparam = ieee80211_set_ringparam,
++ .get_strings = ieee80211_get_strings,
++ .get_ethtool_stats = ieee80211_get_stats,
++ .get_sset_count = ieee80211_get_sset_count,
++};
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80
+ *pos++ = csa_settings->block_tx ? 1 : 0;
+ *pos++ = ieee80211_frequency_to_channel(
+ csa_settings->chandef.chan->center_freq);
+- sdata->csa_counter_offset_beacon[0] = (pos - presp->head);
++ presp->csa_counter_offsets[0] = (pos - presp->head);
+ *pos++ = csa_settings->count;
}
- /* Only use status info from the last fragment */
-@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc
- * This is different from the other corrupt descriptor
- * condition handled above.
- */
-- if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
-- ret = -EINVAL;
-- goto exit;
-- }
-+ if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
-+ goto corrupt;
-
- hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
-
-@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc
- if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
- RX_STAT_INC(rx_spectral);
+@@ -1677,6 +1677,7 @@ int ieee80211_ibss_join(struct ieee80211
+ sdata->u.ibss.control_port = params->control_port;
+ sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs;
+ sdata->u.ibss.basic_rates = params->basic_rates;
++ sdata->u.ibss.last_scan_completed = jiffies;
-- ret = -EINVAL;
-- goto exit;
-+ return -EINVAL;
+ /* fix basic_rates if channel does not support these rates */
+ rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee8
+ *pos++ = 0x0;
+ *pos++ = ieee80211_frequency_to_channel(
+ csa->settings.chandef.chan->center_freq);
+- sdata->csa_counter_offset_beacon[0] = hdr_len + 6;
++ bcn->csa_counter_offsets[0] = hdr_len + 6;
+ *pos++ = csa->settings.count;
+ *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
+ *pos++ = 6;
+--- a/net/wireless/genregdb.awk
++++ b/net/wireless/genregdb.awk
+@@ -65,17 +65,7 @@ function parse_reg_rule()
+ sub(/,/, "", units)
+ dfs_cac = $9
+ if (units == "mW") {
+- if (power == 100) {
+- power = 20
+- } else if (power == 200) {
+- power = 23
+- } else if (power == 500) {
+- power = 27
+- } else if (power == 1000) {
+- power = 30
+- } else {
+- print "Unknown power value in database!"
+- }
++ power = 10 * log(power)/log(10)
+ } else {
+ dfs_cac = $8
}
+@@ -114,7 +104,7 @@ function parse_reg_rule()
- /*
- * everything but the rate is checked here, the rate check is done
- * separately to avoid doing two lookups for a rate for each frame.
- */
-- if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
-- ret = -EINVAL;
-- goto exit;
-- }
-+ if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
-+ return -EINVAL;
-
- if (ath_is_mybeacon(common, hdr)) {
- RX_STAT_INC(rx_beacons);
-@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc
- /*
- * This shouldn't happen, but have a safety check anyway.
- */
-- if (WARN_ON(!ah->curchan)) {
-- ret = -EINVAL;
-- goto exit;
-- }
-+ if (WARN_ON(!ah->curchan))
-+ return -EINVAL;
-
-- if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
-- ret =-EINVAL;
-- goto exit;
-- }
-+ if (ath9k_process_rate(common, hw, rx_stats, rx_status))
-+ return -EINVAL;
-
- ath9k_process_rssi(common, hw, rx_stats, rx_status);
+ }
+ flags = flags "0"
+- printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
++ printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
+ rules++
+ }
-@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc
- sc->rx.num_pkts++;
- #endif
+--- a/net/mac80211/debugfs_netdev.c
++++ b/net/mac80211/debugfs_netdev.c
+@@ -34,8 +34,7 @@ static ssize_t ieee80211_if_read(
+ ssize_t ret = -EINVAL;
--exit:
-- sc->rx.discard_next = false;
-- return ret;
-+ return 0;
-+
-+corrupt:
-+ sc->rx.discard_next = rx_stats->rs_more;
-+ return -EINVAL;
- }
+ read_lock(&dev_base_lock);
+- if (sdata->dev->reg_state == NETREG_REGISTERED)
+- ret = (*format)(sdata, buf, sizeof(buf));
++ ret = (*format)(sdata, buf, sizeof(buf));
+ read_unlock(&dev_base_lock);
- static void ath9k_rx_skb_postprocess(struct ath_common *common,
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -176,16 +176,26 @@ static void ath9k_hw_set_ofdm_nil(struct
- if (ah->opmode == NL80211_IFTYPE_STATION &&
- BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
- weak_sig = true;
--
- /*
-- * OFDM Weak signal detection is always enabled for AP mode.
-+ * Newer chipsets are better at dealing with high PHY error counts -
-+ * keep weak signal detection enabled when no RSSI threshold is
-+ * available to determine if it is needed (mode != STA)
- */
-- if (ah->opmode != NL80211_IFTYPE_AP &&
-- aniState->ofdmWeakSigDetect != weak_sig) {
-- ath9k_hw_ani_control(ah,
-- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-- entry_ofdm->ofdm_weak_signal_on);
-- }
-+ else if (AR_SREV_9300_20_OR_LATER(ah) &&
-+ ah->opmode != NL80211_IFTYPE_STATION)
-+ weak_sig = true;
-+
-+ /* Older chipsets are more sensitive to high PHY error counts */
-+ else if (!AR_SREV_9300_20_OR_LATER(ah) &&
-+ aniState->ofdmNoiseImmunityLevel >= 8)
-+ weak_sig = false;
-+
-+ if (aniState->ofdmWeakSigDetect != weak_sig)
-+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
-+ weak_sig);
-+
-+ if (!AR_SREV_9300_20_OR_LATER(ah))
-+ return;
+ if (ret >= 0)
+@@ -62,8 +61,7 @@ static ssize_t ieee80211_if_write(
- if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
-@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah,
- BUG_ON(aniState == NULL);
- ah->stats.ast_ani_reset++;
-
-- /* only allow a subset of functions in AP mode */
-- if (ah->opmode == NL80211_IFTYPE_AP) {
-- if (IS_CHAN_2GHZ(chan)) {
-- ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
-- ATH9K_ANI_FIRSTEP_LEVEL);
-- if (AR_SREV_9300_20_OR_LATER(ah))
-- ah->ani_function |= ATH9K_ANI_MRC_CCK;
-- } else
-- ah->ani_function = 0;
-- }
--
- ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
- aniState->ofdmNoiseImmunityLevel);
- cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
-@@ -483,10 +482,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah
-
- ath_dbg(common, ANI, "Initialize ANI\n");
-
-- ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
-- ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
-- ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
-- ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
-+ if (AR_SREV_9300_20_OR_LATER(ah)) {
-+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
-+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
-+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
-+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
-+ } else {
-+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
-+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
-+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
-+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
-+ }
+ ret = -ENODEV;
+ rtnl_lock();
+- if (sdata->dev->reg_state == NETREG_REGISTERED)
+- ret = (*write)(sdata, buf, count);
++ ret = (*write)(sdata, buf, count);
+ rtnl_unlock();
- ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
- ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
---- a/drivers/net/wireless/ath/ath9k/ani.h
-+++ b/drivers/net/wireless/ath/ath9k/ani.h
-@@ -22,12 +22,16 @@
- /* units are errors per second */
- #define ATH9K_ANI_OFDM_TRIG_HIGH 3500
- #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
-+#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
-
- #define ATH9K_ANI_OFDM_TRIG_LOW 400
- #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
-+#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
-
- #define ATH9K_ANI_CCK_TRIG_HIGH 600
-+#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
- #define ATH9K_ANI_CCK_TRIG_LOW 300
-+#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
-
- #define ATH9K_ANI_SPUR_IMMUNE_LVL 3
- #define ATH9K_ANI_FIRSTEP_LVL 2
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -26,10 +26,6 @@ static const int firstep_table[] =
- /* level: 0 1 2 3 4 5 6 7 8 */
- { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
-
--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
- */
-@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(st
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_channel *chan = ah->curchan;
- struct ar5416AniState *aniState = &ah->ani;
-- s32 value, value2;
-+ s32 value;
-
- switch (cmd & ah->ani_function) {
- case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
-@@ -1008,42 +1004,9 @@ static bool ar5008_hw_ani_control_new(st
- case ATH9K_ANI_FIRSTEP_LEVEL:{
- u32 level = param;
-
-- if (level >= ARRAY_SIZE(firstep_table)) {
-- ath_dbg(common, ANI,
-- "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
-- level, ARRAY_SIZE(firstep_table));
-- return false;
-- }
--
-- /*
-- * make register setting relative to default
-- * from INI file & cap value
-- */
-- value = firstep_table[level] -
-- firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
-- aniState->iniDef.firstep;
-- if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
-- value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
-- if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
-- value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
-+ value = level;
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-- AR_PHY_FIND_SIG_FIRSTEP,
-- value);
-- /*
-- * we need to set first step low register too
-- * make register setting relative to default
-- * from INI file & cap value
-- */
-- value2 = firstep_table[level] -
-- firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
-- aniState->iniDef.firstepLow;
-- if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
-- value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
-- if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
-- value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
--
-- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
-- AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
-+ AR_PHY_FIND_SIG_FIRSTEP, value);
-
- if (level != aniState->firstepLevel) {
- ath_dbg(common, ANI,
-@@ -1060,7 +1023,7 @@ static bool ar5008_hw_ani_control_new(st
- aniState->firstepLevel,
- level,
- ATH9K_ANI_FIRSTEP_LVL,
-- value2,
-+ value,
- aniState->iniDef.firstepLow);
- if (level > aniState->firstepLevel)
- ah->stats.ast_ani_stepup++;
-@@ -1073,41 +1036,13 @@ static bool ar5008_hw_ani_control_new(st
- case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
- u32 level = param;
-
-- if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
-- ath_dbg(common, ANI,
-- "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
-- level, ARRAY_SIZE(cycpwrThr1_table));
-- return false;
-- }
-- /*
-- * make register setting relative to default
-- * from INI file & cap value
-- */
-- value = cycpwrThr1_table[level] -
-- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
-- aniState->iniDef.cycpwrThr1;
-- if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
-- value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
-- if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
-- value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
-+ value = (level + 1) * 2;
- REG_RMW_FIELD(ah, AR_PHY_TIMING5,
-- AR_PHY_TIMING5_CYCPWR_THR1,
-- value);
-+ AR_PHY_TIMING5_CYCPWR_THR1, value);
-
-- /*
-- * set AR_PHY_EXT_CCA for extension channel
-- * make register setting relative to default
-- * from INI file & cap value
-- */
-- value2 = cycpwrThr1_table[level] -
-- cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
-- aniState->iniDef.cycpwrThr1Ext;
-- if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
-- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
-- if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
-- value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
-- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
-- AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
-+ if (IS_CHAN_HT40(ah->curchan))
-+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
-+ AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
-
- if (level != aniState->spurImmunityLevel) {
- ath_dbg(common, ANI,
-@@ -1124,7 +1059,7 @@ static bool ar5008_hw_ani_control_new(st
- aniState->spurImmunityLevel,
- level,
- ATH9K_ANI_SPUR_IMMUNE_LVL,
-- value2,
-+ value,
- aniState->iniDef.cycpwrThr1Ext);
- if (level > aniState->spurImmunityLevel)
- ah->stats.ast_ani_spurup++;
+ return ret;
diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch
index 389a003..23ecd37 100644
--- a/package/mac80211/patches/310-ap_scan.patch
+++ b/package/mac80211/patches/310-ap_scan.patch
@@ -1,6 +1,6 @@
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy *
+@@ -1903,7 +1903,7 @@ static int ieee80211_scan(struct wiphy *
* the frames sent while scanning on other channel will be
* lost)
*/
diff --git a/package/mac80211/patches/400-ath_move_debug_code.patch b/package/mac80211/patches/400-ath_move_debug_code.patch
index 0dba7ac..4cc77af 100644
--- a/package/mac80211/patches/400-ath_move_debug_code.patch
+++ b/package/mac80211/patches/400-ath_move_debug_code.patch
@@ -12,7 +12,7 @@
ccflags-y += -D__CHECK_ENDIAN__
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
-@@ -282,13 +282,6 @@ void _ath_dbg(struct ath_common *common,
+@@ -295,13 +295,6 @@ void _ath_dbg(struct ath_common *common,
#endif /* CPTCFG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */
diff --git a/package/mac80211/patches/403-ath_regd_optional.patch b/package/mac80211/patches/403-ath_regd_optional.patch
index 07c54cc..808e729 100644
--- a/package/mac80211/patches/403-ath_regd_optional.patch
+++ b/package/mac80211/patches/403-ath_regd_optional.patch
@@ -58,7 +58,7 @@
---help---
--- a/.local-symbols
+++ b/.local-symbols
-@@ -119,6 +119,7 @@ RTL8187_LEDS=
+@@ -116,6 +116,7 @@ RTL8187_LEDS=
ATH_COMMON=
ATH_CARDS=
ATH_DEBUG=
diff --git a/package/mac80211/patches/405-regd_no_assoc_hints.patch b/package/mac80211/patches/405-regd_no_assoc_hints.patch
index 6ad4fda..2152433 100644
--- a/package/mac80211/patches/405-regd_no_assoc_hints.patch
+++ b/package/mac80211/patches/405-regd_no_assoc_hints.patch
@@ -1,6 +1,6 @@
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
-@@ -1878,6 +1878,8 @@ void regulatory_hint_country_ie(struct w
+@@ -2080,6 +2080,8 @@ void regulatory_hint_country_ie(struct w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request = NULL, *lr;
@@ -9,7 +9,7 @@
/* IE len must be evenly divisible by 2 */
if (country_ie_len & 0x01)
return;
-@@ -2072,6 +2074,7 @@ static void restore_regulatory_settings(
+@@ -2276,6 +2278,7 @@ static void restore_regulatory_settings(
void regulatory_hint_disconnect(void)
{
diff --git a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
index 1f71e0b..ce752f1 100644
--- a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
+++ b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
@@ -1,8 +1,8 @@
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -866,6 +866,7 @@ static const struct ieee80211_iface_limi
- #endif
- BIT(NL80211_IFTYPE_AP) |
+@@ -655,6 +655,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) },
};
diff --git a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
index 3487ab2..1f06994 100644
--- a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
+++ b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
@@ -18,7 +18,7 @@
goto end;
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1934,7 +1934,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+@@ -1937,7 +1937,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
}
if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
@@ -27,7 +27,7 @@
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
-@@ -2020,7 +2020,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -2023,7 +2023,7 @@ ath5k_beacon_update_timers(struct ath5k_
intval = ah->bintval & AR5K_BEACON_PERIOD;
if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
@@ -36,7 +36,7 @@
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15)
ATH5K_WARN(ah, "intval %u is too low, min 15\n",
-@@ -2487,6 +2487,7 @@ static const struct ieee80211_iface_limi
+@@ -2490,6 +2490,7 @@ static const struct ieee80211_iface_limi
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_AP) },
diff --git a/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch b/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
index a223b38..5cb4b51 100644
--- a/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
+++ b/package/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch
@@ -22,14 +22,14 @@
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)
++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
+ return false;
-+
++
+ *data = pdata->eeprom_data[offset];
+ return true;
+ }
diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
index 664cf45..65821fe 100644
--- a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
+++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1481,6 +1481,53 @@ void ath9k_deinit_debug(struct ath_softc
+@@ -1289,6 +1289,53 @@ void ath9k_deinit_debug(struct ath_softc
ath9k_spectral_deinit_debug(sc);
}
@@ -54,7 +54,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1500,6 +1547,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1308,6 +1355,8 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_tx99_init_debug(sc);
ath9k_spectral_init_debug(sc);
diff --git a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch
index 96e7c6d..169eb9a 100644
--- a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch
+++ b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch
@@ -81,7 +81,7 @@
struct ath_ops reg_ops;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;
diff --git a/package/mac80211/patches/502-ath9k_ahb_init.patch b/package/mac80211/patches/502-ath9k_ahb_init.patch
index 4edc63b..0c8e813 100644
--- a/package/mac80211/patches/502-ath9k_ahb_init.patch
+++ b/package/mac80211/patches/502-ath9k_ahb_init.patch
@@ -1,15 +1,15 @@
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1112,23 +1112,23 @@ static int __init ath9k_init(void)
- goto err_out;
- }
+@@ -904,23 +904,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_rate_unregister;
+ goto err_out;
}
- error = ath_ahb_init();
@@ -27,6 +27,6 @@
- ath_pci_exit();
+ err_ahb_exit:
+ ath_ahb_exit();
-
- err_rate_unregister:
- ath_rate_control_unregister();
+ err_out:
+ return error;
+ }
diff --git a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
index ef0b9a1..e457267 100644
--- a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
+++ b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc *
+@@ -89,7 +89,7 @@ int ath_descdma_setup(struct ath_softc *
(_l) &= ((_sz) - 1); \
} while (0)
diff --git a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
index 8f3cc03..c0e173f 100644
--- a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
+++ b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1528,6 +1528,52 @@ static const struct file_operations fops
+@@ -1336,6 +1336,52 @@ static const struct file_operations fops
.owner = THIS_MODULE
};
@@ -35,7 +35,7 @@
+ return -EINVAL;
+
+ common->chan_bw = chan_bw;
-+ if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
++ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
+ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ return count;
@@ -53,7 +53,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1549,6 +1595,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1357,6 +1403,8 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_eeprom);
@@ -64,17 +64,17 @@
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
-@@ -130,6 +130,7 @@ struct ath_common {
- struct ieee80211_hw *hw;
+@@ -140,6 +140,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
-@@ -52,11 +52,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
+@@ -296,11 +296,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
/*
* Update internal channel flags.
*/
@@ -89,7 +89,7 @@
ichan->channel = chan->center_freq;
ichan->chan = chan;
-@@ -64,7 +66,19 @@ static void ath9k_cmn_update_ichannel(st
+@@ -308,7 +310,19 @@ static void ath9k_cmn_update_ichannel(st
if (chan->band == IEEE80211_BAND_5GHZ)
flags |= CHANNEL_5GHZ;
@@ -110,7 +110,7 @@
case NL80211_CHAN_WIDTH_5:
flags |= CHANNEL_QUARTER;
break;
-@@ -97,10 +111,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
+@@ -341,10 +355,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
struct cfg80211_chan_def *chandef)
{
struct ieee80211_channel *curchan = chandef->chan;
diff --git a/package/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch
index 6df95bc..ef7906e 100644
--- a/package/mac80211/patches/520-mac80211_cur_txpower.patch
+++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch
@@ -1,6 +1,6 @@
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1711,6 +1711,7 @@ struct ieee80211_hw {
+@@ -1718,6 +1718,7 @@ struct ieee80211_hw {
u8 max_tx_aggregation_subframes;
u8 offchannel_tx_hw_queue;
u8 radiotap_mcs_details;
@@ -10,7 +10,7 @@
u8 uapsd_queues;
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct
+@@ -2084,7 +2084,9 @@ static int ieee80211_get_tx_power(struct
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -23,7 +23,7 @@
*dbm = sdata->vif.bss_conf.txpower;
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -158,6 +158,7 @@ static u32 ieee80211_hw_conf_chan(struct
+@@ -156,6 +156,7 @@ static u32 ieee80211_hw_conf_chan(struct
if (local->hw.conf.power_level != power) {
changed |= IEEE80211_CONF_CHANGE_POWER;
diff --git a/package/mac80211/patches/521-ath9k_cur_txpower.patch b/package/mac80211/patches/521-ath9k_cur_txpower.patch
index 0d6c360..83ff465 100644
--- a/package/mac80211/patches/521-ath9k_cur_txpower.patch
+++ b/package/mac80211/patches/521-ath9k_cur_txpower.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -308,8 +308,12 @@ static int ath_reset_internal(struct ath
+@@ -310,8 +310,12 @@ static int ath_reset_internal(struct ath
(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
ath9k_mci_set_txpower(sc, true, false);
@@ -14,7 +14,7 @@
out:
spin_unlock_bh(&sc->sc_pcu_lock);
-@@ -1371,6 +1375,7 @@ static int ath9k_config(struct ieee80211
+@@ -1405,6 +1409,7 @@ static int ath9k_config(struct ieee80211
sc->config.txpowlimit = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
index 308ee6e..2109d2e 100644
--- a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
+++ b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
@@ -1,6 +1,6 @@
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -2156,6 +2156,7 @@ struct cfg80211_qos_map {
+@@ -2207,6 +2207,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
@@ -8,7 +8,7 @@
*
* @set_wds_peer: set the WDS peer for a WDS interface
*
-@@ -2380,6 +2381,7 @@ struct cfg80211_ops {
+@@ -2431,6 +2432,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);
@@ -18,7 +18,7 @@
const u8 *addr);
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1033,6 +1033,7 @@ enum ieee80211_smps_mode {
+@@ -1032,6 +1032,7 @@ enum ieee80211_smps_mode {
*
* @power_level: requested transmit power (in dBm), backward compatibility
* value only that is set to the minimum of all interfaces
@@ -26,7 +26,7 @@
*
* @chandef: the channel definition to tune to
* @radar_enabled: whether radar detection is enabled
-@@ -1054,6 +1055,7 @@ struct ieee80211_conf {
+@@ -1053,6 +1054,7 @@ struct ieee80211_conf {
u32 flags;
int power_level, dynamic_ps_timeout;
int max_sleep_period;
@@ -36,9 +36,9 @@
u8 ps_dtim_period;
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
-@@ -1555,6 +1555,9 @@ enum nl80211_commands {
- * data is in the format defined for the payload of the QoS Map Set element
- * in IEEE Std 802.11-2012, 8.4.2.97.
+@@ -1591,6 +1591,9 @@ enum nl80211_commands {
+ * creation then the new interface will be owned by the netlink socket
+ * that created it and will be destroyed when the socket is closed
*
+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
+ * transmit power to stay within regulatory limits. u32, dBi.
@@ -46,9 +46,9 @@
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
-@@ -1883,6 +1886,8 @@ enum nl80211_attrs {
-
- NL80211_ATTR_QOS_MAP,
+@@ -1931,6 +1934,8 @@ enum nl80211_attrs {
+ NL80211_ATTR_CSA_C_OFFSETS_TX,
+ NL80211_ATTR_MAX_CSA_COUNTERS,
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
+
@@ -57,7 +57,7 @@
__NL80211_ATTR_AFTER_LAST,
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct
+@@ -2094,6 +2094,19 @@ static int ieee80211_get_tx_power(struct
return 0;
}
@@ -77,7 +77,7 @@
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr)
{
-@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops
+@@ -3517,6 +3530,7 @@ const struct cfg80211_ops mac80211_confi
.set_wiphy_params = ieee80211_set_wiphy_params,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
@@ -87,7 +87,7 @@
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1221,6 +1221,7 @@ struct ieee80211_local {
+@@ -1243,6 +1243,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */
@@ -97,39 +97,29 @@
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
+@@ -97,7 +97,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, ant_gain, max_power;
++ int power, max_power;
u32 offchannel_flag;
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct
+@@ -154,6 +154,12 @@ static u32 ieee80211_hw_conf_chan(struct
}
rcu_read_unlock();
-- if (local->hw.conf.power_level != power) {
+ max_power = chandef.chan->max_reg_power;
-+ ant_gain = chandef.chan->max_antenna_gain;
+ if (local->user_antenna_gain > 0) {
-+ if (local->user_antenna_gain > ant_gain) {
-+ max_power -= local->user_antenna_gain - ant_gain;
-+ ant_gain = 0;
-+ } else
-+ ant_gain -= local->user_antenna_gain;
++ max_power -= local->user_antenna_gain;
+ power = min(power, max_power);
+ }
+
-+ if (local->hw.conf.power_level != power ||
-+ local->hw.conf.max_antenna_gain != ant_gain) {
+ if (local->hw.conf.power_level != power) {
changed |= IEEE80211_CONF_CHANGE_POWER;
-+ local->hw.conf.max_antenna_gain = ant_gain;
local->hw.cur_power_level = power;
- local->hw.conf.power_level = power;
- }
-@@ -584,6 +597,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
+@@ -584,6 +590,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;
@@ -139,32 +129,30 @@
local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -384,6 +384,7 @@ static const struct nla_policy nl80211_p
- [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
- [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
- .len = IEEE80211_QOS_MAP_LEN_MAX },
+@@ -387,6 +387,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
+ [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
+ [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
+ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
};
/* policy for the key attributes */
-@@ -2105,6 +2106,22 @@ static int nl80211_set_wiphy(struct sk_b
- goto bad_res;
+@@ -2162,6 +2163,20 @@ static int nl80211_set_wiphy(struct sk_b
+ return result;
}
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
+ int idx, dbi = 0;
+
-+ if (!rdev->ops->set_antenna_gain) {
-+ result = -EOPNOTSUPP;
-+ goto bad_res;
-+ }
++ 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)
-+ goto bad_res;
++ return result;
+ }
+
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
diff --git a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
index 30aa9ee..0b28ab8 100644
--- a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
+++ b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
-@@ -74,6 +74,7 @@ struct ath_regulatory {
+@@ -83,6 +83,7 @@ struct ath_regulatory {
u16 max_power_level;
u16 current_rd;
int16_t power_limit;
@@ -21,7 +21,7 @@
if (ant_gain > max_gain)
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211
+@@ -1405,7 +1405,10 @@ static int ath9k_config(struct ieee80211
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
diff --git a/package/mac80211/patches/530-ath9k_extra_leds.patch b/package/mac80211/patches/530-ath9k_extra_leds.patch
index 59f78d9..b5f2f8b 100644
--- a/package/mac80211/patches/530-ath9k_extra_leds.patch
+++ b/package/mac80211/patches/530-ath9k_extra_leds.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -563,6 +563,9 @@ static inline int ath9k_dump_btcoex(stru
+@@ -564,6 +564,9 @@ static inline int ath9k_dump_btcoex(stru
void ath_init_leds(struct ath_softc *sc);
void ath_deinit_leds(struct ath_softc *sc);
void ath_fill_led_pin(struct ath_softc *sc);
@@ -10,7 +10,7 @@
#else
static inline void ath_init_leds(struct ath_softc *sc)
{
-@@ -710,6 +713,13 @@ enum sc_op_flags {
+@@ -702,6 +705,13 @@ void ath_ant_comb_scan(struct ath_softc
#define PS_BEACON_SYNC BIT(4)
#define PS_WAIT_FOR_ANI BIT(5)
@@ -24,8 +24,8 @@
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
-@@ -751,9 +761,8 @@ struct ath_softc {
- struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+@@ -744,9 +754,8 @@ struct ath_softc {
+ struct ath_beacon beacon;
#ifdef CPTCFG_MAC80211_LEDS
- bool led_registered;
@@ -162,7 +162,7 @@
void ath_fill_led_pin(struct ath_softc *sc)
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1018,7 +1018,7 @@ int ath9k_init_device(u16 devid, struct
+@@ -815,7 +815,7 @@ int ath9k_init_device(u16 devid, struct
#ifdef CPTCFG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */
@@ -173,7 +173,7 @@
#endif
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1573,6 +1573,61 @@ static const struct file_operations fops
+@@ -1381,6 +1381,61 @@ static const struct file_operations fops
.llseek = default_llseek,
};
@@ -235,7 +235,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
-@@ -1597,6 +1652,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1405,6 +1460,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_eeprom);
debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_chanbw);
diff --git a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
index 6c9832c..718a3d0 100644
--- a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
+++ b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch
@@ -1,9 +1,9 @@
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
-@@ -37,6 +37,9 @@ struct ath9k_platform_data {
-
- int (*get_mac_revision)(void);
+@@ -39,6 +39,9 @@ struct ath9k_platform_data {
int (*external_reset)(void);
+
+ bool use_eeprom;
+
+ int num_leds;
+ const struct gpio_led *leds;
diff --git a/package/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/mac80211/patches/542-ath9k_debugfs_diag.patch
index e1b6ff1..2a56352 100644
--- a/package/mac80211/patches/542-ath9k_debugfs_diag.patch
+++ b/package/mac80211/patches/542-ath9k_debugfs_diag.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1629,6 +1629,50 @@ static const struct file_operations fops
+@@ -1437,6 +1437,50 @@ static const struct file_operations fops
#endif
@@ -51,7 +51,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1656,6 +1700,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1464,6 +1508,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
@@ -125,7 +125,7 @@
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
-@@ -602,6 +602,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+@@ -606,6 +606,11 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_debug_sync_cause(sc, sync_cause);
status &= ah->imask; /* discard unasked-for bits */
diff --git a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
index d26a5af..0501582 100644
--- a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
+++ b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
@@ -58,7 +58,7 @@
};
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -518,6 +518,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;
diff --git a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
index b59c362..7210a02 100644
--- a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
+++ b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
@@ -55,7 +55,7 @@
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -846,7 +846,8 @@ static void ath9k_init_txpower_limits(st
+@@ -646,7 +646,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);
@@ -64,8 +64,8 @@
+ ah->curchan = curchan;
}
- void ath9k_reload_chainmask_settings(struct ath_softc *sc)
-@@ -980,6 +981,18 @@ static void ath9k_set_hw_capab(struct at
+ static const struct ieee80211_iface_limit if_limits[] = {
+@@ -774,6 +775,18 @@ static void ath9k_set_hw_capab(struct at
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
}
@@ -84,7 +84,7 @@
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops)
{
-@@ -1025,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct
+@@ -822,6 +835,8 @@ int ath9k_init_device(u16 devid, struct
ARRAY_SIZE(ath9k_tpt_blink));
#endif
@@ -110,7 +110,7 @@
static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
-@@ -307,6 +307,11 @@ void ath_ani_calibrate(unsigned long dat
+@@ -308,6 +308,11 @@ void ath_ani_calibrate(unsigned long dat
unsigned int timestamp = jiffies_to_msecs(jiffies);
u32 cal_interval, short_cal_interval, long_cal_interval;
unsigned long flags;
diff --git a/package/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/551-ath9k-ar933x-usb-hang-workaround.patch
new file mode 100644
index 0000000..10280d9
--- /dev/null
+++ b/package/mac80211/patches/551-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
+@@ -215,6 +215,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 */
+ /******************/
+@@ -1337,6 +1350,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;
+ }
+
+@@ -1436,6 +1452,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;
+ }
+
+@@ -1730,8 +1749,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;
+ }
+
+@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+
++ 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/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
deleted file mode 100644
index ffffe0c..0000000
--- a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From c997a1da25fe7c717ed099888b8eb35d4e139e70 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@openwrt.org>
-Date: Sun, 8 Dec 2013 08:52:52 +0100
-Subject: [PATCH] ath9k: support only one P2P interface
-
-Preparation for adding P2P powersave and multi-channel support.
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
- drivers/net/wireless/ath/ath9k/init.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -863,15 +863,15 @@ void ath9k_reload_chainmask_settings(str
-
- static const struct ieee80211_iface_limit if_limits[] = {
- { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
-- BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_WDS) },
- { .max = 8, .types =
- #ifdef CPTCFG_MAC80211_MESH
- BIT(NL80211_IFTYPE_MESH_POINT) |
- #endif
-- BIT(NL80211_IFTYPE_AP) |
-- BIT(NL80211_IFTYPE_P2P_GO) },
-+ BIT(NL80211_IFTYPE_AP) },
- { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
-+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-+ BIT(NL80211_IFTYPE_P2P_GO) },
- };
-
- static const struct ieee80211_iface_limit if_dfs_limits[] = {
diff --git a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
deleted file mode 100644
index 4a61db3..0000000
--- a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-From 6744d0a7ea037c7d65e13ca906da93009b241d00 Mon Sep 17 00:00:00 2001
-From: Felix Fietkau <nbd@openwrt.org>
-Date: Tue, 11 Feb 2014 11:16:24 +0100
-Subject: [PATCH] ath9k: implement p2p client powersave support
-
-Use generic TSF timers to trigger powersave state changes based
-information from the P2P NoA attribute.
-Opportunistic Powersave is not handled, because the driver does not
-support powersave at the moment.
-
-Signed-off-by: Felix Fietkau <nbd@openwrt.org>
----
- drivers/net/wireless/ath/ath9k/ath9k.h | 12 ++++
- drivers/net/wireless/ath/ath9k/init.c | 6 ++
- drivers/net/wireless/ath/ath9k/main.c | 104 +++++++++++++++++++++++++++++++++
- drivers/net/wireless/ath/ath9k/recv.c | 3 +
- 4 files changed, 125 insertions(+)
-
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -261,6 +261,8 @@ static bool ath_complete_reset(struct at
- sc->gtt_cnt = 0;
- ieee80211_wake_queues(sc->hw);
-
-+ ath9k_p2p_ps_timer(sc);
-+
- return true;
- }
-
-@@ -1126,6 +1128,8 @@ static int ath9k_add_interface(struct ie
- if (ath9k_uses_beacons(vif->type))
- ath9k_beacon_assign_slot(sc, vif);
-
-+ avp->vif = vif;
-+
- an->sc = sc;
- an->sta = NULL;
- an->vif = vif;
-@@ -1170,6 +1174,29 @@ static int ath9k_change_interface(struct
- return 0;
- }
-
-+static void
-+ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ s32 tsf, target_tsf;
-+
-+ if (!avp || !avp->noa.has_next_tsf)
-+ return;
-+
-+ ath9k_hw_gen_timer_stop(ah, sc->p2p_ps_timer);
-+
-+ tsf = ath9k_hw_gettsf32(sc->sc_ah);
-+
-+ target_tsf = avp->noa.next_tsf;
-+ if (!avp->noa.absent)
-+ target_tsf -= ATH_P2P_PS_STOP_TIME;
-+
-+ if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
-+ target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
-+
-+ ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000);
-+}
-+
- static void ath9k_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
- {
-@@ -1181,6 +1208,13 @@ static void ath9k_remove_interface(struc
-
- mutex_lock(&sc->mutex);
-
-+ spin_lock_bh(&sc->sc_pcu_lock);
-+ if (avp == sc->p2p_ps_vif) {
-+ sc->p2p_ps_vif = NULL;
-+ ath9k_update_p2p_ps_timer(sc, NULL);
-+ }
-+ spin_unlock_bh(&sc->sc_pcu_lock);
-+
- sc->nvifs--;
- sc->tx99_vif = NULL;
-
-@@ -1649,6 +1683,70 @@ static void ath9k_bss_assoc_iter(void *d
- ath9k_set_assoc_state(sc, vif);
- }
-
-+void ath9k_p2p_ps_timer(void *priv)
-+{
-+ struct ath_softc *sc = priv;
-+ struct ath_vif *avp = sc->p2p_ps_vif;
-+ struct ieee80211_vif *vif;
-+ struct ieee80211_sta *sta;
-+ struct ath_node *an;
-+ u32 tsf;
-+
-+ if (!avp)
-+ return;
-+
-+ tsf = ath9k_hw_gettsf32(sc->sc_ah);
-+ if (!avp->noa.absent)
-+ tsf += ATH_P2P_PS_STOP_TIME;
-+
-+ if (!avp->noa.has_next_tsf ||
-+ avp->noa.next_tsf - tsf > BIT(31))
-+ ieee80211_update_p2p_noa(&avp->noa, tsf);
-+
-+ ath9k_update_p2p_ps_timer(sc, avp);
-+
-+ rcu_read_lock();
-+
-+ vif = avp->vif;
-+ sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
-+ if (!sta)
-+ goto out;
-+
-+ an = (void *) sta->drv_priv;
-+ if (an->sleeping == !!avp->noa.absent)
-+ goto out;
-+
-+ an->sleeping = avp->noa.absent;
-+ if (an->sleeping)
-+ ath_tx_aggr_sleep(sta, sc, an);
-+ else
-+ ath_tx_aggr_wakeup(sc, an);
-+
-+out:
-+ rcu_read_unlock();
-+}
-+
-+void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
-+{
-+ struct ath_vif *avp = (void *)vif->drv_priv;
-+ u32 tsf;
-+
-+ if (!sc->p2p_ps_timer)
-+ return;
-+
-+ if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p)
-+ return;
-+
-+ sc->p2p_ps_vif = avp;
-+
-+ if (sc->ps_flags & PS_BEACON_SYNC)
-+ return;
-+
-+ tsf = ath9k_hw_gettsf32(sc->sc_ah);
-+ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
-+ ath9k_update_p2p_ps_timer(sc, avp);
-+}
-+
- static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *bss_conf,
-@@ -1723,6 +1821,12 @@ static void ath9k_bss_info_changed(struc
- }
- }
-
-+ if (changed & BSS_CHANGED_P2P_PS) {
-+ spin_lock_bh(&sc->sc_pcu_lock);
-+ ath9k_update_p2p_ps(sc, vif);
-+ spin_unlock_bh(&sc->sc_pcu_lock);
-+ }
-+
- if (changed & CHECK_ANI)
- ath_check_ani(sc);
-
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -115,6 +115,9 @@ int ath_descdma_setup(struct ath_softc *
- #define ATH_TXFIFO_DEPTH 8
- #define ATH_TX_ERROR 0x01
-
-+/* Stop tx traffic 1ms before the GO goes away */
-+#define ATH_P2P_PS_STOP_TIME 1000
-+
- #define IEEE80211_SEQ_SEQ_SHIFT 4
- #define IEEE80211_SEQ_MAX 4096
- #define IEEE80211_WEP_IVLEN 3
-@@ -363,11 +366,15 @@ void ath9k_release_buffered_frames(struc
- /********/
-
- struct ath_vif {
-+ struct ieee80211_vif *vif;
- struct ath_node mcast_node;
- int av_bslot;
- bool primary_sta_vif;
- __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
- struct ath_buf *av_bcbuf;
-+
-+ /* P2P Client */
-+ struct ieee80211_noa_data noa;
- };
-
- struct ath9k_vif_iter_data {
-@@ -472,6 +479,8 @@ int ath_update_survey_stats(struct ath_s
- void ath_update_survey_nf(struct ath_softc *sc, int channel);
- void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
- void ath_ps_full_sleep(unsigned long data);
-+void ath9k_p2p_ps_timer(void *priv);
-+void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif);
-
- /**********/
- /* BTCOEX */
-@@ -741,6 +750,9 @@ struct ath_softc {
- struct completion paprd_complete;
- wait_queue_head_t tx_wait;
-
-+ struct ath_gen_timer *p2p_ps_timer;
-+ struct ath_vif *p2p_ps_vif;
-+
- unsigned long sc_flags;
- unsigned long driver_data;
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -797,6 +797,9 @@ static int ath9k_init_softc(u16 devid, s
- if (ret)
- goto err_btcoex;
-
-+ sc->p2p_ps_timer = ath_gen_timer_alloc(sc->sc_ah, ath9k_p2p_ps_timer,
-+ NULL, sc, AR_FIRST_NDP_TIMER);
-+
- ath9k_cmn_init_crypto(sc->sc_ah);
- ath9k_init_misc(sc);
- ath_fill_led_pin(sc);
-@@ -1082,6 +1085,9 @@ static void ath9k_deinit_softc(struct at
- {
- int i = 0;
-
-+ if (sc->p2p_ps_timer)
-+ ath_gen_timer_free(sc->sc_ah, sc->p2p_ps_timer);
-+
- ath9k_deinit_btcoex(sc);
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -539,6 +539,9 @@ static void ath_rx_ps_beacon(struct ath_
- ath_dbg(common, PS,
- "Reconfigure beacon timers based on synchronized timestamp\n");
- ath9k_set_beacon(sc);
-+
-+ if (sc->p2p_ps_vif)
-+ ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
- }
-
- if (ath_beacon_dtim_pending_cab(skb)) {
diff --git a/package/mac80211/patches/560-ath9k_pcoem_optional.patch b/package/mac80211/patches/560-ath9k_pcoem_optional.patch
new file mode 100644
index 0000000..4d4ea3b
--- /dev/null
+++ b/package/mac80211/patches/560-ath9k_pcoem_optional.patch
@@ -0,0 +1,249 @@
+--- a/drivers/net/wireless/ath/ath9k/Kconfig
++++ b/drivers/net/wireless/ath/ath9k/Kconfig
+@@ -133,6 +133,11 @@ config ATH9K_RFKILL
+ seconds. Turn off to save power, but enable it if you have
+ a platform that can toggle the RF-Kill GPIO.
+
++config ATH9K_PCOEM
++ bool "Atheros ath9k support for PC OEM cards" if EXPERT
++ depends on ATH9K
++ default y
++
+ config ATH9K_HTC
+ tristate "Atheros HTC based wireless cards support"
+ depends on m
+--- a/drivers/net/wireless/ath/ath9k/Makefile
++++ b/drivers/net/wireless/ath/ath9k/Makefile
+@@ -31,7 +31,6 @@ ath9k_hw-y:= \
+ ar5008_phy.o \
+ ar9002_calib.o \
+ ar9003_calib.o \
+- ar9003_rtt.o \
+ calib.o \
+ eeprom.o \
+ eeprom_def.o \
+@@ -48,6 +47,8 @@ ath9k_hw-$(CPTCFG_ATH9K_WOW) += ar9003_w
+
+ ath9k_hw-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
+ ar9003_mci.o
++ath9k_hw-$(CPTCFG_ATH9K_PCOEM) += ar9003_rtt.o
++
+ obj-$(CPTCFG_ATH9K_HW) += ath9k_hw.o
+
+ obj-$(CPTCFG_ATH9K_COMMON) += ath9k_common.o
+--- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
+@@ -17,6 +17,7 @@
+ #ifndef AR9003_RTT_H
+ #define AR9003_RTT_H
+
++#ifdef CPTCFG_ATH9K_PCOEM
+ void ar9003_hw_rtt_enable(struct ath_hw *ah);
+ void ar9003_hw_rtt_disable(struct ath_hw *ah);
+ void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
+@@ -25,5 +26,40 @@ void ar9003_hw_rtt_load_hist(struct ath_
+ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
+ void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
+ bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
++#else
++static inline void ar9003_hw_rtt_enable(struct ath_hw *ah)
++{
++}
++
++static inline void ar9003_hw_rtt_disable(struct ath_hw *ah)
++{
++}
++
++static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
++{
++}
++
++static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
++{
++ return false;
++}
++
++static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
++{
++}
++
++static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
++{
++}
++
++static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
++{
++}
++
++static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++ return false;
++}
++#endif
+
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -244,13 +244,20 @@ enum ath9k_hw_caps {
+ ATH9K_HW_CAP_2GHZ = BIT(11),
+ ATH9K_HW_CAP_5GHZ = BIT(12),
+ ATH9K_HW_CAP_APM = BIT(13),
++#ifdef CPTCFG_ATH9K_PCOEM
+ ATH9K_HW_CAP_RTT = BIT(14),
+ ATH9K_HW_CAP_MCI = BIT(15),
+- ATH9K_HW_CAP_DFS = BIT(16),
+- ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
+- ATH9K_HW_CAP_PAPRD = BIT(18),
+- ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19),
+- ATH9K_HW_CAP_BT_ANT_DIV = BIT(20),
++ ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16),
++ ATH9K_HW_CAP_BT_ANT_DIV = BIT(17),
++#else
++ ATH9K_HW_CAP_RTT = 0,
++ ATH9K_HW_CAP_MCI = 0,
++ ATH9K_HW_WOW_DEVICE_CAPABLE = 0,
++ ATH9K_HW_CAP_BT_ANT_DIV = 0,
++#endif
++ ATH9K_HW_CAP_DFS = BIT(18),
++ ATH9K_HW_CAP_PAPRD = BIT(19),
++ ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(20),
+ };
+
+ /*
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -355,6 +355,9 @@ static void ath9k_init_pcoem_platform(st
+ struct ath9k_hw_capabilities *pCap = &ah->caps;
+ struct ath_common *common = ath9k_hw_common(ah);
+
++ if (!IS_ENABLED(CPTCFG_ATH9K_PCOEM))
++ return;
++
+ if (common->bus_ops->ath_bus_type != ATH_PCI)
+ return;
+
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -30,6 +30,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+ { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
+ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+
++#ifdef CPTCFG_ATH9K_PCOEM
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x002A,
+ PCI_VENDOR_ID_AZWAVE,
+@@ -82,6 +83,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+ PCI_VENDOR_ID_AZWAVE,
+ 0x2C37),
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
++#endif
+
+ { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
+ { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
+@@ -102,6 +104,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+
+ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
+
++#ifdef CPTCFG_ATH9K_PCOEM
+ /* PCI-E CUS198 */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0032,
+@@ -294,10 +297,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+ PCI_VENDOR_ID_ASUSTEK,
+ 0x850D),
+ .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE },
++#endif
+
+ { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
+ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
+
++#ifdef CPTCFG_ATH9K_PCOEM
+ /* PCI-E CUS217 */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0034,
+@@ -657,6 +662,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+ /* PCI-E AR9565 (WB335) */
+ { PCI_VDEVICE(ATHEROS, 0x0036),
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
++#endif
+
+ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
+ { 0 }
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -891,10 +891,21 @@
+ (AR_SREV_9330((_ah)) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
++#ifdef CPTCFG_ATH9K_PCOEM
++#define AR_SREV_9462(_ah) \
++ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
+ #define AR_SREV_9485(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
++#define AR_SREV_9565(_ah) \
++ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
++#else
++#define AR_SREV_9462(_ah) 0
++#define AR_SREV_9485(_ah) 0
++#define AR_SREV_9565(_ah) 0
++#endif
++
+ #define AR_SREV_9485_11_OR_LATER(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \
++ (AR_SREV_9485(_ah) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11))
+ #define AR_SREV_9485_OR_LATER(_ah) \
+ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
+@@ -910,34 +921,30 @@
+ (AR_SREV_9285_12_OR_LATER(_ah) && \
+ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+
+-#define AR_SREV_9462(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
+ #define AR_SREV_9462_20(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
++ (AR_SREV_9462(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
+ #define AR_SREV_9462_21(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
++ (AR_SREV_9462(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21))
+ #define AR_SREV_9462_20_OR_LATER(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
++ (AR_SREV_9462(_ah) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
+ #define AR_SREV_9462_21_OR_LATER(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
++ (AR_SREV_9462(_ah) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21))
+
+-#define AR_SREV_9565(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
+ #define AR_SREV_9565_10(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
++ (AR_SREV_9565(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
+ #define AR_SREV_9565_101(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
++ (AR_SREV_9565(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101))
+ #define AR_SREV_9565_11(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
++ (AR_SREV_9565(_ah) && \
+ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11))
+ #define AR_SREV_9565_11_OR_LATER(_ah) \
+- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
++ (AR_SREV_9565(_ah) && \
+ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11))
+
+ #define AR_SREV_9550(_ah) \
+--- a/.local-symbols
++++ b/.local-symbols
+@@ -129,6 +129,7 @@ ATH9K_HW=
+ ATH9K_COMMON=
+ ATH9K_DFS_DEBUGFS=
+ ATH9K_BTCOEX_SUPPORT=
++ATH9K_PCOEM=
+ ATH9K=
+ ATH9K_PCI=
+ ATH9K_AHB=
diff --git a/package/mac80211/patches/561-ath9k_remove_gain_tables.patch b/package/mac80211/patches/561-ath9k_remove_gain_tables.patch
new file mode 100644
index 0000000..852eae3
--- /dev/null
+++ b/package/mac80211/patches/561-ath9k_remove_gain_tables.patch
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+@@ -663,9 +663,6 @@ static void ar9003_tx_gain_table_mode5(s
+ if (AR_SREV_9485_11_OR_LATER(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9485Modes_green_ob_db_tx_gain_1_1);
+- else if (AR_SREV_9340(ah))
+- INIT_INI_ARRAY(&ah->iniModesTxGain,
+- ar9340Modes_ub124_tx_gain_table_1p0);
+ else if (AR_SREV_9580(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9580_1p0_type5_tx_gain_table);
diff --git a/package/mac80211/patches/562-ath9k_ani_ws_detect.patch b/package/mac80211/patches/562-ath9k_ani_ws_detect.patch
new file mode 100644
index 0000000..1e4f451
--- /dev/null
+++ b/package/mac80211/patches/562-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
+@@ -929,55 +929,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
+@@ -26,20 +26,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;
+-
+ /**
+ * ar9003_hw_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+@@ -954,11 +940,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) {
+@@ -972,61 +953,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/mac80211/patches/563-ath9k_rxorn_intr_fix.patch b/package/mac80211/patches/563-ath9k_rxorn_intr_fix.patch
new file mode 100644
index 0000000..47a7d82
--- /dev/null
+++ b/package/mac80211/patches/563-ath9k_rxorn_intr_fix.patch
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -628,8 +628,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+ * If a FATAL or RXORN interrupt is received, we have to reset the
+ * chip immediately.
+ */
+- if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
+- !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
++ if (status & ATH9K_INT_FATAL)
+ goto chip_reset;
+
+ if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
diff --git a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
deleted file mode 100644
index af94c9e..0000000
--- a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
+++ /dev/null
@@ -1,79 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -217,6 +217,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 */
- /******************/
-@@ -1337,6 +1350,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;
- }
-
-@@ -1436,6 +1452,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;
- }
-
-@@ -1730,8 +1749,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;
- }
-
-@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- if (AR_SREV_9565(ah) && common->bt_ant_diversity)
- REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
-
-+ 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/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
new file mode 100644
index 0000000..d344957
--- /dev/null
+++ b/package/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch
@@ -0,0 +1,62 @@
+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/rt2800.h
++++ b/drivers/net/wireless/rt2x00/rt2800.h
+@@ -2958,17 +2958,4 @@ enum rt2800_eeprom_word {
+ */
+ #define BCN_TBTT_OFFSET 64
+
+-/*
+- * RT2800 driver data structure
+- */
+-struct rt2800_drv_data {
+- u8 calibration_bw20;
+- u8 calibration_bw40;
+- u8 bbp25;
+- u8 bbp26;
+- u8 txmixer_gain_24g;
+- u8 txmixer_gain_5g;
+- unsigned int tbtt_tick;
+-};
+-
+ #endif /* RT2800_H */
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -20,6 +20,17 @@
+ #ifndef RT2800LIB_H
+ #define RT2800LIB_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;
++};
++
+ struct rt2800_ops {
+ void (*register_read)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset, u32 *value);
diff --git a/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
new file mode 100644
index 0000000..60d4c55
--- /dev/null
+++ b/package/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
+@@ -7734,6 +7734,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;
+
+@@ -7741,6 +7742,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
+@@ -20,6 +20,10 @@
+ #ifndef RT2800LIB_H
+ #define RT2800LIB_H
+
++enum rt2800_flag {
++ RT2800_HAS_HIGH_SHARED_MEM,
++};
++
+ /* RT2800 driver data structure */
+ struct rt2800_drv_data {
+ u8 calibration_bw20;
+@@ -29,6 +33,8 @@ struct rt2800_drv_data {
+ u8 txmixer_gain_24g;
+ u8 txmixer_gain_5g;
+ unsigned int tbtt_tick;
++
++ unsigned long rt2800_flags;
+ };
+
+ struct rt2800_ops {
+@@ -61,6 +67,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/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
new file mode 100644
index 0000000..2accf73
--- /dev/null
+++ b/package/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
+@@ -1437,8 +1467,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);
+ }
+
+ /*
+@@ -4898,14 +4931,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);
+ }
+
+ /*
+@@ -5031,8 +5069,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++) {
+@@ -6728,11 +6768,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);
+
+ /*
+@@ -7738,6 +7786,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;
+@@ -7817,8 +7867,11 @@ void rt2800_get_tkip_seq(struct ieee8021
+ u32 offset;
+
+ offset = MAC_IVEIV_ENTRY(hw_key_idx);
++
++ rt2800_shared_mem_lock(rt2x00dev);
+ rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
++ rt2800_shared_mem_unlock(rt2x00dev);
+
+ memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
+ memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -35,6 +35,11 @@ struct rt2800_drv_data {
+ unsigned int tbtt_tick;
+
+ unsigned long rt2800_flags;
++
++ union {
++ spinlock_t spin;
++ struct mutex mutex;
++ } shmem_lock;
+ };
+
+ struct rt2800_ops {
+@@ -65,6 +70,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)
+@@ -74,6 +83,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.
+ */
+@@ -260,8 +281,10 @@ static int rt2800usb_write_firmware(stru
+ rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ 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,
+@@ -276,7 +299,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;
+ }
+@@ -294,8 +320,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);
+@@ -810,6 +838,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/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
new file mode 100644
index 0000000..7167f28
--- /dev/null
+++ b/package/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
+@@ -572,6 +572,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
+@@ -2024,6 +2025,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/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
new file mode 100644
index 0000000..0b509df
--- /dev/null
+++ b/package/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
+@@ -4628,6 +4628,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;
+@@ -4993,7 +4994,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)) {
+@@ -7839,6 +7840,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
+@@ -33,6 +33,7 @@ struct rt2800_drv_data {
+ u8 txmixer_gain_24g;
+ u8 txmixer_gain_5g;
+ unsigned int tbtt_tick;
++ unsigned int hw_beacon_count;
+
+ unsigned long rt2800_flags;
+
diff --git a/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
new file mode 100644
index 0000000..95f44b5
--- /dev/null
+++ b/package/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
+@@ -627,6 +627,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
+@@ -4640,6 +4640,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/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
new file mode 100644
index 0000000..303d2be
--- /dev/null
+++ b/package/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
+@@ -7864,7 +7864,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/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/package/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch
new file mode 100644
index 0000000..8a10c6e
--- /dev/null
+++ b/package/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/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
new file mode 100644
index 0000000..848d95f
--- /dev/null
+++ b/package/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
+@@ -7834,6 +7834,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/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
new file mode 100644
index 0000000..4ccd47f
--- /dev/null
+++ b/package/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
+@@ -71,6 +72,7 @@
+ #define RF5592 0x000f
+ #define RF3070 0x3070
+ #define RF3290 0x3290
++#define RF3853 0x3853
+ #define RF5360 0x5360
+ #define RF5370 0x5370
+ #define RF5372 0x5372
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -7454,6 +7454,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},
+@@ -7682,6 +7742,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/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
new file mode 100644
index 0000000..7dbfd7f
--- /dev/null
+++ b/package/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
+@@ -4393,6 +4393,7 @@ void rt2800_vco_calibration(struct rt2x0
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5360:
+ case RF5370:
+ case RF5372:
+@@ -7861,6 +7862,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5360:
+ case RF5370:
+ case RF5372:
diff --git a/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
new file mode 100644
index 0000000..4c28f9b
--- /dev/null
+++ b/package/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
+@@ -2649,6 +2649,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
+
+@@ -3261,6 +3466,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 RF5370:
diff --git a/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
new file mode 100644
index 0000000..9419e62
--- /dev/null
+++ b/package/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
+@@ -7420,6 +7420,7 @@ static int rt2800_init_eeprom(struct rt2
+ case RF3290:
+ case RF3320:
+ case RF3322:
++ case RF3853:
+ case RF5360:
+ case RF5370:
+ case RF5372:
diff --git a/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
new file mode 100644
index 0000000..65c6720
--- /dev/null
+++ b/package/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
+@@ -1586,6 +1586,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
+@@ -4995,6 +4995,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)) {
+@@ -5025,9 +5031,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);
+@@ -5180,6 +5188,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/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch b/package/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch
new file mode 100644
index 0000000..837c025
--- /dev/null
+++ b/package/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/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
new file mode 100644
index 0000000..bba96db
--- /dev/null
+++ b/package/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
+@@ -5798,6 +5798,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;
+@@ -6016,6 +6057,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/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
new file mode 100644
index 0000000..568e60e
--- /dev/null
+++ b/package/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
+@@ -2169,6 +2169,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
+@@ -6833,6 +6833,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);
+@@ -7064,6 +7202,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/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch b/package/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/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/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
new file mode 100644
index 0000000..50fa94f
--- /dev/null
+++ b/package/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
+@@ -7601,6 +7601,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/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
new file mode 100644
index 0000000..e717baa
--- /dev/null
+++ b/package/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
+@@ -3429,6 +3429,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,
+@@ -3447,6 +3477,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:
+@@ -3528,6 +3564,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);
+@@ -3540,6 +3585,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))
+@@ -3548,19 +3594,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))
+@@ -3685,6 +3734,23 @@ static void rt2800_config_channel(struct
+ 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);
++ }
++
+ if (rt2x00_rt(rt2x00dev, RT5592)) {
+ rt2800_bbp_write(rt2x00dev, 195, 141);
+ rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
diff --git a/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
new file mode 100644
index 0000000..1773128
--- /dev/null
+++ b/package/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
+@@ -3416,13 +3416,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/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
new file mode 100644
index 0000000..4956373
--- /dev/null
+++ b/package/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
+@@ -4626,7 +4626,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/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
new file mode 100644
index 0000000..a692fd8
--- /dev/null
+++ b/package/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
+@@ -7483,7 +7483,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);
+@@ -7497,7 +7498,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/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch b/package/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/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/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch b/package/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch
new file mode 100644
index 0000000..08f3f88
--- /dev/null
+++ b/package/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/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
new file mode 100644
index 0000000..f8fe496
--- /dev/null
+++ b/package/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
+@@ -8415,7 +8415,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/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
new file mode 100644
index 0000000..22f7110
--- /dev/null
+++ b/package/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
+@@ -1961,7 +1961,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/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
new file mode 100644
index 0000000..9945f38
--- /dev/null
+++ b/package/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
+@@ -1984,7 +1984,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);
+@@ -1994,7 +1995,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/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
new file mode 100644
index 0000000..80b3668
--- /dev/null
+++ b/package/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
+@@ -4825,7 +4825,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);
+@@ -4845,7 +4846,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)) {
+@@ -4892,6 +4894,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/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
new file mode 100644
index 0000000..424acff
--- /dev/null
+++ b/package/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
+@@ -7620,7 +7620,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,
+@@ -7640,7 +7641,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,
+@@ -7648,7 +7650,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/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
new file mode 100644
index 0000000..00be526
--- /dev/null
+++ b/package/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
+@@ -4003,6 +4003,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/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
new file mode 100644
index 0000000..7c4c1ab
--- /dev/null
+++ b/package/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
+@@ -8428,7 +8428,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/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch b/package/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/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/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch b/package/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch
new file mode 100644
index 0000000..79334dd
--- /dev/null
+++ b/package/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
+@@ -986,6 +986,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/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
index 2bbc6f1..e5ba10e 100644
--- a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
+++ b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
@@ -1,6 +1,6 @@
--- a/.local-symbols
+++ b/.local-symbols
-@@ -279,6 +279,7 @@ RT2X00_LIB_FIRMWARE=
+@@ -281,6 +281,7 @@ RT2X00_LIB_FIRMWARE=
RT2X00_LIB_CRYPTO=
RT2X00_LIB_LEDS=
RT2X00_LIB_DEBUGFS=
@@ -48,16 +48,16 @@
obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
-@@ -20,6 +20,8 @@
- #ifndef RT2800LIB_H
- #define RT2800LIB_H
+@@ -43,6 +43,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);
-@@ -119,6 +121,15 @@ static inline int rt2800_read_eeprom(str
+@@ -176,6 +178,15 @@ static inline int rt2800_read_eeprom(str
{
const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
@@ -75,7 +75,7 @@
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
-@@ -95,19 +95,6 @@ static int rt2800soc_set_device_state(st
+@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st
return retval;
}
@@ -95,7 +95,7 @@
/* Firmware functions */
static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
-@@ -171,7 +158,6 @@ static const struct rt2800_ops rt2800soc
+@@ -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,
@@ -127,7 +127,7 @@
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1324,6 +1324,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+@@ -1327,6 +1327,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
@@ -138,7 +138,7 @@
/*
* Let the driver probe the device to detect the capabilities.
*/
-@@ -1454,6 +1458,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+@@ -1457,6 +1461,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
*/
if (rt2x00dev->drv_data)
kfree(rt2x00dev->drv_data);
diff --git a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
index 4116735..70f7b78 100644
--- a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
+++ b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
@@ -12,7 +12,7 @@
#endif /* _RT2X00_PLATFORM_H */
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -937,6 +937,22 @@ static int rt2x00lib_probe_hw_modes(stru
+@@ -940,6 +940,22 @@ static int rt2x00lib_probe_hw_modes(stru
unsigned int num_rates;
unsigned int i;
diff --git a/package/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
index a910cc3..4c2a8b8 100644
--- a/package/mac80211/patches/608-add_platform_data_mac_addr.patch
+++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
@@ -10,7 +10,7 @@
int disable_5ghz;
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -928,6 +928,18 @@ static void rt2x00lib_rate(struct ieee80
+@@ -931,6 +931,18 @@ static void rt2x00lib_rate(struct ieee80
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
}
@@ -31,7 +31,7 @@
{
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -1401,6 +1401,7 @@ static inline void rt2x00debug_dump_fram
+@@ -1406,6 +1406,7 @@ static inline void rt2x00debug_dump_fram
*/
u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif);
diff --git a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
index 83fbcd0..010a9e2 100644
--- a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
+++ b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
@@ -1,14 +1,15 @@
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -3176,11 +3176,17 @@ static void rt2800_config_channel(struct
+@@ -3550,11 +3550,18 @@ static void rt2800_config_channel(struct
/*
* Change BBP settings
*/
-+ 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 (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);
@@ -18,22 +19,7 @@
} else if (rt2x00_rt(rt2x00dev, RT3593)) {
if (rf->channel > 14) {
/* Disable CCK Packet detection on 5GHz */
-@@ -3194,14 +3200,8 @@ static void rt2800_config_channel(struct
- else
- rt2800_bbp_write(rt2x00dev, 105, 0x34);
-
-- 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, 77, 0x98);
- } else {
-- 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, 86, 0);
- }
-
-@@ -6125,6 +6125,12 @@ static void rt2800_init_rfcsr_3290(struc
+@@ -6608,6 +6615,12 @@ static void rt2800_init_rfcsr_3290(struc
static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
{
@@ -46,7 +32,7 @@
rt2800_rf_init_calibration(rt2x00dev, 30);
rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
-@@ -6160,15 +6166,30 @@ static void rt2800_init_rfcsr_3352(struc
+@@ -6643,15 +6656,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);
@@ -80,7 +66,7 @@
rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
-@@ -6176,15 +6197,20 @@ static void rt2800_init_rfcsr_3352(struc
+@@ -6659,15 +6687,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);
@@ -110,7 +96,7 @@
rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
-@@ -7051,6 +7077,7 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7688,6 +7721,7 @@ static int rt2800_init_eeprom(struct rt2
* RT53xx: defined in "EEPROM_CHIP_ID" field
*/
if (rt2x00_rt(rt2x00dev, RT3290) ||
@@ -118,7 +104,7 @@
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
-@@ -7142,7 +7169,8 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7782,7 +7816,8 @@ static int rt2800_init_eeprom(struct rt2
/*
* Detect if this device has Bluetooth co-existence.
*/
@@ -128,7 +114,7 @@
__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
/*
-@@ -7171,6 +7199,22 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7811,6 +7846,22 @@ static int rt2800_init_eeprom(struct rt2
EIRP_MAX_TX_POWER_LIMIT)
__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
@@ -153,7 +139,7 @@
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
-@@ -2299,6 +2299,12 @@ struct mac_iveiv_entry {
+@@ -2333,6 +2333,12 @@ struct mac_iveiv_entry {
#define RFCSR36_RF_BS FIELD8(0x80)
/*
@@ -166,7 +152,7 @@
* RFCSR 38:
*/
#define RFCSR38_RX_LO1_EN FIELD8(0x20)
-@@ -2310,6 +2316,18 @@ struct mac_iveiv_entry {
+@@ -2344,6 +2350,18 @@ struct mac_iveiv_entry {
#define RFCSR39_RX_LO2_EN FIELD8(0x80)
/*
@@ -185,7 +171,7 @@
* RFCSR 49:
*/
#define RFCSR49_TX FIELD8(0x3f)
-@@ -2322,6 +2340,8 @@ struct mac_iveiv_entry {
+@@ -2356,6 +2374,8 @@ struct mac_iveiv_entry {
* RFCSR 50:
*/
#define RFCSR50_TX FIELD8(0x3f)
@@ -194,7 +180,7 @@
#define RFCSR50_EP FIELD8(0xc0)
/* bits for RT3593 */
#define RFCSR50_TX_LO1_EN FIELD8(0x20)
-@@ -2469,6 +2489,8 @@ enum rt2800_eeprom_word {
+@@ -2503,6 +2523,8 @@ enum rt2800_eeprom_word {
* INTERNAL_TX_ALC: 0: disable, 1: enable
* BT_COEXIST: 0: disable, 1: enable
* DAC_TEST: 0: disable, 1: enable
@@ -203,7 +189,7 @@
*/
#define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001)
#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002)
-@@ -2485,6 +2507,8 @@ enum rt2800_eeprom_word {
+@@ -2519,6 +2541,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)
diff --git a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
index 478a0f2..65af89a 100644
--- a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
+++ b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -7491,6 +7491,27 @@ static const struct rf_channel rf_vals_5
+@@ -8198,6 +8198,27 @@ static const struct rf_channel rf_vals_5
{196, 83, 0, 12, 1},
};
@@ -28,7 +28,7 @@
static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
{
struct hw_mode_spec *spec = &rt2x00dev->spec;
-@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r
+@@ -8285,7 +8306,10 @@ static int rt2800_probe_hw_mode(struct r
case RF5390:
case RF5392:
spec->num_channels = 14;
@@ -40,7 +40,7 @@
break;
case RF3052:
-@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00
+@@ -8468,6 +8492,19 @@ static int rt2800_probe_rt(struct rt2x00
return 0;
}
@@ -59,8 +59,8 @@
+
int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
{
- int retval;
-@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+@@ -8510,6 +8547,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
/*
diff --git a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
index f6b4808..119e95c 100644
--- a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
+++ b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
@@ -13,7 +13,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
-@@ -227,11 +227,18 @@ static int rt2800soc_probe(struct platfo
+@@ -237,11 +237,18 @@ static int rt2800soc_probe(struct platfo
return rt2x00soc_probe(pdev, &rt2800soc_ops);
}
diff --git a/package/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
index 3bafa16..41a7f34 100644
--- a/package/mac80211/patches/616-rt2x00-support-rt5350.patch
+++ b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
@@ -1,16 +1,16 @@
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
-@@ -71,6 +71,7 @@
- #define RF5592 0x000f
+@@ -73,6 +73,7 @@
#define RF3070 0x3070
#define RF3290 0x3290
+ #define RF3853 0x3853
+#define RF5350 0x5350
#define RF5360 0x5360
#define RF5370 0x5370
#define RF5372 0x5372
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -2704,6 +2704,13 @@ static void rt2800_config_channel_rf53xx
+@@ -3038,6 +3038,13 @@ static void rt2800_config_channel_rf53xx
rt2800_rfcsr_write(rt2x00dev, 59,
r59_non_bt[idx]);
@@ -24,15 +24,15 @@
}
}
}
-@@ -3141,6 +3148,7 @@ static void rt2800_config_channel(struct
- rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
+@@ -3516,6 +3523,7 @@ static void rt2800_config_channel(struct
+ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
break;
case RF3070:
+ case RF5350:
case RF5360:
case RF5370:
case RF5372:
-@@ -3158,6 +3166,7 @@ static void rt2800_config_channel(struct
+@@ -3533,6 +3541,7 @@ static void rt2800_config_channel(struct
if (rt2x00_rf(rt2x00dev, RF3070) ||
rt2x00_rf(rt2x00dev, RF3290) ||
rt2x00_rf(rt2x00dev, RF3322) ||
@@ -40,7 +40,7 @@
rt2x00_rf(rt2x00dev, RF5360) ||
rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) ||
-@@ -3398,7 +3407,8 @@ static void rt2800_config_channel(struct
+@@ -3810,7 +3819,8 @@ static void rt2800_config_channel(struct
/*
* Clear update flag
*/
@@ -50,15 +50,15 @@
rt2800_bbp_read(rt2x00dev, 49, &bbp);
rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
rt2800_bbp_write(rt2x00dev, 49, bbp);
-@@ -4272,6 +4282,7 @@ void rt2800_vco_calibration(struct rt2x0
- case RF3053:
+@@ -4689,6 +4699,7 @@ void rt2800_vco_calibration(struct rt2x0
case RF3070:
case RF3290:
+ case RF3853:
+ case RF5350:
case RF5360:
case RF5370:
case RF5372:
-@@ -4668,6 +4679,8 @@ static int rt2800_init_registers(struct
+@@ -5101,6 +5112,8 @@ static int rt2800_init_registers(struct
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
@@ -67,7 +67,7 @@
} else {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-@@ -5309,9 +5322,13 @@ static void rt2800_init_bbp_3352(struct
+@@ -5756,9 +5769,13 @@ static void rt2800_init_bbp_3352(struct
rt2800_bbp_write(rt2x00dev, 82, 0x62);
@@ -84,7 +84,7 @@
rt2800_bbp_write(rt2x00dev, 86, 0x38);
-@@ -5325,9 +5342,13 @@ static void rt2800_init_bbp_3352(struct
+@@ -5772,9 +5789,13 @@ static void rt2800_init_bbp_3352(struct
rt2800_bbp_write(rt2x00dev, 104, 0x92);
@@ -101,7 +101,7 @@
rt2800_bbp_write(rt2x00dev, 120, 0x50);
-@@ -5352,6 +5373,13 @@ static void rt2800_init_bbp_3352(struct
+@@ -5799,6 +5820,13 @@ static void rt2800_init_bbp_3352(struct
rt2800_bbp_write(rt2x00dev, 143, 0xa2);
rt2800_bbp_write(rt2x00dev, 148, 0xc8);
@@ -115,7 +115,7 @@
}
static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
-@@ -5652,6 +5680,7 @@ static void rt2800_init_bbp(struct rt2x0
+@@ -6140,6 +6168,7 @@ static void rt2800_init_bbp(struct rt2x0
rt2800_init_bbp_3290(rt2x00dev);
break;
case RT3352:
@@ -123,8 +123,8 @@
rt2800_init_bbp_3352(rt2x00dev);
break;
case RT3390:
-@@ -6462,6 +6491,76 @@ static void rt2800_init_rfcsr_3593(struc
- /* TODO: enable stream mode support */
+@@ -7091,6 +7120,76 @@ static void rt2800_init_rfcsr_3883(struc
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
}
+static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev)
@@ -200,7 +200,7 @@
static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
{
rt2800_rf_init_calibration(rt2x00dev, 2);
-@@ -6699,6 +6798,9 @@ static void rt2800_init_rfcsr(struct rt2
+@@ -7331,6 +7430,9 @@ static void rt2800_init_rfcsr(struct rt2
case RT3593:
rt2800_init_rfcsr_3593(rt2x00dev);
break;
@@ -210,7 +210,7 @@
case RT5390:
rt2800_init_rfcsr_5390(rt2x00dev);
break;
-@@ -6948,6 +7050,12 @@ static int rt2800_validate_eeprom(struct
+@@ -7590,6 +7692,12 @@ static int rt2800_validate_eeprom(struct
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
@@ -223,24 +223,24 @@
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
rt2x00_rt(rt2x00dev, RT2872)) {
/*
-@@ -7081,6 +7189,8 @@ static int rt2800_init_eeprom(struct rt2
- rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+@@ -7728,6 +7836,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);
-@@ -7099,6 +7209,7 @@ static int rt2800_init_eeprom(struct rt2
- case RF3290:
+@@ -7747,6 +7857,7 @@ static int rt2800_init_eeprom(struct rt2
case RF3320:
case RF3322:
+ case RF3853:
+ case RF5350:
case RF5360:
case RF5370:
case RF5372:
-@@ -7594,6 +7705,7 @@ static int rt2800_probe_hw_mode(struct r
+@@ -8301,6 +8412,7 @@ static int rt2800_probe_hw_mode(struct r
case RF3290:
case RF3320:
case RF3322:
@@ -248,18 +248,18 @@
case RF5360:
case RF5370:
case RF5372:
-@@ -7726,6 +7838,7 @@ static int rt2800_probe_hw_mode(struct r
- case RF3053:
+@@ -8439,6 +8551,7 @@ static int rt2800_probe_hw_mode(struct r
case RF3070:
case RF3290:
+ case RF3853:
+ case RF5350:
case RF5360:
case RF5370:
case RF5372:
-@@ -7764,6 +7877,7 @@ static int rt2800_probe_rt(struct rt2x00
- case RT3390:
+@@ -8478,6 +8591,7 @@ static int rt2800_probe_rt(struct rt2x00
case RT3572:
case RT3593:
+ case RT3883:
+ case RT5350:
case RT5390:
case RT5392:
diff --git a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
index f9186d8..d966321 100644
--- a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
+++ b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -36,6 +36,7 @@
+@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -8,7 +8,7 @@
#include "rt2x00.h"
#include "rt2800lib.h"
-@@ -7298,6 +7299,17 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7946,6 +7947,17 @@ static int rt2800_init_eeprom(struct rt2
rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
diff --git a/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
index 419cb60..ce667b8 100644
--- a/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
+++ b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1262,7 +1262,7 @@ static inline void rt2x00lib_set_if_comb
+@@ -1265,7 +1265,7 @@ static inline void rt2x00lib_set_if_comb
*/
if_limit = &rt2x00dev->if_limits_ap;
if_limit->max = rt2x00dev->ops->max_ap_intf;
diff --git a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
index 5e67344..90eab13 100644
--- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
+++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -7186,10 +7186,11 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7831,10 +7831,11 @@ static int rt2800_init_eeprom(struct rt2
* RT53xx: defined in "EEPROM_CHIP_ID" field
*/
if (rt2x00_rt(rt2x00dev, RT3290) ||
@@ -10,6 +10,6 @@
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))
- rf = RF5350;
- else
diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
index 484c075..ae7e927 100644
--- a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
+++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
-@@ -5529,6 +5529,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5682,6 +5682,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
diff --git a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
index fc874ad..7c56369 100644
--- a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
+++ b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch
@@ -22,7 +22,7 @@
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2747,10 +2752,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2749,10 +2754,10 @@ static int b43_gpio_init(struct b43_wlde
u32 mask, set;
b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
diff --git a/package/mac80211/patches/810-b43_no_pio.patch b/package/mac80211/patches/810-b43_no_pio.patch
index 5cd1b8b..2023bf6 100644
--- a/package/mac80211/patches/810-b43_no_pio.patch
+++ b/package/mac80211/patches/810-b43_no_pio.patch
@@ -11,7 +11,7 @@
b43-$(CPTCFG_B43_PCMCIA) += pcmcia.o
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -1915,10 +1915,12 @@ static void b43_do_interrupt_thread(stru
+@@ -1909,10 +1909,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]);
@@ -75,12 +75,12 @@
#endif /* B43_PIO_H_ */
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
-@@ -98,7 +98,7 @@ config B43_BCMA_PIO
+@@ -118,7 +118,7 @@ config B43_BCMA_PIO
default y
config B43_PIO
- bool
+ bool "Broadcom 43xx PIO support"
- depends on B43
+ depends on B43 && B43_SSB
select SSB_BLOCKIO
default y
diff --git a/package/mac80211/patches/820-b43-add-antenna-control.patch b/package/mac80211/patches/820-b43-add-antenna-control.patch
index dea9830..5a23967 100644
--- a/package/mac80211/patches/820-b43-add-antenna-control.patch
+++ b/package/mac80211/patches/820-b43-add-antenna-control.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -1562,7 +1562,7 @@ static void b43_write_beacon_template(st
+@@ -1556,7 +1556,7 @@ static void b43_write_beacon_template(st
len, ram_offset, shm_size_offset, rate);
/* Write the PHY TX control parameters. */
@@ -9,7 +9,7 @@
antenna = b43_antenna_to_phyctl(antenna);
ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
/* We can't send beacons with short preamble. Would get PHY errors. */
-@@ -3105,8 +3105,8 @@ static int b43_chip_init(struct b43_wlde
+@@ -3113,8 +3113,8 @@ static int b43_chip_init(struct b43_wlde
/* Select the antennae */
if (phy->ops->set_rx_antenna)
@@ -20,7 +20,7 @@
if (phy->type == B43_PHYTYPE_B) {
value16 = b43_read16(dev, 0x005E);
-@@ -3850,7 +3850,6 @@ static int b43_op_config(struct ieee8021
+@@ -3806,7 +3806,6 @@ static int b43_op_config(struct ieee8021
struct b43_wldev *dev;
struct b43_phy *phy;
struct ieee80211_conf *conf = &hw->conf;
@@ -28,7 +28,7 @@
int err = 0;
bool reload_bss = false;
-@@ -3904,11 +3903,9 @@ static int b43_op_config(struct ieee8021
+@@ -3860,11 +3859,9 @@ static int b43_op_config(struct ieee8021
}
/* Antennas for RX and management frame TX. */
@@ -42,7 +42,7 @@
if (wl->radio_enabled != phy->radio_on) {
if (wl->radio_enabled) {
-@@ -5041,6 +5038,47 @@ static int b43_op_get_survey(struct ieee
+@@ -4988,6 +4985,47 @@ static int b43_op_get_survey(struct ieee
return 0;
}
@@ -90,7 +90,7 @@
static const struct ieee80211_ops b43_hw_ops = {
.tx = b43_op_tx,
.conf_tx = b43_op_conf_tx,
-@@ -5062,6 +5100,8 @@ static const struct ieee80211_ops b43_hw
+@@ -5009,6 +5047,8 @@ static const struct ieee80211_ops b43_hw
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
.get_survey = b43_op_get_survey,
.rfkill_poll = b43_rfkill_poll,
@@ -99,7 +99,7 @@
};
/* Hard-reset the chip. Do not call this directly.
-@@ -5308,6 +5348,8 @@ static int b43_one_core_attach(struct b4
+@@ -5295,6 +5335,8 @@ static int b43_one_core_attach(struct b4
if (!wldev)
goto out;
@@ -108,7 +108,7 @@
wldev->use_pio = b43_modparam_pio;
wldev->dev = dev;
wldev->wl = wl;
-@@ -5398,6 +5440,9 @@ static struct b43_wl *b43_wireless_init(
+@@ -5385,6 +5427,9 @@ static struct b43_wl *b43_wireless_init(
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
index e76758c..b6db3ac 100644
--- a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
+++ b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
@@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
-@@ -1061,6 +1061,31 @@ static inline bool b43_using_pio_transfe
+@@ -1054,6 +1054,31 @@ static inline bool b43_using_pio_transfe
return dev->__using_pio_transfers;
}
@@ -53,18 +53,20 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
__printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
--- a/drivers/net/wireless/b43/bus.h
+++ b/drivers/net/wireless/b43/bus.h
-@@ -60,6 +60,16 @@ static inline bool b43_bus_host_is_sdio(
- return (dev->bus_type == B43_BUS_SSB &&
- dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+@@ -70,6 +70,18 @@ static inline bool b43_bus_host_is_sdio(
+ return false;
+ #endif
}
+static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
+{
-+ if (dev->bus_type == B43_BUS_SSB)
-+ return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
+#ifdef CPTCFG_B43_BCMA
+ if (dev->bus_type == B43_BUS_BCMA)
+ return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
+#endif
++#ifdef CPTCFG_B43_SSB
++ if (dev->bus_type == B43_BUS_SSB)
++ return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
++#endif
+ return false;
+}
@@ -72,7 +74,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -4437,7 +4437,7 @@ static int b43_phy_versioning(struct b43
+@@ -4380,7 +4380,7 @@ static int b43_phy_versioning(struct b43
u16 radio24[3];
for (tmp = 0; tmp < 3; tmp++) {
@@ -81,7 +83,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
-@@ -4456,10 +4456,10 @@ static int b43_phy_versioning(struct b43
+@@ -4399,10 +4399,10 @@ static int b43_phy_versioning(struct b43
else
tmp = 0x5205017F;
} else {
@@ -96,7 +98,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
<< 16;
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
-@@ -266,6 +266,12 @@ void b43_phy_write(struct b43_wldev *dev
+@@ -267,6 +267,12 @@ void b43_phy_write(struct b43_wldev *dev
{
assert_mac_suspended(dev);
dev->phy.ops->phy_write(dev, reg, value);
@@ -197,7 +199,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
-@@ -5418,14 +5418,14 @@ static inline void check_phyreg(struct b
+@@ -5641,14 +5641,14 @@ static inline void check_phyreg(struct b
static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
{
check_phyreg(dev, reg);
@@ -214,7 +216,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
b43_write16(dev, B43_MMIO_PHY_DATA, value);
}
-@@ -5433,7 +5433,7 @@ static void b43_nphy_op_maskset(struct b
+@@ -5656,7 +5656,7 @@ static void b43_nphy_op_maskset(struct b
u16 set)
{
check_phyreg(dev, reg);
@@ -223,16 +225,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
}
-@@ -5444,7 +5444,7 @@ static u16 b43_nphy_op_radio_read(struct
- /* N-PHY needs 0x100 for read access */
- reg |= 0x100;
+@@ -5670,7 +5670,7 @@ static u16 b43_nphy_op_radio_read(struct
+ else
+ reg |= 0x100;
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
+ b43_wflush16(dev, B43_MMIO_RADIO_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
}
-@@ -5453,7 +5453,7 @@ static void b43_nphy_op_radio_write(stru
+@@ -5679,7 +5679,7 @@ static void b43_nphy_op_radio_write(stru
/* Register 1 is a 32-bit register. */
B43_WARN_ON(reg == 1);
diff --git a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
index 50347cd..efc3451 100644
--- a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
+++ b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -2764,6 +2764,14 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2766,6 +2766,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 */
diff --git a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch b/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch
deleted file mode 100644
index a8af257..0000000
--- a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-Move the wl1251 part of the wl12xx platform data structure into a new
-structure specifically for wl1251. Change the platform data built-in
-block and board files accordingly.
-
-Cc: Tony Lindgren <tony@atomide.com>
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Acked-by: Tony Lindgren <tony@atomide.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wilink_platform_data.c
-+++ b/drivers/net/wireless/ti/wilink_platform_data.c
-@@ -23,17 +23,17 @@
- #include <linux/err.h>
- #include <linux/wl12xx.h>
-
--static struct wl12xx_platform_data *platform_data;
-+static struct wl12xx_platform_data *wl12xx_platform_data;
-
- int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
- {
-- if (platform_data)
-+ if (wl12xx_platform_data)
- return -EBUSY;
- if (!data)
- return -EINVAL;
-
-- platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
-- if (!platform_data)
-+ wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
-+ if (!wl12xx_platform_data)
- return -ENOMEM;
-
- return 0;
-@@ -41,9 +41,34 @@ int __init wl12xx_set_platform_data(cons
-
- struct wl12xx_platform_data *wl12xx_get_platform_data(void)
- {
-- if (!platform_data)
-+ if (!wl12xx_platform_data)
- return ERR_PTR(-ENODEV);
-
-- return platform_data;
-+ return wl12xx_platform_data;
- }
- EXPORT_SYMBOL(wl12xx_get_platform_data);
-+
-+static struct wl1251_platform_data *wl1251_platform_data;
-+
-+int __init wl1251_set_platform_data(const struct wl1251_platform_data *data)
-+{
-+ if (wl1251_platform_data)
-+ return -EBUSY;
-+ if (!data)
-+ return -EINVAL;
-+
-+ wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
-+ if (!wl1251_platform_data)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+struct wl1251_platform_data *wl1251_get_platform_data(void)
-+{
-+ if (!wl1251_platform_data)
-+ return ERR_PTR(-ENODEV);
-+
-+ return wl1251_platform_data;
-+}
-+EXPORT_SYMBOL(wl1251_get_platform_data);
---- a/drivers/net/wireless/ti/wl1251/sdio.c
-+++ b/drivers/net/wireless/ti/wl1251/sdio.c
-@@ -227,7 +227,7 @@ static int wl1251_sdio_probe(struct sdio
- struct wl1251 *wl;
- struct ieee80211_hw *hw;
- struct wl1251_sdio *wl_sdio;
-- const struct wl12xx_platform_data *wl12xx_board_data;
-+ const struct wl1251_platform_data *wl1251_board_data;
-
- hw = wl1251_alloc_hw();
- if (IS_ERR(hw))
-@@ -254,11 +254,11 @@ static int wl1251_sdio_probe(struct sdio
- wl->if_priv = wl_sdio;
- wl->if_ops = &wl1251_sdio_ops;
-
-- wl12xx_board_data = wl12xx_get_platform_data();
-- if (!IS_ERR(wl12xx_board_data)) {
-- wl->set_power = wl12xx_board_data->set_power;
-- wl->irq = wl12xx_board_data->irq;
-- wl->use_eeprom = wl12xx_board_data->use_eeprom;
-+ wl1251_board_data = wl1251_get_platform_data();
-+ if (!IS_ERR(wl1251_board_data)) {
-+ wl->set_power = wl1251_board_data->set_power;
-+ wl->irq = wl1251_board_data->irq;
-+ wl->use_eeprom = wl1251_board_data->use_eeprom;
- }
-
- if (wl->irq) {
---- a/drivers/net/wireless/ti/wl1251/spi.c
-+++ b/drivers/net/wireless/ti/wl1251/spi.c
-@@ -241,7 +241,7 @@ static const struct wl1251_if_operations
-
- static int wl1251_spi_probe(struct spi_device *spi)
- {
-- struct wl12xx_platform_data *pdata;
-+ struct wl1251_platform_data *pdata;
- struct ieee80211_hw *hw;
- struct wl1251 *wl;
- int ret;
diff --git a/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
new file mode 100644
index 0000000..856dea8
--- /dev/null
+++ b/package/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch
@@ -0,0 +1,139 @@
+When running with DT, we no longer have a board file that can set up the
+platform data for wlcore. Allow this data to be passed from DT.
+
+Since some platforms use a gpio-irq, add support for passing either the
+irq number or the gpio number. For the latter case, the driver will
+request the gpio and convert it to the irq number. If an irq is
+specified, it'll be used as is.
+
+[Arik - the pdev_data pointer does not belong to us and is freed when
+the device is released. Dereference to our private data first.]
+
+Signed-off-by: Ido Yariv <ido@wizery.com>
+Signed-off-by: Arik Nemtsov <arik@wizery.com>
+---
+ drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++---
+ include/linux/wl12xx.h | 3 +-
+ 2 files changed, 67 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -34,6 +34,7 @@
+ #include <linux/wl12xx.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/printk.h>
++#include <linux/of.h>
+
+ #include "wlcore.h"
+ #include "wl12xx_80211.h"
+@@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_
+ .set_block_size = wl1271_sdio_set_block_size,
+ };
+
++static const struct of_device_id wlcore_of_match[] = {
++ {
++ .compatible = "wlcore",
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(of, wlcore_of_match);
++
++static struct wl12xx_platform_data *get_platform_data(struct device *dev)
++{
++ struct wl12xx_platform_data *pdata;
++ struct device_node *np;
++ u32 gpio;
++
++ pdata = wl12xx_get_platform_data();
++ if (!IS_ERR(pdata))
++ return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL);
++
++ np = of_find_matching_node(NULL, wlcore_of_match);
++ if (!np) {
++ dev_err(dev, "No platform data set\n");
++ return NULL;
++ }
++
++ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
++ if (!pdata) {
++ dev_err(dev, "Can't allocate platform data\n");
++ return NULL;
++ }
++
++ if (of_property_read_u32(np, "irq", &pdata->irq)) {
++ if (!of_property_read_u32(np, "gpio", &gpio) &&
++ !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) {
++ pdata->gpio = gpio;
++ pdata->irq = gpio_to_irq(gpio);
++ }
++ }
++
++ /* Optional fields */
++ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom");
++ of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock);
++ of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock);
++ of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks);
++
++ return pdata;
++}
++
++static void del_platform_data(struct wl12xx_platform_data *pdata)
++{
++ if (pdata->gpio)
++ gpio_free(pdata->gpio);
++
++ kfree(pdata);
++}
++
+ static int wl1271_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+ {
+@@ -245,10 +301,10 @@ static int wl1271_probe(struct sdio_func
+ /* Use block mode for transferring over one block size of data */
+ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+
+- pdev_data.pdata = wl12xx_get_platform_data();
+- if (IS_ERR(pdev_data.pdata)) {
+- ret = PTR_ERR(pdev_data.pdata);
+- dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
++ pdev_data.pdata = get_platform_data(&func->dev);
++ if (!pdev_data.pdata) {
++ ret = -EINVAL;
++ dev_err(glue->dev, "missing wlan platform data\n");
+ goto out_free_glue;
+ }
+
+@@ -279,7 +335,7 @@ static int wl1271_probe(struct sdio_func
+ if (!glue->core) {
+ dev_err(glue->dev, "can't allocate platform_device");
+ ret = -ENOMEM;
+- goto out_free_glue;
++ goto out_free_pdata;
+ }
+
+ glue->core->dev.parent = &func->dev;
+@@ -313,6 +369,9 @@ static int wl1271_probe(struct sdio_func
+ out_dev_put:
+ platform_device_put(glue->core);
+
++out_free_pdata:
++ del_platform_data(pdev_data->pdata);
++
+ out_free_glue:
+ kfree(glue);
+
+@@ -323,11 +382,14 @@ out:
+ static void wl1271_remove(struct sdio_func *func)
+ {
+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
++ struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data;
++ struct wl12xx_platform_data *pdata = pdev_data->pdata;
+
+ /* Undo decrement done above in wl1271_probe */
+ pm_runtime_get_noresume(&func->dev);
+
+ platform_device_unregister(glue->core);
++ del_platform_data(pdata);
+ kfree(glue);
+ }
+
diff --git a/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch b/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
new file mode 100644
index 0000000..d90508e
--- /dev/null
+++ b/package/mac80211/patches/901-wlcore-don-t-switch-channels-on-disconnected-STA-vif.patch
@@ -0,0 +1,36 @@
+From 4101e8dc540d19f1f6c24930629149191786e4cd Mon Sep 17 00:00:00 2001
+From: Arik Nemtsov <arik@wizery.com>
+Date: Mon, 9 Sep 2013 16:48:59 +0300
+Subject: [PATCH 27/75] wlcore: don't switch channels on disconnected STA vifs
+
+Sending the FW a channel switch command on a disconnected vif may result
+in a beacon loss event. Avoid this edge case.
+
+Signed-off-by: Arik Nemtsov <arik@wizery.com>
+---
+ drivers/net/wireless/ti/wlcore/main.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -5148,6 +5148,10 @@ static void wl12xx_op_channel_switch(str
+ if (unlikely(wl->state == WLCORE_STATE_OFF)) {
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
++
++ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
++ continue;
++
+ ieee80211_chswitch_done(vif, false);
+ }
+ goto out;
+@@ -5163,6 +5167,9 @@ static void wl12xx_op_channel_switch(str
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ unsigned long delay_usec;
+
++ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
++ continue;
++
+ ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
+ if (ret)
+ goto out_sleep;
diff --git a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch b/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch
deleted file mode 100644
index f2789a9..0000000
--- a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-The platform_quirk element in the platform data was used to change the
-way the IRQ is triggered. When set, the EDGE_IRQ quirk would change
-the irqflags used and treat edge trigger differently from the rest.
-
-Instead of hiding this irq flag setting behind the quirk, have the
-board files set the flags during initialization. This will be more
-meaningful than driver-specific quirks when we switch to DT.
-
-Additionally, fix missing gpio_request() calls in the boarding files
-(so that setting the flags actually works).
-
-Cc: Tony Lindgren <tony@atomide.com>
-Cc: Sekhar Nori <nsekhar@ti.com>
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-Acked-by: Sekhar Nori <nsekhar@ti.com>
-
---- a/drivers/net/wireless/ti/wlcore/debugfs.c
-+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
-@@ -502,7 +502,7 @@ static ssize_t driver_state_read(struct
- DRIVER_STATE_PRINT_HEX(irq);
- /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
- DRIVER_STATE_PRINT_HEX(hw_pg_ver);
-- DRIVER_STATE_PRINT_HEX(platform_quirks);
-+ DRIVER_STATE_PRINT_HEX(irq_flags);
- DRIVER_STATE_PRINT_HEX(chip.id);
- DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
- DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
---- a/drivers/net/wireless/ti/wlcore/main.c
-+++ b/drivers/net/wireless/ti/wlcore/main.c
-@@ -27,6 +27,7 @@
- #include <linux/vmalloc.h>
- #include <linux/wl12xx.h>
- #include <linux/interrupt.h>
-+#include <linux/irq.h>
-
- #include "wlcore.h"
- #include "debug.h"
-@@ -528,7 +529,7 @@ static int wlcore_irq_locked(struct wl12
- * In case edge triggered interrupt must be used, we cannot iterate
- * more than once without introducing race conditions with the hardirq.
- */
-- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
-+ if (wl->irq_flags & IRQF_TRIGGER_RISING)
- loopcount = 1;
-
- wl1271_debug(DEBUG_IRQ, "IRQ work");
-@@ -5934,7 +5935,6 @@ struct ieee80211_hw *wlcore_alloc_hw(siz
- wl->ap_ps_map = 0;
- wl->ap_fw_ps_map = 0;
- wl->quirks = 0;
-- wl->platform_quirks = 0;
- wl->system_hlid = WL12XX_SYSTEM_HLID;
- wl->active_sta_count = 0;
- wl->active_link_count = 0;
-@@ -6075,7 +6075,7 @@ static void wlcore_nvs_cb(const struct f
- struct platform_device *pdev = wl->pdev;
- struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
- struct wl12xx_platform_data *pdata = pdev_data->pdata;
-- unsigned long irqflags;
-+
- int ret;
- irq_handler_t hardirq_fn = NULL;
-
-@@ -6103,29 +6103,19 @@ static void wlcore_nvs_cb(const struct f
- wlcore_adjust_conf(wl);
-
- wl->irq = platform_get_irq(pdev, 0);
-- wl->platform_quirks = pdata->platform_quirks;
- wl->if_ops = pdev_data->if_ops;
-
--#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
-- irqflags = IRQF_TRIGGER_RISING;
-+ wl->irq_flags = irq_get_trigger_type(wl->irq) | IRQF_ONESHOT;
- hardirq_fn = wlcore_hardirq;
--#else
-- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) {
-- irqflags = IRQF_TRIGGER_RISING;
-- hardirq_fn = wlcore_hardirq;
-- } else {
-- irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
-- }
--#endif
-
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
- ret = compat_request_threaded_irq(&wl->irq_compat, wl->irq,
- hardirq_fn, wlcore_irq,
-- irqflags,
-+ wl->irqflags,
- pdev->name, wl);
- #else
- ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
-- irqflags, pdev->name, wl);
-+ wl->irq_flags, pdev->name, wl);
- #endif
- if (ret < 0) {
- wl1271_error("request_irq() failed: %d", ret);
---- a/drivers/net/wireless/ti/wlcore/wlcore.h
-+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
-@@ -188,6 +188,8 @@ struct wl1271 {
-
- int irq;
-
-+ int irq_flags;
-+
- spinlock_t wl_lock;
-
- enum wlcore_state state;
-@@ -395,9 +397,6 @@ struct wl1271 {
- /* Quirks of specific hardware revisions */
- unsigned int quirks;
-
-- /* Platform limitations */
-- unsigned int platform_quirks;
--
- /* number of currently active RX BA sessions */
- int ba_rx_session_count;
-
diff --git a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch b/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch
deleted file mode 100644
index 6394377..0000000
--- a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-The pwr_in_suspend flag depends on the MMC settings which can be
-retrieved from the SDIO subsystem, so it doesn't need to be part of
-the platform data structure. Move it to the platform device data that
-is passed from SDIO to wlcore.
-
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wlcore/main.c
-+++ b/drivers/net/wireless/ti/wlcore/main.c
-@@ -6074,7 +6074,6 @@ static void wlcore_nvs_cb(const struct f
- struct wl1271 *wl = context;
- struct platform_device *pdev = wl->pdev;
- struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
-- struct wl12xx_platform_data *pdata = pdev_data->pdata;
-
- int ret;
- irq_handler_t hardirq_fn = NULL;
-@@ -6127,7 +6126,7 @@ static void wlcore_nvs_cb(const struct f
- if (!ret) {
- wl->irq_wake_enabled = true;
- device_init_wakeup(wl->dev, 1);
-- if (pdata->pwr_in_suspend)
-+ if (pdev_data->pwr_in_suspend)
- wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
- }
- #endif
---- a/drivers/net/wireless/ti/wlcore/sdio.c
-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
-@@ -260,7 +260,7 @@ static int wl1271_probe(struct sdio_func
- dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
-
- if (mmcflags & MMC_PM_KEEP_POWER)
-- pdev_data->pdata->pwr_in_suspend = true;
-+ pdev_data->pwr_in_suspend = true;
-
- sdio_set_drvdata(func, glue);
-
---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
-+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
-@@ -209,6 +209,7 @@ struct wl1271_if_operations {
- struct wlcore_platdev_data {
- struct wl12xx_platform_data *pdata;
- struct wl1271_if_operations *if_ops;
-+ bool pwr_in_suspend;
- };
-
- #define MAX_NUM_KEYS 14
diff --git a/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch b/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch
deleted file mode 100644
index 4b20932..0000000
--- a/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-Instead of defining an enumeration with the FW specific values for the
-different clock rates, use the actual frequency instead. Also add a
-boolean to specify whether the clock is XTAL or not.
-
-Change all board files to reflect this.
-
-Additionally, this reverts commit 26f45c (ARM: OMAP2+: Legacy support
-for wl12xx when booted with devicetree), since this is not be needed
-anymore, now that DT support for WiLink is implemented.
-
-Cc: Tony Lindgren <tony@atomide.com>
-Cc: Sekhar Nori <nsekhar@ti.com>
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wl12xx/main.c
-+++ b/drivers/net/wireless/ti/wl12xx/main.c
-@@ -1711,6 +1711,43 @@ static struct ieee80211_sta_ht_cap wl12x
- },
- };
-
-+static const struct wl12xx_clock wl12xx_refclock_table[] = {
-+ { 19200000, false, WL12XX_REFCLOCK_19 },
-+ { 26000000, false, WL12XX_REFCLOCK_26 },
-+ { 26000000, true, WL12XX_REFCLOCK_26_XTAL },
-+ { 38400000, false, WL12XX_REFCLOCK_38 },
-+ { 38400000, true, WL12XX_REFCLOCK_38_XTAL },
-+ { 52000000, false, WL12XX_REFCLOCK_52 },
-+ { 0, false, 0 }
-+};
-+
-+static const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
-+ { 16368000, true, WL12XX_TCXOCLOCK_16_368 },
-+ { 16800000, true, WL12XX_TCXOCLOCK_16_8 },
-+ { 19200000, true, WL12XX_TCXOCLOCK_19_2 },
-+ { 26000000, true, WL12XX_TCXOCLOCK_26 },
-+ { 32736000, true, WL12XX_TCXOCLOCK_32_736 },
-+ { 33600000, true, WL12XX_TCXOCLOCK_33_6 },
-+ { 38400000, true, WL12XX_TCXOCLOCK_38_4 },
-+ { 52000000, true, WL12XX_TCXOCLOCK_52 },
-+ { 0, false, 0 }
-+};
-+
-+static int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
-+ u32 freq, bool xtal)
-+{
-+ int i = 0;
-+
-+ while(table[i].freq != 0) {
-+ if ((table[i].freq == freq) &&
-+ (table[i].xtal == xtal))
-+ return table[i].hw_idx;
-+ i++;
-+ };
-+
-+ return -EINVAL;
-+}
-+
- static int wl12xx_setup(struct wl1271 *wl)
- {
- struct wl12xx_priv *priv = wl->priv;
-@@ -1732,7 +1769,16 @@ static int wl12xx_setup(struct wl1271 *w
- wl12xx_conf_init(wl);
-
- if (!fref_param) {
-- priv->ref_clock = pdata->board_ref_clock;
-+ priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
-+ pdata->ref_clock_freq,
-+ pdata->ref_clock_xtal);
-+ if (priv->ref_clock < 0) {
-+ wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
-+ pdata->ref_clock_freq,
-+ pdata->ref_clock_xtal ? "XTAL" : "not XTAL");
-+
-+ return priv->ref_clock;
-+ }
- } else {
- if (!strcmp(fref_param, "19.2"))
- priv->ref_clock = WL12XX_REFCLOCK_19;
-@@ -1751,7 +1797,15 @@ static int wl12xx_setup(struct wl1271 *w
- }
-
- if (!tcxo_param) {
-- priv->tcxo_clock = pdata->board_tcxo_clock;
-+ priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
-+ pdata->tcxo_clock_freq,
-+ true);
-+ if (priv->tcxo_clock < 0) {
-+ wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
-+ pdata->tcxo_clock_freq);
-+
-+ return priv->tcxo_clock;
-+ }
- } else {
- if (!strcmp(tcxo_param, "19.2"))
- priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
---- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
-+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
-@@ -79,4 +79,32 @@ struct wl12xx_priv {
- struct wl127x_rx_mem_pool_addr *rx_mem_addr;
- };
-
-+/* Reference clock values */
-+enum {
-+ WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
-+ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */
-+ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */
-+ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */
-+ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
-+ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
-+};
-+
-+/* TCXO clock values */
-+enum {
-+ WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */
-+ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */
-+ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */
-+ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */
-+ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
-+ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
-+ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */
-+ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
-+};
-+
-+struct wl12xx_clock {
-+ u32 freq;
-+ bool xtal;
-+ u8 hw_idx;
-+};
-+
- #endif /* __WL12XX_PRIV_H__ */
diff --git a/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch b/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch
deleted file mode 100644
index 9e1d190..0000000
--- a/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch
+++ /dev/null
@@ -1,118 +0,0 @@
-If platform data is not available, try to get the required information
-from the device tree. Register an OF match table and parse the
-appropriate device tree nodes.
-
-Parse interrupt property only, for now.
-
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wlcore/sdio.c
-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
-@@ -30,7 +30,7 @@
- #include <linux/mmc/sdio_ids.h>
- #include <linux/mmc/card.h>
- #include <linux/mmc/host.h>
--#include <linux/gpio.h>
-+#include <linux/of_irq.h>
- #include <linux/wl12xx.h>
- #include <linux/pm_runtime.h>
- #include <linux/printk.h>
-@@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_
- .set_block_size = wl1271_sdio_set_block_size,
- };
-
-+static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
-+{
-+ struct wl12xx_platform_data *pdata;
-+ struct device_node *np = dev->of_node;
-+
-+ if (!np) {
-+ np = of_find_matching_node(NULL, dev->driver->of_match_table);
-+ if (!np) {
-+ dev_notice(dev, "device tree node not available\n");
-+ pdata = ERR_PTR(-ENODEV);
-+ goto out;
-+ }
-+ }
-+
-+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
-+ if (!pdata) {
-+ dev_err(dev, "can't allocate platform data\n");
-+ pdata = ERR_PTR(-ENODEV);
-+ goto out;
-+ }
-+
-+ pdata->irq = irq_of_parse_and_map(np, 0);
-+ if (pdata->irq < 0) {
-+ dev_err(dev, "can't get interrupt gpio from the device tree\n");
-+ goto out_free;
-+ }
-+
-+ goto out;
-+
-+out_free:
-+ kfree(pdata);
-+ pdata = ERR_PTR(-ENODEV);
-+
-+out:
-+ return pdata;
-+}
-+
- static int wl1271_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
- {
-@@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func
- /* Use block mode for transferring over one block size of data */
- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
-
-+ /* The pdata allocated here is freed when the device is freed,
-+ * so we don't need an additional out label to free it in case
-+ * of error further on.
-+ */
-+
-+ /* Try to get legacy platform data from the board file */
- pdev_data->pdata = wl12xx_get_platform_data();
- if (IS_ERR(pdev_data->pdata)) {
-- ret = PTR_ERR(pdev_data->pdata);
-- dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
-- goto out_free_glue;
-+ dev_info(&func->dev,
-+ "legacy platform data not found, trying device tree\n");
-+
-+ pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
-+ if (IS_ERR(pdev_data->pdata)) {
-+ dev_err(&func->dev, "can't get platform data\n");
-+ goto out_free_glue;
-+ }
- }
-
- /* if sdio can keep power while host is suspended, enable wow */
-@@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sd
- };
- #endif
-
-+static const struct of_device_id wlcore_sdio_of_match_table[] = {
-+ { .compatible = "ti,wilink6" },
-+ { .compatible = "ti,wilink7" },
-+ { .compatible = "ti,wilink8" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
-+
- static struct sdio_driver wl1271_sdio_driver = {
- .name = "wl1271_sdio",
- .id_table = wl1271_devices,
- .probe = wl1271_probe,
- .remove = wl1271_remove,
--#ifdef CONFIG_PM
- .drv = {
-+#ifdef CONFIG_PM
- .pm = &wl1271_sdio_pm_ops,
-- },
- #endif
-+ .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
-+ },
- };
-
- static int __init wl1271_init(void)
diff --git a/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch b/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch
deleted file mode 100644
index be1f9ad..0000000
--- a/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-Add refclock and tcxoclock as clock providers in WiLink. These clocks
-are not accesible outside the WiLink module, but they are registered
-in the clock framework anyway. Only the WiLink chip consumes these
-clocks.
-
-In theory, the WiLink chip could be connected to external clocks
-instead of using these internal clocks, so make the clock consumer
-code generic enough. If external clocks are used, then the internal
-clock device tree nodes are not necessary, but the external ones must
-be specified.
-
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wlcore/sdio.c
-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
-@@ -34,6 +34,7 @@
- #include <linux/wl12xx.h>
- #include <linux/pm_runtime.h>
- #include <linux/printk.h>
-+#include <linux/clk-provider.h>
-
- #include "wlcore.h"
- #include "wl12xx_80211.h"
-@@ -214,10 +215,15 @@ static struct wl1271_if_operations sdio_
- .set_block_size = wl1271_sdio_set_block_size,
- };
-
-+static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
-+ { .compatible = "ti,wilink-clock" },
-+};
-+
- static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
- {
- struct wl12xx_platform_data *pdata;
- struct device_node *np = dev->of_node;
-+ struct device_node *clock_node;
-
- if (!np) {
- np = of_find_matching_node(NULL, dev->driver->of_match_table);
-@@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlco
- goto out_free;
- }
-
-+ for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
-+ of_fixed_clk_setup(clock_node);
-+
- goto out;
-
- out_free:
diff --git a/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch b/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch
deleted file mode 100644
index 09ff4af..0000000
--- a/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-Read the clock nodes from the device tree and use them to set the
-frequency for the refclock and the tcxo clock.
-
-Also, call sdio_set_drvdata() earlier, so the glue is already set in
-the driver data when we call wlcore_get_pdata_from_of() and we don't
-need to pass it as a parameter.
-
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wlcore/sdio.c
-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
-@@ -53,6 +53,7 @@ static bool dump = false;
- struct wl12xx_sdio_glue {
- struct device *dev;
- struct platform_device *core;
-+ struct clk *refclock, *tcxoclock;
- };
-
- static const struct sdio_device_id wl1271_devices[] = {
-@@ -224,6 +225,7 @@ static struct wl12xx_platform_data *wlco
- struct wl12xx_platform_data *pdata;
- struct device_node *np = dev->of_node;
- struct device_node *clock_node;
-+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(dev_to_sdio_func(dev));
-
- if (!np) {
- np = of_find_matching_node(NULL, dev->driver->of_match_table);
-@@ -250,6 +252,26 @@ static struct wl12xx_platform_data *wlco
- for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
- of_fixed_clk_setup(clock_node);
-
-+ /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
-+ glue->refclock = of_clk_get_by_name(np, "refclock");
-+ if (IS_ERR(glue->refclock)) {
-+ dev_err(dev, "couldn't find refclock on the device tree\n");
-+ glue->refclock = NULL;
-+ } else {
-+ clk_prepare_enable(glue->refclock);
-+ pdata->ref_clock_freq = clk_get_rate(glue->refclock);
-+ }
-+
-+ /* TODO: make sure we have this when needed (ie. for WL7) */
-+ glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
-+ if (IS_ERR(glue->tcxoclock)) {
-+ dev_err(dev, "couldn't find tcxoclock on the device tree\n");
-+ glue->tcxoclock = NULL;
-+ } else {
-+ clk_prepare_enable(glue->tcxoclock);
-+ pdata->ref_clock_freq = clk_get_rate(glue->tcxoclock);
-+ }
-+
- goto out;
-
- out_free:
-@@ -294,6 +316,8 @@ static int wl1271_probe(struct sdio_func
- /* Use block mode for transferring over one block size of data */
- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
-
-+ sdio_set_drvdata(func, glue);
-+
- /* The pdata allocated here is freed when the device is freed,
- * so we don't need an additional out label to free it in case
- * of error further on.
-@@ -319,8 +343,6 @@ static int wl1271_probe(struct sdio_func
- if (mmcflags & MMC_PM_KEEP_POWER)
- pdev_data->pwr_in_suspend = true;
-
-- sdio_set_drvdata(func, glue);
--
- /* Tell PM core that we don't need the card to be powered now */
- pm_runtime_put_noidle(&func->dev);
-
-@@ -387,6 +409,16 @@ static void wl1271_remove(struct sdio_fu
- {
- struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
-
-+ if (glue->refclock) {
-+ clk_disable_unprepare(glue->refclock);
-+ clk_put(glue->refclock);
-+ }
-+
-+ if (glue->tcxoclock) {
-+ clk_disable_unprepare(glue->tcxoclock);
-+ clk_put(glue->tcxoclock);
-+ }
-+
- /* Undo decrement done above in wl1271_probe */
- pm_runtime_get_noresume(&func->dev);
-
diff --git a/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch b/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch
deleted file mode 100644
index 6b09177..0000000
--- a/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-The fref and the tcxo clocks settings are optional in some platforms.
-WiLink8 doesn't need either, so we don't check the values. WiLink 6
-only needs the fref clock, so we check that it is valid or return with
-an error. WiLink7 needs both clocks, if either is not available we
-return with an error.
-
-Signed-off-by: Luciano Coelho <coelho@ti.com>
-Reviewed-by: Felipe Balbi <balbi@ti.com>
-
---- a/drivers/net/wireless/ti/wl12xx/main.c
-+++ b/drivers/net/wireless/ti/wl12xx/main.c
-@@ -930,6 +930,11 @@ static int wl128x_boot_clk(struct wl1271
- u16 sys_clk_cfg;
- int ret;
-
-+ if ((priv->ref_clock < 0) || (priv->tcxo_clock < 0)) {
-+ wl1271_error("Missing fref and/or tcxo clock settings\n");
-+ return -EINVAL;
-+ }
-+
- /* For XTAL-only modes, FREF will be used after switching from TCXO */
- if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
- priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
-@@ -979,6 +984,11 @@ static int wl127x_boot_clk(struct wl1271
- u32 clk;
- int ret;
-
-+ if (priv->ref_clock < 0) {
-+ wl1271_error("Missing fref clock settings\n");
-+ return -EINVAL;
-+ }
-+
- if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
- wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
-
-@@ -1768,7 +1778,7 @@ static int wl12xx_setup(struct wl1271 *w
- wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
- wl12xx_conf_init(wl);
-
-- if (!fref_param) {
-+ if (!fref_param && (pdata->ref_clock_freq > 0)) {
- priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
- pdata->ref_clock_freq,
- pdata->ref_clock_xtal);
-@@ -1779,6 +1789,8 @@ static int wl12xx_setup(struct wl1271 *w
-
- return priv->ref_clock;
- }
-+ } else if (!fref_param) {
-+ priv->ref_clock = -EINVAL;
- } else {
- if (!strcmp(fref_param, "19.2"))
- priv->ref_clock = WL12XX_REFCLOCK_19;
-@@ -1796,7 +1808,7 @@ static int wl12xx_setup(struct wl1271 *w
- wl1271_error("Invalid fref parameter %s", fref_param);
- }
-
-- if (!tcxo_param) {
-+ if (!fref_param && (pdata->tcxo_clock_freq > 0)) {
- priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
- pdata->tcxo_clock_freq,
- true);
-@@ -1806,7 +1818,9 @@ static int wl12xx_setup(struct wl1271 *w
-
- return priv->tcxo_clock;
- }
-- } else {
-+ } else if (!fref_param) {
-+ priv->tcxo_clock = -EINVAL;
-+ }else {
- if (!strcmp(tcxo_param, "19.2"))
- priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
- else if (!strcmp(tcxo_param, "26"))
---- a/drivers/net/wireless/ti/wlcore/sdio.c
-+++ b/drivers/net/wireless/ti/wlcore/sdio.c
-@@ -252,20 +252,16 @@ static struct wl12xx_platform_data *wlco
- for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
- of_fixed_clk_setup(clock_node);
-
-- /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
- glue->refclock = of_clk_get_by_name(np, "refclock");
- if (IS_ERR(glue->refclock)) {
-- dev_err(dev, "couldn't find refclock on the device tree\n");
- glue->refclock = NULL;
- } else {
- clk_prepare_enable(glue->refclock);
- pdata->ref_clock_freq = clk_get_rate(glue->refclock);
- }
-
-- /* TODO: make sure we have this when needed (ie. for WL7) */
- glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
- if (IS_ERR(glue->tcxoclock)) {
-- dev_err(dev, "couldn't find tcxoclock on the device tree\n");
- glue->tcxoclock = NULL;
- } else {
- clk_prepare_enable(glue->tcxoclock);
diff --git a/package/mac80211/patches/a01-compat_fix_compile.patch b/package/mac80211/patches/a01-compat_fix_compile.patch
new file mode 100644
index 0000000..9e9e6c7
--- /dev/null
+++ b/package/mac80211/patches/a01-compat_fix_compile.patch
@@ -0,0 +1,15 @@
+--- a/compat/compat-3.6.c
++++ b/compat/compat-3.6.c
+@@ -148,6 +148,7 @@ int sg_alloc_table_from_pages(struct sg_
+ }
+ EXPORT_SYMBOL_GPL(sg_alloc_table_from_pages);
+
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
+ /* whoopsie ! */
+ #ifndef CONFIG_COMMON_CLK
+ int clk_enable(struct clk *clk)
+@@ -161,3 +162,4 @@ void clk_disable(struct clk *clk)
+ }
+ EXPORT_SYMBOL_GPL(clk_disable);
+ #endif
++#endif
diff --git a/target/linux/generic/files/include/linux/ath9k_platform.h b/target/linux/generic/files/include/linux/ath9k_platform.h
index a0b7531..03aa636 100644
--- a/target/linux/generic/files/include/linux/ath9k_platform.h
+++ b/target/linux/generic/files/include/linux/ath9k_platform.h
@@ -39,6 +39,8 @@ struct ath9k_platform_data {
int (*get_mac_revision)(void);
int (*external_reset)(void);
+ bool use_eeprom;
+
int num_leds;
const struct gpio_led *leds;
};