From: Matthias Schiffer Date: Mon, 19 May 2014 15:59:37 +0200 Subject: Backport mac80211 from Barrier Breaker (r40804) diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 9a7093c..7eacf24 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-19 PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_BACKPORT_VERSION:= -PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6 +PKG_MD5SUM:=ff5426bf85668c3c36c7f602adeb1e5b 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,7 +363,7 @@ define KernelPackage/rtl8180 $(call KernelPackage/rtl818x/Default) DEPENDS+= @PCI_SUPPORT TITLE+= (RTL8180 PCI) - FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl8180.ko + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtl818x/rtl8180/rtl818x_pci.ko AUTOLOAD:=$(call AutoLoad,27,rtl8180) endef @@ -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 --- 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 +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 +--- + 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 - #include - -+#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..d550bba 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 +@@ -2723,7 +2723,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 +@@ -4688,7 +4688,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 + #include + #include ++#include + #include + + #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..c80b2bb 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 +@@ -1034,14 +1034,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 +@@ -1050,13 +1050,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 +@@ -1101,10 +1101,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..dc1e265 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1,4153 +1,4383 @@ -commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef +commit ff9655bebd25d35ab13c2515a029723b69949720 Author: Felix Fietkau -Date: Sun Apr 6 23:35:28 2014 +0200 +Date: Mon May 19 21:20:49 2014 +0200 - ath9k_hw: reduce ANI firstep range for older chips + ath9k: avoid passing buffers to the hardware during flush - 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. + 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: Felix Fietkau -commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14 -Author: Helmut Schaa -Date: Wed Mar 12 10:37:55 2014 +0100 +commit 46c5d7d207a2a0725066c0928fd19b8c578b7d4f +Author: Oleksij Rempel +Date: Tue May 20 00:02:03 2014 +0200 - 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 - Signed-off-by: Helmut Schaa - -commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e -Author: Felix Fietkau -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 - -commit 91d70d40400c569b49605b78fd7c43e9405694f4 -Author: Felix Fietkau -Date: Tue Mar 11 14:00:37 2014 +0100 - - 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. - - On older chips, the differences are bigger and especially AR5008/AR9001 - are configured to much more sensitive values than what is useful. - - 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 - -commit c977493766310a825f406836636ffd66e1447783 -Author: Felix Fietkau -Date: Mon Mar 10 19:52:56 2014 +0100 - - ath9k_hw: remove ANI function restrictions for AP mode - - 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. - - Signed-off-by: Felix Fietkau - -commit 8d804f1af11e4e058b1e8453327777d73a585cb8 -Author: Felix Fietkau -Date: Sun Mar 9 11:25:43 2014 +0100 - - ath9k: clean up and enhance ANI debugfs file - - Unify scnprintf calls and include the current OFDM/CCK immunity level. - - Signed-off-by: Felix Fietkau - -commit 22e298b5a3a8a49e33805d4e351965123dede35b -Author: Felix Fietkau -Date: Sun Mar 9 10:58:47 2014 +0100 - - 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. - - This should hopefully fix some Tx DMA issues with buffered multicast - frames in AP mode. - - Cc: stable@vger.kernel.org - Signed-off-by: Felix Fietkau - -commit fcb064fdd5a27bec8d24099bc0172468f34c97cb -Author: Felix Fietkau -Date: Sun Mar 9 09:43:09 2014 +0100 - - 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 - Signed-off-by: Felix Fietkau - -commit 31959d8df39319e32c6d5ba9c135727be90cfad7 -Author: Michal Kazior -Date: Fri Mar 7 08:09:38 2014 +0100 - - 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: - - [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 - [ 4605.210789] IP: [] ieee80211_parse_bitrates+0x65/0x110 [mac80211] - - The splat was preceeded by WARN_ON(!chanctx_conf) - in ieee80211_get_sdata_band(). - - Signed-off-by: Michal Kazior - -commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e -Author: Michael Braun -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: # 3.10.x - Cc: # 3.11.x - Cc: # 3.12.x - Cc: # 3.13.x - Cc: - Cc: - Signed-off-by: Michael Braun + ath9k_htc: fix build with disabled debug + + CC [M] drivers/net/wireless/ath/ath9k/htc_drv_txrx.o + drivers/net/wireless/ath/ath9k/htc_drv_txrx.c: In function ‘ath9k_rx_prepare’: + drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:1006:2: warning: passing argument 2 of ‘ath9k_htc_err_stat_rx’ from incompatible pointer type [enabled by default] + ath9k_htc_err_stat_rx(priv, &rx_stats); + ^ + In file included from drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:17:0: + drivers/net/wireless/ath/ath9k/htc.h:380:20: note: expected ‘struct ath_htc_rx_status *’ but argument is of type ‘struct ath_rx_status *’ + static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, + + Signed-off-by: Oleksij Rempel -commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec +commit 2d331334e9dc5659fdf9a89326c34c3db5a15279 Author: Johannes Berg -Date: Mon Mar 3 14:19:08 2014 +0100 +Date: Mon May 19 17:59:50 2014 +0200 - cfg80211: remove racy beacon_interval assignment + cfg80211: constify wowlan/coalesce mask/pattern pointers - 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. + This requires changing the nl80211 parsing code a bit to use + intermediate pointers for the allocation, but clarifies the + API towards the drivers. - Reported-by: Michal Kazior Signed-off-by: Johannes Berg -commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0 -Author: Felix Fietkau -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 - -commit 431e506da5953adc3b65af25f4b90873d528c115 -Author: Felix Fietkau -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 - -commit 98d1a6c5b14688ed030e81b889f607be308e0df9 -Author: Felix Fietkau -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 - Signed-off-by: Felix Fietkau - -commit 52a46300e782fe6994466523eb2b0b59091ea59f -Author: Felix Fietkau -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 - -commit 118945bb12082e9d4edddc868d88143164e0f440 -Author: Felix Fietkau -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 - -commit ee41f72476e1ea44283dfe1cbf75b9543a1e15c8 -Author: Felix Fietkau -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 - -commit b14fbb554fc65a2e0b5c41a319269b0350f187e7 -Author: Felix Fietkau -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 - -commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5 -Author: Felix Fietkau -Date: Sat Feb 22 13:43:29 2014 +0100 - - 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. - - 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 - -commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5 -Author: Felix Fietkau -Date: Fri Feb 21 11:39:59 2014 +0100 - - ath9k: list more reset causes in debugfs - - Number of MAC hangs and stuck beacons were missing - - Signed-off-by: Felix Fietkau - -commit d84856012e0f10fe598a5ad3b7b869397a089e07 +commit 6788105c46babaa6938cbacb72fdf20bec4bb2e3 Author: Johannes Berg -Date: Thu Feb 20 11:19:58 2014 +0100 +Date: Mon May 19 17:53:16 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 - - 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 - - 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(). + cfg80211: constify more pointers in the cfg80211 API - 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. + This also propagates through the drivers. - While at it, fix a cleanup path issue when a station is - removed while the driver is still blocking its wakeup. + The orinoco driver uses the cfg80211 API structs for internal + bookkeeping, and so needs a (void *) cast that removes the + const - but that's OK because it allocates those pointers. Signed-off-by: Johannes Berg -commit 798f2786602cbe93e6b928299614aa36ebf50692 +commit c3d95010fd881da0fa0a4e88532412f5d0c092f6 Author: Johannes Berg -Date: Mon Feb 17 20:49:03 2014 +0100 +Date: Mon May 19 17:19:31 2014 +0200 - mac80211: insert stations before adding to driver + cfg80211: constify MAC addresses in cfg80211 ops - 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 - - 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. - - 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. + This propagates through all the drivers and mac80211. Signed-off-by: Johannes Berg -commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe -Author: Emmanuel Grumbach -Date: Thu Feb 20 09:22:11 2014 +0200 +commit ddf1e6f0f0354c601af7d42e5ace4b51f8b0bffc +Author: Luciano Coelho +Date: Thu May 15 20:32:08 2014 +0300 - 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. + mac80211: fix csa_counter_offs argument name in docbook - 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. + The csa_counter_offs was erroneously described as csa_offs in + the docbook section. - 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. + This fixes two warnings when making htmldocs (at least): - Additionally, it can lead to the crash below. + Warning(include/net/mac80211.h:3428): No description found for parameter 'csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]' + Warning(include/net/mac80211.h:3428): Excess struct/union/enum/typedef member 'csa_offs' description in 'ieee80211_mutable_offsets' - 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: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] - *pde = 00000000 - Oops: 0000 [#1] SMP DEBUG_PAGEALLOC - EIP: 0060:[] 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: - [] ieee80211_free_txskb+0x15/0x20 [mac80211] - [] invoke_tx_handlers+0x1661/0x1780 [mac80211] - [] ieee80211_tx+0x75/0x100 [mac80211] - [] ieee80211_xmit+0x8f/0xc0 [mac80211] - [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] - [] dev_hard_start_xmit+0x450/0x950 - [] sch_direct_xmit+0xa9/0x250 - [] __qdisc_run+0x4b/0x150 - [] dev_queue_xmit+0x2c2/0xca0 - - Cc: stable@vger.kernel.org - Reported-by: Yaara Rozenblum - Signed-off-by: Emmanuel Grumbach - Reviewed-by: Stanislaw Gruszka - [reword commit log, use a separate lock] - Signed-off-by: Johannes Berg - -commit 80e419de0dff38436b30d363311c625766193f86 -Author: Inbal Hacohen -Date: Wed Feb 12 09:32:27 2014 +0200 - - cfg80211: bugfix in regulatory user hint process - - 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". - - Signed-off-by: Inbal Hacohen + Signed-off-by: Luciano Coelho Signed-off-by: Johannes Berg -commit 6514c93afede55284e2cb63359aadedb85884c80 -Author: Jouni Malinen -Date: Tue Feb 18 20:41:08 2014 +0200 - - ath9k: Enable U-APSD AP mode support - - mac80211 handles the actual operations, so ath9k can just indicate - support for this. Based on initial tests, this combination seems to - work fine. - - Signed-off-by: Jouni Malinen - -commit a63caf0a357ad5c1f08d6b7827dc76c451445017 -Author: Stanislaw Gruszka -Date: Wed Feb 19 13:15:17 2014 +0100 +commit 202322d1c04b8e498bd5bb78606fcf3941512b35 +Author: Luciano Coelho +Date: Thu May 15 20:18:09 2014 +0300 - ath9k: protect tid->sched check + cfg80211: add documentation for max_num_csa_counters - 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: + Move the comment in the structure to a description of the + max_num_csa_counters field in the docbook area. - [424271.637220] BUG: unable to handle kernel paging request at 00100104 - [424271.637328] IP: [] ath_tx_aggr_sleep+0x62/0xe0 [ath9k] - ... - [424271.639953] Call Trace: - [424271.639998] [] ? ath9k_get_survey+0x110/0x110 [ath9k] - [424271.640083] [] ath9k_sta_notify+0x42/0x50 [ath9k] - [424271.640177] [] sta_ps_start+0x8f/0x1c0 [mac80211] - [424271.640258] [] ? free_compound_page+0x2e/0x40 - [424271.640346] [] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211] - [424271.640437] [] ? kmem_cache_free+0x1d8/0x1f0 - [424271.640510] [] ? kfree_skbmem+0x34/0x90 - [424271.640578] [] ? put_page+0x2c/0x40 - [424271.640640] [] ? kfree_skbmem+0x34/0x90 - [424271.640706] [] ? kfree_skbmem+0x34/0x90 - [424271.640787] [] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211] - [424271.640897] [] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211] - [424271.641009] [] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211] - [424271.641104] [] ? ip_output+0x7e/0xd0 - [424271.641182] [] ieee80211_rx+0x307/0x7c0 [mac80211] - [424271.641266] [] ath_rx_tasklet+0x88e/0xf70 [ath9k] - [424271.641358] [] ? ieee80211_rx+0x1dc/0x7c0 [mac80211] - [424271.641445] [] ath9k_tasklet+0xcb/0x130 [ath9k] + This fixes a warning when building htmldocs (at least): - Bug report: - https://bugzilla.kernel.org/show_bug.cgi?id=70551 + Warning(include/net/cfg80211.h:3064): No description found for parameter 'max_num_csa_counters' - Reported-and-tested-by: Max Sydorenko - Cc: stable@vger.kernel.org - Signed-off-by: Stanislaw Gruszka + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41 -Author: Felix Fietkau -Date: Tue Feb 11 15:54:13 2014 +0100 +commit 457a33192f64b7637e8fd0ae0e9f32701c908603 +Author: Johannes Berg +Date: Mon May 19 11:24:19 2014 +0200 - mac80211: send control port protocol frames to the VO queue + mac80211: minstrel-ht: small clarifications - Improves reliability of wifi connections with WPA, since authentication - frames are prioritized over normal traffic and also typically exempt - from aggregation. + Antonio and I were looking over this code and some things + didn't immediately make sense, so we came up with two small + clarifications. - Cc: stable@vger.kernel.org - Signed-off-by: Felix Fietkau + Signed-off-by: Johannes Berg -commit d4426800f71e972feaa33e04c5801fc730627bdd -Author: Stanislaw Gruszka -Date: Mon Feb 10 22:38:28 2014 +0100 +commit 1e35dce952a64a957de97ae1f2bb19301756b936 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:50 2014 +0300 - 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. + mac80211: Handle the CSA counters correctly - Bug report: - https://bugzilla.kernel.org/show_bug.cgi?id=54391 + Make the beacon CSA counters part of ieee80211_mutable_offsets and don't + decrement CSA counters when generating a beacon template. This permits the + driver to offload the CSA counters handling. Since mac80211 updates the probe + responses with the correct counter, the driver should sync the counter's value + with mac80211 using ieee80211_csa_update_counter function. - Reported-by: Petr Pisar - Bisected-by: Tom Li - Reported-and-tested-by: Tom Li - Cc: stable@vger.kernel.org - Signed-off-by: Stanislaw Gruszka + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:55 2014 +0530 +commit e7b5c449815d28a2105fde5b42e112f78cc711ac +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:49 2014 +0300 - ath9k: Calculate IQ-CAL median + mac80211: Provide ieee80211_beacon_get_template API - 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. + Add a new API ieee80211_beacon_get_template, which doesn't + affect DTIM counter and should be used if the device generates beacon + frames, and new beacon template is needed. In addition set the offsets + to TIM IE for MESH interface. - Signed-off-by: Sujith Manoharan + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit c52a6fce0820c8d0687443ab86058ae03b478c8f -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:54 2014 +0530 +commit e54eda80273ce8aded058c3c9365dca2342e2e75 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:47 2014 +0300 - ath9k: Expand the IQ coefficient array + mac80211: Support multiple CSA counters - This will be used for storing data for mutiple - IQ calibration runs, for AR955x. + Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters. + This is defined to be 2 now, to support both CSA and eCSA + counters. - Signed-off-by: Sujith Manoharan + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 034969ff5c2b6431d10e07c1938f0b916da85cc3 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:53 2014 +0530 +commit 678e87c3b929dd60d59470e8981eb551cee10319 +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:46 2014 +0300 - 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 + cfg80211: Support multiple CSA counters + + Change the type of NL80211_ATTR_CSA_C_OFF_BEACON and + NL80211_ATTR_CSA_C_OFF_PRESP to be NLA_BINARY which allows + userspace to use beacons and probe responses with + multiple CSA counters. + This isn't breaking the API since userspace can + continue to use nla_put_u16 for this attributes, which + is equivalent to a single element u16 array. + In addition advertise max number of supported CSA counters. + This is needed when using CSA and eCSA IEs together. + + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:52 2014 +0530 +commit 93f4867a966cc8645659031bbd44a9bb4b78485f +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:45 2014 +0300 - ath9k: Fix magnitude/phase calculation + mac80211: Update CSA counters in mgmt frames - Incorrect values are programmed in the registers - containing the IQ correction coefficients by the IQ-CAL - post-processing code. Fix this. + Track current csa counter value and use it + to update mgmt frames at the provided offsets. - Signed-off-by: Sujith Manoharan + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit 36f93484f96f79171dcecb67c5ef0c3de22531a6 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:51 2014 +0530 +commit 6c8461fcc03ff4d250027e47f53315b5e0ec43aa +Author: Andrei Otcheretianski +Date: Fri May 9 14:11:44 2014 +0300 - ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes + cfg80211: Add API to update CSA counters in mgmt frames - Use ar9003_hw_tx_iq_cal_outlier_detection instead. - - Signed-off-by: Sujith Manoharan - -commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:50 2014 +0530 - - ath9k: Check explicitly for IQ calibration + Add NL80211_ATTR_CSA_C_OFFSETS_TX which holds an array + of offsets to the CSA counters which should be updated + when sending a management frames with NL80211_CMD_FRAME. - 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. + This API should be used by the drivers that wish to keep the + CSA counter updated in probe responses, but do not implement + probe response offloading and so, do not use + ieee80211_proberesp_get function. - Signed-off-by: Sujith Manoharan + Signed-off-by: Andrei Otcheretianski + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit cb4969634b93c4643a32cc3fbd27d2b288b25771 -Author: Sujith Manoharan -Date: Fri Feb 7 10:29:49 2014 +0530 +commit 7d09fc9f1903b3d5e7d046bdf10467f37a97c4f9 +Author: Luciano Coelho +Date: Thu May 15 13:05:39 2014 +0300 - ath9k: Fix IQ cal post processing for SoC + cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required() - 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. + There is no need to pass NL80211_IFTYPE_UNSPECIFIED when calling + cfg80211_chandef_dfs_required() since we always already have the + interface type. So, pass the actual interface type instead. - Signed-off-by: Sujith Manoharan - -commit e138e0ef9560c46ce93dbb22a728a57888e94d1c -Author: Sujith Manoharan -Date: Mon Feb 3 13:31:37 2014 +0530 - - ath9k: Fix TX power calculation + Additionally, have cfg80211_chandef_dfs_required() WARN if the passed + interface type is NL80211_IFTYPE_UNSPECIFIED, so we can detect + problems more easily. - 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. - - Cc: Rajkumar Manoharan - Signed-off-by: Sujith Manoharan + Tested-by: Janusz Dziedzic + Reported-by: Eliad Peller + Signed-off-by: Luciano Coelho + Signed-off-by: Johannes Berg -commit b9f268b5b01331c3c82179abca551429450e9417 -Author: Michal Kazior -Date: Wed Jan 29 14:22:27 2014 +0100 +commit 2b7443b15f26ecb98281474666383cf2a882fbad +Author: Janusz Dziedzic +Date: Wed May 14 13:25:04 2014 +0200 - cfg80211: consider existing DFS interfaces - - It was possible to break interface combinations in - the following way: + cfg80211: fix start_radar_detection issue - combo 1: iftype = AP, num_ifaces = 2, num_chans = 2, - combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20 + After patch: + cfg80211/mac80211: refactor cfg80211_chandef_dfs_required() - With the above interface combinations it was - possible to: + start_radar_detection always fail with -EINVAL. - step 1. start AP on DFS channel by matching combo 2 - step 2. start AP on non-DFS channel by matching combo 1 - - 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 + Acked-by: Luciano Coelho + Signed-off-by: Janusz Dziedzic Signed-off-by: Johannes Berg -commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28 -Author: Antonio Quartulli -Date: Wed Jan 29 17:53:43 2014 +0100 +commit 4f46eb8b28f96aca212a364e0fa847eb5333df67 +Author: Felix Fietkau +Date: Mon May 5 11:48:40 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. + cfg80211: allow restricting supported dfs regions - 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. + At the moment, the ath9k/ath10k DFS module only supports detecting ETSI + radar patterns. + Add a bitmap in the interface combinations, indicating which DFS regions + are supported by the detector. If unset, support for all regions is + assumed. - 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). - - Cc: Kalle Valo - Cc: Arend van Spriel - Cc: Bing Zhao - Cc: Jussi Kivilinna - Cc: libertas-dev@lists.infradead.org - Acked-by: Kalle Valo - Signed-off-by: Antonio Quartulli - [minor code cleanup in ath6kl] + Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg -commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85 +commit 0277b034768d1800a00829a755fc56b925aa6b95 Author: Johannes Berg -Date: Fri Jan 24 14:41:44 2014 +0100 +Date: Wed Apr 30 14:19:04 2014 +0200 - mac80211: fix bufferable MMPDU RX handling + mac80211: handle failed restart/resume better - 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. + When the driver fails during HW restart or resume, the whole + stack goes into a very confused state with interfaces being + up while the hardware is down etc. - 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. + Address this by shutting down everything; we'll run into a + lot of warnings in the process but that's better than having + the whole stack get messed up. + Reviewed-by: Arik Nemtsov Signed-off-by: Johannes Berg -commit fc0df6d2343636e3f48a069330d5b972e3d8659d -Author: Janusz Dziedzic -Date: Fri Jan 24 14:29:21 2014 +0100 +commit 43fd71bc4b83d24981e90ca178f505cf6a6b16dc +Author: Luciano Coelho +Date: Wed May 7 20:05:12 2014 +0300 - cfg80211: set preset_chandef after channel switch + mac80211: fix sparse warning caused by __ieee80211_channel_switch() - Set preset_chandef in channel switch notification. - In other case we will have old preset_chandef. + Commit 59af6928 (mac80211: fix CSA tx queue stopping) introduced a + sparse warning: - Signed-off-by: Janusz Dziedzic - Signed-off-by: Johannes Berg - -commit cdec895e2344987ff171cece96e25d7407a3ebf6 -Author: Simon Wunderlich -Date: Fri Jan 24 23:48:29 2014 +0100 - - mac80211: send ibss probe responses with noack flag + net/mac80211/cfg.c:3274:5: warning: symbol '__ieee80211_channel_switch' was not declared. Should it be static? - 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. + Fix it by declaring the function static. - Signed-off-by: Simon Wunderlich - [fix typo & 'wildcard SSID' in commit log] + Signed-off-by: Luciano Coelho Signed-off-by: Johannes Berg -commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b +commit dd4371e2957db19870bb22ab84e841e1ac6e8997 Author: Luciano Coelho -Date: Tue Jan 28 17:09:08 2014 +0200 +Date: Wed May 7 19:07:05 2014 +0300 - mac80211: ibss: remove unnecessary call to release channel + cfg80211: fix docbook warning + + When trying to generate documentation, at least xmldocs, we get the + following warning: + + Warning(include/net/cfg80211.h:461): No description found for parameter 'nl80211_iftype' - 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(). + Fix it by adding the iftype argument name to the + cfg80211_chandef_dfs_required() function declaration. + Reported-and-tested-by: Masanari Iida Signed-off-by: Luciano Coelho Signed-off-by: Johannes Berg -commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7 +commit 56de850ae960f096c784ec07864ca5b71abd16e6 Author: Michal Kazior -Date: Wed Jan 29 07:56:21 2014 +0100 +Date: Thu May 8 09:10:02 2014 +0200 - mac80211: add missing CSA locking + mac80211: disconnect iface if CSA unexpectedly fails - The patch adds a missing sdata lock and adds a few - lockdeps for easier maintenance. + It doesn't make much sense to leave a crippled + interface running. - Signed-off-by: Michal Kazior - Signed-off-by: Johannes Berg - -commit ad17ba7d14d225b109b73c177cd446afb8050598 -Author: Michal Kazior -Date: Wed Jan 29 07:56:20 2014 +0100 - - mac80211: fix sdata->radar_required locking + As a side effect this will unblock tx queues with + CSA reason immediately after failure instead of + until after userspace requests interface to stop. - radar_required setting wasn't protected by - local->mtx in some places. This should prevent - from scanning/radar detection/roc colliding. + This also gives userspace an opportunity to + indirectly see CSA failure. Signed-off-by: Michal Kazior + [small code cleanup] Signed-off-by: Johannes Berg -commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d -Author: Michal Kazior -Date: Wed Jan 29 07:56:19 2014 +0100 +commit f5894c4f19e55bb1ea6376031fe9d47d7528be9e +Author: Loic Poulain +Date: Wed May 7 11:38:11 2014 +0200 - mac80211: move csa_active setting in STA CSA + rfkill-gpio: Use gpio cansleep version - 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. + If gpio controller requires waiting for read and write + GPIO values, then we have to use the gpio cansleep api. + Fix the rfkill_gpio_set_power which calls only the + nonsleep version (causing kernel warning). + There is no problem to use the cansleep version here + because we are not in IRQ handler or similar context + (cf rfkill_set_block). - Signed-off-by: Michal Kazior - Reviewed-by: Luciano Coelho + Signed-off-by: Loic Poulain Signed-off-by: Johannes Berg -commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9 +commit 47fdf5d4f3704d2db9d1c0f647f788edef104fc8 Author: Michal Kazior -Date: Wed Jan 29 07:56:18 2014 +0100 +Date: Wed Apr 9 15:45:36 2014 +0200 - mac80211: fix possible memory leak on AP CSA failure + mac80211: ignore cqm during csa - If CSA for AP interface failed and the interface - was not stopped afterwards another CSA request - would leak sdata->u.ap.next_beacon. + It is not guaranteed that multi-vif channel + switching is tightly synchronized. It makes sense + to ignore cqm (missing beacons, et al) while csa + is progressing and re-check it after it completes. Signed-off-by: Michal Kazior - Reviewed-by: Luciano Coelho Signed-off-by: Johannes Berg -commit 3a77ba08940682bf3d52cf14f980337324af9d4a -Author: Johannes Berg -Date: Sat Feb 1 00:33:29 2014 +0100 +commit 1a8ed386e1684b266a15dacf675102ae53361ee5 +Author: Michal Kazior +Date: Wed Apr 9 15:11:01 2014 +0200 - 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. + cfg80211: export interface stopping function - 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 exports a new cfg80211_stop_iface() function. - 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. + This is intended for driver internal interface + combination management and channel switching. - Fix this by using skb_trim() properly. + Due to locking issues (it re-enters driver) the + call is asynchronous and uses cfg80211 event + list/worker. - Cc: stable@vger.kernel.org - Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") - Reported-by: Jouni Malinen + Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg -commit de5f242e0c10e841017e37eb8c38974a642dbca8 -Author: Sujith Manoharan -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 - Signed-off-by: Sujith Manoharan - -commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a -Author: Geert Uytterhoeven -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 - -commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6 -Author: Emmanuel Grumbach -Date: Mon Jan 27 11:07:42 2014 +0200 +commit 573f31d6d0e572ff8186c45a1ecd9273242233e6 +Author: Michal Kazior +Date: Wed Apr 9 15:11:00 2014 +0200 - mac80211: release the channel in error path in start_ap + mac80211: split CSA finalize function - When the driver cannot start the AP or when the assignement - of the beacon goes wrong, we need to unassign the vif. + Improves readability and modularity. - Cc: stable@vger.kernel.org - Signed-off-by: Emmanuel Grumbach + Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg -commit dfb6889a75c601aedb7450b7e606668e77da6679 -Author: Johannes Berg -Date: Wed Jan 22 11:14:19 2014 +0200 +commit 2d104d52e7c7640d68f29f2136dbe3938b7bc9ba +Author: Michal Kazior +Date: Wed Apr 9 15:10:59 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. + mac80211: fix CSA tx queue stopping + + It was possible for tx queues to be stuck stopped + if AP CSA finalization failed. In that case + neither stop_ap nor do_stop woke the queues up. + This means it was impossible to perform tx at all + until driver was reloaded or a successful CSA was + performed later. + + It was possible to solve this in a simpler manner + however this is more robust and future proof + (having multi-vif CSA in mind). + + New sdata->csa_block_tx is introduced to keep + track of which interfaces requested tx to be + blocked for CSA. This is required because mac80211 + stops all tx queues for that purpose. This means + queues must be awoken only when last tx-blocking + CSA interface is finished. + + It is still possible to have tx queues stopped + after CSA failure but as soon as offending + interfaces are stopped from userspace (stop_ap or + ifdown) tx queues are woken up properly. + Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg -commit 45b7ab41fc08627d9a8428cb413d5d84662a9707 +commit 6be615d6d42aa7fdab6c4278031d8fa0953e594f Author: Johannes Berg -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 - Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans") - Signed-off-by: Johannes Berg - -commit ae04fa489ab31b5a10d3cc8399f52761175d4321 -Author: Emmanuel Grumbach -Date: Thu Jan 23 14:28:16 2014 +0200 +Date: Wed Apr 9 21:31:13 2014 +0200 - mac80211: avoid deadlock revealed by lockdep - - sdata->u.ap.request_smps_work can’t 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: + mac80211: mark local variable __maybe_unused - ====================================================== - [ 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: [] flush_work+0x0/0x90 + The 'local' variable in __ieee80211_vif_copy_chanctx_to_vlans() + is only used/needed when lockdep is compiled in, mark it as such + to avoid compile warnings in the other case. - but task is already holding lock: - (&wdev->mtx){+.+.+.}, at: [] 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){+.+.+.}: - [] lock_acquire+0x79/0xe0 - [] mutex_lock_nested+0x4a/0x360 - [] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211] - [] process_one_work+0x198/0x450 - [] worker_thread+0xf9/0x320 - [] kthread+0x9f/0xb0 - [] ret_from_kernel_thread+0x1b/0x28 - - -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}: - [] __lock_acquire+0x183f/0x1910 - [] lock_acquire+0x79/0xe0 - [] flush_work+0x47/0x90 - [] __cancel_work_timer+0x67/0xe0 - [] cancel_work_sync+0xf/0x20 - [] ieee80211_stop_ap+0x8c/0x340 [mac80211] - [] cfg80211_stop_ap+0x8c/0x230 [cfg80211] - [] cfg80211_leave+0x79/0x100 [cfg80211] - [] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211] - [] notifier_call_chain+0x59/0x130 - [] __raw_notifier_call_chain+0x1e/0x30 - [] raw_notifier_call_chain+0x1f/0x30 - [] call_netdevice_notifiers_info+0x33/0x70 - [] call_netdevice_notifiers+0x13/0x20 - [] __dev_close_many+0x34/0xb0 - [] dev_close_many+0x6e/0xc0 - [] rollback_registered_many+0xa7/0x1f0 - [] unregister_netdevice_many+0x14/0x60 - [] ieee80211_remove_interfaces+0xe9/0x170 [mac80211] - [] ieee80211_unregister_hw+0x56/0x110 [mac80211] - [] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm] - [] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi] - [] iwl_opmode_deregister+0x6f/0x90 [iwlwifi] - [] __exit_compat+0xd/0x19 [iwlmvm] - [] SyS_delete_module+0x179/0x2b0 - [] sysenter_do_call+0x12/0x32 - - Fixes: 687da132234f ("mac80211: implement SMPS for AP") - Cc: [3.13] - Reported-by: Ilan Peer - Signed-off-by: Emmanuel Grumbach - Signed-off-by: Johannes Berg - -commit 178b205e96217164fd7c30113464250d0b6f5eca -Author: Johannes Berg -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. + While at it, fix some indentation where it's used. + Reviewed-by: Luciano Coelho + Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg -commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61 -Author: Pontus Fuchs -Date: Thu Jan 16 15:00:40 2014 +0100 +commit 43279e584aeb78aa0c853728db047b58156c0753 +Author: Arik Nemtsov +Date: Thu May 1 10:17:28 2014 +0300 - 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. + mac80211: move TDLS code to another file - 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. + With new additions planned, this code is getting too big for cfg.c. - Cc: stable@vger.kernel.org - Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps") - Signed-off-by: Pontus Fuchs - [avoid the entire workaround when state->split is set] + Signed-off-by: Arik Nemtsov Signed-off-by: Johannes Berg -commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4 -Author: Eliad Peller -Date: Sun Jan 12 11:06:37 2014 +0200 +commit bf9c234b83c77f1ebbcbab73de2a9e4a5d4aafc6 +Author: Arik Nemtsov +Date: Thu May 1 10:17:27 2014 +0300 - mac80211: move roc cookie assignment earlier + mac80211: set an external flag for TDLS stations - ieee80211_start_roc_work() might add a new roc - to existing roc, and tell cfg80211 it has already - started. + Expose a new tdls flag for the public ieee80211_sta struct. + This can be used in some rate control decisions. - 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 + Signed-off-by: Arik Nemtsov Signed-off-by: Johannes Berg -commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c +commit 910e65141a17f645ab85dae1a497e64ebe63df70 Author: Johannes Berg -Date: Fri Jan 24 14:06:29 2014 +0100 +Date: Tue Apr 29 17:55:26 2014 +0200 - nl80211: send event when AP operation is stopped + mac80211: remove BUG_ON usage - 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. + These BUG_ON statements should never trigger, but in the unlikely + event that somebody does manage don't stop everything but simply + exit the code path with an error. - 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. + Leave the one BUG_ON where changing it would result in a NULL + pointer dereference. Signed-off-by: Johannes Berg -commit d5d567eda7704f190379ca852a8f9a4112e3eee3 +commit ff36b582a10285530351aab036087b57ddb4ae2b Author: Johannes Berg -Date: Thu Jan 23 16:20:29 2014 +0100 +Date: Tue Apr 29 17:52:36 2014 +0200 - mac80211: add length check in ieee80211_is_robust_mgmt_frame() + cfg80211: remove BUG_ON usage - 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. + These really can't trigger unless somebody messes up the code, + but don't make debugging it needlessly complicated, WARN and + return instead of BUG_ON(). Signed-off-by: Johannes Berg -commit f8f6d212a047fc65c7d3442dfc038f65517236fc -Author: Johannes Berg -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 - Acked-by: Luciano Coelho - Signed-off-by: Johannes Berg - -commit de553e8545e65a6dc4e45f43df7e1443d4291922 -Author: Johannes Berg -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 - -commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1 -Author: Karl Beldan -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 - Cc: Helmut Schaa - Cc: Emmanuel Grumbach - Signed-off-by: Johannes Berg --- 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; - } +@@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *m + } -@@ -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); - -@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav); - bool ath9k_hw_check_alive(struct ath_hw *ah) + static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) { - 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); - ---- 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; - } - -@@ -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; - } -@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); +@@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy * + static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - static bool ath9k_has_tx_pending(struct ath_softc *sc) + static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac) ++ const u8 *mac) { -- 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 + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); +@@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wip } - /** -+ * 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 + static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_parameters *params) ++ const u8 *mac, ++ struct station_parameters *params) + { + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm + return ret; } - /** -- * 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) +-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk) ++int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk) + { + struct sk_buff *skb; + struct wmi_add_krk_cmd *cmd; +--- a/drivers/net/wireless/ath/ath6kl/wmi.h ++++ b/drivers/net/wireless/ath/ath6kl/wmi.h +@@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm + u8 *key_material, + u8 key_op_ctrl, u8 *mac_addr, + enum wmi_sync_flag sync_flag); +-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk); ++int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk); + int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index); + int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, + const u8 *pmkid, bool set); +--- a/drivers/net/wireless/ath/ath9k/htc.h ++++ b/drivers/net/wireless/ath/ath9k/htc.h +@@ -378,7 +378,7 @@ void ath9k_htc_get_et_stats(struct ieee8 + #define TX_QSTAT_INC(c) do { } while (0) + + static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, +- struct ath_htc_rx_status *rxs) ++ struct ath_rx_status *rs); { - if (ieee80211_is_disassoc(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control)) -@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m } - /** -+ * 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; - }; - - /** -@@ -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; - - 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. - */ --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); +--- a/drivers/net/wireless/ath/wil6210/cfg80211.c ++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c +@@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil - /** - * 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); + static int wil_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int rc; +@@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct w } - 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, ¶ms->chandef, - IEEE80211_CHANCTX_SHARED); - mutex_unlock(&local->mtx); -@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip - IEEE80211_P2P_OPPPS_ENABLE_BIT; + static int wil_cfg80211_del_station(struct wiphy *wiphy, +- struct net_device *dev, u8 *mac) ++ struct net_device *dev, const u8 *mac) + { + struct wil6210_priv *wil = wiphy_to_wil(wiphy); - err = ieee80211_assign_beacon(sdata, ¶ms->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; - } +--- a/drivers/net/wireless/ath/wil6210/main.c ++++ b/drivers/net/wireless/ath/wil6210/main.c +@@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wi + memset(&sta->stats, 0, sizeof(sta->stats)); + } -@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc - int err; +-static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) ++static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) + { + int cid = -ENOENT; + struct net_device *ndev = wil_to_ndev(wil); +@@ -252,7 +252,7 @@ int wil_priv_init(struct wil6210_priv *w + return 0; + } - sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ sdata_assert_lock(sdata); +-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) ++void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) + { + del_timer_sync(&wil->connect_timer); + _wil6210_disconnect(wil, bssid); +--- a/drivers/net/wireless/ath/wil6210/wil6210.h ++++ b/drivers/net/wireless/ath/wil6210/wil6210.h +@@ -508,7 +508,7 @@ void wil_wdev_free(struct wil6210_priv * + int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); + int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); + int wmi_pcp_stop(struct wil6210_priv *wil); +-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); ++void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); + + int wil_rx_init(struct wil6210_priv *wil); + void wil_rx_fini(struct wil6210_priv *wil); +--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +@@ -2236,7 +2236,7 @@ brcmf_cfg80211_config_default_mgmt_key(s - /* 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; + static s32 + brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; +@@ -4014,7 +4014,7 @@ brcmf_cfg80211_change_beacon(struct wiph -+ sdata_assert_lock(sdata); -+ - 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; + static int + brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, +- u8 *mac) ++ const u8 *mac) + { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_scb_val_le scbval; +@@ -4242,7 +4242,7 @@ static int brcmf_convert_nl80211_tdls_op + } -- 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); + static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, +- struct net_device *ndev, u8 *peer, ++ struct net_device *ndev, const u8 *peer, + enum nl80211_tdls_operation oper) + { + struct brcmf_if *ifp; +--- a/drivers/net/wireless/libertas/cfg.c ++++ b/drivers/net/wireless/libertas/cfg.c +@@ -1006,9 +1006,8 @@ struct cmd_key_material { + } __packed; + + static int lbs_set_key_material(struct lbs_private *priv, +- int key_type, +- int key_info, +- u8 *key, u16 key_len) ++ int key_type, int key_info, ++ const u8 *key, u16 key_len) + { + struct cmd_key_material cmd; + int ret; +@@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy + */ -+ /* -+ * 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); + static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct lbs_private *priv = wiphy_priv(wiphy); + s8 signal, noise; +--- a/drivers/net/wireless/libertas/defs.h ++++ b/drivers/net/wireless/libertas/defs.h +@@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \ + #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) + + #ifdef DEBUG +-static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) ++static inline void lbs_deb_hex(unsigned int grp, const char *prompt, ++ const u8 *buf, int len) + { + int i = 0; -- /* -- * 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; +--- a/drivers/net/wireless/mwifiex/11n.h ++++ b/drivers/net/wireless/mwifiex/11n.h +@@ -200,7 +200,7 @@ static inline int mwifiex_is_sta_11n_ena } -@@ -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; + static inline u8 +-mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra) ++mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra) + { + struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); + if (node) +--- a/drivers/net/wireless/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/mwifiex/cfg80211.c +@@ -994,7 +994,7 @@ mwifiex_dump_station_info(struct mwifiex + */ + static int + mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - 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; +@@ -1270,7 +1270,7 @@ static int mwifiex_cfg80211_change_beaco + */ + static int + mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac) ++ const u8 *mac) + { + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct mwifiex_sta_node *sta_node; +@@ -2629,7 +2629,7 @@ static int mwifiex_cfg80211_set_coalesce + */ + static int + mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, u8 action_code, u8 dialog_token, ++ const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *extra_ies, size_t extra_ies_len) + { +@@ -2701,7 +2701,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy -- lockdep_assert_held(&sdata->wdev.mtx); -+ sdata_assert_lock(sdata); + static int + mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, enum nl80211_tdls_operation action) ++ const u8 *peer, enum nl80211_tdls_operation action) + { + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - 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); +@@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy } - 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); + static int +-mwifiex_cfg80211_add_station(struct wiphy *wiphy, +- struct net_device *dev, +- u8 *mac, struct station_parameters *params) ++mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *mac, struct station_parameters *params) + { + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - 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); +@@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiph } ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee - - ieee80211_roc_purge(local, sdata); - -- if (sdata->vif.type == NL80211_IFTYPE_STATION) -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_STATION: - ieee80211_mgd_stop(sdata); -- -- if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ break; -+ case NL80211_IFTYPE_ADHOC: - ieee80211_ibss_stop(sdata); -- -+ break; -+ case NL80211_IFTYPE_AP: -+ cancel_work_sync(&sdata->u.ap.request_smps_work); -+ break; -+ default: -+ break; -+ } + static int +-mwifiex_cfg80211_change_station(struct wiphy *wiphy, +- struct net_device *dev, +- u8 *mac, struct station_parameters *params) ++mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *mac, ++ struct station_parameters *params) + { + int ret; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); +--- a/drivers/net/wireless/mwifiex/main.h ++++ b/drivers/net/wireless/mwifiex/main.h +@@ -910,8 +910,6 @@ int mwifiex_handle_uap_rx_forward(struct + struct sk_buff *skb); + int mwifiex_process_sta_event(struct mwifiex_private *); + int mwifiex_process_uap_event(struct mwifiex_private *); +-struct mwifiex_sta_node * +-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); + void mwifiex_delete_all_station_list(struct mwifiex_private *priv); + void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); + void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); +@@ -1220,26 +1218,26 @@ void mwifiex_dnld_txpwr_table(struct mwi + extern const struct ethtool_ops mwifiex_ethtool_ops; + + void mwifiex_del_all_sta_list(struct mwifiex_private *priv); +-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac); ++void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac); + void + mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, + int ies_len, struct mwifiex_sta_node *node); + struct mwifiex_sta_node * +-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac); ++mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac); + struct mwifiex_sta_node * +-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); +-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer, ++mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac); ++int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, + u8 action_code, u8 dialog_token, + u16 status_code, const u8 *extra_ies, + size_t extra_ies_len); +-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, const u8 *extra_ies, +- size_t extra_ies_len); ++int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, ++ u8 action_code, u8 dialog_token, ++ u16 status_code, const u8 *extra_ies, ++ size_t extra_ies_len); + void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, + u8 *buf, int len); +-int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action); +-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac); ++int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action); ++int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac); + void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); + bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); + u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, +--- a/drivers/net/wireless/mwifiex/tdls.c ++++ b/drivers/net/wireless/mwifiex/tdls.c +@@ -25,8 +25,8 @@ + #define TDLS_RESP_FIX_LEN 8 + #define TDLS_CONFIRM_FIX_LEN 6 + +-static void +-mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status) ++static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, ++ const u8 *mac, u8 status) + { + struct mwifiex_ra_list_tbl *ra_list; + struct list_head *tid_list; +@@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwif + return; + } - /* - * 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); +-static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac) ++static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, ++ const u8 *mac) + { + struct mwifiex_ra_list_tbl *ra_list; + struct list_head *ra_list_head; +@@ -228,7 +229,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_ + } - cancel_work_sync(&sdata->recalc_smps); -+ sdata_lock(sdata); - sdata->vif.csa_active = false; -+ sdata_unlock(sdata); - cancel_work_sync(&sdata->csa_finalize_work); + static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, +- u8 *mac, struct sk_buff *skb) ++ const u8 *mac, struct sk_buff *skb) + { + struct mwifiex_bssdescriptor *bss_desc; + struct ieee80211_vht_operation *vht_oper; +@@ -367,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(s + } - 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 + static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, struct sk_buff *skb) ++ const u8 *peer, u8 action_code, ++ u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tdls_data *tf; + int ret; +@@ -506,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data( + } -- if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) -+ if (is_multicast_ether_addr(hdr->addr1)) - return 0; + static void +-mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid) ++mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, ++ const u8 *peer, const u8 *bssid) + { + struct ieee80211_tdls_lnkie *lnkid; -- return ieee80211_is_robust_mgmt_frame(hdr); -+ return ieee80211_is_robust_mgmt_frame(skb); +@@ -520,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff + memcpy(lnkid->resp_sta, peer, ETH_ALEN); } +-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, +- u8 *peer, u8 action_code, u8 dialog_token, ++int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, ++ u8 action_code, u8 dialog_token, + u16 status_code, const u8 *extra_ies, + size_t extra_ies_len) + { +@@ -613,7 +616,8 @@ int mwifiex_send_tdls_data_frame(struct + } -@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust + static int +-mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, ++mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, ++ const u8 *peer, + u8 action_code, u8 dialog_token, + u16 status_code, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +@@ -691,10 +695,10 @@ mwifiex_construct_tdls_action_frame(stru + return 0; + } -- if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) -+ if (!is_multicast_ether_addr(hdr->addr1)) - return 0; +-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, const u8 *extra_ies, +- size_t extra_ies_len) ++int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, ++ u8 action_code, u8 dialog_token, ++ u16 status_code, const u8 *extra_ies, ++ size_t extra_ies_len) + { + struct sk_buff *skb; + struct mwifiex_txinfo *tx_info; +@@ -901,7 +905,7 @@ void mwifiex_process_tdls_action_frame(s + } -- return ieee80211_is_robust_mgmt_frame(hdr); -+ return ieee80211_is_robust_mgmt_frame(skb); + static int +-mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer) ++mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer) + { + struct mwifiex_sta_node *sta_ptr; + struct mwifiex_ds_tdls_oper tdls_oper; +@@ -922,7 +926,7 @@ mwifiex_tdls_process_config_link(struct } + static int +-mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) ++mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer) + { + struct mwifiex_sta_node *sta_ptr; + struct mwifiex_ds_tdls_oper tdls_oper; +@@ -949,7 +953,7 @@ mwifiex_tdls_process_create_link(struct + } -@@ -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; - } + static int +-mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) ++mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) + { + struct mwifiex_sta_node *sta_ptr; + struct mwifiex_ds_tdls_oper tdls_oper; +@@ -978,7 +982,7 @@ mwifiex_tdls_process_disable_link(struct + } ---- 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); -+ -+ /* 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; -+ } -+ - 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 - } + static int +-mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer) ++mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) + { + struct mwifiex_sta_node *sta_ptr; + struct ieee80211_mcs_info mcs; +@@ -1035,7 +1039,7 @@ mwifiex_tdls_process_enable_link(struct + return 0; + } - /* adjust first fragment's length */ -- skb->len = hdrlen + per_fragm; -+ skb_trim(skb, hdrlen + per_fragm); +-int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) ++int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action) + { + switch (action) { + case MWIFIEX_TDLS_ENABLE_LINK: +@@ -1050,7 +1054,7 @@ int mwifiex_tdls_oper(struct mwifiex_pri return 0; } -@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802 - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } +-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac) ++int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac) + { + struct mwifiex_sta_node *sta_ptr; -- 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); +--- a/drivers/net/wireless/mwifiex/util.c ++++ b/drivers/net/wireless/mwifiex/util.c +@@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_ + * NULL is returned if station entry is not found in associated STA list. + */ + struct mwifiex_sta_node * +-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) ++mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac) + { + struct mwifiex_sta_node *node; - if (!ieee80211_is_data(hdr->frame_control) && -- !ieee80211_is_robust_mgmt_frame(hdr)) -+ !ieee80211_is_robust_mgmt_frame(skb)) - return RX_CONTINUE; +@@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_pri + * If received mac address is NULL, NULL is returned. + */ + struct mwifiex_sta_node * +-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) ++mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac) + { + struct mwifiex_sta_node *node; + unsigned long flags; +@@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_pr + } - 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); - } + /* This function will delete a station entry from station list */ +-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) ++void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac) + { + struct mwifiex_sta_node *node; + unsigned long flags; +--- a/drivers/net/wireless/mwifiex/wmm.c ++++ b/drivers/net/wireless/mwifiex/wmm.c +@@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct + * The function also initializes the list with the provided RA. + */ + static struct mwifiex_ra_list_tbl * +-mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) ++mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) + { + struct mwifiex_ra_list_tbl *ra_list; - return err; ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg +@@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshol + * This function allocates and adds a RA list for all TIDs + * with the given RA. + */ +-void +-mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) ++void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) + { + int i; + struct mwifiex_ra_list_tbl *ra_list; +@@ -566,7 +565,7 @@ mwifiex_clean_txrx(struct mwifiex_privat + */ + static struct mwifiex_ra_list_tbl * + mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, +- u8 *ra_addr) ++ const u8 *ra_addr) + { + struct mwifiex_ra_list_tbl *ra_list; + +@@ -587,7 +586,8 @@ mwifiex_wmm_get_ralist_node(struct mwifi + * retrieved. + */ + struct mwifiex_ra_list_tbl * +-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) ++mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, ++ const u8 *ra_addr) + { + struct mwifiex_ra_list_tbl *ra_list; + +--- a/drivers/net/wireless/mwifiex/wmm.h ++++ b/drivers/net/wireless/mwifiex/wmm.h +@@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list + + void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, + struct sk_buff *skb); +-void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); ++void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra); + void mwifiex_rotate_priolists(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ra, int tid); + +@@ -123,7 +123,8 @@ void mwifiex_wmm_setup_ac_downgrade(stru + int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, + const struct host_cmd_ds_command *resp); + struct mwifiex_ra_list_tbl * +-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr); ++mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, ++ const u8 *ra_addr); + u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); + + #endif /* !_MWIFIEX_WMM_H_ */ +--- a/drivers/net/wireless/orinoco/hw.c ++++ b/drivers/net/wireless/orinoco/hw.c +@@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoc + * tsc must be NULL or up to 8 bytes + */ + int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, +- int set_tx, u8 *key, u8 *rsc, size_t rsc_len, +- u8 *tsc, size_t tsc_len) ++ int set_tx, const u8 *key, const u8 *rsc, ++ size_t rsc_len, const u8 *tsc, size_t tsc_len) + { + struct { + __le16 idx; +--- a/drivers/net/wireless/orinoco/hw.h ++++ b/drivers/net/wireless/orinoco/hw.h +@@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_ + int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); + int __orinoco_hw_setup_enc(struct orinoco_private *priv); + int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, +- int set_tx, u8 *key, u8 *rsc, size_t rsc_len, +- u8 *tsc, size_t tsc_len); ++ int set_tx, const u8 *key, const u8 *rsc, ++ size_t rsc_len, const u8 *tsc, size_t tsc_len); + int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); + int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, + struct net_device *dev, +--- a/drivers/net/wireless/orinoco/wext.c ++++ b/drivers/net/wireless/orinoco/wext.c +@@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoc + priv->keys[index].seq_len = seq_len; + + if (key_len) +- memcpy(priv->keys[index].key, key, key_len); ++ memcpy((void *)priv->keys[index].key, key, key_len); + if (seq_len) +- memcpy(priv->keys[index].seq, seq, seq_len); ++ memcpy((void *)priv->keys[index].seq, seq, seq_len); + + switch (alg) { + case ORINOCO_ALG_TKIP: +--- a/drivers/net/wireless/rndis_wlan.c ++++ b/drivers/net/wireless/rndis_wlan.c +@@ -517,7 +517,7 @@ static int rndis_set_default_key(struct + u8 key_index, bool unicast, bool multicast); - rdev->opencount--; + static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo); ++ const u8 *mac, struct station_info *sinfo); -- 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); -+ } + static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo); +@@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(stru } - 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; - } + static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct rndis_wlan_private *priv = wiphy_priv(wiphy); + struct usbnet *usbdev = priv->usbdev; +--- a/drivers/net/wireless/ti/wlcore/main.c ++++ b/drivers/net/wireless/ti/wlcore/main.c +@@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx + + int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, + u16 offset, u8 flags, +- u8 *pattern, u8 len) ++ const u8 *pattern, u8 len) + { + struct wl12xx_rx_filter_field *field; + +--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h ++++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h +@@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl + void wl12xx_queue_recovery_work(struct wl1271 *wl); + size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); + int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, +- u16 offset, u8 flags, +- u8 *pattern, u8 len); ++ u16 offset, u8 flags, ++ const u8 *pattern, u8 len); + void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); + struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); + int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -341,8 +341,8 @@ struct vif_params { + * @seq_len: length of @seq. + */ + struct key_params { +- u8 *key; +- u8 *seq; ++ const u8 *key; ++ const u8 *seq; + int key_len; + int seq_len; + u32 cipher; +@@ -458,7 +458,7 @@ bool cfg80211_chandef_usable(struct wiph + */ + int cfg80211_chandef_dfs_required(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, +- enum nl80211_iftype); ++ enum nl80211_iftype iftype); - 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); -+ } + /** + * ieee80211_chandef_rate_flags - returns rate flags for a channel +@@ -694,8 +694,10 @@ struct cfg80211_ap_settings { + * + * @chandef: defines the channel to use after the switch + * @beacon_csa: beacon data while performing the switch +- * @counter_offset_beacon: offset for the counter within the beacon (tail) +- * @counter_offset_presp: offset for the counter within the probe response ++ * @counter_offsets_beacon: offsets of the counters within the beacon (tail) ++ * @counter_offsets_presp: offsets of the counters within the probe response ++ * @n_counter_offsets_beacon: number of csa counters the beacon (tail) ++ * @n_counter_offsets_presp: number of csa counters in the probe response + * @beacon_after: beacon data to be used on the new channel + * @radar_required: whether radar detection is required on the new channel + * @block_tx: whether transmissions should be blocked while changing +@@ -704,7 +706,10 @@ struct cfg80211_ap_settings { + struct cfg80211_csa_settings { + struct cfg80211_chan_def chandef; + struct cfg80211_beacon_data beacon_csa; +- u16 counter_offset_beacon, counter_offset_presp; ++ const u16 *counter_offsets_beacon; ++ const u16 *counter_offsets_presp; ++ unsigned int n_counter_offsets_beacon; ++ unsigned int n_counter_offsets_presp; + struct cfg80211_beacon_data beacon_after; + bool radar_required; + bool block_tx; +@@ -1164,7 +1169,7 @@ struct bss_parameters { + int use_cts_prot; + int use_short_preamble; + int use_short_slot_time; +- u8 *basic_rates; ++ const u8 *basic_rates; + u8 basic_rates_len; + int ap_isolate; + int ht_opmode; +@@ -1694,10 +1699,10 @@ struct cfg80211_disassoc_request { + * @ht_capa_mask: The bits of ht_capa which are to be used. + */ + struct cfg80211_ibss_params { +- u8 *ssid; +- u8 *bssid; ++ const u8 *ssid; ++ const u8 *bssid; + struct cfg80211_chan_def chandef; +- u8 *ie; ++ const u8 *ie; + u8 ssid_len, ie_len; + u16 beacon_interval; + u32 basic_rates; +@@ -1806,8 +1811,8 @@ struct cfg80211_bitrate_mask { + * @pmkid: The PMK material itself. + */ + struct cfg80211_pmksa { +- u8 *bssid; +- u8 *pmkid; ++ const u8 *bssid; ++ const u8 *pmkid; + }; - 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; - }; + /** +@@ -1822,7 +1827,7 @@ struct cfg80211_pmksa { + * memory, free @mask only! + */ + struct cfg80211_pkt_pattern { +- u8 *mask, *pattern; ++ const u8 *mask, *pattern; + int pattern_len; + int pkt_offset; + }; +@@ -1986,6 +1991,8 @@ struct cfg80211_update_ft_ies_params { + * @len: buffer length + * @no_cck: don't use cck rates for this frame + * @dont_wait_for_ack: tells the low level not to wait for an ack ++ * @n_csa_offsets: length of csa_offsets array ++ * @csa_offsets: array of all the csa offsets in the frame + */ + struct cfg80211_mgmt_tx_params { + struct ieee80211_channel *chan; +@@ -1995,6 +2002,8 @@ struct cfg80211_mgmt_tx_params { + size_t len; + bool no_cck; + bool dont_wait_for_ack; ++ int n_csa_offsets; ++ const u16 *csa_offsets; }; -@@ -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); -+ } -+ } + /** +@@ -2336,28 +2345,29 @@ struct cfg80211_ops { + + + int (*add_station)(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_parameters *params); ++ const u8 *mac, ++ struct station_parameters *params); + int (*del_station)(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac); ++ const u8 *mac); + int (*change_station)(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_parameters *params); ++ const u8 *mac, ++ struct station_parameters *params); + int (*get_station)(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo); ++ const u8 *mac, struct station_info *sinfo); + int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, +- int idx, u8 *mac, struct station_info *sinfo); ++ int idx, u8 *mac, struct station_info *sinfo); + + int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst, u8 *next_hop); ++ const u8 *dst, const u8 *next_hop); + int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst); ++ const u8 *dst); + int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst, u8 *next_hop); ++ const u8 *dst, const u8 *next_hop); + int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst, u8 *next_hop, +- struct mpath_info *pinfo); ++ u8 *dst, u8 *next_hop, struct mpath_info *pinfo); + int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, +- int idx, u8 *dst, u8 *next_hop, +- struct mpath_info *pinfo); ++ int idx, u8 *dst, u8 *next_hop, ++ struct mpath_info *pinfo); + int (*get_mesh_config)(struct wiphy *wiphy, + struct net_device *dev, + struct mesh_config *conf); +@@ -2487,11 +2497,11 @@ struct cfg80211_ops { + struct cfg80211_gtk_rekey_data *data); + + int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, u8 action_code, u8 dialog_token, ++ const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + const u8 *buf, size_t len); + int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, enum nl80211_tdls_operation oper); ++ const u8 *peer, enum nl80211_tdls_operation oper); + + int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u64 *cookie); +@@ -2638,6 +2648,7 @@ struct ieee80211_iface_limit { + * between infrastructure and AP types must match. This is required + * only in special cases. + * @radar_detect_widths: bitmap of channel widths supported for radar detection ++ * @radar_detect_regions: bitmap of regions supported for radar detection + * + * With this structure the driver can describe which interface + * combinations it supports concurrently. +@@ -2695,6 +2706,7 @@ struct ieee80211_iface_combination { + u8 n_limits; + bool beacon_int_infra_match; + u8 radar_detect_widths; ++ u8 radar_detect_regions; + }; + + struct ieee80211_txrx_stypes { +@@ -2925,6 +2937,11 @@ struct wiphy_vendor_command { + * (including P2P GO) or 0 to indicate no such limit is advertised. The + * driver is allowed to advertise a theoretical limit that it can reach in + * some cases, but may not always reach. ++ * ++ * @max_num_csa_counters: Number of supported csa_counters in beacons ++ * and probe responses. This value should be set if the driver ++ * wishes to limit the number of csa counters. Default (0) means ++ * infinite. + */ + struct wiphy { + /* assign these fields before you register the wiphy */ +@@ -3045,6 +3062,8 @@ struct wiphy { + + u16 max_ap_assoc_sta; + ++ u8 max_num_csa_counters; + -+ /* 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; + char priv[0] __aligned(NETDEV_ALIGN); + }; - 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++; - } +@@ -3273,7 +3292,7 @@ struct wireless_dev { + struct cfg80211_ibss_params ibss; + struct cfg80211_connect_params connect; + struct cfg80211_cached_keys *keys; +- u8 *ie; ++ const u8 *ie; + size_t ie_len; + u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; +@@ -3514,7 +3533,8 @@ int ieee80211_data_to_8023(struct sk_buf + * Return: 0 on success, or a negative error code. + */ + int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, +- enum nl80211_iftype iftype, u8 *bssid, bool qos); ++ enum nl80211_iftype iftype, const u8 *bssid, ++ bool qos); + + /** + * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame +@@ -4315,7 +4335,7 @@ void cfg80211_roamed_bss(struct net_devi + * and not try to connect to any AP any more. + */ + void cfg80211_disconnected(struct net_device *dev, u16 reason, +- u8 *ie, size_t ie_len, gfp_t gfp); ++ const u8 *ie, size_t ie_len, gfp_t gfp); + + /** + * cfg80211_ready_on_channel - notification of remain_on_channel start +@@ -4771,6 +4791,35 @@ int cfg80211_iter_combinations(struct wi + void *data), + void *data); + ++/* ++ * cfg80211_stop_iface - trigger interface disconnection ++ * ++ * @wiphy: the wiphy ++ * @wdev: wireless device ++ * @gfp: context flags ++ * ++ * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA ++ * disconnected. ++ * ++ * Note: This doesn't need any locks and is asynchronous. ++ */ ++void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, ++ gfp_t gfp); + -+ /* there was no other matchset, so the RSSI one is alone */ -+ if (i == 0) -+ request->match_sets[0].rssi_thold = default_match_rssi; ++/** ++ * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy ++ * @wiphy: the wiphy to shut down ++ * ++ * This function shuts down all interfaces belonging to this wiphy by ++ * calling dev_close() (and treating non-netdev interfaces as needed). ++ * It shouldn't really be used unless there are some fatal device errors ++ * that really can't be recovered in any other way. ++ * ++ * Callers must hold the RTNL and be able to deal with callbacks into ++ * the driver while the function is running. ++ */ ++void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy); + -+ 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 + /* Logging, debugging and troubleshooting/diagnostic helpers. */ + + /* wiphy_printk helpers, similar to dev_printk */ +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1113,7 +1113,9 @@ enum ieee80211_vif_flags { + * @addr: address of this interface + * @p2p: indicates whether this AP or STA interface is a p2p + * interface, i.e. a GO or p2p-sta respectively +- * @csa_active: marks whether a channel switch is going on ++ * @csa_active: marks whether a channel switch is going on. Internally it is ++ * write-protected by sdata_lock and local->mtx so holding either is fine ++ * for read access. + * @driver_flags: flags/capabilities the driver has for this interface, + * these need to be set (or cleared) when the interface is added + * or, if supported by the driver, the interface type is changed +@@ -1374,6 +1376,7 @@ struct ieee80211_sta_rates { + * the station moves to associated state. + * @smps_mode: current SMPS mode (off, static or dynamic) + * @rates: rate control selection table ++ * @tdls: indicates whether the STA is a TDLS peer + */ + struct ieee80211_sta { + u32 supp_rates[IEEE80211_NUM_BANDS]; +@@ -1388,6 +1391,7 @@ struct ieee80211_sta { + enum ieee80211_sta_rx_bandwidth bandwidth; + enum ieee80211_smps_mode smps_mode; + struct ieee80211_sta_rates __rcu *rates; ++ bool tdls; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); +@@ -3407,6 +3411,47 @@ void ieee80211_tx_status_irqsafe(struct + */ + void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); - 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; -+ - 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); ++#define IEEE80211_MAX_CSA_COUNTERS_NUM 2 ++ ++/** ++ * struct ieee80211_mutable_offsets - mutable beacon offsets ++ * @tim_offset: position of TIM element ++ * @tim_length: size of TIM element ++ * @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets ++ * to CSA counters. This array can contain zero values which ++ * should be ignored. ++ */ ++struct ieee80211_mutable_offsets { ++ u16 tim_offset; ++ u16 tim_length; ++ ++ u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]; ++}; ++ ++/** ++ * ieee80211_beacon_get_template - beacon template generation function ++ * @hw: pointer obtained from ieee80211_alloc_hw(). ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will ++ * receive the offsets that may be updated by the driver. ++ * ++ * If the driver implements beaconing modes, it must use this function to ++ * obtain the beacon template. ++ * ++ * This function should be used if the beacon frames are generated by the ++ * device, and then the driver must use the returned beacon as the template ++ * The driver or the device are responsible to update the DTIM and, when ++ * applicable, the CSA count. ++ * ++ * The driver is responsible for freeing the returned skb. ++ * ++ * Return: The beacon template. %NULL on error. ++ */ ++struct sk_buff * ++ieee80211_beacon_get_template(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs); ++ + /** + * ieee80211_beacon_get_tim - beacon generation function + * @hw: pointer obtained from ieee80211_alloc_hw(). +@@ -3418,16 +3463,12 @@ void ieee80211_report_low_ack(struct iee + * Set to 0 if invalid (in non-AP modes). + * + * If the driver implements beaconing modes, it must use this function to +- * obtain the beacon frame/template. ++ * obtain the beacon frame. + * + * If the beacon frames are generated by the host system (i.e., not in + * hardware/firmware), the driver uses this function to get each beacon +- * frame from mac80211 -- it is responsible for calling this function +- * before the beacon is needed (e.g. based on hardware interrupt). +- * +- * If the beacon frames are generated by the device, then the driver +- * must use the returned beacon as the template and change the TIM IE +- * according to the current DTIM parameters/TIM bitmap. ++ * frame from mac80211 -- it is responsible for calling this function exactly ++ * once before the beacon is needed (e.g. based on hardware interrupt). + * + * The driver is responsible for freeing the returned skb. + * +@@ -3453,6 +3494,20 @@ static inline struct sk_buff *ieee80211_ } --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; + /** ++ * ieee80211_csa_update_counter - request mac80211 to decrement the csa counter ++ * @vif: &struct ieee80211_vif pointer from the add_interface callback. ++ * ++ * The csa counter should be updated after each beacon transmission. ++ * This function is called implicitly when ++ * ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the ++ * beacon frames are generated by the device, the driver should call this ++ * function after each beacon transmission to sync mac80211's csa counters. ++ * ++ * Return: new csa counter value ++ */ ++u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif); ++ ++/** + * ieee80211_csa_finish - notify mac80211 about channel switch + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -503,6 +503,9 @@ + * TX status event pertaining to the TX request. + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * management frames at CCK rate or not in 2GHz band. ++ * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA ++ * counters which will be updated to the current value. This attribute ++ * is used during CSA period. + * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this + * command may be used with the corresponding cookie to cancel the wait + * time if it is known that it is no longer necessary. +@@ -1525,10 +1528,10 @@ enum nl80211_commands { + * operation). + * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information + * for the time while performing a channel switch. +- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter +- * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL). +- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter +- * field in the probe response (%NL80211_ATTR_PROBE_RESP). ++ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel ++ * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). ++ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel ++ * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * + * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. + * As specified in the &enum nl80211_rxmgmt_flags. +@@ -1576,6 +1579,11 @@ enum nl80211_commands { + * advertise values that cannot always be met. In such cases, an attempt + * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. + * ++ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which ++ * should be updated when the frame is transmitted. ++ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum ++ * supported number of csa counters. ++ * + * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. + * As specified in the &enum nl80211_tdls_peer_capability. + * +@@ -1920,6 +1928,9 @@ enum nl80211_attrs { - 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; - } + NL80211_ATTR_IFACE_SOCKET_OWNER, -- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, -- NL80211_MCGRP_SCAN, GFP_KERNEL); -+ return msg; ++ NL80211_ATTR_CSA_C_OFFSETS_TX, ++ NL80211_ATTR_MAX_CSA_COUNTERS, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -3688,6 +3699,8 @@ enum nl80211_iface_limit_attrs { + * different channels may be used within this group. + * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap + * of supported channel widths for radar detection. ++ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap ++ * of supported regulatory regions for radar detection. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * +@@ -3721,6 +3734,7 @@ enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_STA_AP_BI_MATCH, + NL80211_IFACE_COMB_NUM_CHANNELS, + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, ++ NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, + + /* keep last */ + NUM_NL80211_IFACE_COMB, +--- a/net/mac80211/Makefile ++++ b/net/mac80211/Makefile +@@ -25,7 +25,8 @@ mac80211-y := \ + wme.o \ + event.o \ + chan.o \ +- trace.o mlme.o ++ trace.o mlme.o \ ++ tdls.o + + mac80211-$(CPTCFG_MAC80211_LEDS) += led.o + mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \ +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -777,7 +777,7 @@ static void ieee80211_get_et_strings(str } --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) + static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, +- int idx, u8 *mac, struct station_info *sinfo) ++ int idx, u8 *mac, struct station_info *sinfo) { -- 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); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +@@ -807,7 +807,7 @@ static int ieee80211_dump_survey(struct } -@@ -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 + static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_info *sinfo) ++ const u8 *mac, struct station_info *sinfo) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +@@ -1084,6 +1084,31 @@ static int ieee80211_change_beacon(struc + return 0; } - EXPORT_SYMBOL(cfg80211_crit_proto_stopped); -+void nl80211_send_ap_stopped(struct wireless_dev *wdev) ++bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local) +{ -+ struct wiphy *wiphy = wdev->wiphy; -+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); -+ struct sk_buff *msg; -+ void *hdr; ++ struct ieee80211_sub_if_data *sdata; + -+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -+ if (!msg) -+ return; ++ lockdep_assert_held(&local->mtx); ++ ++ rcu_read_lock(); ++ list_for_each_entry_rcu(sdata, &local->interfaces, list) { ++ if (!ieee80211_sdata_running(sdata)) ++ continue; + -+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); -+ if (!hdr) -+ goto out; ++ if (!sdata->vif.csa_active) ++ continue; + -+ 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; ++ if (!sdata->csa_block_tx) ++ continue; + -+ genlmsg_end(msg, hdr); ++ rcu_read_unlock(); ++ return true; ++ } ++ rcu_read_unlock(); + -+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, -+ NL80211_MCGRP_MLME, GFP_KERNEL); -+ return; -+ out: -+ nlmsg_free(msg); ++ return false; +} + - /* 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) + static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) { - struct cfg80211_scan_request *request; - struct wireless_dev *wdev; -+ struct sk_buff *msg; - #ifdef CPTCFG_CFG80211_WEXT - union iwreq_data wrqu; - #endif - - ASSERT_RTNL(); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -1101,7 +1126,14 @@ static int ieee80211_stop_ap(struct wiph + old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); -- request = rdev->scan_req; -+ if (rdev->scan_msg) { -+ nl80211_send_scan_result(rdev, rdev->scan_msg); -+ rdev->scan_msg = NULL; -+ return; -+ } + /* abort any running channel switch */ ++ mutex_lock(&local->mtx); + sdata->vif.csa_active = false; ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, ++ IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ mutex_unlock(&local->mtx); ++ + kfree(sdata->u.ap.next_beacon); + sdata->u.ap.next_beacon = NULL; -+ request = rdev->scan_req; - if (!request) - return; +@@ -1425,7 +1457,8 @@ static int sta_apply_parameters(struct i + } -@@ -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); + static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac, struct station_parameters *params) ++ const u8 *mac, ++ struct station_parameters *params) + { + struct ieee80211_local *local = wiphy_priv(wiphy); + struct sta_info *sta; +@@ -1459,6 +1492,8 @@ static int ieee80211_add_station(struct + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { + sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); + sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); ++ } else { ++ sta->sta.tdls = true; } -+ 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 + err = sta_apply_parameters(local, sta, params); +@@ -1492,7 +1527,7 @@ static int ieee80211_add_station(struct + } - rdev->scan_req = NULL; - kfree(request); -+ -+ if (!send_message) -+ rdev->scan_msg = msg; -+ else -+ nl80211_send_scan_result(rdev, msg); + static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, +- u8 *mac) ++ const u8 *mac) + { + struct ieee80211_sub_if_data *sdata; + +@@ -1506,7 +1541,7 @@ static int ieee80211_del_station(struct } - void __cfg80211_scan_done(struct work_struct *wk) -@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st - scan_done_wk); + static int ieee80211_change_station(struct wiphy *wiphy, +- struct net_device *dev, u8 *mac, ++ struct net_device *dev, const u8 *mac, + struct station_parameters *params) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +@@ -1631,7 +1666,7 @@ out_err: - rtnl_lock(); -- ___cfg80211_scan_done(rdev); -+ ___cfg80211_scan_done(rdev, true); - rtnl_unlock(); + #ifdef CPTCFG_MAC80211_MESH + static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst, u8 *next_hop) ++ const u8 *dst, const u8 *next_hop) + { + struct ieee80211_sub_if_data *sdata; + struct mesh_path *mpath; +@@ -1659,7 +1694,7 @@ static int ieee80211_add_mpath(struct wi } -@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev - if (IS_ERR(rdev)) - return PTR_ERR(rdev); + static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, +- u8 *dst) ++ const u8 *dst) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- 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); +@@ -1670,9 +1705,8 @@ static int ieee80211_del_mpath(struct wi + return 0; + } + +-static int ieee80211_change_mpath(struct wiphy *wiphy, +- struct net_device *dev, +- u8 *dst, u8 *next_hop) ++static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *dst, const u8 *next_hop) + { + struct ieee80211_sub_if_data *sdata; + struct mesh_path *mpath; +@@ -1764,8 +1798,8 @@ static int ieee80211_get_mpath(struct wi + } -- if (rdev->scan_req) -+ if (rdev->scan_req || rdev->scan_msg) - return -EAGAIN; + static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, +- int idx, u8 *dst, u8 *next_hop, +- struct mpath_info *pinfo) ++ int idx, u8 *dst, u8 *next_hop, ++ struct mpath_info *pinfo) + { + struct ieee80211_sub_if_data *sdata; + struct mesh_path *mpath; +@@ -3019,26 +3053,11 @@ void ieee80211_csa_finish(struct ieee802 + } + EXPORT_SYMBOL(ieee80211_csa_finish); - 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); +-static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ++static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, ++ u32 *changed) + { +- struct ieee80211_local *local = sdata->local; +- int err, changed = 0; +- +- 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)) +- return; +- +- if (!local->use_chanctx) { +- local->_oper_chandef = sdata->csa_chandef; +- ieee80211_hw_config(local, 0); +- } ++ int err; -- if (rdev->scan_req) -+ if (rdev->scan_req || rdev->scan_msg) - return -EBUSY; +- sdata->vif.csa_active = false; + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); +@@ -3046,35 +3065,75 @@ static void ieee80211_csa_finalize(struc + sdata->u.ap.next_beacon = NULL; - if (wdev->conn->params.channel) ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct + if (err < 0) +- return; +- changed |= err; ++ return err; ++ *changed |= err; + break; + case NL80211_IFTYPE_ADHOC: + err = ieee80211_ibss_finish_csa(sdata); + if (err < 0) +- return; +- changed |= err; ++ return err; ++ *changed |= err; + break; + #ifdef CPTCFG_MAC80211_MESH + case NL80211_IFTYPE_MESH_POINT: + err = ieee80211_mesh_finish_csa(sdata); + if (err < 0) +- return; +- changed |= err; ++ return err; ++ *changed |= err; + break; + #endif + default: + WARN_ON(1); +- return; ++ return -EINVAL; } - ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; -- sdata->vif.csa_active = true; ++ ++ return 0; ++} ++ ++static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ u32 changed = 0; ++ int err; ++ ++ sdata_assert_lock(sdata); ++ lockdep_assert_held(&local->mtx); ++ ++ sdata->radar_required = sdata->csa_radar_required; ++ err = ieee80211_vif_change_channel(sdata, &changed); ++ if (err < 0) ++ return err; ++ ++ if (!local->use_chanctx) { ++ local->_oper_chandef = sdata->csa_chandef; ++ ieee80211_hw_config(local, 0); ++ } ++ ++ sdata->vif.csa_active = false; ++ ++ err = ieee80211_set_after_csa_beacon(sdata, &changed); ++ if (err) ++ return err; ++ + ieee80211_bss_info_change_notify(sdata, changed); ++ cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); - mutex_lock(&local->chanctx_mtx); - if (local->use_chanctx) { -@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct - mutex_unlock(&local->chanctx_mtx); +- ieee80211_wake_queues_by_reason(&sdata->local->hw, ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_MAX_QUEUE_MAP, + IEEE80211_QUEUE_STOP_REASON_CSA); - sdata->csa_chandef = csa_ie.chandef; -+ sdata->vif.csa_active = true; +- cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); ++ return 0; ++} ++ ++static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) ++{ ++ if (__ieee80211_csa_finalize(sdata)) { ++ sdata_info(sdata, "failed to finalize CSA, disconnecting\n"); ++ cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev, ++ GFP_KERNEL); ++ } + } - 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; + void ieee80211_csa_finalize_work(struct work_struct *work) +@@ -3082,8 +3141,11 @@ void ieee80211_csa_finalize_work(struct + struct ieee80211_sub_if_data *sdata = + container_of(work, struct ieee80211_sub_if_data, + csa_finalize_work); ++ struct ieee80211_local *local = sdata->local; -+ lockdep_assert_held(&local->mtx); + sdata_lock(sdata); ++ mutex_lock(&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 - } - - 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); - return; - } -+ sdata->radar_required = radar_required; - mutex_unlock(&local->mtx); + /* AP might have been stopped while waiting for the lock. */ + if (!sdata->vif.csa_active) + goto unlock; +@@ -3094,6 +3156,7 @@ void ieee80211_csa_finalize_work(struct + ieee80211_csa_finalize(sdata); - 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); + unlock: ++ mutex_unlock(&local->mtx); + sdata_unlock(sdata); } - 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; +@@ -3129,9 +3192,25 @@ static int ieee80211_set_csa_beacon(stru + if (params->count <= 1) + break; -+ sdata_assert_lock(sdata); +- sdata->csa_counter_offset_beacon = +- params->counter_offset_beacon; +- sdata->csa_counter_offset_presp = params->counter_offset_presp; ++ if ((params->n_counter_offsets_beacon > ++ IEEE80211_MAX_CSA_COUNTERS_NUM) || ++ (params->n_counter_offsets_presp > ++ IEEE80211_MAX_CSA_COUNTERS_NUM)) ++ return -EINVAL; + - 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; ++ /* 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)); + -+ /* avoid excessive retries for probe request to wildcard SSIDs */ -+ if (pos[1] == 0) -+ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; ++ 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)); + - ieee80211_tx_skb(sdata, skb); + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); + if (err < 0) { + kfree(sdata->u.ap.next_beacon); +@@ -3220,8 +3299,9 @@ static int ieee80211_set_csa_beacon(stru + return 0; } ---- 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; +-int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, +- struct cfg80211_csa_settings *params) ++static int ++__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_csa_settings *params) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; +@@ -3230,6 +3310,7 @@ int ieee80211_channel_switch(struct wiph + int err, num_chanctx, changed = 0; -+ 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; + sdata_assert_lock(sdata); ++ lockdep_assert_held(&local->mtx); -- cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); -+ cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan, -+ GFP_KERNEL); + if (!list_empty(&local->roc_list) || local->scanning) + return -EBUSY; +@@ -3272,15 +3353,16 @@ int ieee80211_channel_switch(struct wiph + return err; - /* 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); + sdata->csa_radar_required = params->radar_required; +- +- if (params->block_tx) +- ieee80211_stop_queues_by_reason(&local->hw, +- IEEE80211_MAX_QUEUE_MAP, +- IEEE80211_QUEUE_STOP_REASON_CSA); +- + 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) ++ ieee80211_stop_queues_by_reason(&local->hw, ++ IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ + if (changed) { + ieee80211_bss_info_change_notify(sdata, changed); + drv_channel_switch_beacon(sdata, ¶ms->chandef); +@@ -3292,6 +3374,20 @@ int ieee80211_channel_switch(struct wiph + return 0; + } - kfree(info); ++int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_csa_settings *params) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ int err; ++ ++ mutex_lock(&local->mtx); ++ err = __ieee80211_channel_switch(wiphy, dev, params); ++ mutex_unlock(&local->mtx); ++ ++ return err; ++} ++ + static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +@@ -3304,6 +3400,7 @@ static int ieee80211_mgmt_tx(struct wiph + bool need_offchan = false; + u32 flags; + int ret; ++ u8 *data; ---- a/net/wireless/ibss.c -+++ b/net/wireless/ibss.c -@@ -14,7 +14,8 @@ - #include "rdev-ops.h" + if (params->dont_wait_for_ack) + flags = IEEE80211_TX_CTL_NO_ACK; +@@ -3397,7 +3494,20 @@ static int ieee80211_mgmt_tx(struct wiph + } + skb_reserve(skb, local->hw.extra_tx_headroom); +- memcpy(skb_put(skb, params->len), params->buf, params->len); ++ data = skb_put(skb, params->len); ++ memcpy(data, params->buf, params->len); ++ ++ /* Update CSA counters */ ++ if (sdata->vif.csa_active && ++ (sdata->vif.type == NL80211_IFTYPE_AP || ++ sdata->vif.type == NL80211_IFTYPE_ADHOC) && ++ params->n_csa_offsets) { ++ int i; ++ u8 c = sdata->csa_current_counter; ++ ++ for (i = 0; i < params->n_csa_offsets; i++) ++ data[params->csa_offsets[i]] = c; ++ } --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; + IEEE80211_SKB_CB(skb)->flags = flags; -- 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); +@@ -3506,320 +3616,6 @@ static int ieee80211_set_rekey_data(stru + return 0; + } - if (WARN_ON(!bss)) -@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d - #endif +-static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) +-{ +- u8 *pos = (void *)skb_put(skb, 7); +- +- *pos++ = WLAN_EID_EXT_CAPABILITY; +- *pos++ = 5; /* len */ +- *pos++ = 0x0; +- *pos++ = 0x0; +- *pos++ = 0x0; +- *pos++ = 0x0; +- *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; +-} +- +-static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) +-{ +- struct ieee80211_local *local = sdata->local; +- u16 capab; +- +- capab = 0; +- if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) +- return capab; +- +- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) +- capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; +- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) +- capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; +- +- return capab; +-} +- +-static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, +- u8 *peer, u8 *bssid) +-{ +- struct ieee80211_tdls_lnkie *lnkid; +- +- lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); +- +- lnkid->ie_type = WLAN_EID_LINK_ID; +- lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; +- +- memcpy(lnkid->bssid, bssid, ETH_ALEN); +- memcpy(lnkid->init_sta, src_addr, ETH_ALEN); +- memcpy(lnkid->resp_sta, peer, ETH_ALEN); +-} +- +-static int +-ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, struct sk_buff *skb) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- enum ieee80211_band band = ieee80211_get_sdata_band(sdata); +- struct ieee80211_tdls_data *tf; +- +- tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); +- +- memcpy(tf->da, peer, ETH_ALEN); +- memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); +- tf->ether_type = cpu_to_be16(ETH_P_TDLS); +- tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; +- +- switch (action_code) { +- case WLAN_TDLS_SETUP_REQUEST: +- tf->category = WLAN_CATEGORY_TDLS; +- tf->action_code = WLAN_TDLS_SETUP_REQUEST; +- +- skb_put(skb, sizeof(tf->u.setup_req)); +- tf->u.setup_req.dialog_token = dialog_token; +- tf->u.setup_req.capability = +- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); +- +- ieee80211_add_srates_ie(sdata, skb, false, band); +- ieee80211_add_ext_srates_ie(sdata, skb, false, band); +- ieee80211_tdls_add_ext_capab(skb); +- break; +- case WLAN_TDLS_SETUP_RESPONSE: +- tf->category = WLAN_CATEGORY_TDLS; +- tf->action_code = WLAN_TDLS_SETUP_RESPONSE; +- +- skb_put(skb, sizeof(tf->u.setup_resp)); +- tf->u.setup_resp.status_code = cpu_to_le16(status_code); +- tf->u.setup_resp.dialog_token = dialog_token; +- tf->u.setup_resp.capability = +- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); +- +- ieee80211_add_srates_ie(sdata, skb, false, band); +- ieee80211_add_ext_srates_ie(sdata, skb, false, band); +- ieee80211_tdls_add_ext_capab(skb); +- break; +- case WLAN_TDLS_SETUP_CONFIRM: +- tf->category = WLAN_CATEGORY_TDLS; +- tf->action_code = WLAN_TDLS_SETUP_CONFIRM; +- +- skb_put(skb, sizeof(tf->u.setup_cfm)); +- tf->u.setup_cfm.status_code = cpu_to_le16(status_code); +- tf->u.setup_cfm.dialog_token = dialog_token; +- break; +- case WLAN_TDLS_TEARDOWN: +- tf->category = WLAN_CATEGORY_TDLS; +- tf->action_code = WLAN_TDLS_TEARDOWN; +- +- skb_put(skb, sizeof(tf->u.teardown)); +- tf->u.teardown.reason_code = cpu_to_le16(status_code); +- break; +- case WLAN_TDLS_DISCOVERY_REQUEST: +- tf->category = WLAN_CATEGORY_TDLS; +- tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; +- +- skb_put(skb, sizeof(tf->u.discover_req)); +- tf->u.discover_req.dialog_token = dialog_token; +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int +-ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, struct sk_buff *skb) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- enum ieee80211_band band = ieee80211_get_sdata_band(sdata); +- struct ieee80211_mgmt *mgmt; +- +- mgmt = (void *)skb_put(skb, 24); +- memset(mgmt, 0, 24); +- memcpy(mgmt->da, peer, ETH_ALEN); +- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); +- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); +- +- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | +- IEEE80211_STYPE_ACTION); +- +- switch (action_code) { +- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: +- skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); +- mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; +- mgmt->u.action.u.tdls_discover_resp.action_code = +- WLAN_PUB_ACTION_TDLS_DISCOVER_RES; +- mgmt->u.action.u.tdls_discover_resp.dialog_token = +- dialog_token; +- mgmt->u.action.u.tdls_discover_resp.capability = +- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); +- +- ieee80211_add_srates_ie(sdata, skb, false, band); +- ieee80211_add_ext_srates_ie(sdata, skb, false, band); +- ieee80211_tdls_add_ext_capab(skb); +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, u8 action_code, u8 dialog_token, +- u16 status_code, u32 peer_capability, +- const u8 *extra_ies, size_t extra_ies_len) +-{ +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- struct ieee80211_local *local = sdata->local; +- struct sk_buff *skb = NULL; +- bool send_direct; +- int ret; +- +- if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) +- return -ENOTSUPP; +- +- /* make sure we are in managed mode, and associated */ +- if (sdata->vif.type != NL80211_IFTYPE_STATION || +- !sdata->u.mgd.associated) +- return -EINVAL; +- +- tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", +- action_code, peer); +- +- skb = dev_alloc_skb(local->hw.extra_tx_headroom + +- max(sizeof(struct ieee80211_mgmt), +- sizeof(struct ieee80211_tdls_data)) + +- 50 + /* supported rates */ +- 7 + /* ext capab */ +- extra_ies_len + +- sizeof(struct ieee80211_tdls_lnkie)); +- if (!skb) +- return -ENOMEM; +- +- skb_reserve(skb, local->hw.extra_tx_headroom); +- +- switch (action_code) { +- case WLAN_TDLS_SETUP_REQUEST: +- case WLAN_TDLS_SETUP_RESPONSE: +- case WLAN_TDLS_SETUP_CONFIRM: +- case WLAN_TDLS_TEARDOWN: +- case WLAN_TDLS_DISCOVERY_REQUEST: +- ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, +- action_code, dialog_token, +- status_code, skb); +- send_direct = false; +- break; +- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: +- ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, +- dialog_token, status_code, +- skb); +- send_direct = true; +- break; +- default: +- ret = -ENOTSUPP; +- break; +- } +- +- if (ret < 0) +- goto fail; +- +- if (extra_ies_len) +- memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); +- +- /* the TDLS link IE is always added last */ +- switch (action_code) { +- case WLAN_TDLS_SETUP_REQUEST: +- case WLAN_TDLS_SETUP_CONFIRM: +- case WLAN_TDLS_TEARDOWN: +- case WLAN_TDLS_DISCOVERY_REQUEST: +- /* we are the initiator */ +- ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, +- sdata->u.mgd.bssid); +- break; +- case WLAN_TDLS_SETUP_RESPONSE: +- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: +- /* we are the responder */ +- ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, +- sdata->u.mgd.bssid); +- break; +- default: +- ret = -ENOTSUPP; +- goto fail; +- } +- +- if (send_direct) { +- ieee80211_tx_skb(sdata, skb); +- return 0; +- } +- +- /* +- * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise +- * we should default to AC_VI. +- */ +- switch (action_code) { +- case WLAN_TDLS_SETUP_REQUEST: +- case WLAN_TDLS_SETUP_RESPONSE: +- skb_set_queue_mapping(skb, IEEE80211_AC_BK); +- skb->priority = 2; +- break; +- default: +- skb_set_queue_mapping(skb, IEEE80211_AC_VI); +- skb->priority = 5; +- break; +- } +- +- /* disable bottom halves when entering the Tx path */ +- local_bh_disable(); +- ret = ieee80211_subif_start_xmit(skb, dev); +- local_bh_enable(); +- +- return ret; +- +-fail: +- dev_kfree_skb(skb); +- return ret; +-} +- +-static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, enum nl80211_tdls_operation oper) +-{ +- struct sta_info *sta; +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- +- if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) +- return -ENOTSUPP; +- +- if (sdata->vif.type != NL80211_IFTYPE_STATION) +- return -EINVAL; +- +- tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); +- +- switch (oper) { +- case NL80211_TDLS_ENABLE_LINK: +- rcu_read_lock(); +- sta = sta_info_get(sdata, peer); +- if (!sta) { +- rcu_read_unlock(); +- return -ENOLINK; +- } +- +- set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); +- rcu_read_unlock(); +- break; +- case NL80211_TDLS_DISABLE_LINK: +- return sta_info_destroy_addr(sdata, peer); +- case NL80211_TDLS_TEARDOWN: +- case NL80211_TDLS_SETUP: +- case NL80211_TDLS_DISCOVERY_REQ: +- /* We don't support in-driver setup/teardown/discovery */ +- return -ENOTSUPP; +- default: +- return -ENOTSUPP; +- } +- +- return 0; +-} +- + static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u64 *cookie) + { +--- a/net/mac80211/chan.c ++++ b/net/mac80211/chan.c +@@ -855,7 +855,7 @@ static void + __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, + bool clear) + { +- struct ieee80211_local *local = sdata->local; ++ struct ieee80211_local *local __maybe_unused = sdata->local; + struct ieee80211_sub_if_data *vlan; + struct ieee80211_chanctx_conf *conf; + +@@ -871,7 +871,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(st + * to a channel context that has already been freed. + */ + conf = rcu_dereference_protected(sdata->vif.chanctx_conf, +- lockdep_is_held(&local->chanctx_mtx)); ++ lockdep_is_held(&local->chanctx_mtx)); + WARN_ON(!conf); + + if (clear) +--- a/net/mac80211/driver-ops.h ++++ b/net/mac80211/driver-ops.h +@@ -5,11 +5,11 @@ + #include "ieee80211_i.h" + #include "trace.h" + +-static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) ++static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) + { +- WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), +- "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", +- sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); ++ return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), ++ "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", ++ sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); } --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) + static inline struct ieee80211_sub_if_data * +@@ -168,7 +168,8 @@ static inline int drv_change_interface(s + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_change_interface(local, sdata, type, p2p); + ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); +@@ -181,7 +182,8 @@ static inline void drv_remove_interface( { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct cfg80211_event *ev; - unsigned long flags; + might_sleep(); -- trace_cfg80211_ibss_joined(dev, bssid); -+ trace_cfg80211_ibss_joined(dev, bssid, channel); -+ -+ if (WARN_ON(!channel)) +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) + return; - ev = kzalloc(sizeof(*ev), gfp); - if (!ev) + trace_drv_remove_interface(local, sdata); + local->ops->remove_interface(&local->hw, &sdata->vif); +@@ -219,7 +221,8 @@ static inline void drv_bss_info_changed( + sdata->vif.type == NL80211_IFTYPE_MONITOR)) return; - ev->type = EVENT_IBSS_JOINED; -- memcpy(ev->cr.bssid, bssid, ETH_ALEN); -+ memcpy(ev->ij.bssid, bssid, ETH_ALEN); -+ ev->ij.channel = channel; +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; - 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 + trace_drv_bss_info_changed(local, sdata, info, changed); + if (local->ops->bss_info_changed) +@@ -278,7 +281,8 @@ static inline int drv_set_key(struct iee + might_sleep(); - 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 + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; - 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)) - ); + trace_drv_set_key(local, cmd, sdata, sta, key); + ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); +@@ -298,7 +302,8 @@ static inline void drv_update_tkip_key(s + ista = &sta->sta; --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) - ); + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; -+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) -+); + trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); + if (local->ops->update_tkip_key) +@@ -315,7 +320,8 @@ static inline int drv_hw_scan(struct iee + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_hw_scan(local, sdata); + ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); +@@ -328,7 +334,8 @@ static inline void drv_cancel_hw_scan(st + { + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_cancel_hw_scan(local, sdata); + local->ops->cancel_hw_scan(&local->hw, &sdata->vif); +@@ -345,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_lo + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_sched_scan_start(local, sdata); + ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, +@@ -361,7 +369,8 @@ static inline int drv_sched_scan_stop(st + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_sched_scan_stop(local, sdata); + ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); +@@ -462,7 +471,8 @@ static inline void drv_sta_notify(struct + struct ieee80211_sta *sta) + { + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_sta_notify(local, sdata, cmd, sta); + if (local->ops->sta_notify) +@@ -479,7 +489,8 @@ static inline int drv_sta_add(struct iee + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_sta_add(local, sdata, sta); + if (local->ops->sta_add) +@@ -497,7 +508,8 @@ static inline void drv_sta_remove(struct + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_sta_remove(local, sdata, sta); + if (local->ops->sta_remove) +@@ -515,7 +527,8 @@ static inline void drv_sta_add_debugfs(s + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + if (local->ops->sta_add_debugfs) + local->ops->sta_add_debugfs(&local->hw, &sdata->vif, +@@ -545,7 +558,8 @@ static inline void drv_sta_pre_rcu_remov + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); + if (local->ops->sta_pre_rcu_remove) +@@ -566,7 +580,8 @@ int drv_sta_state(struct ieee80211_local + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); + if (local->ops->sta_state) { +@@ -590,7 +605,8 @@ static inline void drv_sta_rc_update(str + struct ieee80211_sta *sta, u32 changed) + { + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && + (sdata->vif.type != NL80211_IFTYPE_ADHOC && +@@ -612,7 +628,8 @@ static inline int drv_conf_tx(struct iee + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_conf_tx(local, sdata, ac, params); + if (local->ops->conf_tx) +@@ -629,7 +646,8 @@ static inline u64 drv_get_tsf(struct iee + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return ret; + + trace_drv_get_tsf(local, sdata); + if (local->ops->get_tsf) +@@ -644,7 +662,8 @@ static inline void drv_set_tsf(struct ie + { + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_set_tsf(local, sdata, tsf); + if (local->ops->set_tsf) +@@ -657,7 +676,8 @@ static inline void drv_reset_tsf(struct + { + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_reset_tsf(local, sdata); + if (local->ops->reset_tsf) +@@ -689,7 +709,8 @@ static inline int drv_ampdu_action(struc + might_sleep(); + + sdata = get_bss_sdata(sdata); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); + +@@ -733,8 +754,8 @@ static inline void drv_flush(struct ieee + + might_sleep(); + +- if (sdata) +- check_sdata_in_driver(sdata); ++ if (sdata && !check_sdata_in_driver(sdata)) ++ return; + + trace_drv_flush(local, queues, drop); + if (local->ops->flush) +@@ -854,7 +875,8 @@ static inline int drv_set_bitrate_mask(s + + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_set_bitrate_mask(local, sdata, mask); + if (local->ops->set_bitrate_mask) +@@ -869,7 +891,8 @@ static inline void drv_set_rekey_data(st + struct ieee80211_sub_if_data *sdata, + struct cfg80211_gtk_rekey_data *data) + { +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_set_rekey_data(local, sdata, data); + if (local->ops->set_rekey_data) +@@ -937,7 +960,8 @@ static inline void drv_mgd_prepare_tx(st + { + might_sleep(); + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); + + trace_drv_mgd_prepare_tx(local, sdata); +@@ -964,6 +988,9 @@ static inline int drv_add_chanctx(struct + static inline void drv_remove_chanctx(struct ieee80211_local *local, + struct ieee80211_chanctx *ctx) + { ++ if (WARN_ON(!ctx->driver_present)) ++ return; + - 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) + trace_drv_remove_chanctx(local, ctx); + if (local->ops->remove_chanctx) + local->ops->remove_chanctx(&local->hw, &ctx->conf); +@@ -989,7 +1016,8 @@ static inline int drv_assign_vif_chanctx { - *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; -+ -+ /* 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; -+ -+ 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; -+ -+ 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; + int ret = 0; + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_assign_vif_chanctx(local, sdata, ctx); + if (local->ops->assign_vif_chanctx) { +@@ -1007,7 +1035,8 @@ static inline void drv_unassign_vif_chan + struct ieee80211_sub_if_data *sdata, + struct ieee80211_chanctx *ctx) + { +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_unassign_vif_chanctx(local, sdata, ctx); + if (local->ops->unassign_vif_chanctx) { +@@ -1024,7 +1053,8 @@ static inline int drv_start_ap(struct ie + { + int ret = 0; + +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); + if (local->ops->start_ap) +@@ -1036,7 +1066,8 @@ static inline int drv_start_ap(struct ie + static inline void drv_stop_ap(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) + { +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_stop_ap(local, sdata); + if (local->ops->stop_ap) +@@ -1059,7 +1090,8 @@ drv_set_default_unicast_key(struct ieee8 + struct ieee80211_sub_if_data *sdata, + int key_idx) + { +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + WARN_ON_ONCE(key_idx < -1 || key_idx > 3); + +@@ -1101,7 +1133,8 @@ static inline int drv_join_ibss(struct i + int ret = 0; + + might_sleep(); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return -EIO; + + trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); + if (local->ops->join_ibss) +@@ -1114,7 +1147,8 @@ static inline void drv_leave_ibss(struct + struct ieee80211_sub_if_data *sdata) + { + might_sleep(); +- check_sdata_in_driver(sdata); ++ if (!check_sdata_in_driver(sdata)) ++ return; + + trace_drv_leave_ibss(local, sdata); + if (local->ops->leave_ibss) +--- 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 = (pos - presp->head); ++ sdata->csa_counter_offset_beacon[0] = (pos - presp->head); + *pos++ = csa_settings->count; } - 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; +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -754,9 +754,10 @@ struct ieee80211_sub_if_data { + struct mac80211_qos_map __rcu *qos_map; + + struct work_struct csa_finalize_work; +- int csa_counter_offset_beacon; +- int csa_counter_offset_presp; ++ 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; + + struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ +@@ -766,6 +767,7 @@ struct ieee80211_sub_if_data { + struct ieee80211_chanctx *reserved_chanctx; + struct cfg80211_chan_def reserved_chandef; + bool reserved_radar_required; ++ u8 csa_current_counter; + + /* used to reconfigure hardware SM PS */ + struct work_struct recalc_smps; +@@ -1462,6 +1464,7 @@ __ieee80211_request_sched_scan_start(str + int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, + struct cfg80211_sched_scan_request *req); + int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); ++void ieee80211_sched_scan_end(struct ieee80211_local *local); + void ieee80211_sched_scan_stopped_work(struct work_struct *work); + + /* off-channel helpers */ +@@ -1476,6 +1479,7 @@ void ieee80211_sw_roc_work(struct work_s + void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); + + /* channel switch handling */ ++bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local); + void ieee80211_csa_finalize_work(struct work_struct *work); + int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_csa_settings *params); +@@ -1837,6 +1841,15 @@ int ieee80211_check_combinations(struct + u8 radar_detect); + int ieee80211_max_num_channels(struct ieee80211_local *local); + ++/* TDLS */ ++int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, ++ const u8 *extra_ies, size_t extra_ies_len); ++int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, enum nl80211_tdls_operation oper); ++ ++ + #ifdef CPTCFG_MAC80211_NOINLINE + #define debug_noinline noinline + #else +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -838,8 +838,15 @@ static void ieee80211_do_stop(struct iee + + cancel_work_sync(&sdata->recalc_smps); + sdata_lock(sdata); ++ mutex_lock(&local->mtx); + sdata->vif.csa_active = false; ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, ++ IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ mutex_unlock(&local->mtx); + sdata_unlock(sdata); ++ + cancel_work_sync(&sdata->csa_finalize_work); + + cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -325,7 +325,8 @@ ieee80211_key_alloc(u32 cipher, int idx, + struct ieee80211_key *key; + int i, j, err; + +- BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); ++ if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)) ++ return ERR_PTR(-EINVAL); + + key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); + if (!key) +@@ -481,8 +482,8 @@ int ieee80211_key_link(struct ieee80211_ + int idx, ret; + bool pairwise; + +- BUG_ON(!sdata); +- BUG_ON(!key); ++ if (WARN_ON(!sdata || !key)) ++ return -EINVAL; + + pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; + idx = key->conf.keyidx; +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -956,6 +956,8 @@ int ieee80211_register_hw(struct ieee802 + if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) + local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; + ++ local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM; ++ + result = wiphy_register(local->hw.wiphy); + if (result < 0) + goto fail_wiphy_register; +--- 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 = hdr_len + 6; ++ sdata->csa_counter_offset_beacon[0] = hdr_len + 6; + *pos++ = csa->settings.count; + *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; + *pos++ = 6; +--- a/net/mac80211/mesh_pathtbl.c ++++ b/net/mac80211/mesh_pathtbl.c +@@ -287,8 +287,10 @@ static void mesh_path_move_to_queue(stru + struct sk_buff_head failq; + unsigned long flags; + +- BUG_ON(gate_mpath == from_mpath); +- BUG_ON(!gate_mpath->next_hop); ++ if (WARN_ON(gate_mpath == from_mpath)) ++ return; ++ if (WARN_ON(!gate_mpath->next_hop)) ++ return; + + __skb_queue_head_init(&failq); - 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); - } +--- a/net/mac80211/mesh_sync.c ++++ b/net/mac80211/mesh_sync.c +@@ -171,7 +171,7 @@ static void mesh_sync_offset_adjust_tbtt + u8 cap; ---- 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; + WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); +- BUG_ON(!rcu_read_lock_held()); ++ WARN_ON(!rcu_read_lock_held()); + cap = beacon->meshconf->meshconf_cap; -- if (WARN_ON(!wdev->channel)) -+ if (WARN_ON(!wdev->chandef.chan)) - return; + spin_lock_bh(&ifmsh->sync_offset_lock); +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -975,16 +975,23 @@ static void ieee80211_chswitch_work(stru + /* XXX: shouldn't really modify cfg80211-owned data! */ + ifmgd->associated->channel = sdata->csa_chandef.chan; - 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; - } - } ++ ieee80211_bss_info_change_notify(sdata, changed); + -+ if (is2GHz && !twiceMaxEdgePower) -+ twiceMaxEdgePower = 60; ++ mutex_lock(&local->mtx); ++ sdata->vif.csa_active = false; + /* XXX: wait for a beacon first? */ +- ieee80211_wake_queues_by_reason(&local->hw, ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_MAX_QUEUE_MAP, + IEEE80211_QUEUE_STOP_REASON_CSA); ++ mutex_unlock(&local->mtx); + +- ieee80211_bss_info_change_notify(sdata, changed); +- +- out: +- sdata->vif.csa_active = false; + ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; ++ ++ ieee80211_sta_reset_beacon_monitor(sdata); ++ ieee80211_sta_reset_conn_monitor(sdata); + - return twiceMaxEdgePower; ++out: + sdata_unlock(sdata); } ---- 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]; - }; +@@ -1100,12 +1107,16 @@ ieee80211_sta_process_chanswitch(struct + mutex_unlock(&local->chanctx_mtx); + + sdata->csa_chandef = csa_ie.chandef; ++ ++ mutex_lock(&local->mtx); + sdata->vif.csa_active = true; ++ sdata->csa_block_tx = csa_ie.mode; + +- if (csa_ie.mode) ++ if (sdata->csa_block_tx) + ieee80211_stop_queues_by_reason(&local->hw, +- IEEE80211_MAX_QUEUE_MAP, +- IEEE80211_QUEUE_STOP_REASON_CSA); ++ IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_CSA); ++ mutex_unlock(&local->mtx); + + if (local->ops->channel_switch) { + /* use driver's channel switch callback */ +@@ -1817,6 +1828,12 @@ static void ieee80211_set_disassoc(struc + ifmgd->flags = 0; + mutex_lock(&local->mtx); + ieee80211_vif_release_channel(sdata); ++ ++ sdata->vif.csa_active = false; ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, ++ IEEE80211_MAX_QUEUE_MAP, ++ IEEE80211_QUEUE_STOP_REASON_CSA); + mutex_unlock(&local->mtx); -@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc - if (q_q_coff > 63) - q_q_coff = 63; + sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; +@@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) -- iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; -+ iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff); + static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) + { ++ struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - 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; +@@ -2058,10 +2076,14 @@ static void __ieee80211_disconnect(struc + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, + true, frame_buf); + ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; ++ ++ mutex_lock(&local->mtx); + sdata->vif.csa_active = false; +- ieee80211_wake_queues_by_reason(&sdata->local->hw, ++ if (!ieee80211_csa_needs_block_tx(local)) ++ ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_MAX_QUEUE_MAP, + IEEE80211_QUEUE_STOP_REASON_CSA); ++ mutex_unlock(&local->mtx); + + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); +@@ -3546,6 +3568,9 @@ static void ieee80211_sta_bcn_mon_timer( + if (local->quiescing) + return; -- iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; -+ iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff); ++ if (sdata->vif.csa_active) ++ return; ++ + sdata->u.mgd.connection_loss = false; + ieee80211_queue_work(&sdata->local->hw, + &sdata->u.mgd.beacon_connection_loss_work); +@@ -3561,6 +3586,9 @@ static void ieee80211_sta_conn_mon_timer + if (local->quiescing) + return; - 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; ++ if (sdata->vif.csa_active) ++ return; ++ + ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); } --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 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; - } - } +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -22,7 +22,7 @@ + #define MCS_NBITS (AVG_PKT_SIZE << 3) - /* 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; - } + /* Number of symbols for a packet with (bps) bits per symbol */ +-#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) ++#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) + + /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ + #define MCS_SYMBOL_TIME(sgi, syms) \ +@@ -226,8 +226,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_s + nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); + + nsecs += minstrel_mcs_groups[group].duration[rate]; +- tp = 1000000 * ((prob * 1000) / nsecs); + ++ /* prob is scaled - see MINSTREL_FRAC above */ ++ tp = 1000000 * ((prob * 1000) / nsecs); + mr->cur_tp = MINSTREL_TRUNC(tp); } --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) +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -1076,12 +1076,8 @@ void ieee80211_sched_scan_results(struct + } + EXPORT_SYMBOL(ieee80211_sched_scan_results); + +-void ieee80211_sched_scan_stopped_work(struct work_struct *work) ++void ieee80211_sched_scan_end(struct ieee80211_local *local) { - 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); +- struct ieee80211_local *local = +- container_of(work, struct ieee80211_local, +- sched_scan_stopped_work); - -- /* 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]; - -- 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); + mutex_lock(&local->mtx); - 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; + if (!rcu_access_pointer(local->sched_scan_sdata)) { +@@ -1099,6 +1095,15 @@ void ieee80211_sched_scan_stopped_work(s + cfg80211_sched_scan_stopped(local->hw.wiphy); } --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) ++void ieee80211_sched_scan_stopped_work(struct work_struct *work) +{ -+ 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]); ++ struct ieee80211_local *local = ++ container_of(work, struct ieee80211_local, ++ sched_scan_stopped_work); ++ ++ ieee80211_sched_scan_end(local); ++} ++ + void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) + { + struct ieee80211_local *local = hw_to_local(hw); +--- /dev/null ++++ b/net/mac80211/tdls.c +@@ -0,0 +1,325 @@ ++/* ++ * mac80211 TDLS handling code ++ * ++ * Copyright 2006-2010 Johannes Berg ++ * Copyright 2014, Intel Corporation ++ * ++ * This file is GPLv2 as found in COPYING. ++ */ ++ ++#include ++#include "ieee80211_i.h" ++ ++static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) ++{ ++ u8 *pos = (void *)skb_put(skb, 7); ++ ++ *pos++ = WLAN_EID_EXT_CAPABILITY; ++ *pos++ = 5; /* len */ ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = 0x0; ++ *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; ++} ++ ++static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) ++{ ++ struct ieee80211_local *local = sdata->local; ++ u16 capab; ++ ++ capab = 0; ++ if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) ++ return capab; ++ ++ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) ++ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; ++ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) ++ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; ++ ++ return capab; ++} ++ ++static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, ++ const u8 *peer, const u8 *bssid) ++{ ++ struct ieee80211_tdls_lnkie *lnkid; ++ ++ lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); ++ ++ lnkid->ie_type = WLAN_EID_LINK_ID; ++ lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; ++ ++ memcpy(lnkid->bssid, bssid, ETH_ALEN); ++ memcpy(lnkid->init_sta, src_addr, ETH_ALEN); ++ memcpy(lnkid->resp_sta, peer, ETH_ALEN); ++} ++ ++static int ++ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ enum ieee80211_band band = ieee80211_get_sdata_band(sdata); ++ struct ieee80211_tdls_data *tf; ++ ++ tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); ++ ++ memcpy(tf->da, peer, ETH_ALEN); ++ memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); ++ tf->ether_type = cpu_to_be16(ETH_P_TDLS); ++ tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = WLAN_TDLS_SETUP_REQUEST; ++ ++ skb_put(skb, sizeof(tf->u.setup_req)); ++ tf->u.setup_req.dialog_token = dialog_token; ++ tf->u.setup_req.capability = ++ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); ++ ++ ieee80211_add_srates_ie(sdata, skb, false, band); ++ ieee80211_add_ext_srates_ie(sdata, skb, false, band); ++ ieee80211_tdls_add_ext_capab(skb); ++ break; ++ case WLAN_TDLS_SETUP_RESPONSE: ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = WLAN_TDLS_SETUP_RESPONSE; ++ ++ skb_put(skb, sizeof(tf->u.setup_resp)); ++ tf->u.setup_resp.status_code = cpu_to_le16(status_code); ++ tf->u.setup_resp.dialog_token = dialog_token; ++ tf->u.setup_resp.capability = ++ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); ++ ++ ieee80211_add_srates_ie(sdata, skb, false, band); ++ ieee80211_add_ext_srates_ie(sdata, skb, false, band); ++ ieee80211_tdls_add_ext_capab(skb); ++ break; ++ case WLAN_TDLS_SETUP_CONFIRM: ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = WLAN_TDLS_SETUP_CONFIRM; ++ ++ skb_put(skb, sizeof(tf->u.setup_cfm)); ++ tf->u.setup_cfm.status_code = cpu_to_le16(status_code); ++ tf->u.setup_cfm.dialog_token = dialog_token; ++ break; ++ case WLAN_TDLS_TEARDOWN: ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = WLAN_TDLS_TEARDOWN; ++ ++ skb_put(skb, sizeof(tf->u.teardown)); ++ tf->u.teardown.reason_code = cpu_to_le16(status_code); ++ break; ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ tf->category = WLAN_CATEGORY_TDLS; ++ tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; ++ ++ skb_put(skb, sizeof(tf->u.discover_req)); ++ tf->u.discover_req.dialog_token = dialog_token; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int ++ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, struct sk_buff *skb) ++{ ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ enum ieee80211_band band = ieee80211_get_sdata_band(sdata); ++ struct ieee80211_mgmt *mgmt; ++ ++ mgmt = (void *)skb_put(skb, 24); ++ memset(mgmt, 0, 24); ++ memcpy(mgmt->da, peer, ETH_ALEN); ++ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); ++ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); ++ ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | ++ IEEE80211_STYPE_ACTION); ++ ++ switch (action_code) { ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); ++ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; ++ mgmt->u.action.u.tdls_discover_resp.action_code = ++ WLAN_PUB_ACTION_TDLS_DISCOVER_RES; ++ mgmt->u.action.u.tdls_discover_resp.dialog_token = ++ dialog_token; ++ mgmt->u.action.u.tdls_discover_resp.capability = ++ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); ++ ++ ieee80211_add_srates_ie(sdata, skb, false, band); ++ ieee80211_add_ext_srates_ie(sdata, skb, false, band); ++ ieee80211_tdls_add_ext_capab(skb); ++ break; ++ default: ++ return -EINVAL; + } ++ ++ return 0; +} + -+static bool ar955x_tx_iq_cal_median(struct ath_hw *ah, -+ struct coeff *coeff, -+ int iqcal_idx, -+ int nmeasurement) ++int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, u8 action_code, u8 dialog_token, ++ u16 status_code, u32 peer_capability, ++ const u8 *extra_ies, size_t extra_ies_len) +{ -+ int i; ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct ieee80211_local *local = sdata->local; ++ struct sk_buff *skb = NULL; ++ bool send_direct; ++ int ret; ++ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ /* make sure we are in managed mode, and associated */ ++ if (sdata->vif.type != NL80211_IFTYPE_STATION || ++ !sdata->u.mgd.associated) ++ return -EINVAL; ++ ++ tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", ++ action_code, peer); ++ ++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + ++ max(sizeof(struct ieee80211_mgmt), ++ sizeof(struct ieee80211_tdls_data)) + ++ 50 + /* supported rates */ ++ 7 + /* ext capab */ ++ extra_ies_len + ++ sizeof(struct ieee80211_tdls_lnkie)); ++ if (!skb) ++ return -ENOMEM; ++ ++ skb_reserve(skb, local->hw.extra_tx_headroom); ++ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, ++ action_code, dialog_token, ++ status_code, skb); ++ send_direct = false; ++ break; ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, ++ dialog_token, status_code, ++ skb); ++ send_direct = true; ++ break; ++ default: ++ ret = -ENOTSUPP; ++ break; ++ } ++ ++ if (ret < 0) ++ goto fail; ++ ++ if (extra_ies_len) ++ memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); ++ ++ /* the TDLS link IE is always added last */ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_CONFIRM: ++ case WLAN_TDLS_TEARDOWN: ++ case WLAN_TDLS_DISCOVERY_REQUEST: ++ /* we are the initiator */ ++ ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, ++ sdata->u.mgd.bssid); ++ break; ++ case WLAN_TDLS_SETUP_RESPONSE: ++ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: ++ /* we are the responder */ ++ ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, ++ sdata->u.mgd.bssid); ++ break; ++ default: ++ ret = -ENOTSUPP; ++ goto fail; ++ } + -+ if ((iqcal_idx + 1) != MAXIQCAL) -+ return false; ++ if (send_direct) { ++ ieee80211_tx_skb(sdata, skb); ++ return 0; ++ } + -+ for (i = 0; i < AR9300_MAX_CHAINS; i++) { -+ __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement); ++ /* ++ * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise ++ * we should default to AC_VI. ++ */ ++ switch (action_code) { ++ case WLAN_TDLS_SETUP_REQUEST: ++ case WLAN_TDLS_SETUP_RESPONSE: ++ skb_set_queue_mapping(skb, IEEE80211_AC_BK); ++ skb->priority = 2; ++ break; ++ default: ++ skb_set_queue_mapping(skb, IEEE80211_AC_VI); ++ skb->priority = 5; ++ break; + } + -+ return true; ++ /* disable bottom halves when entering the Tx path */ ++ local_bh_disable(); ++ ret = ieee80211_subif_start_xmit(skb, dev); ++ local_bh_enable(); ++ ++ return ret; ++ ++fail: ++ dev_kfree_skb(skb); ++ return ret; +} + -+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, -+ int iqcal_idx, -+ bool is_reusable) ++int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, ++ const u8 *peer, enum nl80211_tdls_operation oper) ++{ ++ struct sta_info *sta; ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ ++ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) ++ return -ENOTSUPP; ++ ++ if (sdata->vif.type != NL80211_IFTYPE_STATION) ++ return -EINVAL; ++ ++ tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); ++ ++ switch (oper) { ++ case NL80211_TDLS_ENABLE_LINK: ++ rcu_read_lock(); ++ sta = sta_info_get(sdata, peer); ++ if (!sta) { ++ rcu_read_unlock(); ++ return -ENOLINK; ++ } ++ ++ set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); ++ rcu_read_unlock(); ++ break; ++ case NL80211_TDLS_DISABLE_LINK: ++ return sta_info_destroy_addr(sdata, peer); ++ case NL80211_TDLS_TEARDOWN: ++ case NL80211_TDLS_SETUP: ++ case NL80211_TDLS_DISCOVERY_REQ: ++ /* We don't support in-driver setup/teardown/discovery */ ++ return -ENOTSUPP; ++ default: ++ return -ENOTSUPP; ++ } ++ ++ return 0; ++} +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2330,7 +2330,8 @@ void ieee80211_tx_pending(unsigned long + /* functions for drivers to get certain frames */ + + static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, +- struct ps_data *ps, struct sk_buff *skb) ++ struct ps_data *ps, struct sk_buff *skb, ++ bool is_template) { - 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; - } + u8 *pos, *tim; + int aid0 = 0; +@@ -2343,11 +2344,12 @@ static void __ieee80211_beacon_add_tim(s + * checking byte-for-byte */ + have_bits = !bitmap_empty((unsigned long *)ps->tim, + IEEE80211_MAX_AID+1); +- +- if (ps->dtim_count == 0) +- ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; +- else +- ps->dtim_count--; ++ if (!is_template) { ++ if (ps->dtim_count == 0) ++ ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; ++ else ++ ps->dtim_count--; ++ } -- 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; + tim = pos = (u8 *) skb_put(skb, 6); + *pos++ = WLAN_EID_TIM; +@@ -2393,7 +2395,8 @@ static void __ieee80211_beacon_add_tim(s + } + + static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, +- struct ps_data *ps, struct sk_buff *skb) ++ struct ps_data *ps, struct sk_buff *skb, ++ bool is_template) + { + struct ieee80211_local *local = sdata->local; + +@@ -2405,24 +2408,24 @@ static int ieee80211_beacon_add_tim(stru + * of the tim bitmap in mac80211 and the driver. + */ + if (local->tim_in_locked_section) { +- __ieee80211_beacon_add_tim(sdata, ps, skb); ++ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); + } else { + spin_lock_bh(&local->tim_lock); +- __ieee80211_beacon_add_tim(sdata, ps, skb); ++ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); + spin_unlock_bh(&local->tim_lock); + } + + return 0; + } + +-static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, +- struct beacon_data *beacon) ++static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, ++ struct beacon_data *beacon) + { + struct probe_resp *resp; +- int counter_offset_beacon = sdata->csa_counter_offset_beacon; +- int counter_offset_presp = sdata->csa_counter_offset_presp; + u8 *beacon_data; + size_t beacon_data_len; ++ int i; ++ u8 count = sdata->csa_current_counter; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +@@ -2440,40 +2443,57 @@ static void ieee80211_update_csa(struct + default: + return; + } +- if (WARN_ON(counter_offset_beacon >= beacon_data_len)) +- return; + +- /* Warn if the driver did not check for/react to csa +- * completeness. A beacon with CSA counter set to 0 should +- * never occur, because a counter of 1 means switch just +- * before the next beacon. +- */ +- if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) +- return; ++ 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]--; ++ 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); ++ if (sdata->vif.type == NL80211_IFTYPE_AP && ++ counter_offset_presp) { ++ rcu_read_lock(); ++ resp = rcu_dereference(sdata->u.ap.probe_resp); + +- /* if nl80211 accepted the offset, this should not happen. */ +- if (WARN_ON(!resp)) { ++ /* If nl80211 accepted the offset, this should ++ * not happen. ++ */ ++ if (WARN_ON(!resp)) { ++ rcu_read_unlock(); ++ return; ++ } ++ resp->data[counter_offset_presp] = count; + rcu_read_unlock(); +- return; } +- resp->data[counter_offset_presp]--; +- rcu_read_unlock(); } -- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable); + } + ++u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) ++{ ++ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); ++ ++ sdata->csa_current_counter--; ++ ++ /* the counter should never reach 0 */ ++ WARN_ON(!sdata->csa_current_counter); + -+ 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 sdata->csa_current_counter; ++} ++EXPORT_SYMBOL(ieee80211_csa_update_counter); ++ + bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) + { + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct beacon_data *beacon = NULL; + u8 *beacon_data; + size_t beacon_data_len; +- int counter_beacon = sdata->csa_counter_offset_beacon; ++ int counter_beacon = sdata->csa_counter_offset_beacon[0]; + int ret = false; - return; + if (!ieee80211_sdata_running(sdata)) +@@ -2523,9 +2543,11 @@ bool ieee80211_csa_is_complete(struct ie + } + EXPORT_SYMBOL(ieee80211_csa_is_complete); + +-struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- u16 *tim_offset, u16 *tim_length) ++static struct sk_buff * ++__ieee80211_beacon_get(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs, ++ bool is_template) + { + struct ieee80211_local *local = hw_to_local(hw); + struct sk_buff *skb = NULL; +@@ -2534,6 +2556,7 @@ struct sk_buff *ieee80211_beacon_get_tim + enum ieee80211_band band; + struct ieee80211_tx_rate_control txrc; + struct ieee80211_chanctx_conf *chanctx_conf; ++ int csa_off_base = 0; + + rcu_read_lock(); + +@@ -2543,18 +2566,20 @@ struct sk_buff *ieee80211_beacon_get_tim + if (!ieee80211_sdata_running(sdata) || !chanctx_conf) + goto out; + +- if (tim_offset) +- *tim_offset = 0; +- if (tim_length) +- *tim_length = 0; ++ if (offs) ++ memset(offs, 0, sizeof(*offs)); + + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_if_ap *ap = &sdata->u.ap; + struct beacon_data *beacon = rcu_dereference(ap->beacon); + + if (beacon) { +- if (sdata->vif.csa_active) +- ieee80211_update_csa(sdata, beacon); ++ if (sdata->vif.csa_active) { ++ if (!is_template) ++ ieee80211_csa_update_counter(vif); ++ ++ ieee80211_set_csa(sdata, beacon); ++ } + + /* + * headroom, head length, +@@ -2571,12 +2596,16 @@ struct sk_buff *ieee80211_beacon_get_tim + memcpy(skb_put(skb, beacon->head_len), beacon->head, + beacon->head_len); + +- ieee80211_beacon_add_tim(sdata, &ap->ps, skb); ++ ieee80211_beacon_add_tim(sdata, &ap->ps, skb, ++ is_template); ++ ++ if (offs) { ++ offs->tim_offset = beacon->head_len; ++ offs->tim_length = skb->len - beacon->head_len; + +- if (tim_offset) +- *tim_offset = beacon->head_len; +- if (tim_length) +- *tim_length = skb->len - beacon->head_len; ++ /* for AP the csa offsets are from tail */ ++ csa_off_base = skb->len; ++ } + + if (beacon->tail) + memcpy(skb_put(skb, beacon->tail_len), +@@ -2591,9 +2620,12 @@ struct sk_buff *ieee80211_beacon_get_tim + if (!presp) + goto out; + +- if (sdata->vif.csa_active) +- ieee80211_update_csa(sdata, presp); ++ if (sdata->vif.csa_active) { ++ if (!is_template) ++ ieee80211_csa_update_counter(vif); + ++ ieee80211_set_csa(sdata, presp); ++ } + + skb = dev_alloc_skb(local->tx_headroom + presp->head_len + + local->hw.extra_beacon_tailroom); +@@ -2613,8 +2645,17 @@ struct sk_buff *ieee80211_beacon_get_tim + if (!bcn) + goto out; + +- if (sdata->vif.csa_active) +- ieee80211_update_csa(sdata, bcn); ++ if (sdata->vif.csa_active) { ++ if (!is_template) ++ /* TODO: For mesh csa_counter is in TU, so ++ * decrementing it by one isn't correct, but ++ * for now we leave it consistent with overall ++ * mac80211's behavior. ++ */ ++ ieee80211_csa_update_counter(vif); ++ ++ ieee80211_set_csa(sdata, bcn); ++ } -@@ -1409,7 +1484,7 @@ skip_tx_iqcal: + if (ifmsh->sync_ops) + ifmsh->sync_ops->adjust_tbtt(sdata, bcn); +@@ -2628,13 +2669,33 @@ struct sk_buff *ieee80211_beacon_get_tim + goto out; + skb_reserve(skb, local->tx_headroom); + memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); +- ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb); ++ 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; ++ } ++ + memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); + } else { + WARN_ON(1); + goto out; } - 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); ++ /* CSA offsets */ ++ if (offs) { ++ int i; ++ ++ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { ++ u16 csa_off = sdata->csa_counter_offset_beacon[i]; ++ ++ if (!csa_off) ++ continue; ++ ++ offs->csa_counter_offs[i] = csa_off_base + csa_off; ++ } ++ } ++ + band = chanctx_conf->def.chan->band; + + info = IEEE80211_SKB_CB(skb); +@@ -2665,6 +2726,32 @@ struct sk_buff *ieee80211_beacon_get_tim + out: + rcu_read_unlock(); + return skb; ++ ++} ++ ++struct sk_buff * ++ieee80211_beacon_get_template(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ struct ieee80211_mutable_offsets *offs) ++{ ++ return __ieee80211_beacon_get(hw, vif, offs, true); ++} ++EXPORT_SYMBOL(ieee80211_beacon_get_template); ++ ++struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, ++ struct ieee80211_vif *vif, ++ u16 *tim_offset, u16 *tim_length) ++{ ++ struct ieee80211_mutable_offsets offs = {}; ++ struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); ++ ++ if (tim_offset) ++ *tim_offset = offs.tim_offset; ++ ++ if (tim_length) ++ *tim_length = offs.tim_length; ++ ++ return bcn; + } + EXPORT_SYMBOL(ieee80211_beacon_get_tim); -@@ -1455,14 +1530,38 @@ skip_tx_iqcal: - return true; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80 + drv_stop(local); } -+static bool do_ar9003_agc_cal(struct ath_hw *ah) ++static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) +{ -+ 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; -+ } ++ struct ieee80211_sub_if_data *sdata; ++ struct ieee80211_chanctx *ctx; ++ ++ /* ++ * We get here if during resume the device can't be restarted properly. ++ * We might also get here if this happens during HW reset, which is a ++ * slightly different situation and we need to drop all connections in ++ * the latter case. ++ * ++ * Ask cfg80211 to turn off all interfaces, this will result in more ++ * warnings but at least we'll then get into a clean stopped state. ++ */ ++ ++ local->resuming = false; ++ local->suspended = false; ++ local->started = false; ++ ++ /* scheduled scan clearly can't be running any more, but tell ++ * cfg80211 and clear local state ++ */ ++ ieee80211_sched_scan_end(local); + -+ return true; ++ list_for_each_entry(sdata, &local->interfaces, list) ++ sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; ++ ++ /* Mark channel contexts as not being in the driver any more to avoid ++ * removing them from the driver during the shutdown process... ++ */ ++ mutex_lock(&local->chanctx_mtx); ++ list_for_each_entry(ctx, &local->chanctx_list, list) ++ ctx->driver_present = false; ++ mutex_unlock(&local->chanctx_mtx); ++ ++ cfg80211_shutdown_all_interfaces(local->hw.wiphy); +} + - static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, - struct ath9k_channel *chan) + static void ieee80211_assign_chanctx(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) { - 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. +@@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_ */ - 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); -- -- /* Poll for offset calibration complete */ -- status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, -- AR_PHY_AGC_CONTROL_CAL, -- 0, AH_WAIT_TIMEOUT); -- } -+ /* -+ * 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); -+ } -+ } -+ } + res = drv_start(local); + if (res) { +- WARN(local->suspended, "Hardware became unavailable " +- "upon resume. This could be a software issue " +- "prior to suspend or a hardware issue.\n"); ++ if (local->suspended) ++ WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n"); ++ else ++ WARN(1, "Hardware became unavailable during restart.\n"); ++ ieee80211_handle_reconfig_failure(local); + return res; } -- if (txiqcal_done) -- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); -- - /* Revert chainmask to runtime parameters */ - ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); +--- a/net/wireless/ap.c ++++ b/net/wireless/ap.c +@@ -6,8 +6,8 @@ + #include "rdev-ops.h" ---- 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 -+#include -+ - #include "rtl818x.h" - #include "leds.h" +-static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, +- struct net_device *dev, bool notify) ++int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, bool notify) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -370,8 +370,8 @@ int cfg80211_chandef_dfs_required(struct + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_WDS: + case NL80211_IFTYPE_P2P_DEVICE: +- case NL80211_IFTYPE_UNSPECIFIED: + break; ++ case NL80211_IFTYPE_UNSPECIFIED: + case NUM_NL80211_IFTYPES: + WARN_ON(1); + } +@@ -796,8 +796,7 @@ bool cfg80211_reg_can_beacon(struct wiph + !cfg80211_go_permissive_chan(rdev, chandef->chan)) + prohibited_flags |= IEEE80211_CHAN_NO_IR; + +- if (cfg80211_chandef_dfs_required(wiphy, chandef, +- NL80211_IFTYPE_UNSPECIFIED) > 0 && ++ if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && + cfg80211_chandef_dfs_available(wiphy, chandef)) { + /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ + prohibited_flags = IEEE80211_CHAN_DISABLED; +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -210,15 +210,12 @@ void cfg80211_stop_p2p_device(struct cfg + } + } -@@ -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; +-static int cfg80211_rfkill_set_block(void *data, bool blocked) ++void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) + { +- struct cfg80211_registered_device *rdev = data; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct wireless_dev *wdev; + +- if (!blocked) +- return 0; +- +- rtnl_lock(); ++ ASSERT_RTNL(); + + list_for_each_entry(wdev, &rdev->wdev_list, list) { + if (wdev->netdev) { +@@ -234,7 +231,18 @@ static int cfg80211_rfkill_set_block(voi + break; + } } ++} ++EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces); -+ if (skb->protocol == sdata->control_port_protocol) { -+ skb->priority = 7; -+ return ieee80211_downgrade_queue(sdata, skb); -+ } ++static int cfg80211_rfkill_set_block(void *data, bool blocked) ++{ ++ struct cfg80211_registered_device *rdev = data; + - /* 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; ++ if (!blocked) ++ return 0; ++ ++ rtnl_lock(); ++ cfg80211_shutdown_all_interfaces(&rdev->wiphy); + rtnl_unlock(); - ath_txq_lock(sc, txq); + return 0; +@@ -401,6 +409,8 @@ struct wiphy *wiphy_new(const struct cfg + rdev->wiphy.rts_threshold = (u32) -1; + rdev->wiphy.coverage_class = 0; -+ if (!tid->sched) { -+ ath_txq_unlock(sc, txq); -+ continue; -+ } ++ rdev->wiphy.max_num_csa_counters = 1; + - buffered = ath_tid_has_buffered(tid); + return &rdev->wiphy; + } + EXPORT_SYMBOL(wiphy_new); +@@ -697,7 +707,7 @@ void wiphy_unregister(struct wiphy *wiph + rtnl_lock(); + rdev->wiphy.registered = false; - tid->sched = false; -@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc +- BUG_ON(!list_empty(&rdev->wdev_list)); ++ WARN_ON(!list_empty(&rdev->wdev_list)); - ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); + /* + * First remove the hardware from everywhere, this makes +@@ -799,23 +809,23 @@ void cfg80211_update_iface_num(struct cf + rdev->num_running_monitor_ifaces += num; + } -- 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); +-void cfg80211_leave(struct cfg80211_registered_device *rdev, +- struct wireless_dev *wdev) ++void __cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev) + { + struct net_device *dev = wdev->netdev; -@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff + ASSERT_RTNL(); ++ ASSERT_WDEV_LOCK(wdev); - ATH_TXBUF_RESET(bf); + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: +- cfg80211_leave_ibss(rdev, dev, true); ++ __cfg80211_leave_ibss(rdev, dev, true); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) + __cfg80211_stop_sched_scan(rdev, false); -- 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; +- wdev_lock(wdev); + #ifdef CPTCFG_CFG80211_WEXT + kfree(wdev->wext.ie); + wdev->wext.ie = NULL; +@@ -824,20 +834,49 @@ void cfg80211_leave(struct cfg80211_regi + #endif + cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, true); +- wdev_unlock(wdev); + break; + case NL80211_IFTYPE_MESH_POINT: +- cfg80211_leave_mesh(rdev, dev); ++ __cfg80211_leave_mesh(rdev, dev); + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: +- cfg80211_stop_ap(rdev, dev, true); ++ __cfg80211_stop_ap(rdev, dev, true); + break; + default: + break; } - -+ 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) --{ -- ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); --} -+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); - ---- 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; } --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; - -- 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; - - clear_sta_flag(sta, WLAN_STA_PS_STA); -+ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); - - 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); - } ++void cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev) ++{ ++ wdev_lock(wdev); ++ __cfg80211_leave(rdev, wdev); ++ wdev_unlock(wdev); +} - -+static void cleanup_single_sta(struct sta_info *sta) ++ ++void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, ++ gfp_t gfp) +{ -+ struct ieee80211_sub_if_data *sdata = sta->sdata; -+ struct ieee80211_local *local = sdata->local; ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ struct cfg80211_event *ev; ++ unsigned long flags; + -+ __cleanup_single_sta(sta); - sta_info_free(local, sta); - } - -@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i - rcu_read_unlock(); - - 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; - } - -- /* notify driver */ -- err = sta_info_insert_drv_state(local, sdata, sta); -- if (err) -- goto out_err; -- - local->num_sta++; - local->sta_generation++; - smp_mb(); - -+ /* simplify things and don't accept BA sessions yet */ -+ set_sta_flag(sta, WLAN_STA_BLOCK_BA); ++ trace_cfg80211_stop_iface(wiphy, wdev); ++ ++ ev = kzalloc(sizeof(*ev), gfp); ++ if (!ev) ++ return; + - /* make the station visible */ - sta_info_hash_add(local, sta); ++ ev->type = EVENT_STOPPED; ++ ++ spin_lock_irqsave(&wdev->event_lock, flags); ++ list_add_tail(&ev->list, &wdev->event_list); ++ spin_unlock_irqrestore(&wdev->event_lock, flags); ++ queue_work(cfg80211_wq, &rdev->event_work); ++} ++EXPORT_SYMBOL(cfg80211_stop_iface); ++ + static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + unsigned long state, void *ptr) + { +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -185,6 +185,7 @@ enum cfg80211_event_type { + EVENT_ROAMED, + EVENT_DISCONNECTED, + EVENT_IBSS_JOINED, ++ EVENT_STOPPED, + }; - list_add_rcu(&sta->list, &local->sta_list); + struct cfg80211_event { +@@ -281,6 +282,8 @@ int cfg80211_join_mesh(struct cfg80211_r + struct net_device *dev, + struct mesh_setup *setup, + const struct mesh_config *conf); ++int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, ++ struct net_device *dev); + int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, + struct net_device *dev); + int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, +@@ -288,6 +291,8 @@ int cfg80211_set_mesh_channel(struct cfg + struct cfg80211_chan_def *chandef); + + /* AP */ ++int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, ++ struct net_device *dev, bool notify); + int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, + struct net_device *dev, bool notify); + +@@ -441,6 +446,8 @@ int cfg80211_validate_beacon_int(struct + void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, + enum nl80211_iftype iftype, int num); + ++void __cfg80211_leave(struct cfg80211_registered_device *rdev, ++ struct wireless_dev *wdev); + void cfg80211_leave(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); -+ /* notify driver */ -+ err = sta_info_insert_drv_state(local, sdata, sta); -+ if (err) -+ goto out_remove; -+ - set_sta_flag(sta, WLAN_STA_INSERTED); -+ /* accept BA sessions now */ -+ clear_sta_flag(sta, WLAN_STA_BLOCK_BA); +--- a/net/wireless/ibss.c ++++ b/net/wireless/ibss.c +@@ -420,8 +420,8 @@ int cfg80211_ibss_wext_siwessid(struct n + if (len > 0 && ssid[len - 1] == '\0') + len--; - 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); ++ memcpy(wdev->ssid, ssid, len); + wdev->wext.ibss.ssid = wdev->ssid; +- memcpy(wdev->wext.ibss.ssid, ssid, len); + wdev->wext.ibss.ssid_len = len; + wdev_lock(wdev); +--- a/net/wireless/mesh.c ++++ b/net/wireless/mesh.c +@@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg 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); --static void clear_sta_ps_flags(void *_sta) -+/* powersave support code */ -+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) +-static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, +- struct net_device *dev) ++int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, ++ struct net_device *dev) { -- 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; + struct wireless_dev *wdev = dev->ieee80211_ptr; + int err; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -371,8 +371,8 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, + [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, + [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, +- [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, +- [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, ++ [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY }, ++ [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY }, + [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, + [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, + [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, +@@ -386,6 +386,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, + [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 }, + }; - if (sdata->vif.type == NL80211_IFTYPE_AP || -@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st - else - return; + /* policy for the key attributes */ +@@ -970,8 +971,10 @@ static int nl80211_put_iface_combination + c->max_interfaces)) + goto nla_put_failure; + if (large && +- nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, +- c->radar_detect_widths)) ++ (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, ++ c->radar_detect_widths) || ++ nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, ++ c->radar_detect_regions))) + goto nla_put_failure; + + nla_nest_end(msg, nl_combi); +@@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg + } + nla_nest_end(msg, nested); + } ++ state->split_start++; ++ break; ++ case 12: ++ if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH && ++ nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS, ++ rdev->wiphy.max_num_csa_counters)) ++ goto nla_put_failure; + + /* done */ + state->split_start = 0; +@@ -5825,7 +5835,7 @@ static int nl80211_start_radar_detection + return -EBUSY; -- 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); --} -- --/* powersave support code */ --void ieee80211_sta_ps_deliver_wakeup(struct sta_info *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; -- - clear_sta_flag(sta, WLAN_STA_SP); + err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, +- NL80211_IFTYPE_UNSPECIFIED); ++ wdev->iftype); + if (err < 0) + return err; - BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); -@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str +@@ -5866,6 +5876,7 @@ static int nl80211_channel_switch(struct + u8 radar_detect_width = 0; + int err; + bool need_new_beacon = false; ++ int len, i; - skb_queue_head_init(&pending); + if (!rdev->ops->channel_switch || + !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) +@@ -5924,26 +5935,55 @@ static int nl80211_channel_switch(struct + if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) + return -EINVAL; -+ /* 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; - } +- params.counter_offset_beacon = +- nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); +- if (params.counter_offset_beacon >= params.beacon_csa.tail_len) ++ len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); ++ if (!len || (len % sizeof(u16))) + return -EINVAL; -- 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); - - /* 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; +- /* sanity check - counters should be the same */ +- if (params.beacon_csa.tail[params.counter_offset_beacon] != +- params.count) ++ params.n_counter_offsets_beacon = len / sizeof(u16); ++ if (rdev->wiphy.max_num_csa_counters && ++ (params.n_counter_offsets_beacon > ++ rdev->wiphy.max_num_csa_counters)) + return -EINVAL; -- /* -- * 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); - } ++ params.counter_offsets_beacon = ++ nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); ++ ++ /* sanity checks - counters should fit and be the same */ ++ for (i = 0; i < params.n_counter_offsets_beacon; i++) { ++ u16 offset = params.counter_offsets_beacon[i]; ++ ++ if (offset >= params.beacon_csa.tail_len) ++ return -EINVAL; ++ ++ if (params.beacon_csa.tail[offset] != params.count) ++ return -EINVAL; ++ } ++ + if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { +- params.counter_offset_presp = +- nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); +- if (params.counter_offset_presp >= +- params.beacon_csa.probe_resp_len) ++ len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); ++ if (!len || (len % sizeof(u16))) + return -EINVAL; --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); +- if (params.beacon_csa.probe_resp[params.counter_offset_presp] != +- params.count) ++ params.n_counter_offsets_presp = len / sizeof(u16); ++ if (rdev->wiphy.max_num_csa_counters && ++ (params.n_counter_offsets_beacon > ++ rdev->wiphy.max_num_csa_counters)) + return -EINVAL; ++ ++ params.counter_offsets_presp = ++ nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); ++ ++ /* sanity checks - counters should fit and be the same */ ++ for (i = 0; i < params.n_counter_offsets_presp; i++) { ++ u16 offset = params.counter_offsets_presp[i]; ++ ++ if (offset >= params.beacon_csa.probe_resp_len) ++ return -EINVAL; ++ ++ if (params.beacon_csa.probe_resp[offset] != ++ params.count) ++ return -EINVAL; ++ } } -- if (fn) -- fn(data); -- - 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(®_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"); -+ -+ if (common->disable_ani) - goto exit; -- } + skip_beacons: +@@ -7793,6 +7833,27 @@ static int nl80211_tx_mgmt(struct sk_buf + if (!chandef.chan && params.offchan) + return -EINVAL; -- 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); -+ - 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; ++ params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); ++ params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); ++ ++ if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) { ++ int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); ++ int i; ++ ++ if (len % sizeof(u16)) ++ return -EINVAL; ++ ++ params.n_csa_offsets = len / sizeof(u16); ++ params.csa_offsets = ++ nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); ++ ++ /* check that all the offsets fit the frame */ ++ for (i = 0; i < params.n_csa_offsets; i++) { ++ if (params.csa_offsets[i] >= params.len) ++ return -EINVAL; + } ++ } ++ + if (!params.dont_wait_for_ack) { + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) +@@ -7807,8 +7868,6 @@ static int nl80211_tx_mgmt(struct sk_buf + } } - 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; +- params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); +- params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); + params.chan = chandef.chan; + err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); + if (err) +@@ -8507,6 +8566,8 @@ static int nl80211_set_wowlan(struct sk_ - /* - * 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; + nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], + rem) { ++ u8 *mask_pat; + -+ sc->rx.discard_next = false; - - /* - * Discard zero-length packets. - */ - if (!rx_stats->rs_datalen) { - RX_STAT_INC(rx_len_err); -- return -EINVAL; -+ goto corrupt; - } + nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), + nla_len(pat), NULL); + err = -EINVAL; +@@ -8530,19 +8591,18 @@ static int nl80211_set_wowlan(struct sk_ + goto error; + new_triggers.patterns[i].pkt_offset = pkt_offset; + +- new_triggers.patterns[i].mask = +- kmalloc(mask_len + pat_len, GFP_KERNEL); +- if (!new_triggers.patterns[i].mask) { ++ mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); ++ if (!mask_pat) { + err = -ENOMEM; + goto error; + } +- new_triggers.patterns[i].pattern = +- new_triggers.patterns[i].mask + mask_len; +- memcpy(new_triggers.patterns[i].mask, +- nla_data(pat_tb[NL80211_PKTPAT_MASK]), ++ new_triggers.patterns[i].mask = mask_pat; ++ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), + mask_len); ++ mask_pat += mask_len; ++ new_triggers.patterns[i].pattern = mask_pat; + new_triggers.patterns[i].pattern_len = pat_len; +- memcpy(new_triggers.patterns[i].pattern, ++ memcpy(mask_pat, + nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), + pat_len); + i++; +@@ -8735,6 +8795,8 @@ static int nl80211_parse_coalesce_rule(s -- /* -- * 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. -+ */ - if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { - RX_STAT_INC(rx_len_err); -- return -EINVAL; -+ goto corrupt; + nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], + rem) { ++ u8 *mask_pat; ++ + nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), + nla_len(pat), NULL); + if (!pat_tb[NL80211_PKTPAT_MASK] || +@@ -8756,17 +8818,19 @@ static int nl80211_parse_coalesce_rule(s + return -EINVAL; + new_rule->patterns[i].pkt_offset = pkt_offset; + +- new_rule->patterns[i].mask = +- kmalloc(mask_len + pat_len, GFP_KERNEL); +- if (!new_rule->patterns[i].mask) ++ mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); ++ if (!mask_pat) + return -ENOMEM; +- new_rule->patterns[i].pattern = +- new_rule->patterns[i].mask + mask_len; +- memcpy(new_rule->patterns[i].mask, +- nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len); ++ ++ new_rule->patterns[i].mask = mask_pat; ++ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), ++ mask_len); ++ ++ mask_pat += mask_len; ++ new_rule->patterns[i].pattern = mask_pat; + new_rule->patterns[i].pattern_len = pat_len; +- memcpy(new_rule->patterns[i].pattern, +- nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len); ++ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), ++ pat_len); + i++; } - /* 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); - -- ret = -EINVAL; -- goto exit; -+ return -EINVAL; - } +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -149,7 +149,8 @@ static int cfg80211_conn_do_work(struct + case CFG80211_CONN_SCAN_AGAIN: + return cfg80211_conn_scan(wdev); + case CFG80211_CONN_AUTHENTICATE_NEXT: +- BUG_ON(!rdev->ops->auth); ++ if (WARN_ON(!rdev->ops->auth)) ++ return -EOPNOTSUPP; + wdev->conn->state = CFG80211_CONN_AUTHENTICATING; + return cfg80211_mlme_auth(rdev, wdev->netdev, + params->channel, params->auth_type, +@@ -161,7 +162,8 @@ static int cfg80211_conn_do_work(struct + case CFG80211_CONN_AUTH_FAILED: + return -ENOTCONN; + case CFG80211_CONN_ASSOCIATE_NEXT: +- BUG_ON(!rdev->ops->assoc); ++ if (WARN_ON(!rdev->ops->assoc)) ++ return -EOPNOTSUPP; + wdev->conn->state = CFG80211_CONN_ASSOCIATING; + if (wdev->conn->prev_bssid_valid) + req.prev_bssid = wdev->conn->prev_bssid; +@@ -877,7 +879,7 @@ void __cfg80211_disconnected(struct net_ + } - /* - * 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; + void cfg80211_disconnected(struct net_device *dev, u16 reason, +- u8 *ie, size_t ie_len, gfp_t gfp) ++ const u8 *ie, size_t ie_len, gfp_t gfp) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch, + WIPHY_ENTRY + NETDEV_ENTRY + CHAN_DEF_ENTRY +- __field(u16, counter_offset_beacon) +- __field(u16, counter_offset_presp) + __field(bool, radar_required) + __field(bool, block_tx) + __field(u8, count) ++ __dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon) ++ __dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp) + ), + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; + CHAN_DEF_ASSIGN(¶ms->chandef); +- __entry->counter_offset_beacon = params->counter_offset_beacon; +- __entry->counter_offset_presp = params->counter_offset_presp; + __entry->radar_required = params->radar_required; + __entry->block_tx = params->block_tx; + __entry->count = params->count; ++ memcpy(__get_dynamic_array(bcn_ofs), ++ params->counter_offsets_beacon, ++ params->n_counter_offsets_beacon * sizeof(u16)); ++ ++ /* probe response offsets are optional */ ++ if (params->n_counter_offsets_presp) ++ memcpy(__get_dynamic_array(pres_ofs), ++ params->counter_offsets_presp, ++ params->n_counter_offsets_presp * sizeof(u16)); + ), + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT +- ", block_tx: %d, count: %u, radar_required: %d" +- ", counter offsets (beacon/presp): %u/%u", ++ ", block_tx: %d, count: %u, radar_required: %d", + WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, +- __entry->block_tx, __entry->count, __entry->radar_required, +- __entry->counter_offset_beacon, +- __entry->counter_offset_presp) ++ __entry->block_tx, __entry->count, __entry->radar_required) + ); - 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; + TRACE_EVENT(rdev_set_qos_map, +@@ -2636,6 +2640,21 @@ TRACE_EVENT(cfg80211_ft_event, + WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) + ); -- 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; ++TRACE_EVENT(cfg80211_stop_iface, ++ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), ++ TP_ARGS(wiphy, wdev), ++ TP_STRUCT__entry( ++ WIPHY_ENTRY ++ WDEV_ENTRY ++ ), ++ TP_fast_assign( ++ WIPHY_ASSIGN; ++ WDEV_ASSIGN; ++ ), ++ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, ++ WIPHY_PR_ARG, WDEV_PR_ARG) ++); ++ + #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ - ath9k_process_rssi(common, hw, rx_stats, rx_status); + #undef TRACE_INCLUDE_PATH +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buf + EXPORT_SYMBOL(ieee80211_data_to_8023); -@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc - sc->rx.num_pkts++; - #endif + int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, +- enum nl80211_iftype iftype, u8 *bssid, bool qos) ++ enum nl80211_iftype iftype, ++ const u8 *bssid, bool qos) + { + struct ieee80211_hdr hdr; + u16 hdrlen, ethertype; +@@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct + __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, + ev->ij.channel); + break; ++ case EVENT_STOPPED: ++ __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); ++ break; + } + wdev_unlock(wdev); --exit: -- sc->rx.discard_next = false; -- return ret; -+ return 0; +@@ -1271,10 +1275,20 @@ int cfg80211_iter_combinations(struct wi + void *data), + void *data) + { ++ const struct ieee80211_regdomain *regdom; ++ enum nl80211_dfs_regions region = 0; + int i, j, iftype; + int num_interfaces = 0; + u32 used_iftypes = 0; + ++ if (radar_detect) { ++ rcu_read_lock(); ++ regdom = rcu_dereference(cfg80211_regdomain); ++ if (regdom) ++ region = regdom->dfs_region; ++ rcu_read_unlock(); ++ } + -+corrupt: -+ sc->rx.discard_next = rx_stats->rs_more; -+ return -EINVAL; + for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { + num_interfaces += iftype_num[iftype]; + if (iftype_num[iftype] > 0 && +@@ -1315,6 +1329,10 @@ int cfg80211_iter_combinations(struct wi + if (radar_detect != (c->radar_detect_widths & radar_detect)) + goto cont; + ++ if (radar_detect && c->radar_detect_regions && ++ !(c->radar_detect_regions & BIT(region))) ++ goto cont; ++ + /* Finally check that all iftypes that we're currently + * using are actually part of this combination. If they + * aren't then we can't use this combination and have +--- 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; } - 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; +-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) + { + if (sc->rx.buf_hold) +- ath_rx_buf_link(sc, sc->rx.buf_hold); ++ ath_rx_buf_link(sc, sc->rx.buf_hold, flush); - 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; -+ } + 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); + } - 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++; + /* 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); + } + + if (!budget--) diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch index 389a003..a12e7e5 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 * +@@ -2197,7 +2197,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..ef60f9e 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 +@@ -2079,6 +2079,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( +@@ -2275,6 +2277,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/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..b79a3c4 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 +@@ -2378,7 +2378,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..3564323 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 +@@ -1404,6 +1408,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..6ad04ac 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 { +@@ -2188,6 +2188,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 { +@@ -2422,6 +2423,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 +@@ -2388,6 +2388,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 +@@ -3820,6 +3833,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 { +@@ -1233,6 +1233,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..aaefa2f 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 +@@ -1404,7 +1404,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..4cf0700 100644 --- a/package/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/mac80211/patches/530-ath9k_extra_leds.patch @@ -10,7 +10,7 @@ #else static inline void ath_init_leds(struct ath_softc *sc) { -@@ -710,6 +713,13 @@ enum sc_op_flags { +@@ -701,6 +704,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]; +@@ -743,9 +753,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..764e5e2 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) +@@ -605,6 +605,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 -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 ---- - 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 -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 ---- - 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/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 +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 +--- +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..98c9203 --- /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 +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 +--- +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 +@@ -7711,6 +7711,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; + +@@ -7718,6 +7719,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..97e213f --- /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 +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 +--- +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(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, 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, ®); ++ 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); +@@ -1001,8 +1011,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); + + /* + * Restore beaconing state. +@@ -1026,6 +1038,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 +@@ -1033,6 +1047,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) +@@ -1216,7 +1232,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, +@@ -1229,11 +1247,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, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); + rt2x00_set_field32(®, 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, +@@ -1246,6 +1266,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, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, +@@ -1270,6 +1291,7 @@ static void rt2800_config_wcid_attr_ciph + rt2x00_set_field32(®, 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); + +@@ -1279,8 +1301,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, +@@ -1303,8 +1328,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); + } + + /* +@@ -1319,10 +1347,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, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2800_register_write(rt2x00dev, offset, reg); ++ rt2800_shared_mem_unlock(rt2x00dev); + + /* + * Update WCID information +@@ -1392,8 +1422,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); + } + + /* +@@ -4875,14 +4908,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); + } + + /* +@@ -5008,8 +5046,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++) { +@@ -6705,11 +6745,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); + + /* +@@ -7715,6 +7763,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; +@@ -7794,8 +7844,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(®, 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, ®); ++ 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(®, 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, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); ++ rt2800_shared_mem_unlock(rt2x00dev); + + reg = 0; + rt2x00_set_field32(®, 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..5cb6eae --- /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 +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 +--- +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, ®); ++ rt2x00_set_field32(®, 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); + } + +@@ -1012,8 +1048,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); + + /* +@@ -1040,6 +1080,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 +@@ -1048,6 +1090,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..d832f99 --- /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 +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 +--- + 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 +@@ -4583,6 +4583,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; +@@ -4970,7 +4971,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)) { +@@ -7816,6 +7817,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..040c69c --- /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 +Date: Mon, 2 Sep 2013 10:58:32 +0200 +Subject: [PATCH] rt2x00: rt2800lib: init additional beacon offset registers + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -4617,6 +4617,30 @@ static int rt2800_init_registers(struct + rt2800_get_beacon_offset(rt2x00dev, 7)); + rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg); + ++ if (drv_data->hw_beacon_count == 16) { ++ rt2800_register_read(rt2x00dev, BCN_OFFSET2, ®); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN8, ++ rt2800_get_beacon_offset(rt2x00dev, 8)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN9, ++ rt2800_get_beacon_offset(rt2x00dev, 9)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN10, ++ rt2800_get_beacon_offset(rt2x00dev, 10)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN11, ++ rt2800_get_beacon_offset(rt2x00dev, 11)); ++ rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg); ++ ++ rt2800_register_read(rt2x00dev, BCN_OFFSET3, ®); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN12, ++ rt2800_get_beacon_offset(rt2x00dev, 12)); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN13, ++ rt2800_get_beacon_offset(rt2x00dev, 13)); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN14, ++ rt2800_get_beacon_offset(rt2x00dev, 14)); ++ rt2x00_set_field32(®, 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..752cd89 --- /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 +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 +--- + 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 +@@ -7841,7 +7841,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 +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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..8cb93ec --- /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 +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -7811,6 +7811,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..e85ae97 --- /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 +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -7431,6 +7431,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}, +@@ -7659,6 +7719,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, ®); + 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..898e385 --- /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 +Date: Thu, 1 Aug 2013 14:40:44 +0200 +Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -4348,6 +4348,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3053: + case RF3070: + case RF3290: ++ case RF3853: + case RF5360: + case RF5370: + case RF5372: +@@ -7838,6 +7839,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..1de99ea --- /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 +Date: Sun, 24 Mar 2013 19:26:27 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for + RF3853 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -2604,6 +2604,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 + +@@ -3216,6 +3421,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..e7e17a9 --- /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 +Date: Thu, 1 Aug 2013 14:42:05 +0200 +Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -7397,6 +7397,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..95423d1 --- /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 +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for + RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -4972,6 +4972,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)) { +@@ -5002,9 +5008,11 @@ static int rt2800_init_registers(struct + + rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, 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(®, 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(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); +@@ -5157,6 +5165,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, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, 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 +Date: Sun, 24 Mar 2013 19:26:27 +0100 +Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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(®, 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..d9694da --- /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 +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for + RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -5775,6 +5775,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; +@@ -5993,6 +6034,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..dc45109 --- /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 +Date: Mon, 29 Apr 2013 13:21:48 +0200 +Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -6810,6 +6810,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); +@@ -7041,6 +7179,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 +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 +--- + 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..4bfe8e1 --- /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 +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 +--- + 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 +@@ -7578,6 +7578,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..59b74ad --- /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 +Date: Sun, 24 Mar 2013 19:26:28 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -3384,6 +3384,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, +@@ -3402,6 +3432,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: +@@ -3483,6 +3519,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); +@@ -3495,6 +3540,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)) +@@ -3503,19 +3549,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)) +@@ -3640,6 +3689,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..e88a7c6 --- /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 +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 +--- + 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 +@@ -3371,13 +3371,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..95484a0 --- /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 +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 +--- + 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 +@@ -4581,7 +4581,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..c57af60 --- /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 +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 +--- + 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 +@@ -7460,7 +7460,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); +@@ -7474,7 +7475,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 +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 +--- + 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 +Date: Sun, 24 Mar 2013 19:26:29 +0100 +Subject: [PATCH] rt2x00: rt2800lib: use correct beacon base for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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..f606ed4 --- /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 +Date: Sun, 18 Aug 2013 09:57:58 +0200 +Subject: [PATCH] rt2x00: rt2800lib: use correct beacon count for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -8392,7 +8392,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..4096493 --- /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 +Date: Mon, 30 Sep 2013 16:53:33 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -1916,7 +1916,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..2fc9d9d --- /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 +Date: Mon, 30 Sep 2013 16:58:23 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -1939,7 +1939,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); +@@ -1949,7 +1950,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..060d4c6 --- /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 +Date: Tue, 1 Oct 2013 15:40:08 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -4780,7 +4780,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); +@@ -4800,7 +4801,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)) { +@@ -4847,6 +4849,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..3e9a7d9 --- /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 +Date: Tue, 1 Oct 2013 17:27:57 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -7597,7 +7597,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, +@@ -7617,7 +7618,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, +@@ -7625,7 +7627,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..b87f36a --- /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 +Date: Wed, 2 Oct 2013 10:11:59 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883 + +Signed-off-by: Gabor Juhos +--- + 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 +@@ -3958,6 +3958,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..18d65e0 --- /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 +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 +--- + 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 +@@ -8405,7 +8405,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 +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 +--- + 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 +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 +--- + 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, ®); ++ ++ 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(®, ++ 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..c7d71e2 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= +@@ -280,6 +280,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, 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..1db09a3 100644 --- a/package/mac80211/patches/608-add_platform_data_mac_addr.patch +++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch @@ -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..725f81f 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 +@@ -3505,11 +3505,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 +@@ -6585,6 +6592,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 +@@ -6620,15 +6633,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 +@@ -6636,15 +6664,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 +@@ -7665,6 +7698,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 +@@ -7759,7 +7793,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 +@@ -7788,6 +7823,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..6b29aa8 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 +@@ -8175,6 +8175,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 +@@ -8262,7 +8283,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 +@@ -8445,6 +8469,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; +@@ -8487,6 +8524,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 --- 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..fd897e9 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 +@@ -2993,6 +2993,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); +@@ -3471,6 +3478,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 +@@ -3488,6 +3496,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 +@@ -3765,7 +3774,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: +@@ -4644,6 +4654,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 +@@ -5078,6 +5089,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 +@@ -5733,9 +5746,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 +@@ -5749,9 +5766,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 +@@ -5776,6 +5797,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 +@@ -6117,6 +6145,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 */ +@@ -7068,6 +7097,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 +@@ -7308,6 +7407,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 +@@ -7567,6 +7669,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)) +@@ -7705,6 +7813,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: +@@ -7724,6 +7834,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 +@@ -8278,6 +8389,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: +@@ -8416,6 +8528,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: +@@ -8455,6 +8568,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..ee473dc 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 #include #include @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -7298,6 +7299,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -7923,6 +7924,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-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch index 5e67344..86a990c 100644 --- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch @@ -1,15 +1,11 @@ --- 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 - * RT53xx: defined in "EEPROM_CHIP_ID" field - */ - if (rt2x00_rt(rt2x00dev, RT3290) || -- rt2x00_rt(rt2x00dev, RT3352) || +@@ -7812,6 +7812,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, 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..e4d2f44 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 +@@ -2739,10 +2744,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..bc9fda2 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 +@@ -1899,10 +1899,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..b55c669 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 +@@ -1546,7 +1546,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 +@@ -3103,8 +3103,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 +@@ -3796,7 +3796,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 +@@ -3850,11 +3849,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 +@@ -4978,6 +4975,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 +@@ -4999,6 +5037,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 +@@ -5239,6 +5279,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( +@@ -5329,6 +5371,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..86b61fc 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 --- 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,9 +53,9 @@ Signed-off-by: Hauke Mehrtens __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,16 @@ static inline bool b43_bus_host_is_sdio( + return false; + #endif } +static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev) +{ @@ -72,7 +72,7 @@ Signed-off-by: Hauke Mehrtens 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 +@@ -4370,7 +4370,7 @@ static int b43_phy_versioning(struct b43 u16 radio24[3]; for (tmp = 0; tmp < 3; tmp++) { @@ -81,7 +81,7 @@ Signed-off-by: Hauke Mehrtens radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); } -@@ -4456,10 +4456,10 @@ static int b43_phy_versioning(struct b43 +@@ -4389,10 +4389,10 @@ static int b43_phy_versioning(struct b43 else tmp = 0x5205017F; } else { @@ -96,7 +96,7 @@ Signed-off-by: Hauke Mehrtens << 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 +197,7 @@ Signed-off-by: Hauke Mehrtens --- 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 +214,7 @@ Signed-off-by: Hauke Mehrtens 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 +223,16 @@ Signed-off-by: Hauke Mehrtens 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..8555ccf 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 +@@ -2756,6 +2756,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 -Signed-off-by: Luciano Coelho -Acked-by: Tony Lindgren -Reviewed-by: Felipe Balbi - ---- a/drivers/net/wireless/ti/wilink_platform_data.c -+++ b/drivers/net/wireless/ti/wilink_platform_data.c -@@ -23,17 +23,17 @@ - #include - #include - --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 +Signed-off-by: Arik Nemtsov +--- + 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 + #include + #include ++#include + + #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 +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 +--- + 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 -Cc: Sekhar Nori -Signed-off-by: Luciano Coelho -Reviewed-by: Felipe Balbi -Acked-by: Sekhar Nori - ---- 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 - #include - #include -+#include - - #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 -Reviewed-by: Felipe Balbi - ---- 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 -Cc: Sekhar Nori -Signed-off-by: Luciano Coelho -Reviewed-by: Felipe Balbi - ---- 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 -Reviewed-by: Felipe Balbi - ---- a/drivers/net/wireless/ti/wlcore/sdio.c -+++ b/drivers/net/wireless/ti/wlcore/sdio.c -@@ -30,7 +30,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -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 -Reviewed-by: Felipe Balbi - ---- a/drivers/net/wireless/ti/wlcore/sdio.c -+++ b/drivers/net/wireless/ti/wlcore/sdio.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #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 -Reviewed-by: Felipe Balbi - ---- 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 -Reviewed-by: Felipe Balbi - ---- 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; };