rt2x00: move under ralink vendor directory
authorKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 08:18:44 +0000 (10:18 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 12:28:31 +0000 (14:28 +0200)
Part of reorganising wireless drivers directory and Kconfig.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
97 files changed:
MAINTAINERS
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/ralink/Kconfig [new file with mode: 0644]
drivers/net/wireless/ralink/Makefile [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/Kconfig [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/Makefile [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2400pci.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2400pci.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2500pci.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2500pci.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2500usb.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2500usb.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800lib.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800lib.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800mmio.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800mmio.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800pci.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800pci.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800soc.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800usb.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2800usb.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00config.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00crypto.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00debug.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00debug.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00dump.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00leds.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00leds.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00lib.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00link.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00mac.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00pci.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00pci.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00queue.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00queue.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00reg.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00soc.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00soc.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00usb.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt2x00usb.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt61pci.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt61pci.h [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt73usb.c [new file with mode: 0644]
drivers/net/wireless/ralink/rt2x00/rt73usb.h [new file with mode: 0644]
drivers/net/wireless/rt2x00/Kconfig [deleted file]
drivers/net/wireless/rt2x00/Makefile [deleted file]
drivers/net/wireless/rt2x00/rt2400pci.c [deleted file]
drivers/net/wireless/rt2x00/rt2400pci.h [deleted file]
drivers/net/wireless/rt2x00/rt2500pci.c [deleted file]
drivers/net/wireless/rt2x00/rt2500pci.h [deleted file]
drivers/net/wireless/rt2x00/rt2500usb.c [deleted file]
drivers/net/wireless/rt2x00/rt2500usb.h [deleted file]
drivers/net/wireless/rt2x00/rt2800.h [deleted file]
drivers/net/wireless/rt2x00/rt2800lib.c [deleted file]
drivers/net/wireless/rt2x00/rt2800lib.h [deleted file]
drivers/net/wireless/rt2x00/rt2800mmio.c [deleted file]
drivers/net/wireless/rt2x00/rt2800mmio.h [deleted file]
drivers/net/wireless/rt2x00/rt2800pci.c [deleted file]
drivers/net/wireless/rt2x00/rt2800pci.h [deleted file]
drivers/net/wireless/rt2x00/rt2800soc.c [deleted file]
drivers/net/wireless/rt2x00/rt2800usb.c [deleted file]
drivers/net/wireless/rt2x00/rt2800usb.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00config.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00crypto.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00debug.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00debug.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00dev.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00dump.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00firmware.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00leds.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00leds.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00lib.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00link.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00mac.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00mmio.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00mmio.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00pci.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00pci.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00queue.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00queue.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00reg.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00soc.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00soc.h [deleted file]
drivers/net/wireless/rt2x00/rt2x00usb.c [deleted file]
drivers/net/wireless/rt2x00/rt2x00usb.h [deleted file]
drivers/net/wireless/rt2x00/rt61pci.c [deleted file]
drivers/net/wireless/rt2x00/rt61pci.h [deleted file]
drivers/net/wireless/rt2x00/rt73usb.c [deleted file]
drivers/net/wireless/rt2x00/rt73usb.h [deleted file]

index a9f7f96..38c049d 100644 (file)
@@ -8801,7 +8801,7 @@ M:        Stanislaw Gruszka <sgruszka@redhat.com>
 M:     Helmut Schaa <helmut.schaa@googlemail.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
-F:     drivers/net/wireless/rt2x00/
+F:     drivers/net/wireless/ralink/rt2x00/
 
 RAMDISK RAM BLOCK DEVICE DRIVER
 M:     Jens Axboe <axboe@kernel.dk>
index 5186084..c58e244 100644 (file)
@@ -24,6 +24,7 @@ source "drivers/net/wireless/cisco/Kconfig"
 source "drivers/net/wireless/intel/Kconfig"
 source "drivers/net/wireless/intersil/Kconfig"
 source "drivers/net/wireless/marvell/Kconfig"
+source "drivers/net/wireless/ralink/Kconfig"
 source "drivers/net/wireless/realtek/Kconfig"
 source "drivers/net/wireless/rsi/Kconfig"
 source "drivers/net/wireless/st/Kconfig"
@@ -97,7 +98,6 @@ config MAC80211_HWSIM
          called mac80211_hwsim.  If unsure, say N.
 
 source "drivers/net/wireless/ath/Kconfig"
-source "drivers/net/wireless/rt2x00/Kconfig"
 source "drivers/net/wireless/mediatek/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
 
index d38b6cc..8ac72fd 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_WLAN_VENDOR_CISCO) += cisco/
 obj-$(CONFIG_WLAN_VENDOR_INTEL) += intel/
 obj-$(CONFIG_WLAN_VENDOR_INTERSIL) += intersil/
 obj-$(CONFIG_WLAN_VENDOR_MARVELL) += marvell/
+obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
 obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
 obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
 obj-$(CONFIG_WLAN_VENDOR_ST) += st/
@@ -20,8 +21,6 @@ obj-$(CONFIG_PCMCIA_WL3501)   += wl3501_cs.o
 
 obj-$(CONFIG_USB_NET_RNDIS_WLAN)       += rndis_wlan.o
 
-obj-$(CONFIG_RT2X00)   += rt2x00/
-
 obj-$(CONFIG_WL_MEDIATEK)      += mediatek/
 
 obj-$(CONFIG_ATH_CARDS)                += ath/
diff --git a/drivers/net/wireless/ralink/Kconfig b/drivers/net/wireless/ralink/Kconfig
new file mode 100644 (file)
index 0000000..41dbf31
--- /dev/null
@@ -0,0 +1,16 @@
+config WLAN_VENDOR_RALINK
+       bool "Ralink devices"
+       default y
+       ---help---
+         If you have a wireless card belonging to this class, say Y.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about  cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if WLAN_VENDOR_RALINK
+
+source "drivers/net/wireless/ralink/rt2x00/Kconfig"
+
+endif # WLAN_VENDOR_RALINK
diff --git a/drivers/net/wireless/ralink/Makefile b/drivers/net/wireless/ralink/Makefile
new file mode 100644 (file)
index 0000000..f84c0a2
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_RT2X00)   += rt2x00/
diff --git a/drivers/net/wireless/ralink/rt2x00/Kconfig b/drivers/net/wireless/ralink/rt2x00/Kconfig
new file mode 100644 (file)
index 0000000..de62f5d
--- /dev/null
@@ -0,0 +1,269 @@
+menuconfig RT2X00
+       tristate "Ralink driver support"
+       depends on MAC80211 && HAS_DMA
+       ---help---
+         This will enable the support for the Ralink drivers,
+         developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
+
+         These drivers make use of the mac80211 stack.
+
+         When building one of the individual drivers, the rt2x00 library
+         will also be created. That library (when the driver is built as
+         a module) will be called rt2x00lib.
+
+         Additionally PCI and USB libraries will also be build depending
+         on the types of drivers being selected, these libraries will be
+         called rt2x00pci and rt2x00usb.
+
+if RT2X00
+
+config RT2400PCI
+       tristate "Ralink rt2400 (PCI/PCMCIA) support"
+       depends on PCI
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_PCI
+       select EEPROM_93CX6
+       ---help---
+         This adds support for rt2400 wireless chipset family.
+         Supported chips: RT2460.
+
+         When compiled as a module, this driver will be called rt2400pci.
+
+config RT2500PCI
+       tristate "Ralink rt2500 (PCI/PCMCIA) support"
+       depends on PCI
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_PCI
+       select EEPROM_93CX6
+       ---help---
+         This adds support for rt2500 wireless chipset family.
+         Supported chips: RT2560.
+
+         When compiled as a module, this driver will be called rt2500pci.
+
+config RT61PCI
+       tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
+       depends on PCI
+       select RT2X00_LIB_PCI
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_FIRMWARE
+       select RT2X00_LIB_CRYPTO
+       select CRC_ITU_T
+       select EEPROM_93CX6
+       ---help---
+         This adds support for rt2501 wireless chipset family.
+         Supported chips: RT2561, RT2561S & RT2661.
+
+         When compiled as a module, this driver will be called rt61pci.
+
+config RT2800PCI
+       tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
+       depends on PCI
+       select RT2800_LIB
+       select RT2800_LIB_MMIO
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_PCI
+       select RT2X00_LIB_FIRMWARE
+       select RT2X00_LIB_CRYPTO
+       select CRC_CCITT
+       select EEPROM_93CX6
+       ---help---
+         This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
+         Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052,
+                          RT3090, RT3091 & RT3092
+
+         When compiled as a module, this driver will be called "rt2800pci.ko".
+
+if RT2800PCI
+
+config RT2800PCI_RT33XX
+       bool "rt2800pci - Include support for rt33xx devices"
+       default y
+       ---help---
+         This adds support for rt33xx wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT3390
+
+config RT2800PCI_RT35XX
+       bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
+       default y
+       ---help---
+         This adds support for rt35xx wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT3060, RT3062, RT3562, RT3592
+
+
+config RT2800PCI_RT53XX
+       bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
+       default y
+       ---help---
+         This adds support for rt53xx wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT5390
+
+config RT2800PCI_RT3290
+       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
+       default y
+       ---help---
+         This adds support for rt3290 wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT3290
+endif
+
+config RT2500USB
+       tristate "Ralink rt2500 (USB) support"
+       depends on USB
+       select RT2X00_LIB_USB
+       select RT2X00_LIB_CRYPTO
+       ---help---
+         This adds support for rt2500 wireless chipset family.
+         Supported chips: RT2571 & RT2572.
+
+         When compiled as a module, this driver will be called rt2500usb.
+
+config RT73USB
+       tristate "Ralink rt2501/rt73 (USB) support"
+       depends on USB
+       select RT2X00_LIB_USB
+       select RT2X00_LIB_FIRMWARE
+       select RT2X00_LIB_CRYPTO
+       select CRC_ITU_T
+       ---help---
+         This adds support for rt2501 wireless chipset family.
+         Supported chips: RT2571W, RT2573 & RT2671.
+
+         When compiled as a module, this driver will be called rt73usb.
+
+config RT2800USB
+       tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support"
+       depends on USB
+       select RT2800_LIB
+       select RT2X00_LIB_USB
+       select RT2X00_LIB_FIRMWARE
+       select RT2X00_LIB_CRYPTO
+       select CRC_CCITT
+       ---help---
+         This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
+         Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072
+
+         When compiled as a module, this driver will be called "rt2800usb.ko".
+
+if RT2800USB
+
+config RT2800USB_RT33XX
+       bool "rt2800usb - Include support for rt33xx devices"
+       default y
+       ---help---
+         This adds support for rt33xx wireless chipset family to the
+         rt2800usb driver.
+         Supported chips: RT3370
+
+config RT2800USB_RT35XX
+       bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
+       default y
+       ---help---
+         This adds support for rt35xx wireless chipset family to the
+         rt2800usb driver.
+         Supported chips: RT3572
+
+config RT2800USB_RT3573
+       bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
+       ---help---
+         This enables support for RT3573 chipset based wireless USB devices
+         in the rt2800usb driver.
+
+config RT2800USB_RT53XX
+       bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
+       ---help---
+         This adds support for rt53xx wireless chipset family to the
+         rt2800usb driver.
+         Supported chips: RT5370
+
+config RT2800USB_RT55XX
+       bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)"
+       ---help---
+         This adds support for rt55xx wireless chipset family to the
+         rt2800usb driver.
+         Supported chips: RT5572
+
+config RT2800USB_UNKNOWN
+       bool "rt2800usb - Include support for unknown (USB) devices"
+       default n
+       ---help---
+         This adds support for rt2800usb devices that are known to
+         have a rt28xx family compatible chipset, but for which the exact
+         chipset is unknown.
+
+         Support status for these devices is unknown, and enabling these
+         devices may or may not work.
+
+endif
+
+config RT2800SOC
+       tristate "Ralink WiSoC support"
+       depends on SOC_RT288X || SOC_RT305X
+       select RT2X00_LIB_SOC
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_CRYPTO
+       select RT2X00_LIB_FIRMWARE
+       select RT2800_LIB
+       select RT2800_LIB_MMIO
+       ---help---
+         This adds support for Ralink WiSoC devices.
+         Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+
+         When compiled as a module, this driver will be called rt2800soc.
+
+
+config RT2800_LIB
+       tristate
+
+config RT2800_LIB_MMIO
+       tristate
+       select RT2X00_LIB_MMIO
+       select RT2800_LIB
+
+config RT2X00_LIB_MMIO
+       tristate
+
+config RT2X00_LIB_PCI
+       tristate
+       select RT2X00_LIB
+
+config RT2X00_LIB_SOC
+       tristate
+       select RT2X00_LIB
+
+config RT2X00_LIB_USB
+       tristate
+       select RT2X00_LIB
+
+config RT2X00_LIB
+       tristate
+
+config RT2X00_LIB_FIRMWARE
+       bool
+       select FW_LOADER
+
+config RT2X00_LIB_CRYPTO
+       bool
+
+config RT2X00_LIB_LEDS
+       bool
+       default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+
+config RT2X00_LIB_DEBUGFS
+       bool "Ralink debugfs support"
+       depends on RT2X00_LIB && MAC80211_DEBUGFS
+       ---help---
+         Enable creation of debugfs files for the rt2x00 drivers.
+         These debugfs files support both reading and writing of the
+         most important register types of the rt2x00 hardware.
+
+config RT2X00_DEBUG
+       bool "Ralink debug output"
+       depends on RT2X00_LIB
+       ---help---
+         Enable debugging output for all rt2x00 modules
+
+endif
diff --git a/drivers/net/wireless/ralink/rt2x00/Makefile b/drivers/net/wireless/ralink/rt2x00/Makefile
new file mode 100644 (file)
index 0000000..24a6601
--- /dev/null
@@ -0,0 +1,25 @@
+rt2x00lib-y                            += rt2x00dev.o
+rt2x00lib-y                            += rt2x00mac.o
+rt2x00lib-y                            += rt2x00config.o
+rt2x00lib-y                            += rt2x00queue.o
+rt2x00lib-y                            += rt2x00link.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)  += rt2x00crypto.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)        += rt2x00firmware.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)    += rt2x00leds.o
+
+obj-$(CONFIG_RT2X00_LIB)               += rt2x00lib.o
+obj-$(CONFIG_RT2X00_LIB_MMIO)          += rt2x00mmio.o
+obj-$(CONFIG_RT2X00_LIB_PCI)           += rt2x00pci.o
+obj-$(CONFIG_RT2X00_LIB_SOC)           += rt2x00soc.o
+obj-$(CONFIG_RT2X00_LIB_USB)           += rt2x00usb.o
+obj-$(CONFIG_RT2800_LIB)               += rt2800lib.o
+obj-$(CONFIG_RT2800_LIB_MMIO)          += rt2800mmio.o
+obj-$(CONFIG_RT2400PCI)                        += rt2400pci.o
+obj-$(CONFIG_RT2500PCI)                        += rt2500pci.o
+obj-$(CONFIG_RT61PCI)                  += rt61pci.o
+obj-$(CONFIG_RT2800PCI)                        += rt2800pci.o
+obj-$(CONFIG_RT2500USB)                        += rt2500usb.o
+obj-$(CONFIG_RT73USB)                  += rt73usb.o
+obj-$(CONFIG_RT2800USB)                        += rt2800usb.o
+obj-$(CONFIG_RT2800SOC)                        += rt2800soc.o
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
new file mode 100644 (file)
index 0000000..9a3966c
--- /dev/null
@@ -0,0 +1,1850 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2400pci
+       Abstract: rt2400pci device specific routines.
+       Supported chipsets: RT2460.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/eeprom_93cx6.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00pci.h"
+#include "rt2400pci.h"
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attempt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+
+static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
+                               const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
+               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
+
+               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
+
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, const u32 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, RFCSR_VALUE, value);
+               rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
+               rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
+               rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+
+       eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
+       eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
+       eeprom->reg_data_clock =
+           !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
+       eeprom->reg_chip_select =
+           !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
+}
+
+static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg = 0;
+
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_CLOCK,
+                          !!eeprom->reg_data_clock);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
+                          !!eeprom->reg_chip_select);
+
+       rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static const struct rt2x00debug rt2400pci_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = rt2x00mmio_register_read,
+               .write          = rt2x00mmio_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = CSR_REG_SIZE / sizeof(u32),
+       },
+       .eeprom = {
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt2400pci_bbp_read,
+               .write          = rt2400pci_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt2400pci_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       return rt2x00_get_field32(reg, GPIOCSR_VAL0);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
+                                    enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       u32 reg;
+
+       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+
+       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
+               rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
+       else if (led->type == LED_TYPE_ACTIVITY)
+               rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
+
+       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
+}
+
+static int rt2400pci_blink_set(struct led_classdev *led_cdev,
+                              unsigned long *delay_on,
+                              unsigned long *delay_off)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       u32 reg;
+
+       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
+       rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
+       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
+
+       return 0;
+}
+
+static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00_led *led,
+                              enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt2400pci_brightness_set;
+       led->led_dev.blink_set = rt2400pci_blink_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int filter_flags)
+{
+       u32 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * since there is no filter for it at this time.
+        */
+       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+                          !rt2x00dev->intf_ap_count);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+}
+
+static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
+                                 struct rt2x00_intf *intf,
+                                 struct rt2x00intf_conf *conf,
+                                 const unsigned int flags)
+{
+       unsigned int bcn_preload;
+       u32 reg;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable beacon config
+                */
+               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
+               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+               rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
+               rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
+
+               /*
+                * Enable synchronisation.
+                */
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+       }
+
+       if (flags & CONFIG_UPDATE_MAC)
+               rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
+                                              conf->mac, sizeof(conf->mac));
+
+       if (flags & CONFIG_UPDATE_BSSID)
+               rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
+                                              conf->bssid,
+                                              sizeof(conf->bssid));
+}
+
+static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
+                                struct rt2x00lib_erp *erp,
+                                u32 changed)
+{
+       int preamble_mask;
+       u32 reg;
+
+       /*
+        * When short preamble is enabled, we should set bit 0x08
+        */
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               preamble_mask = erp->short_preamble << 3;
+
+               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+               rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
+               rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
+               rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+               rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+               rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+               rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 10));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+               rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 20));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+               rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 55));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+               rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 110));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+               rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+               rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+               rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+               rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+               rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+               rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+               rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+               rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
+       }
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+               rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+                                  erp->beacon_int * 16);
+               rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
+       }
+}
+
+static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
+                                struct antenna_setup *ant)
+{
+       u8 r1;
+       u8 r4;
+
+       /*
+        * We should never come here because rt2x00lib is supposed
+        * to catch this and send us the correct antenna explicitely.
+        */
+       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+              ant->tx == ANTENNA_SW_DIVERSITY);
+
+       rt2400pci_bbp_read(rt2x00dev, 4, &r4);
+       rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+               break;
+       }
+
+       rt2400pci_bbp_write(rt2x00dev, 4, r4);
+       rt2400pci_bbp_write(rt2x00dev, 1, r1);
+}
+
+static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
+                                    struct rf_channel *rf)
+{
+       /*
+        * Switch on tuning bits.
+        */
+       rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
+       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
+
+       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
+
+       /*
+        * RF2420 chipset don't need any additional actions.
+        */
+       if (rt2x00_rf(rt2x00dev, RF2420))
+               return;
+
+       /*
+        * For the RT2421 chipsets we need to write an invalid
+        * reference clock rate to activate auto_tune.
+        * After that we set the value back to the correct channel.
+        */
+       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32);
+       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
+
+       msleep(1);
+
+       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
+
+       msleep(1);
+
+       /*
+        * Switch off tuning bits.
+        */
+       rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
+       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
+
+       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
+
+       /*
+        * Clear false CRC during channel switch.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+}
+
+static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
+{
+       rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
+}
+
+static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+                                        struct rt2x00lib_conf *libconf)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+                          libconf->conf->long_frame_max_tx_count);
+       rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+                          libconf->conf->short_frame_max_tx_count);
+       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+}
+
+static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
+                                  (rt2x00dev->beacon_int - 20) * 16);
+               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+       } else {
+               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
+static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_conf *libconf,
+                            const unsigned int flags)
+{
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt2400pci_config_channel(rt2x00dev, &libconf->rf);
+       if (flags & IEEE80211_CONF_CHANGE_POWER)
+               rt2400pci_config_txpower(rt2x00dev,
+                                        libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt2400pci_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2400pci_config_ps(rt2x00dev, libconf);
+}
+
+static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
+                               const int cw_min, const int cw_max)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
+       rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
+       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+}
+
+/*
+ * Link tuning
+ */
+static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual)
+{
+       u32 reg;
+       u8 bbp;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
+
+       /*
+        * Update False CCA count from register.
+        */
+       rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
+       qual->false_cca = bbp;
+}
+
+static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                    struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level_reg != vgc_level) {
+               rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
+{
+       rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
+}
+
+static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual, const u32 count)
+{
+       /*
+        * The link tuner should not run longer then 60 seconds,
+        * and should run once every 2 seconds.
+        */
+       if (count > 60 || !(count & 1))
+               return;
+
+       /*
+        * Base r13 link tuning on the false cca count.
+        */
+       if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
+               rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+       else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
+               rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt2400pci_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+               rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2400pci_kick_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_AC_VI:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_ATIM:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2400pci_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_ATIM:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+               rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+               /*
+                * Wait for possibly running tbtt tasklets.
+                */
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Initialization functions.
+ */
+static bool rt2400pci_get_entry_state(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                       rt2x00_get_field32(word, TXD_W0_VALID));
+       }
+}
+
+static void rt2400pci_clear_entry(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 2, &word);
+               rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
+               rt2x00_desc_write(entry_priv->desc, 2, word);
+
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+               rt2x00_desc_write(entry_priv->desc, 1, word);
+
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       }
+}
+
+static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct queue_entry_priv_mmio *entry_priv;
+       u32 reg;
+
+       /*
+        * Initialize registers.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+       rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
+
+       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+       rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
+
+       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+       rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
+
+       entry_priv = rt2x00dev->atim->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+       rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
+
+       entry_priv = rt2x00dev->bcn->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+       rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+       rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+       rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
+
+       entry_priv = rt2x00dev->rx->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+       rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
+
+       return 0;
+}
+
+static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
+
+       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+       rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
+       rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
+       rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
+       rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+       rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
+                          (rt2x00dev->rx->data_size / 128));
+       rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
+
+       rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
+       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
+       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
+       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
+       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
+       rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 36); /* Rssi */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               return -EBUSY;
+
+       rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
+       rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
+
+       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+       rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
+       rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
+       rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
+       rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
+       rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
+       rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
+       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
+
+       /*
+        * We must clear the FCS and FIFO error count.
+        * These registers are cleared on read,
+        * so we may pass a useless variable to store the value.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+
+       return 0;
+}
+
+static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2400pci_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
+
+       rt2400pci_bbp_write(rt2x00dev, 1, 0x00);
+       rt2400pci_bbp_write(rt2x00dev, 3, 0x27);
+       rt2400pci_bbp_write(rt2x00dev, 4, 0x08);
+       rt2400pci_bbp_write(rt2x00dev, 10, 0x0f);
+       rt2400pci_bbp_write(rt2x00dev, 15, 0x72);
+       rt2400pci_bbp_write(rt2x00dev, 16, 0x74);
+       rt2400pci_bbp_write(rt2x00dev, 17, 0x20);
+       rt2400pci_bbp_write(rt2x00dev, 18, 0x72);
+       rt2400pci_bbp_write(rt2x00dev, 19, 0x0b);
+       rt2400pci_bbp_write(rt2x00dev, 20, 0x00);
+       rt2400pci_bbp_write(rt2x00dev, 28, 0x11);
+       rt2400pci_bbp_write(rt2x00dev, 29, 0x04);
+       rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
+       rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt2400pci_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
+                                enum dev_state state)
+{
+       int mask = (state == STATE_RADIO_IRQ_OFF);
+       u32 reg;
+       unsigned long flags;
+
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+               rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
+       rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+       if (state == STATE_RADIO_IRQ_OFF) {
+               /*
+                * Ensure that all tasklets are finished before
+                * disabling the interrupts.
+                */
+               tasklet_kill(&rt2x00dev->txstatus_tasklet);
+               tasklet_kill(&rt2x00dev->rxdone_tasklet);
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+       }
+}
+
+static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Initialize all registers.
+        */
+       if (unlikely(rt2400pci_init_queues(rt2x00dev) ||
+                    rt2400pci_init_registers(rt2x00dev) ||
+                    rt2400pci_init_bbp(rt2x00dev)))
+               return -EIO;
+
+       return 0;
+}
+
+static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Disable power
+        */
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
+}
+
+static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       u32 reg, reg2;
+       unsigned int i;
+       char put_to_sleep;
+       char bbp_state;
+       char rf_state;
+
+       put_to_sleep = (state != STATE_AWAKE);
+
+       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+       rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
+       rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
+       rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
+       rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
+
+       /*
+        * Device is not guaranteed to be in the requested state yet.
+        * We must wait until the register indicates that the
+        * device has entered the correct state.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+               bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
+               rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
+               if (bbp_state == state && rf_state == state)
+                       return 0;
+               rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
+               msleep(10);
+       }
+
+       return -EBUSY;
+}
+
+static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt2400pci_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               rt2400pci_disable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt2400pci_toggle_irq(rt2x00dev, state);
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt2400pci_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt2400pci_write_tx_desc(struct queue_entry *entry,
+                                   struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       __le32 *txd = entry_priv->desc;
+       u32 word;
+
+       /*
+        * Start writing the descriptor words.
+        */
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+       rt2x00_desc_write(txd, 1, word);
+
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
+       rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
+       rt2x00_desc_write(txd, 2, word);
+
+       rt2x00_desc_read(txd, 3, &word);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
+       rt2x00_desc_write(txd, 3, word);
+
+       rt2x00_desc_read(txd, 4, &word);
+       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
+       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
+       rt2x00_desc_write(txd, 4, word);
+
+       /*
+        * Writing TXD word 0 must the last to prevent a race condition with
+        * the device, whereby the device may take hold of the TXD before we
+        * finished updating it.
+        */
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_RTS,
+                          test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
+       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
+       rt2x00_desc_write(txd, 0, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->desc = txd;
+       skbdesc->desc_len = TXD_DESC_SIZE;
+}
+
+/*
+ * TX data initialization
+ */
+static void rt2400pci_write_beacon(struct queue_entry *entry,
+                                  struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+       if (rt2x00queue_map_txskb(entry)) {
+               rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
+               goto out;
+       }
+       /*
+        * Enable beaconing again.
+        */
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt2400pci_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+out:
+       /*
+        * Enable beaconing again.
+        */
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+}
+
+/*
+ * RX control handlers
+ */
+static void rt2400pci_fill_rxdone(struct queue_entry *entry,
+                                 struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word0;
+       u32 word2;
+       u32 word3;
+       u32 word4;
+       u64 tsf;
+       u32 rx_low;
+       u32 rx_high;
+
+       rt2x00_desc_read(entry_priv->desc, 0, &word0);
+       rt2x00_desc_read(entry_priv->desc, 2, &word2);
+       rt2x00_desc_read(entry_priv->desc, 3, &word3);
+       rt2x00_desc_read(entry_priv->desc, 4, &word4);
+
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+
+       /*
+        * We only get the lower 32bits from the timestamp,
+        * to get the full 64bits we must complement it with
+        * the timestamp from get_tsf().
+        * Note that when a wraparound of the lower 32bits
+        * has occurred between the frame arrival and the get_tsf()
+        * call, we must decrease the higher 32bits with 1 to get
+        * to correct value.
+        */
+       tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
+       rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
+       rx_high = upper_32_bits(tsf);
+
+       if ((u32)tsf <= rx_low)
+               rx_high--;
+
+       /*
+        * Obtain the status about this packet.
+        * The signal is the PLCP value, and needs to be stripped
+        * of the preamble bit (0x08).
+        */
+       rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;
+       rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
+       rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) -
+           entry->queue->rt2x00dev->rssi_offset;
+       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+
+       rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+}
+
+/*
+ * Interrupt functions.
+ */
+static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
+                            const enum data_queue_qid queue_idx)
+{
+       struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+       struct queue_entry_priv_mmio *entry_priv;
+       struct queue_entry *entry;
+       struct txdone_entry_desc txdesc;
+       u32 word;
+
+       while (!rt2x00queue_empty(queue)) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               entry_priv = entry->priv_data;
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                   !rt2x00_get_field32(word, TXD_W0_VALID))
+                       break;
+
+               /*
+                * Obtain the status about this packet.
+                */
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
+               case 0: /* Success */
+               case 1: /* Success with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 2: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
+               txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+
+               rt2x00lib_txdone(entry, &txdesc);
+       }
+}
+
+static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                             struct rt2x00_field32 irq_field)
+{
+       u32 reg;
+
+       /*
+        * Enable a single interrupt. The interrupt mask register
+        * access needs locking.
+        */
+       spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, irq_field, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt2400pci_txstatus_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       u32 reg;
+
+       /*
+        * Handle all tx queues.
+        */
+       rt2400pci_txdone(rt2x00dev, QID_ATIM);
+       rt2400pci_txdone(rt2x00dev, QID_AC_VO);
+       rt2400pci_txdone(rt2x00dev, QID_AC_VI);
+
+       /*
+        * Enable all TXDONE interrupts again.
+        */
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+               spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+               spin_unlock_irq(&rt2x00dev->irqmask_lock);
+       }
+}
+
+static void rt2400pci_tbtt_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt2x00lib_beacondone(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2400pci_rxdone_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       if (rt2x00mmio_rxdone(rt2x00dev))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
+}
+
+static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
+{
+       struct rt2x00_dev *rt2x00dev = dev_instance;
+       u32 reg, mask;
+
+       /*
+        * Get the interrupt sources & saved to local variable.
+        * Write register value back to clear pending interrupts.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+       rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
+
+       if (!reg)
+               return IRQ_NONE;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return IRQ_HANDLED;
+
+       mask = reg;
+
+       /*
+        * Schedule tasklets for interrupt handling.
+        */
+       if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+       if (rt2x00_get_field32(reg, CSR7_RXDONE))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+       if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+           rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+           rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+               /*
+                * Mask out all txdone interrupts.
+                */
+               rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+               rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+               rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+       }
+
+       /*
+        * Disable all interrupts for which a tasklet was scheduled right now,
+        * the tasklet will reenable the appropriate interrupts.
+        */
+       spin_lock(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg |= mask;
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock(&rt2x00dev->irqmask_lock);
+
+
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       struct eeprom_93cx6 eeprom;
+       u32 reg;
+       u16 word;
+       u8 *mac;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+
+       eeprom.data = rt2x00dev;
+       eeprom.register_read = rt2400pci_eepromregister_read;
+       eeprom.register_write = rt2400pci_eepromregister_write;
+       eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?
+           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
+       eeprom.reg_data_in = 0;
+       eeprom.reg_data_out = 0;
+       eeprom.reg_data_clock = 0;
+       eeprom.reg_chip_select = 0;
+
+       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
+                              EEPROM_SIZE / sizeof(u16));
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       if (word == 0xffff) {
+               rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 value;
+       u16 eeprom;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+       /*
+        * Identify RF chipset.
+        */
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+       rt2x00_set_chip(rt2x00dev, RT2460, value,
+                       rt2x00_get_field32(reg, CSR0_REVISION));
+
+       if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
+               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
+       rt2x00dev->default_ant.rx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
+
+       /*
+        * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
+        * I am not 100% sure about this, but the legacy drivers do not
+        * indicate antenna swapping in software is required when
+        * diversity is enabled.
+        */
+       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
+       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
+
+       /*
+        * Store led mode, for correct led behaviour.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
+
+       rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
+               rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                  LED_TYPE_ACTIVITY);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+
+       /*
+        * Check if the BBP tuning should be enabled.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
+               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+
+       return 0;
+}
+
+/*
+ * RF value list for RF2420 & RF2421
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_b[] = {
+       { 1,  0x00022058, 0x000c1fda, 0x00000101, 0 },
+       { 2,  0x00022058, 0x000c1fee, 0x00000101, 0 },
+       { 3,  0x00022058, 0x000c2002, 0x00000101, 0 },
+       { 4,  0x00022058, 0x000c2016, 0x00000101, 0 },
+       { 5,  0x00022058, 0x000c202a, 0x00000101, 0 },
+       { 6,  0x00022058, 0x000c203e, 0x00000101, 0 },
+       { 7,  0x00022058, 0x000c2052, 0x00000101, 0 },
+       { 8,  0x00022058, 0x000c2066, 0x00000101, 0 },
+       { 9,  0x00022058, 0x000c207a, 0x00000101, 0 },
+       { 10, 0x00022058, 0x000c208e, 0x00000101, 0 },
+       { 11, 0x00022058, 0x000c20a2, 0x00000101, 0 },
+       { 12, 0x00022058, 0x000c20b6, 0x00000101, 0 },
+       { 13, 0x00022058, 0x000c20ca, 0x00000101, 0 },
+       { 14, 0x00022058, 0x000c20fa, 0x00000101, 0 },
+};
+
+static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *tx_power;
+       unsigned int i;
+
+       /*
+        * Initialize all hw fields.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2x00_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       spec->supported_rates = SUPPORT_RATE_CCK;
+
+       spec->num_channels = ARRAY_SIZE(rf_vals_b);
+       spec->channels = rf_vals_b;
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
+
+       return 0;
+}
+
+static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u32 reg;
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt2400pci_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt2400pci_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
+       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt2400pci_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * This device requires the atim queue and DMA-mapped skbs.
+        */
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif, u16 queue,
+                            const struct ieee80211_tx_queue_params *params)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * We don't support variating cw_min and cw_max variables
+        * per queue. So by default we only configure the TX queue,
+        * and ignore all other configurations.
+        */
+       if (queue != 0)
+               return -EINVAL;
+
+       if (rt2x00mac_conf_tx(hw, vif, queue, params))
+               return -EINVAL;
+
+       /*
+        * Write configuration to register.
+        */
+       rt2400pci_config_cw(rt2x00dev,
+                           rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
+
+       return 0;
+}
+
+static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u64 tsf;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+       tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
+       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+       tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
+
+       return tsf;
+}
+
+static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+       return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
+}
+
+static const struct ieee80211_ops rt2400pci_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2400pci_conf_tx,
+       .get_tsf                = rt2400pci_get_tsf,
+       .tx_last_beacon         = rt2400pci_tx_last_beacon,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
+       .irq_handler            = rt2400pci_interrupt,
+       .txstatus_tasklet       = rt2400pci_txstatus_tasklet,
+       .tbtt_tasklet           = rt2400pci_tbtt_tasklet,
+       .rxdone_tasklet         = rt2400pci_rxdone_tasklet,
+       .probe_hw               = rt2400pci_probe_hw,
+       .initialize             = rt2x00mmio_initialize,
+       .uninitialize           = rt2x00mmio_uninitialize,
+       .get_entry_state        = rt2400pci_get_entry_state,
+       .clear_entry            = rt2400pci_clear_entry,
+       .set_device_state       = rt2400pci_set_device_state,
+       .rfkill_poll            = rt2400pci_rfkill_poll,
+       .link_stats             = rt2400pci_link_stats,
+       .reset_tuner            = rt2400pci_reset_tuner,
+       .link_tuner             = rt2400pci_link_tuner,
+       .start_queue            = rt2400pci_start_queue,
+       .kick_queue             = rt2400pci_kick_queue,
+       .stop_queue             = rt2400pci_stop_queue,
+       .flush_queue            = rt2x00mmio_flush_queue,
+       .write_tx_desc          = rt2400pci_write_tx_desc,
+       .write_beacon           = rt2400pci_write_beacon,
+       .fill_rxdone            = rt2400pci_fill_rxdone,
+       .config_filter          = rt2400pci_config_filter,
+       .config_intf            = rt2400pci_config_intf,
+       .config_erp             = rt2400pci_config_erp,
+       .config_ant             = rt2400pci_config_ant,
+       .config                 = rt2400pci_config,
+};
+
+static void rt2400pci_queue_init(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 24;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 24;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 1;
+               queue->data_size = MGMT_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_ATIM:
+               queue->limit = 8;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt2400pci_ops = {
+       .name                   = KBUILD_MODNAME,
+       .max_ap_intf            = 1,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2400pci_queue_init,
+       .lib                    = &rt2400pci_rt2x00_ops,
+       .hw                     = &rt2400pci_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2400pci_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * RT2400pci module information.
+ */
+static const struct pci_device_id rt2400pci_device_table[] = {
+       { PCI_DEVICE(0x1814, 0x0101) },
+       { 0, }
+};
+
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
+MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
+MODULE_LICENSE("GPL");
+
+static int rt2400pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
+static struct pci_driver rt2400pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt2400pci_device_table,
+       .probe          = rt2400pci_probe,
+       .remove         = rt2x00pci_remove,
+       .suspend        = rt2x00pci_suspend,
+       .resume         = rt2x00pci_resume,
+};
+
+module_pci_driver(rt2400pci_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.h b/drivers/net/wireless/ralink/rt2x00/rt2400pci.h
new file mode 100644 (file)
index 0000000..0fd3a9d
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2400pci
+       Abstract: Data structures and registers for the rt2400pci module.
+       Supported chipsets: RT2460.
+ */
+
+#ifndef RT2400PCI_H
+#define RT2400PCI_H
+
+/*
+ * RF chip defines.
+ */
+#define RF2420                         0x0000
+#define RF2421                         0x0001
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET            100
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x0000
+#define CSR_REG_SIZE                   0x014c
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x0100
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x0020
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x000c
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
+/*
+ * Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * CSR0: ASIC revision number.
+ */
+#define CSR0                           0x0000
+#define CSR0_REVISION                  FIELD32(0x0000ffff)
+
+/*
+ * CSR1: System control register.
+ * SOFT_RESET: Software reset, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset, 1: reset, 0, release.
+ * HOST_READY: Host ready after initialization.
+ */
+#define CSR1                           0x0004
+#define CSR1_SOFT_RESET                        FIELD32(0x00000001)
+#define CSR1_BBP_RESET                 FIELD32(0x00000002)
+#define CSR1_HOST_READY                        FIELD32(0x00000004)
+
+/*
+ * CSR2: System admin status register (invalid).
+ */
+#define CSR2                           0x0008
+
+/*
+ * CSR3: STA MAC address register 0.
+ */
+#define CSR3                           0x000c
+#define CSR3_BYTE0                     FIELD32(0x000000ff)
+#define CSR3_BYTE1                     FIELD32(0x0000ff00)
+#define CSR3_BYTE2                     FIELD32(0x00ff0000)
+#define CSR3_BYTE3                     FIELD32(0xff000000)
+
+/*
+ * CSR4: STA MAC address register 1.
+ */
+#define CSR4                           0x0010
+#define CSR4_BYTE4                     FIELD32(0x000000ff)
+#define CSR4_BYTE5                     FIELD32(0x0000ff00)
+
+/*
+ * CSR5: BSSID register 0.
+ */
+#define CSR5                           0x0014
+#define CSR5_BYTE0                     FIELD32(0x000000ff)
+#define CSR5_BYTE1                     FIELD32(0x0000ff00)
+#define CSR5_BYTE2                     FIELD32(0x00ff0000)
+#define CSR5_BYTE3                     FIELD32(0xff000000)
+
+/*
+ * CSR6: BSSID register 1.
+ */
+#define CSR6                           0x0018
+#define CSR6_BYTE4                     FIELD32(0x000000ff)
+#define CSR6_BYTE5                     FIELD32(0x0000ff00)
+
+/*
+ * CSR7: Interrupt source register.
+ * Write 1 to clear interrupt.
+ * TBCN_EXPIRE: Beacon timer expired interrupt.
+ * TWAKE_EXPIRE: Wakeup timer expired interrupt.
+ * TATIMW_EXPIRE: Timer of atim window expired interrupt.
+ * TXDONE_TXRING: Tx ring transmit done interrupt.
+ * TXDONE_ATIMRING: Atim ring transmit done interrupt.
+ * TXDONE_PRIORING: Priority ring transmit done interrupt.
+ * RXDONE: Receive done interrupt.
+ */
+#define CSR7                           0x001c
+#define CSR7_TBCN_EXPIRE               FIELD32(0x00000001)
+#define CSR7_TWAKE_EXPIRE              FIELD32(0x00000002)
+#define CSR7_TATIMW_EXPIRE             FIELD32(0x00000004)
+#define CSR7_TXDONE_TXRING             FIELD32(0x00000008)
+#define CSR7_TXDONE_ATIMRING           FIELD32(0x00000010)
+#define CSR7_TXDONE_PRIORING           FIELD32(0x00000020)
+#define CSR7_RXDONE                    FIELD32(0x00000040)
+
+/*
+ * CSR8: Interrupt mask register.
+ * Write 1 to mask interrupt.
+ * TBCN_EXPIRE: Beacon timer expired interrupt.
+ * TWAKE_EXPIRE: Wakeup timer expired interrupt.
+ * TATIMW_EXPIRE: Timer of atim window expired interrupt.
+ * TXDONE_TXRING: Tx ring transmit done interrupt.
+ * TXDONE_ATIMRING: Atim ring transmit done interrupt.
+ * TXDONE_PRIORING: Priority ring transmit done interrupt.
+ * RXDONE: Receive done interrupt.
+ */
+#define CSR8                           0x0020
+#define CSR8_TBCN_EXPIRE               FIELD32(0x00000001)
+#define CSR8_TWAKE_EXPIRE              FIELD32(0x00000002)
+#define CSR8_TATIMW_EXPIRE             FIELD32(0x00000004)
+#define CSR8_TXDONE_TXRING             FIELD32(0x00000008)
+#define CSR8_TXDONE_ATIMRING           FIELD32(0x00000010)
+#define CSR8_TXDONE_PRIORING           FIELD32(0x00000020)
+#define CSR8_RXDONE                    FIELD32(0x00000040)
+
+/*
+ * CSR9: Maximum frame length register.
+ * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12.
+ */
+#define CSR9                           0x0024
+#define CSR9_MAX_FRAME_UNIT            FIELD32(0x00000f80)
+
+/*
+ * CSR11: Back-off control register.
+ * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1).
+ * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1).
+ * SLOT_TIME: Slot time, default is 20us for 802.11b.
+ * LONG_RETRY: Long retry count.
+ * SHORT_RETRY: Short retry count.
+ */
+#define CSR11                          0x002c
+#define CSR11_CWMIN                    FIELD32(0x0000000f)
+#define CSR11_CWMAX                    FIELD32(0x000000f0)
+#define CSR11_SLOT_TIME                        FIELD32(0x00001f00)
+#define CSR11_LONG_RETRY               FIELD32(0x00ff0000)
+#define CSR11_SHORT_RETRY              FIELD32(0xff000000)
+
+/*
+ * CSR12: Synchronization configuration register 0.
+ * All units in 1/16 TU.
+ * BEACON_INTERVAL: Beacon interval, default is 100 TU.
+ * CFPMAX_DURATION: Cfp maximum duration, default is 100 TU.
+ */
+#define CSR12                          0x0030
+#define CSR12_BEACON_INTERVAL          FIELD32(0x0000ffff)
+#define CSR12_CFP_MAX_DURATION         FIELD32(0xffff0000)
+
+/*
+ * CSR13: Synchronization configuration register 1.
+ * All units in 1/16 TU.
+ * ATIMW_DURATION: Atim window duration.
+ * CFP_PERIOD: Cfp period, default is 0 TU.
+ */
+#define CSR13                          0x0034
+#define CSR13_ATIMW_DURATION           FIELD32(0x0000ffff)
+#define CSR13_CFP_PERIOD               FIELD32(0x00ff0000)
+
+/*
+ * CSR14: Synchronization control register.
+ * TSF_COUNT: Enable tsf auto counting.
+ * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
+ * TBCN: Enable tbcn with reload value.
+ * TCFP: Enable tcfp & cfp / cp switching.
+ * TATIMW: Enable tatimw & atim window switching.
+ * BEACON_GEN: Enable beacon generator.
+ * CFP_COUNT_PRELOAD: Cfp count preload value.
+ * TBCM_PRELOAD: Tbcn preload value in units of 64us.
+ */
+#define CSR14                          0x0038
+#define CSR14_TSF_COUNT                        FIELD32(0x00000001)
+#define CSR14_TSF_SYNC                 FIELD32(0x00000006)
+#define CSR14_TBCN                     FIELD32(0x00000008)
+#define CSR14_TCFP                     FIELD32(0x00000010)
+#define CSR14_TATIMW                   FIELD32(0x00000020)
+#define CSR14_BEACON_GEN               FIELD32(0x00000040)
+#define CSR14_CFP_COUNT_PRELOAD                FIELD32(0x0000ff00)
+#define CSR14_TBCM_PRELOAD             FIELD32(0xffff0000)
+
+/*
+ * CSR15: Synchronization status register.
+ * CFP: ASIC is in contention-free period.
+ * ATIMW: ASIC is in ATIM window.
+ * BEACON_SENT: Beacon is send.
+ */
+#define CSR15                          0x003c
+#define CSR15_CFP                      FIELD32(0x00000001)
+#define CSR15_ATIMW                    FIELD32(0x00000002)
+#define CSR15_BEACON_SENT              FIELD32(0x00000004)
+
+/*
+ * CSR16: TSF timer register 0.
+ */
+#define CSR16                          0x0040
+#define CSR16_LOW_TSFTIMER             FIELD32(0xffffffff)
+
+/*
+ * CSR17: TSF timer register 1.
+ */
+#define CSR17                          0x0044
+#define CSR17_HIGH_TSFTIMER            FIELD32(0xffffffff)
+
+/*
+ * CSR18: IFS timer register 0.
+ * SIFS: Sifs, default is 10 us.
+ * PIFS: Pifs, default is 30 us.
+ */
+#define CSR18                          0x0048
+#define CSR18_SIFS                     FIELD32(0x0000ffff)
+#define CSR18_PIFS                     FIELD32(0xffff0000)
+
+/*
+ * CSR19: IFS timer register 1.
+ * DIFS: Difs, default is 50 us.
+ * EIFS: Eifs, default is 364 us.
+ */
+#define CSR19                          0x004c
+#define CSR19_DIFS                     FIELD32(0x0000ffff)
+#define CSR19_EIFS                     FIELD32(0xffff0000)
+
+/*
+ * CSR20: Wakeup timer register.
+ * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU.
+ * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
+ * AUTOWAKE: Enable auto wakeup / sleep mechanism.
+ */
+#define CSR20                          0x0050
+#define CSR20_DELAY_AFTER_TBCN         FIELD32(0x0000ffff)
+#define CSR20_TBCN_BEFORE_WAKEUP       FIELD32(0x00ff0000)
+#define CSR20_AUTOWAKE                 FIELD32(0x01000000)
+
+/*
+ * CSR21: EEPROM control register.
+ * RELOAD: Write 1 to reload eeprom content.
+ * TYPE_93C46: 1: 93c46, 0:93c66.
+ */
+#define CSR21                          0x0054
+#define CSR21_RELOAD                   FIELD32(0x00000001)
+#define CSR21_EEPROM_DATA_CLOCK                FIELD32(0x00000002)
+#define CSR21_EEPROM_CHIP_SELECT       FIELD32(0x00000004)
+#define CSR21_EEPROM_DATA_IN           FIELD32(0x00000008)
+#define CSR21_EEPROM_DATA_OUT          FIELD32(0x00000010)
+#define CSR21_TYPE_93C46               FIELD32(0x00000020)
+
+/*
+ * CSR22: CFP control register.
+ * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU.
+ * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain.
+ */
+#define CSR22                          0x0058
+#define CSR22_CFP_DURATION_REMAIN      FIELD32(0x0000ffff)
+#define CSR22_RELOAD_CFP_DURATION      FIELD32(0x00010000)
+
+/*
+ * Transmit related CSRs.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * TXCSR0: TX Control Register.
+ * KICK_TX: Kick tx ring.
+ * KICK_ATIM: Kick atim ring.
+ * KICK_PRIO: Kick priority ring.
+ * ABORT: Abort all transmit related ring operation.
+ */
+#define TXCSR0                         0x0060
+#define TXCSR0_KICK_TX                 FIELD32(0x00000001)
+#define TXCSR0_KICK_ATIM               FIELD32(0x00000002)
+#define TXCSR0_KICK_PRIO               FIELD32(0x00000004)
+#define TXCSR0_ABORT                   FIELD32(0x00000008)
+
+/*
+ * TXCSR1: TX Configuration Register.
+ * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps.
+ * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps.
+ * TSF_OFFSET: Insert tsf offset.
+ * AUTORESPONDER: Enable auto responder which include ack & cts.
+ */
+#define TXCSR1                         0x0064
+#define TXCSR1_ACK_TIMEOUT             FIELD32(0x000001ff)
+#define TXCSR1_ACK_CONSUME_TIME                FIELD32(0x0003fe00)
+#define TXCSR1_TSF_OFFSET              FIELD32(0x00fc0000)
+#define TXCSR1_AUTORESPONDER           FIELD32(0x01000000)
+
+/*
+ * TXCSR2: Tx descriptor configuration register.
+ * TXD_SIZE: Tx descriptor size, default is 48.
+ * NUM_TXD: Number of tx entries in ring.
+ * NUM_ATIM: Number of atim entries in ring.
+ * NUM_PRIO: Number of priority entries in ring.
+ */
+#define TXCSR2                         0x0068
+#define TXCSR2_TXD_SIZE                        FIELD32(0x000000ff)
+#define TXCSR2_NUM_TXD                 FIELD32(0x0000ff00)
+#define TXCSR2_NUM_ATIM                        FIELD32(0x00ff0000)
+#define TXCSR2_NUM_PRIO                        FIELD32(0xff000000)
+
+/*
+ * TXCSR3: TX Ring Base address register.
+ */
+#define TXCSR3                         0x006c
+#define TXCSR3_TX_RING_REGISTER                FIELD32(0xffffffff)
+
+/*
+ * TXCSR4: TX Atim Ring Base address register.
+ */
+#define TXCSR4                         0x0070
+#define TXCSR4_ATIM_RING_REGISTER      FIELD32(0xffffffff)
+
+/*
+ * TXCSR5: TX Prio Ring Base address register.
+ */
+#define TXCSR5                         0x0074
+#define TXCSR5_PRIO_RING_REGISTER      FIELD32(0xffffffff)
+
+/*
+ * TXCSR6: Beacon Base address register.
+ */
+#define TXCSR6                         0x0078
+#define TXCSR6_BEACON_RING_REGISTER    FIELD32(0xffffffff)
+
+/*
+ * TXCSR7: Auto responder control register.
+ * AR_POWERMANAGEMENT: Auto responder power management bit.
+ */
+#define TXCSR7                         0x007c
+#define TXCSR7_AR_POWERMANAGEMENT      FIELD32(0x00000001)
+
+/*
+ * Receive related CSRs.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * RXCSR0: RX Control Register.
+ * DISABLE_RX: Disable rx engine.
+ * DROP_CRC: Drop crc error.
+ * DROP_PHYSICAL: Drop physical error.
+ * DROP_CONTROL: Drop control frame.
+ * DROP_NOT_TO_ME: Drop not to me unicast frame.
+ * DROP_TODS: Drop frame tods bit is true.
+ * DROP_VERSION_ERROR: Drop version error frame.
+ * PASS_CRC: Pass all packets with crc attached.
+ */
+#define RXCSR0                         0x0080
+#define RXCSR0_DISABLE_RX              FIELD32(0x00000001)
+#define RXCSR0_DROP_CRC                        FIELD32(0x00000002)
+#define RXCSR0_DROP_PHYSICAL           FIELD32(0x00000004)
+#define RXCSR0_DROP_CONTROL            FIELD32(0x00000008)
+#define RXCSR0_DROP_NOT_TO_ME          FIELD32(0x00000010)
+#define RXCSR0_DROP_TODS               FIELD32(0x00000020)
+#define RXCSR0_DROP_VERSION_ERROR      FIELD32(0x00000040)
+#define RXCSR0_PASS_CRC                        FIELD32(0x00000080)
+
+/*
+ * RXCSR1: RX descriptor configuration register.
+ * RXD_SIZE: Rx descriptor size, default is 32b.
+ * NUM_RXD: Number of rx entries in ring.
+ */
+#define RXCSR1                         0x0084
+#define RXCSR1_RXD_SIZE                        FIELD32(0x000000ff)
+#define RXCSR1_NUM_RXD                 FIELD32(0x0000ff00)
+
+/*
+ * RXCSR2: RX Ring base address register.
+ */
+#define RXCSR2                         0x0088
+#define RXCSR2_RX_RING_REGISTER                FIELD32(0xffffffff)
+
+/*
+ * RXCSR3: BBP ID register for Rx operation.
+ * BBP_ID#: BBP register # id.
+ * BBP_ID#_VALID: BBP register # id is valid or not.
+ */
+#define RXCSR3                         0x0090
+#define RXCSR3_BBP_ID0                 FIELD32(0x0000007f)
+#define RXCSR3_BBP_ID0_VALID           FIELD32(0x00000080)
+#define RXCSR3_BBP_ID1                 FIELD32(0x00007f00)
+#define RXCSR3_BBP_ID1_VALID           FIELD32(0x00008000)
+#define RXCSR3_BBP_ID2                 FIELD32(0x007f0000)
+#define RXCSR3_BBP_ID2_VALID           FIELD32(0x00800000)
+#define RXCSR3_BBP_ID3                 FIELD32(0x7f000000)
+#define RXCSR3_BBP_ID3_VALID           FIELD32(0x80000000)
+
+/*
+ * RXCSR4: BBP ID register for Rx operation.
+ * BBP_ID#: BBP register # id.
+ * BBP_ID#_VALID: BBP register # id is valid or not.
+ */
+#define RXCSR4                         0x0094
+#define RXCSR4_BBP_ID4                 FIELD32(0x0000007f)
+#define RXCSR4_BBP_ID4_VALID           FIELD32(0x00000080)
+#define RXCSR4_BBP_ID5                 FIELD32(0x00007f00)
+#define RXCSR4_BBP_ID5_VALID           FIELD32(0x00008000)
+
+/*
+ * ARCSR0: Auto Responder PLCP config register 0.
+ * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data.
+ * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id.
+ */
+#define ARCSR0                         0x0098
+#define ARCSR0_AR_BBP_DATA0            FIELD32(0x000000ff)
+#define ARCSR0_AR_BBP_ID0              FIELD32(0x0000ff00)
+#define ARCSR0_AR_BBP_DATA1            FIELD32(0x00ff0000)
+#define ARCSR0_AR_BBP_ID1              FIELD32(0xff000000)
+
+/*
+ * ARCSR1: Auto Responder PLCP config register 1.
+ * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data.
+ * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id.
+ */
+#define ARCSR1                         0x009c
+#define ARCSR1_AR_BBP_DATA2            FIELD32(0x000000ff)
+#define ARCSR1_AR_BBP_ID2              FIELD32(0x0000ff00)
+#define ARCSR1_AR_BBP_DATA3            FIELD32(0x00ff0000)
+#define ARCSR1_AR_BBP_ID3              FIELD32(0xff000000)
+
+/*
+ * Miscellaneous Registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * PCICSR: PCI control register.
+ * BIG_ENDIAN: 1: big endian, 0: little endian.
+ * RX_TRESHOLD: Rx threshold in dw to start pci access
+ * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
+ * TX_TRESHOLD: Tx threshold in dw to start pci access
+ * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward.
+ * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw.
+ * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational.
+ */
+#define PCICSR                         0x008c
+#define PCICSR_BIG_ENDIAN              FIELD32(0x00000001)
+#define PCICSR_RX_TRESHOLD             FIELD32(0x00000006)
+#define PCICSR_TX_TRESHOLD             FIELD32(0x00000018)
+#define PCICSR_BURST_LENTH             FIELD32(0x00000060)
+#define PCICSR_ENABLE_CLK              FIELD32(0x00000080)
+
+/*
+ * CNT0: FCS error count.
+ * FCS_ERROR: FCS error count, cleared when read.
+ */
+#define CNT0                           0x00a0
+#define CNT0_FCS_ERROR                 FIELD32(0x0000ffff)
+
+/*
+ * Statistic Register.
+ * CNT1: PLCP error count.
+ * CNT2: Long error count.
+ * CNT3: CCA false alarm count.
+ * CNT4: Rx FIFO overflow count.
+ * CNT5: Tx FIFO underrun count.
+ */
+#define TIMECSR2                       0x00a8
+#define CNT1                           0x00ac
+#define CNT2                           0x00b0
+#define TIMECSR3                       0x00b4
+#define CNT3                           0x00b8
+#define CNT4                           0x00bc
+#define CNT5                           0x00c0
+
+/*
+ * Baseband Control Register.
+ */
+
+/*
+ * PWRCSR0: Power mode configuration register.
+ */
+#define PWRCSR0                                0x00c4
+
+/*
+ * Power state transition time registers.
+ */
+#define PSCSR0                         0x00c8
+#define PSCSR1                         0x00cc
+#define PSCSR2                         0x00d0
+#define PSCSR3                         0x00d4
+
+/*
+ * PWRCSR1: Manual power control / status register.
+ * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
+ * SET_STATE: Set state. Write 1 to trigger, self cleared.
+ * BBP_DESIRE_STATE: BBP desired state.
+ * RF_DESIRE_STATE: RF desired state.
+ * BBP_CURR_STATE: BBP current state.
+ * RF_CURR_STATE: RF current state.
+ * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
+ */
+#define PWRCSR1                                0x00d8
+#define PWRCSR1_SET_STATE              FIELD32(0x00000001)
+#define PWRCSR1_BBP_DESIRE_STATE       FIELD32(0x00000006)
+#define PWRCSR1_RF_DESIRE_STATE                FIELD32(0x00000018)
+#define PWRCSR1_BBP_CURR_STATE         FIELD32(0x00000060)
+#define PWRCSR1_RF_CURR_STATE          FIELD32(0x00000180)
+#define PWRCSR1_PUT_TO_SLEEP           FIELD32(0x00000200)
+
+/*
+ * TIMECSR: Timer control register.
+ * US_COUNT: 1 us timer count in units of clock cycles.
+ * US_64_COUNT: 64 us timer count in units of 1 us timer.
+ * BEACON_EXPECT: Beacon expect window.
+ */
+#define TIMECSR                                0x00dc
+#define TIMECSR_US_COUNT               FIELD32(0x000000ff)
+#define TIMECSR_US_64_COUNT            FIELD32(0x0000ff00)
+#define TIMECSR_BEACON_EXPECT          FIELD32(0x00070000)
+
+/*
+ * MACCSR0: MAC configuration register 0.
+ */
+#define MACCSR0                                0x00e0
+
+/*
+ * MACCSR1: MAC configuration register 1.
+ * KICK_RX: Kick one-shot rx in one-shot rx mode.
+ * ONESHOT_RXMODE: Enable one-shot rx mode for debugging.
+ * BBPRX_RESET_MODE: Ralink bbp rx reset mode.
+ * AUTO_TXBBP: Auto tx logic access bbp control register.
+ * AUTO_RXBBP: Auto rx logic access bbp control register.
+ * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd.
+ * INTERSIL_IF: Intersil if calibration pin.
+ */
+#define MACCSR1                                0x00e4
+#define MACCSR1_KICK_RX                        FIELD32(0x00000001)
+#define MACCSR1_ONESHOT_RXMODE         FIELD32(0x00000002)
+#define MACCSR1_BBPRX_RESET_MODE       FIELD32(0x00000004)
+#define MACCSR1_AUTO_TXBBP             FIELD32(0x00000008)
+#define MACCSR1_AUTO_RXBBP             FIELD32(0x00000010)
+#define MACCSR1_LOOPBACK               FIELD32(0x00000060)
+#define MACCSR1_INTERSIL_IF            FIELD32(0x00000080)
+
+/*
+ * RALINKCSR: Ralink Rx auto-reset BBCR.
+ * AR_BBP_DATA#: Auto reset BBP register # data.
+ * AR_BBP_ID#: Auto reset BBP register # id.
+ */
+#define RALINKCSR                      0x00e8
+#define RALINKCSR_AR_BBP_DATA0         FIELD32(0x000000ff)
+#define RALINKCSR_AR_BBP_ID0           FIELD32(0x0000ff00)
+#define RALINKCSR_AR_BBP_DATA1         FIELD32(0x00ff0000)
+#define RALINKCSR_AR_BBP_ID1           FIELD32(0xff000000)
+
+/*
+ * BCNCSR: Beacon interval control register.
+ * CHANGE: Write one to change beacon interval.
+ * DELTATIME: The delta time value.
+ * NUM_BEACON: Number of beacon according to mode.
+ * MODE: Please refer to asic specs.
+ * PLUS: Plus or minus delta time value.
+ */
+#define BCNCSR                         0x00ec
+#define BCNCSR_CHANGE                  FIELD32(0x00000001)
+#define BCNCSR_DELTATIME               FIELD32(0x0000001e)
+#define BCNCSR_NUM_BEACON              FIELD32(0x00001fe0)
+#define BCNCSR_MODE                    FIELD32(0x00006000)
+#define BCNCSR_PLUS                    FIELD32(0x00008000)
+
+/*
+ * BBP / RF / IF Control Register.
+ */
+
+/*
+ * BBPCSR: BBP serial control register.
+ * VALUE: Register value to program into BBP.
+ * REGNUM: Selected BBP register.
+ * BUSY: 1: asic is busy execute BBP programming.
+ * WRITE_CONTROL: 1: write BBP, 0: read BBP.
+ */
+#define BBPCSR                         0x00f0
+#define BBPCSR_VALUE                   FIELD32(0x000000ff)
+#define BBPCSR_REGNUM                  FIELD32(0x00007f00)
+#define BBPCSR_BUSY                    FIELD32(0x00008000)
+#define BBPCSR_WRITE_CONTROL           FIELD32(0x00010000)
+
+/*
+ * RFCSR: RF serial control register.
+ * VALUE: Register value + id to program into rf/if.
+ * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
+ * IF_SELECT: Chip to program: 0: rf, 1: if.
+ * PLL_LD: Rf pll_ld status.
+ * BUSY: 1: asic is busy execute rf programming.
+ */
+#define RFCSR                          0x00f4
+#define RFCSR_VALUE                    FIELD32(0x00ffffff)
+#define RFCSR_NUMBER_OF_BITS           FIELD32(0x1f000000)
+#define RFCSR_IF_SELECT                        FIELD32(0x20000000)
+#define RFCSR_PLL_LD                   FIELD32(0x40000000)
+#define RFCSR_BUSY                     FIELD32(0x80000000)
+
+/*
+ * LEDCSR: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ * LINK: 0: linkoff, 1: linkup.
+ * ACTIVITY: 0: idle, 1: active.
+ */
+#define LEDCSR                         0x00f8
+#define LEDCSR_ON_PERIOD               FIELD32(0x000000ff)
+#define LEDCSR_OFF_PERIOD              FIELD32(0x0000ff00)
+#define LEDCSR_LINK                    FIELD32(0x00010000)
+#define LEDCSR_ACTIVITY                        FIELD32(0x00020000)
+
+/*
+ * ASIC pointer information.
+ * RXPTR: Current RX ring address.
+ * TXPTR: Current Tx ring address.
+ * PRIPTR: Current Priority ring address.
+ * ATIMPTR: Current ATIM ring address.
+ */
+#define RXPTR                          0x0100
+#define TXPTR                          0x0104
+#define PRIPTR                         0x0108
+#define ATIMPTR                                0x010c
+
+/*
+ * GPIO and others.
+ */
+
+/*
+ * GPIOCSR: GPIO control register.
+ *     GPIOCSR_VALx: Actual GPIO pin x value
+ *     GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
+ */
+#define GPIOCSR                                0x0120
+#define GPIOCSR_VAL0                   FIELD32(0x00000001)
+#define GPIOCSR_VAL1                   FIELD32(0x00000002)
+#define GPIOCSR_VAL2                   FIELD32(0x00000004)
+#define GPIOCSR_VAL3                   FIELD32(0x00000008)
+#define GPIOCSR_VAL4                   FIELD32(0x00000010)
+#define GPIOCSR_VAL5                   FIELD32(0x00000020)
+#define GPIOCSR_VAL6                   FIELD32(0x00000040)
+#define GPIOCSR_VAL7                   FIELD32(0x00000080)
+#define GPIOCSR_DIR0                   FIELD32(0x00000100)
+#define GPIOCSR_DIR1                   FIELD32(0x00000200)
+#define GPIOCSR_DIR2                   FIELD32(0x00000400)
+#define GPIOCSR_DIR3                   FIELD32(0x00000800)
+#define GPIOCSR_DIR4                   FIELD32(0x00001000)
+#define GPIOCSR_DIR5                   FIELD32(0x00002000)
+#define GPIOCSR_DIR6                   FIELD32(0x00004000)
+#define GPIOCSR_DIR7                   FIELD32(0x00008000)
+
+/*
+ * BBPPCSR: BBP Pin control register.
+ */
+#define BBPPCSR                                0x0124
+
+/*
+ * BCNCSR1: Tx BEACON offset time control register.
+ * PRELOAD: Beacon timer offset in units of usec.
+ */
+#define BCNCSR1                                0x0130
+#define BCNCSR1_PRELOAD                        FIELD32(0x0000ffff)
+
+/*
+ * MACCSR2: TX_PE to RX_PE turn-around time control register
+ * DELAY: RX_PE low width, in units of pci clock cycle.
+ */
+#define MACCSR2                                0x0134
+#define MACCSR2_DELAY                  FIELD32(0x000000ff)
+
+/*
+ * ARCSR2: 1 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR2                         0x013c
+#define ARCSR2_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR2_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR2_LENGTH_LOW              FIELD32(0x00ff0000)
+#define ARCSR2_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR3: 2 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR3                         0x0140
+#define ARCSR3_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR3_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR3_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR4: 5.5 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR4                         0x0144
+#define ARCSR4_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR4_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR4_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR5: 11 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR5                         0x0148
+#define ARCSR5_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR5_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR5_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R1: TX antenna control
+ */
+#define BBP_R1_TX_ANTENNA              FIELD8(0x03)
+
+/*
+ * R4: RX antenna control
+ */
+#define BBP_R4_RX_ANTENNA              FIELD8(0x06)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 1
+ */
+#define RF1_TUNER                      FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TUNER                      FIELD32(0x00000100)
+#define RF3_TXPOWER                    FIELD32(0x00003e00)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0              0x0002
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1               0x0003
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2              0x0004
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM antenna.
+ * ANTENNA_NUM: Number of antenna's.
+ * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RF_TYPE: Rf_type of this adapter.
+ * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd.
+ * RX_AGCVGC: 0: disable, 1:enable BBP R13 tuning.
+ * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
+ */
+#define EEPROM_ANTENNA                 0x0b
+#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
+#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
+#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
+#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0x0040)
+#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x0180)
+#define EEPROM_ANTENNA_RX_AGCVGC_TUNING        FIELD16(0x0200)
+#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START               0x0c
+#define EEPROM_BBP_SIZE                        7
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER
+ */
+#define EEPROM_TXPOWER_START           0x13
+#define EEPROM_TXPOWER_SIZE            7
+#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
+#define EEPROM_TXPOWER_2               FIELD16(0xff00)
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  (8 * sizeof(__le32))
+#define RXD_DESC_SIZE                  (8 * sizeof(__le32))
+
+/*
+ * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define TXD_W0_VALID                   FIELD32(0x00000002)
+#define TXD_W0_RESULT                  FIELD32(0x0000001c)
+#define TXD_W0_RETRY_COUNT             FIELD32(0x000000e0)
+#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
+#define TXD_W0_ACK                     FIELD32(0x00000200)
+#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
+#define TXD_W0_RTS                     FIELD32(0x00000800)
+#define TXD_W0_IFS                     FIELD32(0x00006000)
+#define TXD_W0_RETRY_MODE              FIELD32(0x00008000)
+#define TXD_W0_AGC                     FIELD32(0x00ff0000)
+#define TXD_W0_R2                      FIELD32(0xff000000)
+
+/*
+ * Word1
+ */
+#define TXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
+
+/*
+ * Word2
+ */
+#define TXD_W2_BUFFER_LENGTH           FIELD32(0x0000ffff)
+#define TXD_W2_DATABYTE_COUNT          FIELD32(0xffff0000)
+
+/*
+ * Word3 & 4: PLCP information
+ * The PLCP values should be treated as if they were BBP values.
+ */
+#define TXD_W3_PLCP_SIGNAL             FIELD32(0x000000ff)
+#define TXD_W3_PLCP_SIGNAL_REGNUM      FIELD32(0x00007f00)
+#define TXD_W3_PLCP_SIGNAL_BUSY                FIELD32(0x00008000)
+#define TXD_W3_PLCP_SERVICE            FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_SERVICE_REGNUM     FIELD32(0x7f000000)
+#define TXD_W3_PLCP_SERVICE_BUSY       FIELD32(0x80000000)
+
+#define TXD_W4_PLCP_LENGTH_LOW         FIELD32(0x000000ff)
+#define TXD_W3_PLCP_LENGTH_LOW_REGNUM  FIELD32(0x00007f00)
+#define TXD_W3_PLCP_LENGTH_LOW_BUSY    FIELD32(0x00008000)
+#define TXD_W4_PLCP_LENGTH_HIGH                FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM FIELD32(0x7f000000)
+#define TXD_W3_PLCP_LENGTH_HIGH_BUSY   FIELD32(0x80000000)
+
+/*
+ * Word5
+ */
+#define TXD_W5_BBCR4                   FIELD32(0x0000ffff)
+#define TXD_W5_AGC_REG                 FIELD32(0x007f0000)
+#define TXD_W5_AGC_REG_VALID           FIELD32(0x00800000)
+#define TXD_W5_XXX_REG                 FIELD32(0x7f000000)
+#define TXD_W5_XXX_REG_VALID           FIELD32(0x80000000)
+
+/*
+ * Word6
+ */
+#define TXD_W6_SK_BUFF                 FIELD32(0xffffffff)
+
+/*
+ * Word7
+ */
+#define TXD_W7_RESERVED                        FIELD32(0xffffffff)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ */
+#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
+#define RXD_W0_MULTICAST               FIELD32(0x00000004)
+#define RXD_W0_BROADCAST               FIELD32(0x00000008)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
+#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
+#define RXD_W0_DATABYTE_COUNT          FIELD32(0xffff0000)
+
+/*
+ * Word1
+ */
+#define RXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
+
+/*
+ * Word2
+ */
+#define RXD_W2_BUFFER_LENGTH           FIELD32(0x0000ffff)
+#define RXD_W2_BBR0                    FIELD32(0x00ff0000)
+#define RXD_W2_SIGNAL                  FIELD32(0xff000000)
+
+/*
+ * Word3
+ */
+#define RXD_W3_RSSI                    FIELD32(0x000000ff)
+#define RXD_W3_BBR3                    FIELD32(0x0000ff00)
+#define RXD_W3_BBR4                    FIELD32(0x00ff0000)
+#define RXD_W3_BBR5                    FIELD32(0xff000000)
+
+/*
+ * Word4
+ */
+#define RXD_W4_RX_END_TIME             FIELD32(0xffffffff)
+
+/*
+ * Word5 & 6 & 7: Reserved
+ */
+#define RXD_W5_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W6_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W7_RESERVED                        FIELD32(0xffffffff)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ * NOTE: Logics in rt2400pci for txpower are reversed
+ * compared to the other rt2x00 drivers. A higher txpower
+ * value means that the txpower must be lowered. This is
+ * important when converting the value coming from the
+ * mac80211 stack to the rt2400 acceptable value.
+ */
+#define MIN_TXPOWER    31
+#define MAX_TXPOWER    62
+#define DEFAULT_TXPOWER        39
+
+#define __CLAMP_TX(__txpower) \
+       clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER)
+
+#define TXPOWER_FROM_DEV(__txpower) \
+       ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
+
+#define TXPOWER_TO_DEV(__txpower) \
+       (MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER))
+
+#endif /* RT2400PCI_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
new file mode 100644 (file)
index 0000000..1a6740b
--- /dev/null
@@ -0,0 +1,2148 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2500pci
+       Abstract: rt2500pci device specific routines.
+       Supported chipsets: RT2560.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/eeprom_93cx6.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00pci.h"
+#include "rt2500pci.h"
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+
+static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
+                               const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
+               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
+
+               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
+
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, const u32 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, RFCSR_VALUE, value);
+               rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
+               rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
+               rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+
+       eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
+       eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
+       eeprom->reg_data_clock =
+           !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
+       eeprom->reg_chip_select =
+           !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
+}
+
+static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg = 0;
+
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_CLOCK,
+                          !!eeprom->reg_data_clock);
+       rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
+                          !!eeprom->reg_chip_select);
+
+       rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static const struct rt2x00debug rt2500pci_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = rt2x00mmio_register_read,
+               .write          = rt2x00mmio_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = CSR_REG_SIZE / sizeof(u32),
+       },
+       .eeprom = {
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt2500pci_bbp_read,
+               .write          = rt2500pci_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt2500pci_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       return rt2x00_get_field32(reg, GPIOCSR_VAL0);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
+                                    enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       u32 reg;
+
+       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+
+       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
+               rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
+       else if (led->type == LED_TYPE_ACTIVITY)
+               rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
+
+       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
+}
+
+static int rt2500pci_blink_set(struct led_classdev *led_cdev,
+                              unsigned long *delay_on,
+                              unsigned long *delay_off)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       u32 reg;
+
+       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
+       rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
+       rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
+       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
+
+       return 0;
+}
+
+static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00_led *led,
+                              enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt2500pci_brightness_set;
+       led->led_dev.blink_set = rt2500pci_blink_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int filter_flags)
+{
+       u32 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
+                          !rt2x00dev->intf_ap_count);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
+       rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
+                          !(filter_flags & FIF_ALLMULTI));
+       rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+}
+
+static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
+                                 struct rt2x00_intf *intf,
+                                 struct rt2x00intf_conf *conf,
+                                 const unsigned int flags)
+{
+       struct data_queue *queue = rt2x00dev->bcn;
+       unsigned int bcn_preload;
+       u32 reg;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable beacon config
+                */
+               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
+               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
+               rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
+               rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
+               rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
+
+               /*
+                * Enable synchronisation.
+                */
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+       }
+
+       if (flags & CONFIG_UPDATE_MAC)
+               rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
+                                             conf->mac, sizeof(conf->mac));
+
+       if (flags & CONFIG_UPDATE_BSSID)
+               rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
+                                             conf->bssid, sizeof(conf->bssid));
+}
+
+static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
+                                struct rt2x00lib_erp *erp,
+                                u32 changed)
+{
+       int preamble_mask;
+       u32 reg;
+
+       /*
+        * When short preamble is enabled, we should set bit 0x08
+        */
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               preamble_mask = erp->short_preamble << 3;
+
+               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
+               rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
+               rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
+               rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
+               rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
+               rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
+               rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 10));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
+               rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 20));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
+               rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 55));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
+               rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
+               rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
+               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
+                                  GET_DURATION(ACK_SIZE, 110));
+               rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+               rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+               rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
+               rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+               rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+               rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
+               rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+               rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+               rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
+       }
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
+               rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
+                                  erp->beacon_int * 16);
+               rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
+       }
+
+}
+
+static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
+                                struct antenna_setup *ant)
+{
+       u32 reg;
+       u8 r14;
+       u8 r2;
+
+       /*
+        * We should never come here because rt2x00lib is supposed
+        * to catch this and send us the correct antenna explicitely.
+        */
+       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+              ant->tx == ANTENNA_SW_DIVERSITY);
+
+       rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
+       rt2500pci_bbp_read(rt2x00dev, 14, &r14);
+       rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
+               rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
+               rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+               rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
+               rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+               break;
+       }
+
+       /*
+        * RT2525E and RT5222 need to flip TX I/Q
+        */
+       if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
+               rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
+               rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
+               rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
+
+               /*
+                * RT2525E does not need RX I/Q Flip.
+                */
+               if (rt2x00_rf(rt2x00dev, RF2525E))
+                       rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
+       } else {
+               rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
+               rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
+       }
+
+       rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg);
+       rt2500pci_bbp_write(rt2x00dev, 14, r14);
+       rt2500pci_bbp_write(rt2x00dev, 2, r2);
+}
+
+static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
+                                    struct rf_channel *rf, const int txpower)
+{
+       u8 r70;
+
+       /*
+        * Set TXpower.
+        */
+       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+
+       /*
+        * Switch on tuning bits.
+        * For RT2523 devices we do not need to update the R1 register.
+        */
+       if (!rt2x00_rf(rt2x00dev, RF2523))
+               rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
+       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
+
+       /*
+        * For RT2525 we should first set the channel to half band higher.
+        */
+       if (rt2x00_rf(rt2x00dev, RF2525)) {
+               static const u32 vals[] = {
+                       0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
+                       0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
+                       0x00080d1e, 0x00080d22, 0x00080d26, 0x00080d2a,
+                       0x00080d2e, 0x00080d3a
+               };
+
+               rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
+               rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+               rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
+               if (rf->rf4)
+                       rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
+       }
+
+       rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2500pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
+       if (rf->rf4)
+               rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+       /*
+        * Channel 14 requires the Japan filter bit to be set.
+        */
+       r70 = 0x46;
+       rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14);
+       rt2500pci_bbp_write(rt2x00dev, 70, r70);
+
+       msleep(1);
+
+       /*
+        * Switch off tuning bits.
+        * For RT2523 devices we do not need to update the R1 register.
+        */
+       if (!rt2x00_rf(rt2x00dev, RF2523)) {
+               rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
+               rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
+       }
+
+       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
+       rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
+
+       /*
+        * Clear false CRC during channel switch.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
+}
+
+static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
+                                    const int txpower)
+{
+       u32 rf3;
+
+       rt2x00_rf_read(rt2x00dev, 3, &rf3);
+       rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+       rt2500pci_rf_write(rt2x00dev, 3, rf3);
+}
+
+static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+                                        struct rt2x00lib_conf *libconf)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+                          libconf->conf->long_frame_max_tx_count);
+       rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+                          libconf->conf->short_frame_max_tx_count);
+       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+}
+
+static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
+                                  (rt2x00dev->beacon_int - 20) * 16);
+               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+       } else {
+               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
+               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
+static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_conf *libconf,
+                            const unsigned int flags)
+{
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt2500pci_config_channel(rt2x00dev, &libconf->rf,
+                                        libconf->conf->power_level);
+       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
+               rt2500pci_config_txpower(rt2x00dev,
+                                        libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt2500pci_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2500pci_config_ps(rt2x00dev, libconf);
+}
+
+/*
+ * Link tuning
+ */
+static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual)
+{
+       u32 reg;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
+
+       /*
+        * Update False CCA count from register.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
+       qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
+}
+
+static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                    struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level_reg != vgc_level) {
+               rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
+{
+       rt2500pci_set_vgc(rt2x00dev, qual, 0x48);
+}
+
+static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual, const u32 count)
+{
+       /*
+        * To prevent collisions with MAC ASIC on chipsets
+        * up to version C the link tuning should halt after 20
+        * seconds while being associated.
+        */
+       if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D &&
+           rt2x00dev->intf_associated && count > 20)
+               return;
+
+       /*
+        * Chipset versions C and lower should directly continue
+        * to the dynamic CCA tuning. Chipset version D and higher
+        * should go straight to dynamic CCA tuning when they
+        * are not associated.
+        */
+       if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D ||
+           !rt2x00dev->intf_associated)
+               goto dynamic_cca_tune;
+
+       /*
+        * A too low RSSI will cause too much false CCA which will
+        * then corrupt the R17 tuning. To remidy this the tuning should
+        * be stopped (While making sure the R17 value will not exceed limits)
+        */
+       if (qual->rssi < -80 && count > 20) {
+               if (qual->vgc_level_reg >= 0x41)
+                       rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
+               return;
+       }
+
+       /*
+        * Special big-R17 for short distance
+        */
+       if (qual->rssi >= -58) {
+               rt2500pci_set_vgc(rt2x00dev, qual, 0x50);
+               return;
+       }
+
+       /*
+        * Special mid-R17 for middle distance
+        */
+       if (qual->rssi >= -74) {
+               rt2500pci_set_vgc(rt2x00dev, qual, 0x41);
+               return;
+       }
+
+       /*
+        * Leave short or middle distance condition, restore r17
+        * to the dynamic tuning range.
+        */
+       if (qual->vgc_level_reg >= 0x41) {
+               rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
+               return;
+       }
+
+dynamic_cca_tune:
+
+       /*
+        * R17 is inside the dynamic tuning range,
+        * start tuning the link based on the false cca counter.
+        */
+       if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40)
+               rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg);
+       else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32)
+               rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt2500pci_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
+               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+               rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2500pci_kick_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_AC_VI:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_ATIM:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2500pci_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_ATIM:
+               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
+               rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
+               break;
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
+               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
+               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+               rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+               /*
+                * Wait for possibly running tbtt tasklets.
+                */
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Initialization functions.
+ */
+static bool rt2500pci_get_entry_state(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                       rt2x00_get_field32(word, TXD_W0_VALID));
+       }
+}
+
+static void rt2500pci_clear_entry(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+               rt2x00_desc_write(entry_priv->desc, 1, word);
+
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       }
+}
+
+static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct queue_entry_priv_mmio *entry_priv;
+       u32 reg;
+
+       /*
+        * Initialize registers.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
+       rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
+       rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
+
+       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
+       rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
+
+       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
+       rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
+
+       entry_priv = rt2x00dev->atim->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
+       rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
+
+       entry_priv = rt2x00dev->bcn->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
+       rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
+       rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
+       rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
+
+       entry_priv = rt2x00dev->rx->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
+       rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
+
+       return 0;
+}
+
+static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
+       rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
+
+       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
+       rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
+       rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
+       rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
+       rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
+       rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
+                          rt2x00dev->rx->data_size / 128);
+       rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
+
+       /*
+        * Always use CWmin and CWmax set in descriptor.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
+       rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
+
+       rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID0, 10);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID1, 11);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID2, 13);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID3, 12);
+       rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
+       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_1MBS, 112);
+       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_2MBS, 56);
+       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_5_5MBS, 20);
+       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_11MBS, 10);
+       rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
+       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_6MBS, 45);
+       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_9MBS, 37);
+       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_12MBS, 33);
+       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_18MBS, 29);
+       rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
+       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_24MBS, 29);
+       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_36MBS, 25);
+       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_48MBS, 25);
+       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_54MBS, 25);
+       rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 47); /* CCK Signal */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 51); /* Rssi */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 42); /* OFDM Rate */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID3, 51); /* RSSI */
+       rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
+       rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
+       rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
+       rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
+       rt2x00_set_field32(&reg, PCICSR_BURST_LENTH, 1);
+       rt2x00_set_field32(&reg, PCICSR_ENABLE_CLK, 1);
+       rt2x00_set_field32(&reg, PCICSR_READ_MULTIPLE, 1);
+       rt2x00_set_field32(&reg, PCICSR_WRITE_INVALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, PCICSR, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+
+       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
+       rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               return -EBUSY;
+
+       rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
+       rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
+
+       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
+       rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
+       rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 26);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID0, 1);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 26);
+       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID1, 1);
+       rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200);
+
+       rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
+       rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
+       rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
+       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
+       rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
+       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
+
+       /*
+        * We must clear the FCS and FIFO error count.
+        * These registers are cleared on read,
+        * so we may pass a useless variable to store the value.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
+
+       return 0;
+}
+
+static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2500pci_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
+
+       rt2500pci_bbp_write(rt2x00dev, 3, 0x02);
+       rt2500pci_bbp_write(rt2x00dev, 4, 0x19);
+       rt2500pci_bbp_write(rt2x00dev, 14, 0x1c);
+       rt2500pci_bbp_write(rt2x00dev, 15, 0x30);
+       rt2500pci_bbp_write(rt2x00dev, 16, 0xac);
+       rt2500pci_bbp_write(rt2x00dev, 18, 0x18);
+       rt2500pci_bbp_write(rt2x00dev, 19, 0xff);
+       rt2500pci_bbp_write(rt2x00dev, 20, 0x1e);
+       rt2500pci_bbp_write(rt2x00dev, 21, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 22, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 23, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 24, 0x70);
+       rt2500pci_bbp_write(rt2x00dev, 25, 0x40);
+       rt2500pci_bbp_write(rt2x00dev, 26, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 27, 0x23);
+       rt2500pci_bbp_write(rt2x00dev, 30, 0x10);
+       rt2500pci_bbp_write(rt2x00dev, 31, 0x2b);
+       rt2500pci_bbp_write(rt2x00dev, 32, 0xb9);
+       rt2500pci_bbp_write(rt2x00dev, 34, 0x12);
+       rt2500pci_bbp_write(rt2x00dev, 35, 0x50);
+       rt2500pci_bbp_write(rt2x00dev, 39, 0xc4);
+       rt2500pci_bbp_write(rt2x00dev, 40, 0x02);
+       rt2500pci_bbp_write(rt2x00dev, 41, 0x60);
+       rt2500pci_bbp_write(rt2x00dev, 53, 0x10);
+       rt2500pci_bbp_write(rt2x00dev, 54, 0x18);
+       rt2500pci_bbp_write(rt2x00dev, 56, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 57, 0x10);
+       rt2500pci_bbp_write(rt2x00dev, 58, 0x08);
+       rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
+       rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt2500pci_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
+                                enum dev_state state)
+{
+       int mask = (state == STATE_RADIO_IRQ_OFF);
+       u32 reg;
+       unsigned long flags;
+
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+               rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
+       rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+       if (state == STATE_RADIO_IRQ_OFF) {
+               /*
+                * Ensure that all tasklets are finished.
+                */
+               tasklet_kill(&rt2x00dev->txstatus_tasklet);
+               tasklet_kill(&rt2x00dev->rxdone_tasklet);
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+       }
+}
+
+static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Initialize all registers.
+        */
+       if (unlikely(rt2500pci_init_queues(rt2x00dev) ||
+                    rt2500pci_init_registers(rt2x00dev) ||
+                    rt2500pci_init_bbp(rt2x00dev)))
+               return -EIO;
+
+       return 0;
+}
+
+static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Disable power
+        */
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
+}
+
+static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       u32 reg, reg2;
+       unsigned int i;
+       char put_to_sleep;
+       char bbp_state;
+       char rf_state;
+
+       put_to_sleep = (state != STATE_AWAKE);
+
+       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
+       rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
+       rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
+       rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
+       rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
+       rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
+
+       /*
+        * Device is not guaranteed to be in the requested state yet.
+        * We must wait until the register indicates that the
+        * device has entered the correct state.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
+               bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
+               rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
+               if (bbp_state == state && rf_state == state)
+                       return 0;
+               rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
+               msleep(10);
+       }
+
+       return -EBUSY;
+}
+
+static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt2500pci_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               rt2500pci_disable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt2500pci_toggle_irq(rt2x00dev, state);
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt2500pci_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt2500pci_write_tx_desc(struct queue_entry *entry,
+                                   struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       __le32 *txd = entry_priv->desc;
+       u32 word;
+
+       /*
+        * Start writing the descriptor words.
+        */
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+       rt2x00_desc_write(txd, 1, word);
+
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
+       rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
+       rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
+       rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
+       rt2x00_desc_write(txd, 2, word);
+
+       rt2x00_desc_read(txd, 3, &word);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
+       rt2x00_desc_write(txd, 3, word);
+
+       rt2x00_desc_read(txd, 10, &word);
+       rt2x00_set_field32(&word, TXD_W10_RTS,
+                          test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
+       rt2x00_desc_write(txd, 10, word);
+
+       /*
+        * Writing TXD word 0 must the last to prevent a race condition with
+        * the device, whereby the device may take hold of the TXD before we
+        * finished updating it.
+        */
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_OFDM,
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
+       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
+       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+       rt2x00_desc_write(txd, 0, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->desc = txd;
+       skbdesc->desc_len = TXD_DESC_SIZE;
+}
+
+/*
+ * TX data initialization
+ */
+static void rt2500pci_write_beacon(struct queue_entry *entry,
+                                  struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+
+       if (rt2x00queue_map_txskb(entry)) {
+               rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
+               goto out;
+       }
+
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt2500pci_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+out:
+       /*
+        * Enable beaconing again.
+        */
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
+}
+
+/*
+ * RX control handlers
+ */
+static void rt2500pci_fill_rxdone(struct queue_entry *entry,
+                                 struct rxdone_entry_desc *rxdesc)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word0;
+       u32 word2;
+
+       rt2x00_desc_read(entry_priv->desc, 0, &word0);
+       rt2x00_desc_read(entry_priv->desc, 2, &word2);
+
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+
+       /*
+        * Obtain the status about this packet.
+        * When frame was received with an OFDM bitrate,
+        * the signal is the PLCP value. If it was received with
+        * a CCK bitrate the signal is the rate in 100kbit/s.
+        */
+       rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+       rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+           entry->queue->rt2x00dev->rssi_offset;
+       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+
+       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
+               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+       else
+               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
+       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+}
+
+/*
+ * Interrupt functions.
+ */
+static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
+                            const enum data_queue_qid queue_idx)
+{
+       struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+       struct queue_entry_priv_mmio *entry_priv;
+       struct queue_entry *entry;
+       struct txdone_entry_desc txdesc;
+       u32 word;
+
+       while (!rt2x00queue_empty(queue)) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               entry_priv = entry->priv_data;
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                   !rt2x00_get_field32(word, TXD_W0_VALID))
+                       break;
+
+               /*
+                * Obtain the status about this packet.
+                */
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
+               case 0: /* Success */
+               case 1: /* Success with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 2: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
+               txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
+
+               rt2x00lib_txdone(entry, &txdesc);
+       }
+}
+
+static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                             struct rt2x00_field32 irq_field)
+{
+       u32 reg;
+
+       /*
+        * Enable a single interrupt. The interrupt mask register
+        * access needs locking.
+        */
+       spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, irq_field, 0);
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt2500pci_txstatus_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       u32 reg;
+
+       /*
+        * Handle all tx queues.
+        */
+       rt2500pci_txdone(rt2x00dev, QID_ATIM);
+       rt2500pci_txdone(rt2x00dev, QID_AC_VO);
+       rt2500pci_txdone(rt2x00dev, QID_AC_VI);
+
+       /*
+        * Enable all TXDONE interrupts again.
+        */
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+               spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+               rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+               rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+               spin_unlock_irq(&rt2x00dev->irqmask_lock);
+       }
+}
+
+static void rt2500pci_tbtt_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt2x00lib_beacondone(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2500pci_rxdone_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       if (rt2x00mmio_rxdone(rt2x00dev))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
+}
+
+static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
+{
+       struct rt2x00_dev *rt2x00dev = dev_instance;
+       u32 reg, mask;
+
+       /*
+        * Get the interrupt sources & saved to local variable.
+        * Write register value back to clear pending interrupts.
+        */
+       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+       rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
+
+       if (!reg)
+               return IRQ_NONE;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return IRQ_HANDLED;
+
+       mask = reg;
+
+       /*
+        * Schedule tasklets for interrupt handling.
+        */
+       if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+       if (rt2x00_get_field32(reg, CSR7_RXDONE))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+       if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+           rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+           rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+               /*
+                * Mask out all txdone interrupts.
+                */
+               rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+               rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+               rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+       }
+
+       /*
+        * Disable all interrupts for which a tasklet was scheduled right now,
+        * the tasklet will reenable the appropriate interrupts.
+        */
+       spin_lock(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
+       reg |= mask;
+       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
+
+       spin_unlock(&rt2x00dev->irqmask_lock);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       struct eeprom_93cx6 eeprom;
+       u32 reg;
+       u16 word;
+       u8 *mac;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
+
+       eeprom.data = rt2x00dev;
+       eeprom.register_read = rt2500pci_eepromregister_read;
+       eeprom.register_write = rt2500pci_eepromregister_write;
+       eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?
+           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
+       eeprom.reg_data_in = 0;
+       eeprom.reg_data_out = 0;
+       eeprom.reg_data_clock = 0;
+       eeprom.reg_chip_select = 0;
+
+       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
+                              EEPROM_SIZE / sizeof(u16));
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
+                                  LED_MODE_DEFAULT);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
+                                  DEFAULT_RSSI_OFFSET);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+                                 word);
+       }
+
+       return 0;
+}
+
+static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 value;
+       u16 eeprom;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+       /*
+        * Identify RF chipset.
+        */
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
+       rt2x00_set_chip(rt2x00dev, RT2560, value,
+                       rt2x00_get_field32(reg, CSR0_REVISION));
+
+       if (!rt2x00_rf(rt2x00dev, RF2522) &&
+           !rt2x00_rf(rt2x00dev, RF2523) &&
+           !rt2x00_rf(rt2x00dev, RF2524) &&
+           !rt2x00_rf(rt2x00dev, RF2525) &&
+           !rt2x00_rf(rt2x00dev, RF2525E) &&
+           !rt2x00_rf(rt2x00dev, RF5222)) {
+               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
+       rt2x00dev->default_ant.rx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
+
+       /*
+        * Store led mode, for correct led behaviour.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
+
+       rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
+               rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                  LED_TYPE_ACTIVITY);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) {
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+               /*
+                * On this device RFKILL initialized during probe does not work.
+                */
+               __set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags);
+       }
+
+       /*
+        * Check if the BBP tuning should be enabled.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+       if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
+               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+
+       /*
+        * Read the RSSI <-> dBm offset information.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+       rt2x00dev->rssi_offset =
+           rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
+
+       return 0;
+}
+
+/*
+ * RF value list for RF2522
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2522[] = {
+       { 1,  0x00002050, 0x000c1fda, 0x00000101, 0 },
+       { 2,  0x00002050, 0x000c1fee, 0x00000101, 0 },
+       { 3,  0x00002050, 0x000c2002, 0x00000101, 0 },
+       { 4,  0x00002050, 0x000c2016, 0x00000101, 0 },
+       { 5,  0x00002050, 0x000c202a, 0x00000101, 0 },
+       { 6,  0x00002050, 0x000c203e, 0x00000101, 0 },
+       { 7,  0x00002050, 0x000c2052, 0x00000101, 0 },
+       { 8,  0x00002050, 0x000c2066, 0x00000101, 0 },
+       { 9,  0x00002050, 0x000c207a, 0x00000101, 0 },
+       { 10, 0x00002050, 0x000c208e, 0x00000101, 0 },
+       { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 },
+       { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 },
+       { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 },
+       { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 },
+};
+
+/*
+ * RF value list for RF2523
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2523[] = {
+       { 1,  0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b },
+       { 2,  0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b },
+       { 3,  0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b },
+       { 4,  0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b },
+       { 5,  0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b },
+       { 6,  0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b },
+       { 7,  0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b },
+       { 8,  0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b },
+       { 9,  0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b },
+       { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b },
+       { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b },
+       { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b },
+       { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b },
+       { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2524
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2524[] = {
+       { 1,  0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b },
+       { 2,  0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b },
+       { 3,  0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b },
+       { 4,  0x00032020, 0x00000caa, 0x00000101, 0x00000a1b },
+       { 5,  0x00032020, 0x00000cae, 0x00000101, 0x00000a1b },
+       { 6,  0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b },
+       { 7,  0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b },
+       { 8,  0x00032020, 0x00000cba, 0x00000101, 0x00000a1b },
+       { 9,  0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b },
+       { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b },
+       { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b },
+       { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b },
+       { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b },
+       { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2525
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2525[] = {
+       { 1,  0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b },
+       { 2,  0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b },
+       { 3,  0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b },
+       { 4,  0x00022020, 0x00080caa, 0x00060111, 0x00000a1b },
+       { 5,  0x00022020, 0x00080cae, 0x00060111, 0x00000a1b },
+       { 6,  0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b },
+       { 7,  0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b },
+       { 8,  0x00022020, 0x00080cba, 0x00060111, 0x00000a1b },
+       { 9,  0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b },
+       { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b },
+       { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b },
+       { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b },
+       { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b },
+       { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2525e
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2525e[] = {
+       { 1,  0x00022020, 0x00081136, 0x00060111, 0x00000a0b },
+       { 2,  0x00022020, 0x0008113a, 0x00060111, 0x00000a0b },
+       { 3,  0x00022020, 0x0008113e, 0x00060111, 0x00000a0b },
+       { 4,  0x00022020, 0x00081182, 0x00060111, 0x00000a0b },
+       { 5,  0x00022020, 0x00081186, 0x00060111, 0x00000a0b },
+       { 6,  0x00022020, 0x0008118a, 0x00060111, 0x00000a0b },
+       { 7,  0x00022020, 0x0008118e, 0x00060111, 0x00000a0b },
+       { 8,  0x00022020, 0x00081192, 0x00060111, 0x00000a0b },
+       { 9,  0x00022020, 0x00081196, 0x00060111, 0x00000a0b },
+       { 10, 0x00022020, 0x0008119a, 0x00060111, 0x00000a0b },
+       { 11, 0x00022020, 0x0008119e, 0x00060111, 0x00000a0b },
+       { 12, 0x00022020, 0x000811a2, 0x00060111, 0x00000a0b },
+       { 13, 0x00022020, 0x000811a6, 0x00060111, 0x00000a0b },
+       { 14, 0x00022020, 0x000811ae, 0x00060111, 0x00000a1b },
+};
+
+/*
+ * RF value list for RF5222
+ * Supports: 2.4 GHz & 5.2 GHz
+ */
+static const struct rf_channel rf_vals_5222[] = {
+       { 1,  0x00022020, 0x00001136, 0x00000101, 0x00000a0b },
+       { 2,  0x00022020, 0x0000113a, 0x00000101, 0x00000a0b },
+       { 3,  0x00022020, 0x0000113e, 0x00000101, 0x00000a0b },
+       { 4,  0x00022020, 0x00001182, 0x00000101, 0x00000a0b },
+       { 5,  0x00022020, 0x00001186, 0x00000101, 0x00000a0b },
+       { 6,  0x00022020, 0x0000118a, 0x00000101, 0x00000a0b },
+       { 7,  0x00022020, 0x0000118e, 0x00000101, 0x00000a0b },
+       { 8,  0x00022020, 0x00001192, 0x00000101, 0x00000a0b },
+       { 9,  0x00022020, 0x00001196, 0x00000101, 0x00000a0b },
+       { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b },
+       { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b },
+       { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b },
+       { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b },
+       { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f },
+       { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f },
+       { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f },
+       { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f },
+       { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f },
+       { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f },
+       { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f },
+       { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f },
+       { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f },
+       { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f },
+       { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f },
+       { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f },
+       { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f },
+       { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f },
+       { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f },
+       { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f },
+       { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f },
+
+       /* 802.11 UNII */
+       { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f },
+       { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 },
+       { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 },
+       { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 },
+       { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
+};
+
+static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *tx_power;
+       unsigned int i;
+
+       /*
+        * Initialize all hw fields.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2x00_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+       if (rt2x00_rf(rt2x00dev, RF2522)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
+               spec->channels = rf_vals_bg_2522;
+       } else if (rt2x00_rf(rt2x00dev, RF2523)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
+               spec->channels = rf_vals_bg_2523;
+       } else if (rt2x00_rf(rt2x00dev, RF2524)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
+               spec->channels = rf_vals_bg_2524;
+       } else if (rt2x00_rf(rt2x00dev, RF2525)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
+               spec->channels = rf_vals_bg_2525;
+       } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+               spec->channels = rf_vals_bg_2525e;
+       } else if (rt2x00_rf(rt2x00dev, RF5222)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+               spec->channels = rf_vals_5222;
+       }
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = MAX_TXPOWER;
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
+
+       if (spec->num_channels > 14) {
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].max_power = MAX_TXPOWER;
+                       info[i].default_power1 = DEFAULT_TXPOWER;
+               }
+       }
+
+       return 0;
+}
+
+static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u32 reg;
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt2500pci_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt2500pci_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
+       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt2500pci_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * This device requires the atim queue and DMA-mapped skbs.
+        */
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u64 tsf;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
+       tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
+       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
+       tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
+
+       return tsf;
+}
+
+static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
+       return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
+}
+
+static const struct ieee80211_ops rt2500pci_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2x00mac_conf_tx,
+       .get_tsf                = rt2500pci_get_tsf,
+       .tx_last_beacon         = rt2500pci_tx_last_beacon,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
+       .irq_handler            = rt2500pci_interrupt,
+       .txstatus_tasklet       = rt2500pci_txstatus_tasklet,
+       .tbtt_tasklet           = rt2500pci_tbtt_tasklet,
+       .rxdone_tasklet         = rt2500pci_rxdone_tasklet,
+       .probe_hw               = rt2500pci_probe_hw,
+       .initialize             = rt2x00mmio_initialize,
+       .uninitialize           = rt2x00mmio_uninitialize,
+       .get_entry_state        = rt2500pci_get_entry_state,
+       .clear_entry            = rt2500pci_clear_entry,
+       .set_device_state       = rt2500pci_set_device_state,
+       .rfkill_poll            = rt2500pci_rfkill_poll,
+       .link_stats             = rt2500pci_link_stats,
+       .reset_tuner            = rt2500pci_reset_tuner,
+       .link_tuner             = rt2500pci_link_tuner,
+       .start_queue            = rt2500pci_start_queue,
+       .kick_queue             = rt2500pci_kick_queue,
+       .stop_queue             = rt2500pci_stop_queue,
+       .flush_queue            = rt2x00mmio_flush_queue,
+       .write_tx_desc          = rt2500pci_write_tx_desc,
+       .write_beacon           = rt2500pci_write_beacon,
+       .fill_rxdone            = rt2500pci_fill_rxdone,
+       .config_filter          = rt2500pci_config_filter,
+       .config_intf            = rt2500pci_config_intf,
+       .config_erp             = rt2500pci_config_erp,
+       .config_ant             = rt2500pci_config_ant,
+       .config                 = rt2500pci_config,
+};
+
+static void rt2500pci_queue_init(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 1;
+               queue->data_size = MGMT_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_ATIM:
+               queue->limit = 8;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt2500pci_ops = {
+       .name                   = KBUILD_MODNAME,
+       .max_ap_intf            = 1,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2500pci_queue_init,
+       .lib                    = &rt2500pci_rt2x00_ops,
+       .hw                     = &rt2500pci_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2500pci_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * RT2500pci module information.
+ */
+static const struct pci_device_id rt2500pci_device_table[] = {
+       { PCI_DEVICE(0x1814, 0x0201) },
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2500 PCI & PCMCIA Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
+MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
+MODULE_LICENSE("GPL");
+
+static int rt2500pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
+static struct pci_driver rt2500pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt2500pci_device_table,
+       .probe          = rt2500pci_probe,
+       .remove         = rt2x00pci_remove,
+       .suspend        = rt2x00pci_suspend,
+       .resume         = rt2x00pci_resume,
+};
+
+module_pci_driver(rt2500pci_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.h b/drivers/net/wireless/ralink/rt2x00/rt2500pci.h
new file mode 100644 (file)
index 0000000..573e87b
--- /dev/null
@@ -0,0 +1,1235 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2500pci
+       Abstract: Data structures and registers for the rt2500pci module.
+       Supported chipsets: RT2560.
+ */
+
+#ifndef RT2500PCI_H
+#define RT2500PCI_H
+
+/*
+ * RF chip defines.
+ */
+#define RF2522                         0x0000
+#define RF2523                         0x0001
+#define RF2524                         0x0002
+#define RF2525                         0x0003
+#define RF2525E                                0x0004
+#define RF5222                         0x0010
+
+/*
+ * RT2560 version
+ */
+#define RT2560_VERSION_B               2
+#define RT2560_VERSION_C               3
+#define RT2560_VERSION_D               4
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET            121
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x0000
+#define CSR_REG_SIZE                   0x0174
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x0200
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x0040
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
+/*
+ * Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * CSR0: ASIC revision number.
+ */
+#define CSR0                           0x0000
+#define CSR0_REVISION                  FIELD32(0x0000ffff)
+
+/*
+ * CSR1: System control register.
+ * SOFT_RESET: Software reset, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset, 1: reset, 0, release.
+ * HOST_READY: Host ready after initialization.
+ */
+#define CSR1                           0x0004
+#define CSR1_SOFT_RESET                        FIELD32(0x00000001)
+#define CSR1_BBP_RESET                 FIELD32(0x00000002)
+#define CSR1_HOST_READY                        FIELD32(0x00000004)
+
+/*
+ * CSR2: System admin status register (invalid).
+ */
+#define CSR2                           0x0008
+
+/*
+ * CSR3: STA MAC address register 0.
+ */
+#define CSR3                           0x000c
+#define CSR3_BYTE0                     FIELD32(0x000000ff)
+#define CSR3_BYTE1                     FIELD32(0x0000ff00)
+#define CSR3_BYTE2                     FIELD32(0x00ff0000)
+#define CSR3_BYTE3                     FIELD32(0xff000000)
+
+/*
+ * CSR4: STA MAC address register 1.
+ */
+#define CSR4                           0x0010
+#define CSR4_BYTE4                     FIELD32(0x000000ff)
+#define CSR4_BYTE5                     FIELD32(0x0000ff00)
+
+/*
+ * CSR5: BSSID register 0.
+ */
+#define CSR5                           0x0014
+#define CSR5_BYTE0                     FIELD32(0x000000ff)
+#define CSR5_BYTE1                     FIELD32(0x0000ff00)
+#define CSR5_BYTE2                     FIELD32(0x00ff0000)
+#define CSR5_BYTE3                     FIELD32(0xff000000)
+
+/*
+ * CSR6: BSSID register 1.
+ */
+#define CSR6                           0x0018
+#define CSR6_BYTE4                     FIELD32(0x000000ff)
+#define CSR6_BYTE5                     FIELD32(0x0000ff00)
+
+/*
+ * CSR7: Interrupt source register.
+ * Write 1 to clear.
+ * TBCN_EXPIRE: Beacon timer expired interrupt.
+ * TWAKE_EXPIRE: Wakeup timer expired interrupt.
+ * TATIMW_EXPIRE: Timer of atim window expired interrupt.
+ * TXDONE_TXRING: Tx ring transmit done interrupt.
+ * TXDONE_ATIMRING: Atim ring transmit done interrupt.
+ * TXDONE_PRIORING: Priority ring transmit done interrupt.
+ * RXDONE: Receive done interrupt.
+ * DECRYPTION_DONE: Decryption done interrupt.
+ * ENCRYPTION_DONE: Encryption done interrupt.
+ * UART1_TX_TRESHOLD: UART1 TX reaches threshold.
+ * UART1_RX_TRESHOLD: UART1 RX reaches threshold.
+ * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold.
+ * UART1_TX_BUFF_ERROR: UART1 TX buffer error.
+ * UART1_RX_BUFF_ERROR: UART1 RX buffer error.
+ * UART2_TX_TRESHOLD: UART2 TX reaches threshold.
+ * UART2_RX_TRESHOLD: UART2 RX reaches threshold.
+ * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold.
+ * UART2_TX_BUFF_ERROR: UART2 TX buffer error.
+ * UART2_RX_BUFF_ERROR: UART2 RX buffer error.
+ * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period).
+
+ */
+#define CSR7                           0x001c
+#define CSR7_TBCN_EXPIRE               FIELD32(0x00000001)
+#define CSR7_TWAKE_EXPIRE              FIELD32(0x00000002)
+#define CSR7_TATIMW_EXPIRE             FIELD32(0x00000004)
+#define CSR7_TXDONE_TXRING             FIELD32(0x00000008)
+#define CSR7_TXDONE_ATIMRING           FIELD32(0x00000010)
+#define CSR7_TXDONE_PRIORING           FIELD32(0x00000020)
+#define CSR7_RXDONE                    FIELD32(0x00000040)
+#define CSR7_DECRYPTION_DONE           FIELD32(0x00000080)
+#define CSR7_ENCRYPTION_DONE           FIELD32(0x00000100)
+#define CSR7_UART1_TX_TRESHOLD         FIELD32(0x00000200)
+#define CSR7_UART1_RX_TRESHOLD         FIELD32(0x00000400)
+#define CSR7_UART1_IDLE_TRESHOLD       FIELD32(0x00000800)
+#define CSR7_UART1_TX_BUFF_ERROR       FIELD32(0x00001000)
+#define CSR7_UART1_RX_BUFF_ERROR       FIELD32(0x00002000)
+#define CSR7_UART2_TX_TRESHOLD         FIELD32(0x00004000)
+#define CSR7_UART2_RX_TRESHOLD         FIELD32(0x00008000)
+#define CSR7_UART2_IDLE_TRESHOLD       FIELD32(0x00010000)
+#define CSR7_UART2_TX_BUFF_ERROR       FIELD32(0x00020000)
+#define CSR7_UART2_RX_BUFF_ERROR       FIELD32(0x00040000)
+#define CSR7_TIMER_CSR3_EXPIRE         FIELD32(0x00080000)
+
+/*
+ * CSR8: Interrupt mask register.
+ * Write 1 to mask interrupt.
+ * TBCN_EXPIRE: Beacon timer expired interrupt.
+ * TWAKE_EXPIRE: Wakeup timer expired interrupt.
+ * TATIMW_EXPIRE: Timer of atim window expired interrupt.
+ * TXDONE_TXRING: Tx ring transmit done interrupt.
+ * TXDONE_ATIMRING: Atim ring transmit done interrupt.
+ * TXDONE_PRIORING: Priority ring transmit done interrupt.
+ * RXDONE: Receive done interrupt.
+ * DECRYPTION_DONE: Decryption done interrupt.
+ * ENCRYPTION_DONE: Encryption done interrupt.
+ * UART1_TX_TRESHOLD: UART1 TX reaches threshold.
+ * UART1_RX_TRESHOLD: UART1 RX reaches threshold.
+ * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold.
+ * UART1_TX_BUFF_ERROR: UART1 TX buffer error.
+ * UART1_RX_BUFF_ERROR: UART1 RX buffer error.
+ * UART2_TX_TRESHOLD: UART2 TX reaches threshold.
+ * UART2_RX_TRESHOLD: UART2 RX reaches threshold.
+ * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold.
+ * UART2_TX_BUFF_ERROR: UART2 TX buffer error.
+ * UART2_RX_BUFF_ERROR: UART2 RX buffer error.
+ * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period).
+ */
+#define CSR8                           0x0020
+#define CSR8_TBCN_EXPIRE               FIELD32(0x00000001)
+#define CSR8_TWAKE_EXPIRE              FIELD32(0x00000002)
+#define CSR8_TATIMW_EXPIRE             FIELD32(0x00000004)
+#define CSR8_TXDONE_TXRING             FIELD32(0x00000008)
+#define CSR8_TXDONE_ATIMRING           FIELD32(0x00000010)
+#define CSR8_TXDONE_PRIORING           FIELD32(0x00000020)
+#define CSR8_RXDONE                    FIELD32(0x00000040)
+#define CSR8_DECRYPTION_DONE           FIELD32(0x00000080)
+#define CSR8_ENCRYPTION_DONE           FIELD32(0x00000100)
+#define CSR8_UART1_TX_TRESHOLD         FIELD32(0x00000200)
+#define CSR8_UART1_RX_TRESHOLD         FIELD32(0x00000400)
+#define CSR8_UART1_IDLE_TRESHOLD       FIELD32(0x00000800)
+#define CSR8_UART1_TX_BUFF_ERROR       FIELD32(0x00001000)
+#define CSR8_UART1_RX_BUFF_ERROR       FIELD32(0x00002000)
+#define CSR8_UART2_TX_TRESHOLD         FIELD32(0x00004000)
+#define CSR8_UART2_RX_TRESHOLD         FIELD32(0x00008000)
+#define CSR8_UART2_IDLE_TRESHOLD       FIELD32(0x00010000)
+#define CSR8_UART2_TX_BUFF_ERROR       FIELD32(0x00020000)
+#define CSR8_UART2_RX_BUFF_ERROR       FIELD32(0x00040000)
+#define CSR8_TIMER_CSR3_EXPIRE         FIELD32(0x00080000)
+
+/*
+ * CSR9: Maximum frame length register.
+ * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12.
+ */
+#define CSR9                           0x0024
+#define CSR9_MAX_FRAME_UNIT            FIELD32(0x00000f80)
+
+/*
+ * SECCSR0: WEP control register.
+ * KICK_DECRYPT: Kick decryption engine, self-clear.
+ * ONE_SHOT: 0: ring mode, 1: One shot only mode.
+ * DESC_ADDRESS: Descriptor physical address of frame.
+ */
+#define SECCSR0                                0x0028
+#define SECCSR0_KICK_DECRYPT           FIELD32(0x00000001)
+#define SECCSR0_ONE_SHOT               FIELD32(0x00000002)
+#define SECCSR0_DESC_ADDRESS           FIELD32(0xfffffffc)
+
+/*
+ * CSR11: Back-off control register.
+ * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1).
+ * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1).
+ * SLOT_TIME: Slot time, default is 20us for 802.11b
+ * CW_SELECT: CWmin/CWmax selection, 1: Register, 0: TXD.
+ * LONG_RETRY: Long retry count.
+ * SHORT_RETRY: Short retry count.
+ */
+#define CSR11                          0x002c
+#define CSR11_CWMIN                    FIELD32(0x0000000f)
+#define CSR11_CWMAX                    FIELD32(0x000000f0)
+#define CSR11_SLOT_TIME                        FIELD32(0x00001f00)
+#define CSR11_CW_SELECT                        FIELD32(0x00002000)
+#define CSR11_LONG_RETRY               FIELD32(0x00ff0000)
+#define CSR11_SHORT_RETRY              FIELD32(0xff000000)
+
+/*
+ * CSR12: Synchronization configuration register 0.
+ * All units in 1/16 TU.
+ * BEACON_INTERVAL: Beacon interval, default is 100 TU.
+ * CFP_MAX_DURATION: Cfp maximum duration, default is 100 TU.
+ */
+#define CSR12                          0x0030
+#define CSR12_BEACON_INTERVAL          FIELD32(0x0000ffff)
+#define CSR12_CFP_MAX_DURATION         FIELD32(0xffff0000)
+
+/*
+ * CSR13: Synchronization configuration register 1.
+ * All units in 1/16 TU.
+ * ATIMW_DURATION: Atim window duration.
+ * CFP_PERIOD: Cfp period, default is 0 TU.
+ */
+#define CSR13                          0x0034
+#define CSR13_ATIMW_DURATION           FIELD32(0x0000ffff)
+#define CSR13_CFP_PERIOD               FIELD32(0x00ff0000)
+
+/*
+ * CSR14: Synchronization control register.
+ * TSF_COUNT: Enable tsf auto counting.
+ * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
+ * TBCN: Enable tbcn with reload value.
+ * TCFP: Enable tcfp & cfp / cp switching.
+ * TATIMW: Enable tatimw & atim window switching.
+ * BEACON_GEN: Enable beacon generator.
+ * CFP_COUNT_PRELOAD: Cfp count preload value.
+ * TBCM_PRELOAD: Tbcn preload value in units of 64us.
+ */
+#define CSR14                          0x0038
+#define CSR14_TSF_COUNT                        FIELD32(0x00000001)
+#define CSR14_TSF_SYNC                 FIELD32(0x00000006)
+#define CSR14_TBCN                     FIELD32(0x00000008)
+#define CSR14_TCFP                     FIELD32(0x00000010)
+#define CSR14_TATIMW                   FIELD32(0x00000020)
+#define CSR14_BEACON_GEN               FIELD32(0x00000040)
+#define CSR14_CFP_COUNT_PRELOAD                FIELD32(0x0000ff00)
+#define CSR14_TBCM_PRELOAD             FIELD32(0xffff0000)
+
+/*
+ * CSR15: Synchronization status register.
+ * CFP: ASIC is in contention-free period.
+ * ATIMW: ASIC is in ATIM window.
+ * BEACON_SENT: Beacon is send.
+ */
+#define CSR15                          0x003c
+#define CSR15_CFP                      FIELD32(0x00000001)
+#define CSR15_ATIMW                    FIELD32(0x00000002)
+#define CSR15_BEACON_SENT              FIELD32(0x00000004)
+
+/*
+ * CSR16: TSF timer register 0.
+ */
+#define CSR16                          0x0040
+#define CSR16_LOW_TSFTIMER             FIELD32(0xffffffff)
+
+/*
+ * CSR17: TSF timer register 1.
+ */
+#define CSR17                          0x0044
+#define CSR17_HIGH_TSFTIMER            FIELD32(0xffffffff)
+
+/*
+ * CSR18: IFS timer register 0.
+ * SIFS: Sifs, default is 10 us.
+ * PIFS: Pifs, default is 30 us.
+ */
+#define CSR18                          0x0048
+#define CSR18_SIFS                     FIELD32(0x000001ff)
+#define CSR18_PIFS                     FIELD32(0x001f0000)
+
+/*
+ * CSR19: IFS timer register 1.
+ * DIFS: Difs, default is 50 us.
+ * EIFS: Eifs, default is 364 us.
+ */
+#define CSR19                          0x004c
+#define CSR19_DIFS                     FIELD32(0x0000ffff)
+#define CSR19_EIFS                     FIELD32(0xffff0000)
+
+/*
+ * CSR20: Wakeup timer register.
+ * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU.
+ * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
+ * AUTOWAKE: Enable auto wakeup / sleep mechanism.
+ */
+#define CSR20                          0x0050
+#define CSR20_DELAY_AFTER_TBCN         FIELD32(0x0000ffff)
+#define CSR20_TBCN_BEFORE_WAKEUP       FIELD32(0x00ff0000)
+#define CSR20_AUTOWAKE                 FIELD32(0x01000000)
+
+/*
+ * CSR21: EEPROM control register.
+ * RELOAD: Write 1 to reload eeprom content.
+ * TYPE_93C46: 1: 93c46, 0:93c66.
+ */
+#define CSR21                          0x0054
+#define CSR21_RELOAD                   FIELD32(0x00000001)
+#define CSR21_EEPROM_DATA_CLOCK                FIELD32(0x00000002)
+#define CSR21_EEPROM_CHIP_SELECT       FIELD32(0x00000004)
+#define CSR21_EEPROM_DATA_IN           FIELD32(0x00000008)
+#define CSR21_EEPROM_DATA_OUT          FIELD32(0x00000010)
+#define CSR21_TYPE_93C46               FIELD32(0x00000020)
+
+/*
+ * CSR22: CFP control register.
+ * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU.
+ * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain.
+ */
+#define CSR22                          0x0058
+#define CSR22_CFP_DURATION_REMAIN      FIELD32(0x0000ffff)
+#define CSR22_RELOAD_CFP_DURATION      FIELD32(0x00010000)
+
+/*
+ * Transmit related CSRs.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * TXCSR0: TX Control Register.
+ * KICK_TX: Kick tx ring.
+ * KICK_ATIM: Kick atim ring.
+ * KICK_PRIO: Kick priority ring.
+ * ABORT: Abort all transmit related ring operation.
+ */
+#define TXCSR0                         0x0060
+#define TXCSR0_KICK_TX                 FIELD32(0x00000001)
+#define TXCSR0_KICK_ATIM               FIELD32(0x00000002)
+#define TXCSR0_KICK_PRIO               FIELD32(0x00000004)
+#define TXCSR0_ABORT                   FIELD32(0x00000008)
+
+/*
+ * TXCSR1: TX Configuration Register.
+ * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps.
+ * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps.
+ * TSF_OFFSET: Insert tsf offset.
+ * AUTORESPONDER: Enable auto responder which include ack & cts.
+ */
+#define TXCSR1                         0x0064
+#define TXCSR1_ACK_TIMEOUT             FIELD32(0x000001ff)
+#define TXCSR1_ACK_CONSUME_TIME                FIELD32(0x0003fe00)
+#define TXCSR1_TSF_OFFSET              FIELD32(0x00fc0000)
+#define TXCSR1_AUTORESPONDER           FIELD32(0x01000000)
+
+/*
+ * TXCSR2: Tx descriptor configuration register.
+ * TXD_SIZE: Tx descriptor size, default is 48.
+ * NUM_TXD: Number of tx entries in ring.
+ * NUM_ATIM: Number of atim entries in ring.
+ * NUM_PRIO: Number of priority entries in ring.
+ */
+#define TXCSR2                         0x0068
+#define TXCSR2_TXD_SIZE                        FIELD32(0x000000ff)
+#define TXCSR2_NUM_TXD                 FIELD32(0x0000ff00)
+#define TXCSR2_NUM_ATIM                        FIELD32(0x00ff0000)
+#define TXCSR2_NUM_PRIO                        FIELD32(0xff000000)
+
+/*
+ * TXCSR3: TX Ring Base address register.
+ */
+#define TXCSR3                         0x006c
+#define TXCSR3_TX_RING_REGISTER                FIELD32(0xffffffff)
+
+/*
+ * TXCSR4: TX Atim Ring Base address register.
+ */
+#define TXCSR4                         0x0070
+#define TXCSR4_ATIM_RING_REGISTER      FIELD32(0xffffffff)
+
+/*
+ * TXCSR5: TX Prio Ring Base address register.
+ */
+#define TXCSR5                         0x0074
+#define TXCSR5_PRIO_RING_REGISTER      FIELD32(0xffffffff)
+
+/*
+ * TXCSR6: Beacon Base address register.
+ */
+#define TXCSR6                         0x0078
+#define TXCSR6_BEACON_RING_REGISTER    FIELD32(0xffffffff)
+
+/*
+ * TXCSR7: Auto responder control register.
+ * AR_POWERMANAGEMENT: Auto responder power management bit.
+ */
+#define TXCSR7                         0x007c
+#define TXCSR7_AR_POWERMANAGEMENT      FIELD32(0x00000001)
+
+/*
+ * TXCSR8: CCK Tx BBP register.
+ */
+#define TXCSR8                         0x0098
+#define TXCSR8_BBP_ID0                 FIELD32(0x0000007f)
+#define TXCSR8_BBP_ID0_VALID           FIELD32(0x00000080)
+#define TXCSR8_BBP_ID1                 FIELD32(0x00007f00)
+#define TXCSR8_BBP_ID1_VALID           FIELD32(0x00008000)
+#define TXCSR8_BBP_ID2                 FIELD32(0x007f0000)
+#define TXCSR8_BBP_ID2_VALID           FIELD32(0x00800000)
+#define TXCSR8_BBP_ID3                 FIELD32(0x7f000000)
+#define TXCSR8_BBP_ID3_VALID           FIELD32(0x80000000)
+
+/*
+ * TXCSR9: OFDM TX BBP registers
+ * OFDM_SIGNAL: BBP rate field address for OFDM.
+ * OFDM_SERVICE: BBP service field address for OFDM.
+ * OFDM_LENGTH_LOW: BBP length low byte address for OFDM.
+ * OFDM_LENGTH_HIGH: BBP length high byte address for OFDM.
+ */
+#define TXCSR9                         0x0094
+#define TXCSR9_OFDM_RATE               FIELD32(0x000000ff)
+#define TXCSR9_OFDM_SERVICE            FIELD32(0x0000ff00)
+#define TXCSR9_OFDM_LENGTH_LOW         FIELD32(0x00ff0000)
+#define TXCSR9_OFDM_LENGTH_HIGH                FIELD32(0xff000000)
+
+/*
+ * Receive related CSRs.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * RXCSR0: RX Control Register.
+ * DISABLE_RX: Disable rx engine.
+ * DROP_CRC: Drop crc error.
+ * DROP_PHYSICAL: Drop physical error.
+ * DROP_CONTROL: Drop control frame.
+ * DROP_NOT_TO_ME: Drop not to me unicast frame.
+ * DROP_TODS: Drop frame tods bit is true.
+ * DROP_VERSION_ERROR: Drop version error frame.
+ * PASS_CRC: Pass all packets with crc attached.
+ * PASS_CRC: Pass all packets with crc attached.
+ * PASS_PLCP: Pass all packets with 4 bytes PLCP attached.
+ * DROP_MCAST: Drop multicast frames.
+ * DROP_BCAST: Drop broadcast frames.
+ * ENABLE_QOS: Accept QOS data frame and parse QOS field.
+ */
+#define RXCSR0                         0x0080
+#define RXCSR0_DISABLE_RX              FIELD32(0x00000001)
+#define RXCSR0_DROP_CRC                        FIELD32(0x00000002)
+#define RXCSR0_DROP_PHYSICAL           FIELD32(0x00000004)
+#define RXCSR0_DROP_CONTROL            FIELD32(0x00000008)
+#define RXCSR0_DROP_NOT_TO_ME          FIELD32(0x00000010)
+#define RXCSR0_DROP_TODS               FIELD32(0x00000020)
+#define RXCSR0_DROP_VERSION_ERROR      FIELD32(0x00000040)
+#define RXCSR0_PASS_CRC                        FIELD32(0x00000080)
+#define RXCSR0_PASS_PLCP               FIELD32(0x00000100)
+#define RXCSR0_DROP_MCAST              FIELD32(0x00000200)
+#define RXCSR0_DROP_BCAST              FIELD32(0x00000400)
+#define RXCSR0_ENABLE_QOS              FIELD32(0x00000800)
+
+/*
+ * RXCSR1: RX descriptor configuration register.
+ * RXD_SIZE: Rx descriptor size, default is 32b.
+ * NUM_RXD: Number of rx entries in ring.
+ */
+#define RXCSR1                         0x0084
+#define RXCSR1_RXD_SIZE                        FIELD32(0x000000ff)
+#define RXCSR1_NUM_RXD                 FIELD32(0x0000ff00)
+
+/*
+ * RXCSR2: RX Ring base address register.
+ */
+#define RXCSR2                         0x0088
+#define RXCSR2_RX_RING_REGISTER                FIELD32(0xffffffff)
+
+/*
+ * RXCSR3: BBP ID register for Rx operation.
+ * BBP_ID#: BBP register # id.
+ * BBP_ID#_VALID: BBP register # id is valid or not.
+ */
+#define RXCSR3                         0x0090
+#define RXCSR3_BBP_ID0                 FIELD32(0x0000007f)
+#define RXCSR3_BBP_ID0_VALID           FIELD32(0x00000080)
+#define RXCSR3_BBP_ID1                 FIELD32(0x00007f00)
+#define RXCSR3_BBP_ID1_VALID           FIELD32(0x00008000)
+#define RXCSR3_BBP_ID2                 FIELD32(0x007f0000)
+#define RXCSR3_BBP_ID2_VALID           FIELD32(0x00800000)
+#define RXCSR3_BBP_ID3                 FIELD32(0x7f000000)
+#define RXCSR3_BBP_ID3_VALID           FIELD32(0x80000000)
+
+/*
+ * ARCSR1: Auto Responder PLCP config register 1.
+ * AR_BBP_DATA#: Auto responder BBP register # data.
+ * AR_BBP_ID#: Auto responder BBP register # Id.
+ */
+#define ARCSR1                         0x009c
+#define ARCSR1_AR_BBP_DATA2            FIELD32(0x000000ff)
+#define ARCSR1_AR_BBP_ID2              FIELD32(0x0000ff00)
+#define ARCSR1_AR_BBP_DATA3            FIELD32(0x00ff0000)
+#define ARCSR1_AR_BBP_ID3              FIELD32(0xff000000)
+
+/*
+ * Miscellaneous Registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+
+ */
+
+/*
+ * PCICSR: PCI control register.
+ * BIG_ENDIAN: 1: big endian, 0: little endian.
+ * RX_TRESHOLD: Rx threshold in dw to start pci access
+ * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
+ * TX_TRESHOLD: Tx threshold in dw to start pci access
+ * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward.
+ * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw.
+ * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational.
+ * READ_MULTIPLE: Enable memory read multiple.
+ * WRITE_INVALID: Enable memory write & invalid.
+ */
+#define PCICSR                         0x008c
+#define PCICSR_BIG_ENDIAN              FIELD32(0x00000001)
+#define PCICSR_RX_TRESHOLD             FIELD32(0x00000006)
+#define PCICSR_TX_TRESHOLD             FIELD32(0x00000018)
+#define PCICSR_BURST_LENTH             FIELD32(0x00000060)
+#define PCICSR_ENABLE_CLK              FIELD32(0x00000080)
+#define PCICSR_READ_MULTIPLE           FIELD32(0x00000100)
+#define PCICSR_WRITE_INVALID           FIELD32(0x00000200)
+
+/*
+ * CNT0: FCS error count.
+ * FCS_ERROR: FCS error count, cleared when read.
+ */
+#define CNT0                           0x00a0
+#define CNT0_FCS_ERROR                 FIELD32(0x0000ffff)
+
+/*
+ * Statistic Register.
+ * CNT1: PLCP error count.
+ * CNT2: Long error count.
+ */
+#define TIMECSR2                       0x00a8
+#define CNT1                           0x00ac
+#define CNT2                           0x00b0
+#define TIMECSR3                       0x00b4
+
+/*
+ * CNT3: CCA false alarm count.
+ */
+#define CNT3                           0x00b8
+#define CNT3_FALSE_CCA                 FIELD32(0x0000ffff)
+
+/*
+ * Statistic Register.
+ * CNT4: Rx FIFO overflow count.
+ * CNT5: Tx FIFO underrun count.
+ */
+#define CNT4                           0x00bc
+#define CNT5                           0x00c0
+
+/*
+ * Baseband Control Register.
+ */
+
+/*
+ * PWRCSR0: Power mode configuration register.
+ */
+#define PWRCSR0                                0x00c4
+
+/*
+ * Power state transition time registers.
+ */
+#define PSCSR0                         0x00c8
+#define PSCSR1                         0x00cc
+#define PSCSR2                         0x00d0
+#define PSCSR3                         0x00d4
+
+/*
+ * PWRCSR1: Manual power control / status register.
+ * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
+ * SET_STATE: Set state. Write 1 to trigger, self cleared.
+ * BBP_DESIRE_STATE: BBP desired state.
+ * RF_DESIRE_STATE: RF desired state.
+ * BBP_CURR_STATE: BBP current state.
+ * RF_CURR_STATE: RF current state.
+ * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
+ */
+#define PWRCSR1                                0x00d8
+#define PWRCSR1_SET_STATE              FIELD32(0x00000001)
+#define PWRCSR1_BBP_DESIRE_STATE       FIELD32(0x00000006)
+#define PWRCSR1_RF_DESIRE_STATE                FIELD32(0x00000018)
+#define PWRCSR1_BBP_CURR_STATE         FIELD32(0x00000060)
+#define PWRCSR1_RF_CURR_STATE          FIELD32(0x00000180)
+#define PWRCSR1_PUT_TO_SLEEP           FIELD32(0x00000200)
+
+/*
+ * TIMECSR: Timer control register.
+ * US_COUNT: 1 us timer count in units of clock cycles.
+ * US_64_COUNT: 64 us timer count in units of 1 us timer.
+ * BEACON_EXPECT: Beacon expect window.
+ */
+#define TIMECSR                                0x00dc
+#define TIMECSR_US_COUNT               FIELD32(0x000000ff)
+#define TIMECSR_US_64_COUNT            FIELD32(0x0000ff00)
+#define TIMECSR_BEACON_EXPECT          FIELD32(0x00070000)
+
+/*
+ * MACCSR0: MAC configuration register 0.
+ */
+#define MACCSR0                                0x00e0
+
+/*
+ * MACCSR1: MAC configuration register 1.
+ * KICK_RX: Kick one-shot rx in one-shot rx mode.
+ * ONESHOT_RXMODE: Enable one-shot rx mode for debugging.
+ * BBPRX_RESET_MODE: Ralink bbp rx reset mode.
+ * AUTO_TXBBP: Auto tx logic access bbp control register.
+ * AUTO_RXBBP: Auto rx logic access bbp control register.
+ * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd.
+ * INTERSIL_IF: Intersil if calibration pin.
+ */
+#define MACCSR1                                0x00e4
+#define MACCSR1_KICK_RX                        FIELD32(0x00000001)
+#define MACCSR1_ONESHOT_RXMODE         FIELD32(0x00000002)
+#define MACCSR1_BBPRX_RESET_MODE       FIELD32(0x00000004)
+#define MACCSR1_AUTO_TXBBP             FIELD32(0x00000008)
+#define MACCSR1_AUTO_RXBBP             FIELD32(0x00000010)
+#define MACCSR1_LOOPBACK               FIELD32(0x00000060)
+#define MACCSR1_INTERSIL_IF            FIELD32(0x00000080)
+
+/*
+ * RALINKCSR: Ralink Rx auto-reset BBCR.
+ * AR_BBP_DATA#: Auto reset BBP register # data.
+ * AR_BBP_ID#: Auto reset BBP register # id.
+ */
+#define RALINKCSR                      0x00e8
+#define RALINKCSR_AR_BBP_DATA0         FIELD32(0x000000ff)
+#define RALINKCSR_AR_BBP_ID0           FIELD32(0x00007f00)
+#define RALINKCSR_AR_BBP_VALID0                FIELD32(0x00008000)
+#define RALINKCSR_AR_BBP_DATA1         FIELD32(0x00ff0000)
+#define RALINKCSR_AR_BBP_ID1           FIELD32(0x7f000000)
+#define RALINKCSR_AR_BBP_VALID1                FIELD32(0x80000000)
+
+/*
+ * BCNCSR: Beacon interval control register.
+ * CHANGE: Write one to change beacon interval.
+ * DELTATIME: The delta time value.
+ * NUM_BEACON: Number of beacon according to mode.
+ * MODE: Please refer to asic specs.
+ * PLUS: Plus or minus delta time value.
+ */
+#define BCNCSR                         0x00ec
+#define BCNCSR_CHANGE                  FIELD32(0x00000001)
+#define BCNCSR_DELTATIME               FIELD32(0x0000001e)
+#define BCNCSR_NUM_BEACON              FIELD32(0x00001fe0)
+#define BCNCSR_MODE                    FIELD32(0x00006000)
+#define BCNCSR_PLUS                    FIELD32(0x00008000)
+
+/*
+ * BBP / RF / IF Control Register.
+ */
+
+/*
+ * BBPCSR: BBP serial control register.
+ * VALUE: Register value to program into BBP.
+ * REGNUM: Selected BBP register.
+ * BUSY: 1: asic is busy execute BBP programming.
+ * WRITE_CONTROL: 1: write BBP, 0: read BBP.
+ */
+#define BBPCSR                         0x00f0
+#define BBPCSR_VALUE                   FIELD32(0x000000ff)
+#define BBPCSR_REGNUM                  FIELD32(0x00007f00)
+#define BBPCSR_BUSY                    FIELD32(0x00008000)
+#define BBPCSR_WRITE_CONTROL           FIELD32(0x00010000)
+
+/*
+ * RFCSR: RF serial control register.
+ * VALUE: Register value + id to program into rf/if.
+ * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
+ * IF_SELECT: Chip to program: 0: rf, 1: if.
+ * PLL_LD: Rf pll_ld status.
+ * BUSY: 1: asic is busy execute rf programming.
+ */
+#define RFCSR                          0x00f4
+#define RFCSR_VALUE                    FIELD32(0x00ffffff)
+#define RFCSR_NUMBER_OF_BITS           FIELD32(0x1f000000)
+#define RFCSR_IF_SELECT                        FIELD32(0x20000000)
+#define RFCSR_PLL_LD                   FIELD32(0x40000000)
+#define RFCSR_BUSY                     FIELD32(0x80000000)
+
+/*
+ * LEDCSR: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ * LINK: 0: linkoff, 1: linkup.
+ * ACTIVITY: 0: idle, 1: active.
+ * LINK_POLARITY: 0: active low, 1: active high.
+ * ACTIVITY_POLARITY: 0: active low, 1: active high.
+ * LED_DEFAULT: LED state for "enable" 0: ON, 1: OFF.
+ */
+#define LEDCSR                         0x00f8
+#define LEDCSR_ON_PERIOD               FIELD32(0x000000ff)
+#define LEDCSR_OFF_PERIOD              FIELD32(0x0000ff00)
+#define LEDCSR_LINK                    FIELD32(0x00010000)
+#define LEDCSR_ACTIVITY                        FIELD32(0x00020000)
+#define LEDCSR_LINK_POLARITY           FIELD32(0x00040000)
+#define LEDCSR_ACTIVITY_POLARITY       FIELD32(0x00080000)
+#define LEDCSR_LED_DEFAULT             FIELD32(0x00100000)
+
+/*
+ * SECCSR3: AES control register.
+ */
+#define SECCSR3                                0x00fc
+
+/*
+ * ASIC pointer information.
+ * RXPTR: Current RX ring address.
+ * TXPTR: Current Tx ring address.
+ * PRIPTR: Current Priority ring address.
+ * ATIMPTR: Current ATIM ring address.
+ */
+#define RXPTR                          0x0100
+#define TXPTR                          0x0104
+#define PRIPTR                         0x0108
+#define ATIMPTR                                0x010c
+
+/*
+ * TXACKCSR0: TX ACK timeout.
+ */
+#define TXACKCSR0                      0x0110
+
+/*
+ * ACK timeout count registers.
+ * ACKCNT0: TX ACK timeout count.
+ * ACKCNT1: RX ACK timeout count.
+ */
+#define ACKCNT0                                0x0114
+#define ACKCNT1                                0x0118
+
+/*
+ * GPIO and others.
+ */
+
+/*
+ * GPIOCSR: GPIO control register.
+ *     GPIOCSR_VALx: GPIO value
+ *     GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
+ */
+#define GPIOCSR                                0x0120
+#define GPIOCSR_VAL0                   FIELD32(0x00000001)
+#define GPIOCSR_VAL1                   FIELD32(0x00000002)
+#define GPIOCSR_VAL2                   FIELD32(0x00000004)
+#define GPIOCSR_VAL3                   FIELD32(0x00000008)
+#define GPIOCSR_VAL4                   FIELD32(0x00000010)
+#define GPIOCSR_VAL5                   FIELD32(0x00000020)
+#define GPIOCSR_VAL6                   FIELD32(0x00000040)
+#define GPIOCSR_VAL7                   FIELD32(0x00000080)
+#define GPIOCSR_DIR0                   FIELD32(0x00000100)
+#define GPIOCSR_DIR1                   FIELD32(0x00000200)
+#define GPIOCSR_DIR2                   FIELD32(0x00000400)
+#define GPIOCSR_DIR3                   FIELD32(0x00000800)
+#define GPIOCSR_DIR4                   FIELD32(0x00001000)
+#define GPIOCSR_DIR5                   FIELD32(0x00002000)
+#define GPIOCSR_DIR6                   FIELD32(0x00004000)
+#define GPIOCSR_DIR7                   FIELD32(0x00008000)
+
+/*
+ * FIFO pointer registers.
+ * FIFOCSR0: TX FIFO pointer.
+ * FIFOCSR1: RX FIFO pointer.
+ */
+#define FIFOCSR0                       0x0128
+#define FIFOCSR1                       0x012c
+
+/*
+ * BCNCSR1: Tx BEACON offset time control register.
+ * PRELOAD: Beacon timer offset in units of usec.
+ * BEACON_CWMIN: 2^CwMin.
+ */
+#define BCNCSR1                                0x0130
+#define BCNCSR1_PRELOAD                        FIELD32(0x0000ffff)
+#define BCNCSR1_BEACON_CWMIN           FIELD32(0x000f0000)
+
+/*
+ * MACCSR2: TX_PE to RX_PE turn-around time control register
+ * DELAY: RX_PE low width, in units of pci clock cycle.
+ */
+#define MACCSR2                                0x0134
+#define MACCSR2_DELAY                  FIELD32(0x000000ff)
+
+/*
+ * TESTCSR: TEST mode selection register.
+ */
+#define TESTCSR                                0x0138
+
+/*
+ * ARCSR2: 1 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR2                         0x013c
+#define ARCSR2_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR2_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR2_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR3: 2 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR3                         0x0140
+#define ARCSR3_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR3_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR3_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR4: 5.5 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR4                         0x0144
+#define ARCSR4_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR4_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR4_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARCSR5: 11 Mbps ACK/CTS PLCP.
+ */
+#define ARCSR5                         0x0148
+#define ARCSR5_SIGNAL                  FIELD32(0x000000ff)
+#define ARCSR5_SERVICE                 FIELD32(0x0000ff00)
+#define ARCSR5_LENGTH                  FIELD32(0xffff0000)
+
+/*
+ * ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps.
+ */
+#define ARTCSR0                                0x014c
+#define ARTCSR0_ACK_CTS_11MBS          FIELD32(0x000000ff)
+#define ARTCSR0_ACK_CTS_5_5MBS         FIELD32(0x0000ff00)
+#define ARTCSR0_ACK_CTS_2MBS           FIELD32(0x00ff0000)
+#define ARTCSR0_ACK_CTS_1MBS           FIELD32(0xff000000)
+
+
+/*
+ * ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
+#define ARTCSR1                                0x0150
+#define ARTCSR1_ACK_CTS_6MBS           FIELD32(0x000000ff)
+#define ARTCSR1_ACK_CTS_9MBS           FIELD32(0x0000ff00)
+#define ARTCSR1_ACK_CTS_12MBS          FIELD32(0x00ff0000)
+#define ARTCSR1_ACK_CTS_18MBS          FIELD32(0xff000000)
+
+/*
+ * ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
+#define ARTCSR2                                0x0154
+#define ARTCSR2_ACK_CTS_24MBS          FIELD32(0x000000ff)
+#define ARTCSR2_ACK_CTS_36MBS          FIELD32(0x0000ff00)
+#define ARTCSR2_ACK_CTS_48MBS          FIELD32(0x00ff0000)
+#define ARTCSR2_ACK_CTS_54MBS          FIELD32(0xff000000)
+
+/*
+ * SECCSR1: WEP control register.
+ * KICK_ENCRYPT: Kick encryption engine, self-clear.
+ * ONE_SHOT: 0: ring mode, 1: One shot only mode.
+ * DESC_ADDRESS: Descriptor physical address of frame.
+ */
+#define SECCSR1                                0x0158
+#define SECCSR1_KICK_ENCRYPT           FIELD32(0x00000001)
+#define SECCSR1_ONE_SHOT               FIELD32(0x00000002)
+#define SECCSR1_DESC_ADDRESS           FIELD32(0xfffffffc)
+
+/*
+ * BBPCSR1: BBP TX configuration.
+ */
+#define BBPCSR1                                0x015c
+#define BBPCSR1_CCK                    FIELD32(0x00000003)
+#define BBPCSR1_CCK_FLIP               FIELD32(0x00000004)
+#define BBPCSR1_OFDM                   FIELD32(0x00030000)
+#define BBPCSR1_OFDM_FLIP              FIELD32(0x00040000)
+
+/*
+ * Dual band configuration registers.
+ * DBANDCSR0: Dual band configuration register 0.
+ * DBANDCSR1: Dual band configuration register 1.
+ */
+#define DBANDCSR0                      0x0160
+#define DBANDCSR1                      0x0164
+
+/*
+ * BBPPCSR: BBP Pin control register.
+ */
+#define BBPPCSR                                0x0168
+
+/*
+ * MAC special debug mode selection registers.
+ * DBGSEL0: MAC special debug mode selection register 0.
+ * DBGSEL1: MAC special debug mode selection register 1.
+ */
+#define DBGSEL0                                0x016c
+#define DBGSEL1                                0x0170
+
+/*
+ * BISTCSR: BBP BIST register.
+ */
+#define BISTCSR                                0x0174
+
+/*
+ * Multicast filter registers.
+ * MCAST0: Multicast filter register 0.
+ * MCAST1: Multicast filter register 1.
+ */
+#define MCAST0                         0x0178
+#define MCAST1                         0x017c
+
+/*
+ * UART registers.
+ * UARTCSR0: UART1 TX register.
+ * UARTCSR1: UART1 RX register.
+ * UARTCSR3: UART1 frame control register.
+ * UARTCSR4: UART1 buffer control register.
+ * UART2CSR0: UART2 TX register.
+ * UART2CSR1: UART2 RX register.
+ * UART2CSR3: UART2 frame control register.
+ * UART2CSR4: UART2 buffer control register.
+ */
+#define UARTCSR0                       0x0180
+#define UARTCSR1                       0x0184
+#define UARTCSR3                       0x0188
+#define UARTCSR4                       0x018c
+#define UART2CSR0                      0x0190
+#define UART2CSR1                      0x0194
+#define UART2CSR3                      0x0198
+#define UART2CSR4                      0x019c
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2: TX antenna control
+ */
+#define BBP_R2_TX_ANTENNA              FIELD8(0x03)
+#define BBP_R2_TX_IQ_FLIP              FIELD8(0x04)
+
+/*
+ * R14: RX antenna control
+ */
+#define BBP_R14_RX_ANTENNA             FIELD8(0x03)
+#define BBP_R14_RX_IQ_FLIP             FIELD8(0x04)
+
+/*
+ * BBP_R70
+ */
+#define BBP_R70_JAPAN_FILTER           FIELD8(0x08)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 1
+ */
+#define RF1_TUNER                      FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TUNER                      FIELD32(0x00000100)
+#define RF3_TXPOWER                    FIELD32(0x00003e00)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0              0x0002
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1               0x0003
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2              0x0004
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM antenna.
+ * ANTENNA_NUM: Number of antenna's.
+ * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd.
+ * DYN_TXAGC: Dynamic TX AGC control.
+ * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
+ * RF_TYPE: Rf_type of this adapter.
+ */
+#define EEPROM_ANTENNA                 0x10
+#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
+#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
+#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
+#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x01c0)
+#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
+#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
+#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
+
+/*
+ * EEPROM NIC config.
+ * CARDBUS_ACCEL: 0: enable, 1: disable.
+ * DYN_BBP_TUNE: 0: enable, 1: disable.
+ * CCK_TX_POWER: CCK TX power compensation.
+ */
+#define EEPROM_NIC                     0x11
+#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0001)
+#define EEPROM_NIC_DYN_BBP_TUNE                FIELD16(0x0002)
+#define EEPROM_NIC_CCK_TX_POWER                FIELD16(0x000c)
+
+/*
+ * EEPROM geography.
+ * GEO: Default geography setting for device.
+ */
+#define EEPROM_GEOGRAPHY               0x12
+#define EEPROM_GEOGRAPHY_GEO           FIELD16(0x0f00)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START               0x13
+#define EEPROM_BBP_SIZE                        16
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER
+ */
+#define EEPROM_TXPOWER_START           0x23
+#define EEPROM_TXPOWER_SIZE            7
+#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
+#define EEPROM_TXPOWER_2               FIELD16(0xff00)
+
+/*
+ * RSSI <-> dBm offset calibration
+ */
+#define EEPROM_CALIBRATE_OFFSET                0x3e
+#define EEPROM_CALIBRATE_OFFSET_RSSI   FIELD16(0x00ff)
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  (11 * sizeof(__le32))
+#define RXD_DESC_SIZE                  (11 * sizeof(__le32))
+
+/*
+ * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define TXD_W0_VALID                   FIELD32(0x00000002)
+#define TXD_W0_RESULT                  FIELD32(0x0000001c)
+#define TXD_W0_RETRY_COUNT             FIELD32(0x000000e0)
+#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
+#define TXD_W0_ACK                     FIELD32(0x00000200)
+#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
+#define TXD_W0_OFDM                    FIELD32(0x00000800)
+#define TXD_W0_CIPHER_OWNER            FIELD32(0x00001000)
+#define TXD_W0_IFS                     FIELD32(0x00006000)
+#define TXD_W0_RETRY_MODE              FIELD32(0x00008000)
+#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * Word1
+ */
+#define TXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
+
+/*
+ * Word2
+ */
+#define TXD_W2_IV_OFFSET               FIELD32(0x0000003f)
+#define TXD_W2_AIFS                    FIELD32(0x000000c0)
+#define TXD_W2_CWMIN                   FIELD32(0x00000f00)
+#define TXD_W2_CWMAX                   FIELD32(0x0000f000)
+
+/*
+ * Word3: PLCP information
+ */
+#define TXD_W3_PLCP_SIGNAL             FIELD32(0x000000ff)
+#define TXD_W3_PLCP_SERVICE            FIELD32(0x0000ff00)
+#define TXD_W3_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
+
+/*
+ * Word4
+ */
+#define TXD_W4_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word5
+ */
+#define TXD_W5_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word6-9: Key
+ */
+#define TXD_W6_KEY                     FIELD32(0xffffffff)
+#define TXD_W7_KEY                     FIELD32(0xffffffff)
+#define TXD_W8_KEY                     FIELD32(0xffffffff)
+#define TXD_W9_KEY                     FIELD32(0xffffffff)
+
+/*
+ * Word10
+ */
+#define TXD_W10_RTS                    FIELD32(0x00000001)
+#define TXD_W10_TX_RATE                        FIELD32(0x000000fe)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ */
+#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
+#define RXD_W0_MULTICAST               FIELD32(0x00000004)
+#define RXD_W0_BROADCAST               FIELD32(0x00000008)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
+#define RXD_W0_OFDM                    FIELD32(0x00000040)
+#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
+#define RXD_W0_CIPHER_OWNER            FIELD32(0x00000100)
+#define RXD_W0_ICV_ERROR               FIELD32(0x00000200)
+#define RXD_W0_IV_OFFSET               FIELD32(0x0000fc00)
+#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * Word1
+ */
+#define RXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
+
+/*
+ * Word2
+ */
+#define RXD_W2_SIGNAL                  FIELD32(0x000000ff)
+#define RXD_W2_RSSI                    FIELD32(0x0000ff00)
+#define RXD_W2_TA                      FIELD32(0xffff0000)
+
+/*
+ * Word3
+ */
+#define RXD_W3_TA                      FIELD32(0xffffffff)
+
+/*
+ * Word4
+ */
+#define RXD_W4_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word5
+ */
+#define RXD_W5_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word6-9: Key
+ */
+#define RXD_W6_KEY                     FIELD32(0xffffffff)
+#define RXD_W7_KEY                     FIELD32(0xffffffff)
+#define RXD_W8_KEY                     FIELD32(0xffffffff)
+#define RXD_W9_KEY                     FIELD32(0xffffffff)
+
+/*
+ * Word10
+ */
+#define RXD_W10_DROP                   FIELD32(0x00000001)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_TXPOWER    0
+#define MAX_TXPOWER    31
+#define DEFAULT_TXPOWER        24
+
+#define TXPOWER_FROM_DEV(__txpower) \
+       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
+
+#endif /* RT2500PCI_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
new file mode 100644 (file)
index 0000000..b50d873
--- /dev/null
@@ -0,0 +1,2001 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2500usb
+       Abstract: rt2500usb device specific routines.
+       Supported chipsets: RT2570.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "rt2x00.h"
+#include "rt2x00usb.h"
+#include "rt2500usb.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static bool modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2500usb_register_read and rt2500usb_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_USB_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ * If the csr_mutex is already held then the _lock variants must
+ * be used instead.
+ */
+static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                          const unsigned int offset,
+                                          u16 *value)
+{
+       __le16 reg;
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+                                     USB_VENDOR_REQUEST_IN, offset,
+                                     &reg, sizeof(reg));
+       *value = le16_to_cpu(reg);
+}
+
+static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               u16 *value)
+{
+       __le16 reg;
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+                                      USB_VENDOR_REQUEST_IN, offset,
+                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
+       *value = le16_to_cpu(reg);
+}
+
+static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               void *value, const u16 length)
+{
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+                                     USB_VENDOR_REQUEST_IN, offset,
+                                     value, length);
+}
+
+static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
+                                           const unsigned int offset,
+                                           u16 value)
+{
+       __le16 reg = cpu_to_le16(value);
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+                                     USB_VENDOR_REQUEST_OUT, offset,
+                                     &reg, sizeof(reg));
+}
+
+static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                u16 value)
+{
+       __le16 reg = cpu_to_le16(value);
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+                                      USB_VENDOR_REQUEST_OUT, offset,
+                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
+}
+
+static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                void *value, const u16 length)
+{
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+                                     USB_VENDOR_REQUEST_OUT, offset,
+                                     value, length);
+}
+
+static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                                 const unsigned int offset,
+                                 struct rt2x00_field16 field,
+                                 u16 *reg)
+{
+       unsigned int i;
+
+       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+               rt2500usb_register_read_lock(rt2x00dev, offset, reg);
+               if (!rt2x00_get_field16(*reg, field))
+                       return 1;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+                  offset, *reg);
+       *reg = ~0;
+
+       return 0;
+}
+
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
+
+static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
+                               const unsigned int word, const u8 value)
+{
+       u16 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR7_DATA, value);
+               rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
+               rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
+
+               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, u8 *value)
+{
+       u16 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
+               rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
+
+               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+
+               if (WAIT_FOR_BBP(rt2x00dev, &reg))
+                       rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
+       }
+
+       *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, const u32 value)
+{
+       u16 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
+               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
+
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
+               rt2x00_set_field16(&reg, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
+               rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
+               rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
+
+               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                    const unsigned int offset,
+                                    u32 *value)
+{
+       rt2500usb_register_read(rt2x00dev, offset, (u16 *)value);
+}
+
+static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
+                                     const unsigned int offset,
+                                     u32 value)
+{
+       rt2500usb_register_write(rt2x00dev, offset, value);
+}
+
+static const struct rt2x00debug rt2500usb_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = _rt2500usb_register_read,
+               .write          = _rt2500usb_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = CSR_REG_SIZE / sizeof(u16),
+       },
+       .eeprom = {
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt2500usb_bbp_read,
+               .write          = rt2500usb_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt2500usb_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u16 reg;
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
+                                    enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       u16 reg;
+
+       rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
+
+       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
+               rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
+       else if (led->type == LED_TYPE_ACTIVITY)
+               rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, enabled);
+
+       rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
+}
+
+static int rt2500usb_blink_set(struct led_classdev *led_cdev,
+                              unsigned long *delay_on,
+                              unsigned long *delay_off)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       u16 reg;
+
+       rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
+       rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
+       rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
+
+       return 0;
+}
+
+static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00_led *led,
+                              enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt2500usb_brightness_set;
+       led->led_dev.blink_set = rt2500usb_blink_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+
+/*
+ * rt2500usb does not differentiate between shared and pairwise
+ * keys, so we should use the same function for both key types.
+ */
+static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_crypto *crypto,
+                               struct ieee80211_key_conf *key)
+{
+       u32 mask;
+       u16 reg;
+       enum cipher curr_cipher;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * Disallow to set WEP key other than with index 0,
+                * it is known that not work at least on some hardware.
+                * SW crypto will be used in that case.
+                */
+               if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+                    key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+                   key->keyidx != 0)
+                       return -EOPNOTSUPP;
+
+               /*
+                * Pairwise key will always be entry 0, but this
+                * could collide with a shared key on the same
+                * position...
+                */
+               mask = TXRX_CSR0_KEY_ID.bit_mask;
+
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
+               reg &= mask;
+
+               if (reg && reg == mask)
+                       return -ENOSPC;
+
+               reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+
+               key->hw_key_idx += reg ? ffz(reg) : 0;
+               /*
+                * Hardware requires that all keys use the same cipher
+                * (e.g. TKIP-only, AES-only, but not TKIP+AES).
+                * If this is not the first key, compare the cipher with the
+                * first one and fall back to SW crypto if not the same.
+                */
+               if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
+                       return -EOPNOTSUPP;
+
+               rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx),
+                                             crypto->key, sizeof(crypto->key));
+
+               /*
+                * The driver does not support the IV/EIV generation
+                * in hardware. However it demands the data to be provided
+                * both separately as well as inside the frame.
+                * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
+                * to ensure rt2x00lib will not strip the data from the
+                * frame after the copy, now we must tell mac80211
+                * to generate the IV/EIV data.
+                */
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+       }
+
+       /*
+        * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
+        * a particular key is valid.
+        */
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
+       rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
+
+       mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+       if (crypto->cmd == SET_KEY)
+               mask |= 1 << key->hw_key_idx;
+       else if (crypto->cmd == DISABLE_KEY)
+               mask &= ~(1 << key->hw_key_idx);
+       rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, mask);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       return 0;
+}
+
+static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int filter_flags)
+{
+       u16 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
+                          !rt2x00dev->intf_ap_count);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
+                          !(filter_flags & FIF_ALLMULTI));
+       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+}
+
+static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
+                                 struct rt2x00_intf *intf,
+                                 struct rt2x00intf_conf *conf,
+                                 const unsigned int flags)
+{
+       unsigned int bcn_preload;
+       u16 reg;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable beacon config
+                */
+               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
+               rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
+                                  2 * (conf->type != NL80211_IFTYPE_STATION));
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
+
+               /*
+                * Enable synchronisation.
+                */
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+       }
+
+       if (flags & CONFIG_UPDATE_MAC)
+               rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
+                                             (3 * sizeof(__le16)));
+
+       if (flags & CONFIG_UPDATE_BSSID)
+               rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
+                                             (3 * sizeof(__le16)));
+}
+
+static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
+                                struct rt2x00lib_erp *erp,
+                                u32 changed)
+{
+       u16 reg;
+
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
+                                  !!erp->short_preamble);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
+                                        erp->basic_rates);
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
+                                  erp->beacon_int * 4);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
+       }
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
+       }
+}
+
+static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
+                                struct antenna_setup *ant)
+{
+       u8 r2;
+       u8 r14;
+       u16 csr5;
+       u16 csr6;
+
+       /*
+        * We should never come here because rt2x00lib is supposed
+        * to catch this and send us the correct antenna explicitely.
+        */
+       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+              ant->tx == ANTENNA_SW_DIVERSITY);
+
+       rt2500usb_bbp_read(rt2x00dev, 2, &r2);
+       rt2500usb_bbp_read(rt2x00dev, 14, &r14);
+       rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
+       rt2500usb_register_read(rt2x00dev, PHY_CSR6, &csr6);
+
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1);
+               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1);
+               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
+               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
+               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
+               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+               break;
+       }
+
+       /*
+        * RT2525E and RT5222 need to flip TX I/Q
+        */
+       if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
+               rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
+               rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
+               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1);
+
+               /*
+                * RT2525E does not need RX I/Q Flip.
+                */
+               if (rt2x00_rf(rt2x00dev, RF2525E))
+                       rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
+       } else {
+               rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
+               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 0);
+       }
+
+       rt2500usb_bbp_write(rt2x00dev, 2, r2);
+       rt2500usb_bbp_write(rt2x00dev, 14, r14);
+       rt2500usb_register_write(rt2x00dev, PHY_CSR5, csr5);
+       rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6);
+}
+
+static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
+                                    struct rf_channel *rf, const int txpower)
+{
+       /*
+        * Set TXpower.
+        */
+       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+
+       /*
+        * For RT2525E we should first set the channel to half band higher.
+        */
+       if (rt2x00_rf(rt2x00dev, RF2525E)) {
+               static const u32 vals[] = {
+                       0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
+                       0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
+                       0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
+                       0x00000902, 0x00000906
+               };
+
+               rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+               if (rf->rf4)
+                       rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+       }
+
+       rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
+       if (rf->rf4)
+               rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+                                    const int txpower)
+{
+       u32 rf3;
+
+       rt2x00_rf_read(rt2x00dev, 3, &rf3);
+       rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+       rt2500usb_rf_write(rt2x00dev, 3, rf3);
+}
+
+static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u16 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
+                                  rt2x00dev->beacon_int - 20);
+               rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+       } else {
+               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
+               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+       }
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
+static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_conf *libconf,
+                            const unsigned int flags)
+{
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt2500usb_config_channel(rt2x00dev, &libconf->rf,
+                                        libconf->conf->power_level);
+       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
+               rt2500usb_config_txpower(rt2x00dev,
+                                        libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2500usb_config_ps(rt2x00dev, libconf);
+}
+
+/*
+ * Link tuning
+ */
+static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
+                                struct link_qual *qual)
+{
+       u16 reg;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
+
+       /*
+        * Update False CCA count from register.
+        */
+       rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
+       qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
+}
+
+static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual)
+{
+       u16 eeprom;
+       u16 value;
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom);
+       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW);
+       rt2500usb_bbp_write(rt2x00dev, 24, value);
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom);
+       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW);
+       rt2500usb_bbp_write(rt2x00dev, 25, value);
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom);
+       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW);
+       rt2500usb_bbp_write(rt2x00dev, 61, value);
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom);
+       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
+       rt2500usb_bbp_write(rt2x00dev, 17, value);
+
+       qual->vgc_level = value;
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt2500usb_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u16 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+               break;
+       case QID_BEACON:
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
+               rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+               rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2500usb_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u16 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+               break;
+       case QID_BEACON:
+               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+               rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+               rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Initialization functions.
+ */
+static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u16 reg;
+
+       rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001,
+                                   USB_MODE_TEST, REGISTER_TIMEOUT);
+       rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308,
+                                   0x00f0, REGISTER_TIMEOUT);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+
+       rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 1);
+       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 1);
+       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
+       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
+       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR5, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
+       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1, 12);
+       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1_VALID, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR6, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0, 10);
+       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0_VALID, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1, 11);
+       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1_VALID, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0, 7);
+       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0_VALID, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1, 6);
+       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1_VALID, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0, 5);
+       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0_VALID, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               return -EBUSY;
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
+       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
+       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
+               rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
+       } else {
+               reg = 0;
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 1);
+               rt2x00_set_field16(&reg, PHY_CSR2_LNA_MODE, 3);
+       }
+       rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg);
+
+       rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0002);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR22, 0x0053);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000);
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR8_MAX_FRAME_UNIT,
+                          rt2x00dev->rx->data_size);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
+       rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
+       rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON, 90);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
+
+       rt2500usb_register_read(rt2x00dev, PHY_CSR4, &reg);
+       rt2x00_set_field16(&reg, PHY_CSR4_LOW_RF_LE, 1);
+       rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg);
+
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR1_AUTO_SEQUENCE, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+
+       return 0;
+}
+
+static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+               rt2500usb_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 value;
+       u8 reg_id;
+
+       if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
+
+       rt2500usb_bbp_write(rt2x00dev, 3, 0x02);
+       rt2500usb_bbp_write(rt2x00dev, 4, 0x19);
+       rt2500usb_bbp_write(rt2x00dev, 14, 0x1c);
+       rt2500usb_bbp_write(rt2x00dev, 15, 0x30);
+       rt2500usb_bbp_write(rt2x00dev, 16, 0xac);
+       rt2500usb_bbp_write(rt2x00dev, 18, 0x18);
+       rt2500usb_bbp_write(rt2x00dev, 19, 0xff);
+       rt2500usb_bbp_write(rt2x00dev, 20, 0x1e);
+       rt2500usb_bbp_write(rt2x00dev, 21, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 22, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 23, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 24, 0x80);
+       rt2500usb_bbp_write(rt2x00dev, 25, 0x50);
+       rt2500usb_bbp_write(rt2x00dev, 26, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 27, 0x23);
+       rt2500usb_bbp_write(rt2x00dev, 30, 0x10);
+       rt2500usb_bbp_write(rt2x00dev, 31, 0x2b);
+       rt2500usb_bbp_write(rt2x00dev, 32, 0xb9);
+       rt2500usb_bbp_write(rt2x00dev, 34, 0x12);
+       rt2500usb_bbp_write(rt2x00dev, 35, 0x50);
+       rt2500usb_bbp_write(rt2x00dev, 39, 0xc4);
+       rt2500usb_bbp_write(rt2x00dev, 40, 0x02);
+       rt2500usb_bbp_write(rt2x00dev, 41, 0x60);
+       rt2500usb_bbp_write(rt2x00dev, 53, 0x10);
+       rt2500usb_bbp_write(rt2x00dev, 54, 0x18);
+       rt2500usb_bbp_write(rt2x00dev, 56, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 57, 0x10);
+       rt2500usb_bbp_write(rt2x00dev, 58, 0x08);
+       rt2500usb_bbp_write(rt2x00dev, 61, 0x60);
+       rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
+       rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt2500usb_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Initialize all registers.
+        */
+       if (unlikely(rt2500usb_init_registers(rt2x00dev) ||
+                    rt2500usb_init_bbp(rt2x00dev)))
+               return -EIO;
+
+       return 0;
+}
+
+static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
+
+       /*
+        * Disable synchronisation.
+        */
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
+
+       rt2x00usb_disable_radio(rt2x00dev);
+}
+
+static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       u16 reg;
+       u16 reg2;
+       unsigned int i;
+       char put_to_sleep;
+       char bbp_state;
+       char rf_state;
+
+       put_to_sleep = (state != STATE_AWAKE);
+
+       reg = 0;
+       rt2x00_set_field16(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
+       rt2x00_set_field16(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
+       rt2x00_set_field16(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
+       rt2x00_set_field16(&reg, MAC_CSR17_SET_STATE, 1);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
+
+       /*
+        * Device is not guaranteed to be in the requested state yet.
+        * We must wait until the register indicates that the
+        * device has entered the correct state.
+        */
+       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+               rt2500usb_register_read(rt2x00dev, MAC_CSR17, &reg2);
+               bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
+               rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
+               if (bbp_state == state && rf_state == state)
+                       return 0;
+               rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
+               msleep(30);
+       }
+
+       return -EBUSY;
+}
+
+static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt2500usb_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               rt2500usb_disable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               /* No support, but no error either */
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt2500usb_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt2500usb_write_tx_desc(struct queue_entry *entry,
+                                   struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *txd = (__le32 *) entry->skb->data;
+       u32 word;
+
+       /*
+        * Start writing the descriptor words.
+        */
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
+       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_OFDM,
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
+       rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
+                          test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
+       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
+       rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
+       rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
+       rt2x00_desc_write(txd, 0, word);
+
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
+       rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
+       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
+       rt2x00_desc_write(txd, 1, word);
+
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
+       rt2x00_desc_write(txd, 2, word);
+
+       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
+       }
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
+       skbdesc->desc = txd;
+       skbdesc->desc_len = TXD_DESC_SIZE;
+}
+
+/*
+ * TX data initialization
+ */
+static void rt2500usb_beacondone(struct urb *urb);
+
+static void rt2500usb_write_beacon(struct queue_entry *entry,
+                                  struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+       int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
+       int length;
+       u16 reg, reg0;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
+       /*
+        * Add space for the descriptor in front of the skb.
+        */
+       skb_push(entry->skb, TXD_DESC_SIZE);
+       memset(entry->skb->data, 0, TXD_DESC_SIZE);
+
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt2500usb_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
+       /*
+        * USB devices cannot blindly pass the skb->len as the
+        * length of the data to usb_fill_bulk_urb. Pass the skb
+        * to the driver to determine what the length should be.
+        */
+       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+
+       usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
+                         entry->skb->data, length, rt2500usb_beacondone,
+                         entry);
+
+       /*
+        * Second we need to create the guardian byte.
+        * We only need a single byte, so lets recycle
+        * the 'flags' field we are not using for beacons.
+        */
+       bcn_priv->guardian_data = 0;
+       usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
+                         &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
+                         entry);
+
+       /*
+        * Send out the guardian byte.
+        */
+       usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
+
+       /*
+        * Enable beaconing again.
+        */
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+       reg0 = reg;
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
+       /*
+        * Beacon generation will fail initially.
+        * To prevent this we need to change the TXRX_CSR19
+        * register several times (reg0 is the same as reg
+        * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
+        * and 1 in reg).
+        */
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+}
+
+static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
+{
+       int length;
+
+       /*
+        * The length _must_ be a multiple of 2,
+        * but it must _not_ be a multiple of the USB packet size.
+        */
+       length = roundup(entry->skb->len, 2);
+       length += (2 * !(length % entry->queue->usb_maxpacket));
+
+       return length;
+}
+
+/*
+ * RX control handlers
+ */
+static void rt2500usb_fill_rxdone(struct queue_entry *entry,
+                                 struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *rxd =
+           (__le32 *)(entry->skb->data +
+                      (entry_priv->urb->actual_length -
+                       entry->queue->desc_size));
+       u32 word0;
+       u32 word1;
+
+       /*
+        * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
+        * frame data in rt2x00usb.
+        */
+       memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
+       rxd = (__le32 *)skbdesc->desc;
+
+       /*
+        * It is now safe to read the descriptor on all architectures.
+        */
+       rt2x00_desc_read(rxd, 0, &word0);
+       rt2x00_desc_read(rxd, 1, &word1);
+
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+
+       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
+       if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
+               rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
+
+       if (rxdesc->cipher != CIPHER_NONE) {
+               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
+               /* ICV is located at the end of frame */
+
+               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+                       rxdesc->flags |= RX_FLAG_DECRYPTED;
+               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+       }
+
+       /*
+        * Obtain the status about this packet.
+        * When frame was received with an OFDM bitrate,
+        * the signal is the PLCP value. If it was received with
+        * a CCK bitrate the signal is the rate in 100kbit/s.
+        */
+       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       rxdesc->rssi =
+           rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset;
+       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+
+       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
+               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+       else
+               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
+       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+       /*
+        * Adjust the skb memory window to the frame boundaries.
+        */
+       skb_trim(entry->skb, rxdesc->size);
+}
+
+/*
+ * Interrupt functions.
+ */
+static void rt2500usb_beacondone(struct urb *urb)
+{
+       struct queue_entry *entry = (struct queue_entry *)urb->context;
+       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
+               return;
+
+       /*
+        * Check if this was the guardian beacon,
+        * if that was the case we need to send the real beacon now.
+        * Otherwise we should free the sk_buffer, the device
+        * should be doing the rest of the work now.
+        */
+       if (bcn_priv->guardian_urb == urb) {
+               usb_submit_urb(bcn_priv->urb, GFP_ATOMIC);
+       } else if (bcn_priv->urb == urb) {
+               dev_kfree_skb(entry->skb);
+               entry->skb = NULL;
+       }
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+       u8 *mac;
+       u8 bbp;
+
+       rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+                                  ANTENNA_SW_DIVERSITY);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
+                                  LED_MODE_DEFAULT);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
+                                  DEFAULT_RSSI_OFFSET);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+                                 word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);
+       }
+
+       /*
+        * Switch lower vgc bound to current BBP R17 value,
+        * lower the value a bit for better quality.
+        */
+       rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
+       bbp -= 6;
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
+       } else {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
+               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
+       }
+
+       return 0;
+}
+
+static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u16 reg;
+       u16 value;
+       u16 eeprom;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+       /*
+        * Identify RF chipset.
+        */
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+       rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+       rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
+
+       if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
+               rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
+               return -ENODEV;
+       }
+
+       if (!rt2x00_rf(rt2x00dev, RF2522) &&
+           !rt2x00_rf(rt2x00dev, RF2523) &&
+           !rt2x00_rf(rt2x00dev, RF2524) &&
+           !rt2x00_rf(rt2x00dev, RF2525) &&
+           !rt2x00_rf(rt2x00dev, RF2525E) &&
+           !rt2x00_rf(rt2x00dev, RF5222)) {
+               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
+       rt2x00dev->default_ant.rx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
+
+       /*
+        * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
+        * I am not 100% sure about this, but the legacy drivers do not
+        * indicate antenna swapping in software is required when
+        * diversity is enabled.
+        */
+       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
+       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
+
+       /*
+        * Store led mode, for correct led behaviour.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
+
+       rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       if (value == LED_MODE_TXRX_ACTIVITY ||
+           value == LED_MODE_DEFAULT ||
+           value == LED_MODE_ASUS)
+               rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                  LED_TYPE_ACTIVITY);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+
+       /*
+        * Read the RSSI <-> dBm offset information.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
+       rt2x00dev->rssi_offset =
+           rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
+
+       return 0;
+}
+
+/*
+ * RF value list for RF2522
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2522[] = {
+       { 1,  0x00002050, 0x000c1fda, 0x00000101, 0 },
+       { 2,  0x00002050, 0x000c1fee, 0x00000101, 0 },
+       { 3,  0x00002050, 0x000c2002, 0x00000101, 0 },
+       { 4,  0x00002050, 0x000c2016, 0x00000101, 0 },
+       { 5,  0x00002050, 0x000c202a, 0x00000101, 0 },
+       { 6,  0x00002050, 0x000c203e, 0x00000101, 0 },
+       { 7,  0x00002050, 0x000c2052, 0x00000101, 0 },
+       { 8,  0x00002050, 0x000c2066, 0x00000101, 0 },
+       { 9,  0x00002050, 0x000c207a, 0x00000101, 0 },
+       { 10, 0x00002050, 0x000c208e, 0x00000101, 0 },
+       { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 },
+       { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 },
+       { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 },
+       { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 },
+};
+
+/*
+ * RF value list for RF2523
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2523[] = {
+       { 1,  0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b },
+       { 2,  0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b },
+       { 3,  0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b },
+       { 4,  0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b },
+       { 5,  0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b },
+       { 6,  0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b },
+       { 7,  0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b },
+       { 8,  0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b },
+       { 9,  0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b },
+       { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b },
+       { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b },
+       { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b },
+       { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b },
+       { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2524
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2524[] = {
+       { 1,  0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b },
+       { 2,  0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b },
+       { 3,  0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b },
+       { 4,  0x00032020, 0x00000caa, 0x00000101, 0x00000a1b },
+       { 5,  0x00032020, 0x00000cae, 0x00000101, 0x00000a1b },
+       { 6,  0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b },
+       { 7,  0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b },
+       { 8,  0x00032020, 0x00000cba, 0x00000101, 0x00000a1b },
+       { 9,  0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b },
+       { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b },
+       { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b },
+       { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b },
+       { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b },
+       { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2525
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2525[] = {
+       { 1,  0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b },
+       { 2,  0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b },
+       { 3,  0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b },
+       { 4,  0x00022020, 0x00080caa, 0x00060111, 0x00000a1b },
+       { 5,  0x00022020, 0x00080cae, 0x00060111, 0x00000a1b },
+       { 6,  0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b },
+       { 7,  0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b },
+       { 8,  0x00022020, 0x00080cba, 0x00060111, 0x00000a1b },
+       { 9,  0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b },
+       { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b },
+       { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b },
+       { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b },
+       { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b },
+       { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 },
+};
+
+/*
+ * RF value list for RF2525e
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2525e[] = {
+       { 1,  0x00022010, 0x0000089a, 0x00060111, 0x00000e1b },
+       { 2,  0x00022010, 0x0000089e, 0x00060111, 0x00000e07 },
+       { 3,  0x00022010, 0x0000089e, 0x00060111, 0x00000e1b },
+       { 4,  0x00022010, 0x000008a2, 0x00060111, 0x00000e07 },
+       { 5,  0x00022010, 0x000008a2, 0x00060111, 0x00000e1b },
+       { 6,  0x00022010, 0x000008a6, 0x00060111, 0x00000e07 },
+       { 7,  0x00022010, 0x000008a6, 0x00060111, 0x00000e1b },
+       { 8,  0x00022010, 0x000008aa, 0x00060111, 0x00000e07 },
+       { 9,  0x00022010, 0x000008aa, 0x00060111, 0x00000e1b },
+       { 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 },
+       { 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b },
+       { 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 },
+       { 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b },
+       { 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 },
+};
+
+/*
+ * RF value list for RF5222
+ * Supports: 2.4 GHz & 5.2 GHz
+ */
+static const struct rf_channel rf_vals_5222[] = {
+       { 1,  0x00022020, 0x00001136, 0x00000101, 0x00000a0b },
+       { 2,  0x00022020, 0x0000113a, 0x00000101, 0x00000a0b },
+       { 3,  0x00022020, 0x0000113e, 0x00000101, 0x00000a0b },
+       { 4,  0x00022020, 0x00001182, 0x00000101, 0x00000a0b },
+       { 5,  0x00022020, 0x00001186, 0x00000101, 0x00000a0b },
+       { 6,  0x00022020, 0x0000118a, 0x00000101, 0x00000a0b },
+       { 7,  0x00022020, 0x0000118e, 0x00000101, 0x00000a0b },
+       { 8,  0x00022020, 0x00001192, 0x00000101, 0x00000a0b },
+       { 9,  0x00022020, 0x00001196, 0x00000101, 0x00000a0b },
+       { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b },
+       { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b },
+       { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b },
+       { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b },
+       { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f },
+       { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f },
+       { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f },
+       { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f },
+       { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f },
+       { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f },
+       { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f },
+       { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f },
+       { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f },
+       { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f },
+       { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f },
+       { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f },
+       { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f },
+       { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f },
+       { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f },
+       { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f },
+       { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f },
+
+       /* 802.11 UNII */
+       { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f },
+       { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 },
+       { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 },
+       { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 },
+       { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
+};
+
+static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *tx_power;
+       unsigned int i;
+
+       /*
+        * Initialize all hw fields.
+        *
+        * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
+        * capable of sending the buffered frames out after the DTIM
+        * transmission using rt2x00lib_beacondone. This will send out
+        * multicast and broadcast traffic immediately instead of buffering it
+        * infinitly and thus dropping it after some time.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+       ieee80211_hw_set(rt2x00dev->hw, RX_INCLUDES_FCS);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2x00_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+       if (rt2x00_rf(rt2x00dev, RF2522)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
+               spec->channels = rf_vals_bg_2522;
+       } else if (rt2x00_rf(rt2x00dev, RF2523)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
+               spec->channels = rf_vals_bg_2523;
+       } else if (rt2x00_rf(rt2x00dev, RF2524)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
+               spec->channels = rf_vals_bg_2524;
+       } else if (rt2x00_rf(rt2x00dev, RF2525)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
+               spec->channels = rf_vals_bg_2525;
+       } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
+               spec->channels = rf_vals_bg_2525e;
+       } else if (rt2x00_rf(rt2x00dev, RF5222)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_5222);
+               spec->channels = rf_vals_5222;
+       }
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = MAX_TXPOWER;
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
+
+       if (spec->num_channels > 14) {
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].max_power = MAX_TXPOWER;
+                       info[i].default_power1 = DEFAULT_TXPOWER;
+               }
+       }
+
+       return 0;
+}
+
+static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u16 reg;
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt2500usb_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt2500usb_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt2500usb_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * This device requires the atim queue
+        */
+       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
+       if (!modparam_nohwcrypt) {
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+               __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
+       }
+       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+
+static const struct ieee80211_ops rt2500usb_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_tim                = rt2x00mac_set_tim,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2x00mac_conf_tx,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
+       .probe_hw               = rt2500usb_probe_hw,
+       .initialize             = rt2x00usb_initialize,
+       .uninitialize           = rt2x00usb_uninitialize,
+       .clear_entry            = rt2x00usb_clear_entry,
+       .set_device_state       = rt2500usb_set_device_state,
+       .rfkill_poll            = rt2500usb_rfkill_poll,
+       .link_stats             = rt2500usb_link_stats,
+       .reset_tuner            = rt2500usb_reset_tuner,
+       .watchdog               = rt2x00usb_watchdog,
+       .start_queue            = rt2500usb_start_queue,
+       .kick_queue             = rt2x00usb_kick_queue,
+       .stop_queue             = rt2500usb_stop_queue,
+       .flush_queue            = rt2x00usb_flush_queue,
+       .write_tx_desc          = rt2500usb_write_tx_desc,
+       .write_beacon           = rt2500usb_write_beacon,
+       .get_tx_data_len        = rt2500usb_get_tx_data_len,
+       .fill_rxdone            = rt2500usb_fill_rxdone,
+       .config_shared_key      = rt2500usb_config_key,
+       .config_pairwise_key    = rt2500usb_config_key,
+       .config_filter          = rt2500usb_config_filter,
+       .config_intf            = rt2500usb_config_intf,
+       .config_erp             = rt2500usb_config_erp,
+       .config_ant             = rt2500usb_config_ant,
+       .config                 = rt2500usb_config,
+};
+
+static void rt2500usb_queue_init(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 1;
+               queue->data_size = MGMT_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn);
+               break;
+
+       case QID_ATIM:
+               queue->limit = 8;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt2500usb_ops = {
+       .name                   = KBUILD_MODNAME,
+       .max_ap_intf            = 1,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2500usb_queue_init,
+       .lib                    = &rt2500usb_rt2x00_ops,
+       .hw                     = &rt2500usb_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2500usb_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * rt2500usb module information.
+ */
+static struct usb_device_id rt2500usb_device_table[] = {
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x1706) },
+       { USB_DEVICE(0x0b05, 0x1707) },
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050A ver. 2.x */
+       { USB_DEVICE(0x050d, 0x7051) },
+       /* Cisco Systems */
+       { USB_DEVICE(0x13b1, 0x000d) },
+       { USB_DEVICE(0x13b1, 0x0011) },
+       { USB_DEVICE(0x13b1, 0x001a) },
+       /* Conceptronic */
+       { USB_DEVICE(0x14b2, 0x3c02) },
+       /* D-LINK */
+       { USB_DEVICE(0x2001, 0x3c00) },
+       /* Gigabyte */
+       { USB_DEVICE(0x1044, 0x8001) },
+       { USB_DEVICE(0x1044, 0x8007) },
+       /* Hercules */
+       { USB_DEVICE(0x06f8, 0xe000) },
+       /* Melco */
+       { USB_DEVICE(0x0411, 0x005e) },
+       { USB_DEVICE(0x0411, 0x0066) },
+       { USB_DEVICE(0x0411, 0x0067) },
+       { USB_DEVICE(0x0411, 0x008b) },
+       { USB_DEVICE(0x0411, 0x0097) },
+       /* MSI */
+       { USB_DEVICE(0x0db0, 0x6861) },
+       { USB_DEVICE(0x0db0, 0x6865) },
+       { USB_DEVICE(0x0db0, 0x6869) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x1706) },
+       { USB_DEVICE(0x148f, 0x2570) },
+       { USB_DEVICE(0x148f, 0x9020) },
+       /* Sagem */
+       { USB_DEVICE(0x079b, 0x004b) },
+       /* Siemens */
+       { USB_DEVICE(0x0681, 0x3c06) },
+       /* SMC */
+       { USB_DEVICE(0x0707, 0xee13) },
+       /* Spairon */
+       { USB_DEVICE(0x114b, 0x0110) },
+       /* SURECOM */
+       { USB_DEVICE(0x0769, 0x11f3) },
+       /* Trust */
+       { USB_DEVICE(0x0eb0, 0x9020) },
+       /* VTech */
+       { USB_DEVICE(0x0f88, 0x3012) },
+       /* Zinwell */
+       { USB_DEVICE(0x5a57, 0x0260) },
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
+MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
+MODULE_LICENSE("GPL");
+
+static int rt2500usb_probe(struct usb_interface *usb_intf,
+                          const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
+static struct usb_driver rt2500usb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt2500usb_device_table,
+       .probe          = rt2500usb_probe,
+       .disconnect     = rt2x00usb_disconnect,
+       .suspend        = rt2x00usb_suspend,
+       .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
+       .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(rt2500usb_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.h b/drivers/net/wireless/ralink/rt2x00/rt2500usb.h
new file mode 100644 (file)
index 0000000..78cc035
--- /dev/null
@@ -0,0 +1,855 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2500usb
+       Abstract: Data structures and registers for the rt2500usb module.
+       Supported chipsets: RT2570.
+ */
+
+#ifndef RT2500USB_H
+#define RT2500USB_H
+
+/*
+ * RF chip defines.
+ */
+#define RF2522                         0x0000
+#define RF2523                         0x0001
+#define RF2524                         0x0002
+#define RF2525                         0x0003
+#define RF2525E                                0x0005
+#define RF5222                         0x0010
+
+/*
+ * RT2570 version
+ */
+#define RT2570_VERSION_B               2
+#define RT2570_VERSION_C               3
+#define RT2570_VERSION_D               4
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET            120
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x0400
+#define CSR_REG_SIZE                   0x0100
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x006e
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x0060
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
+/*
+ * Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ */
+#define MAC_CSR0                       0x0400
+
+/*
+ * MAC_CSR1: System control.
+ * SOFT_RESET: Software reset, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset, 1: reset, 0, release.
+ * HOST_READY: Host ready after initialization.
+ */
+#define MAC_CSR1                       0x0402
+#define MAC_CSR1_SOFT_RESET            FIELD16(0x00000001)
+#define MAC_CSR1_BBP_RESET             FIELD16(0x00000002)
+#define MAC_CSR1_HOST_READY            FIELD16(0x00000004)
+
+/*
+ * MAC_CSR2: STA MAC register 0.
+ */
+#define MAC_CSR2                       0x0404
+#define MAC_CSR2_BYTE0                 FIELD16(0x00ff)
+#define MAC_CSR2_BYTE1                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR3: STA MAC register 1.
+ */
+#define MAC_CSR3                       0x0406
+#define MAC_CSR3_BYTE2                 FIELD16(0x00ff)
+#define MAC_CSR3_BYTE3                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR4: STA MAC register 2.
+ */
+#define MAC_CSR4                       0X0408
+#define MAC_CSR4_BYTE4                 FIELD16(0x00ff)
+#define MAC_CSR4_BYTE5                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR5: BSSID register 0.
+ */
+#define MAC_CSR5                       0x040a
+#define MAC_CSR5_BYTE0                 FIELD16(0x00ff)
+#define MAC_CSR5_BYTE1                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR6: BSSID register 1.
+ */
+#define MAC_CSR6                       0x040c
+#define MAC_CSR6_BYTE2                 FIELD16(0x00ff)
+#define MAC_CSR6_BYTE3                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR7: BSSID register 2.
+ */
+#define MAC_CSR7                       0x040e
+#define MAC_CSR7_BYTE4                 FIELD16(0x00ff)
+#define MAC_CSR7_BYTE5                 FIELD16(0xff00)
+
+/*
+ * MAC_CSR8: Max frame length.
+ */
+#define MAC_CSR8                       0x0410
+#define MAC_CSR8_MAX_FRAME_UNIT                FIELD16(0x0fff)
+
+/*
+ * Misc MAC_CSR registers.
+ * MAC_CSR9: Timer control.
+ * MAC_CSR10: Slot time.
+ * MAC_CSR11: SIFS.
+ * MAC_CSR12: EIFS.
+ * MAC_CSR13: Power mode0.
+ * MAC_CSR14: Power mode1.
+ * MAC_CSR15: Power saving transition0
+ * MAC_CSR16: Power saving transition1
+ */
+#define MAC_CSR9                       0x0412
+#define MAC_CSR10                      0x0414
+#define MAC_CSR11                      0x0416
+#define MAC_CSR12                      0x0418
+#define MAC_CSR13                      0x041a
+#define MAC_CSR14                      0x041c
+#define MAC_CSR15                      0x041e
+#define MAC_CSR16                      0x0420
+
+/*
+ * MAC_CSR17: Manual power control / status register.
+ * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
+ * SET_STATE: Set state. Write 1 to trigger, self cleared.
+ * BBP_DESIRE_STATE: BBP desired state.
+ * RF_DESIRE_STATE: RF desired state.
+ * BBP_CURRENT_STATE: BBP current state.
+ * RF_CURRENT_STATE: RF current state.
+ * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
+ */
+#define MAC_CSR17                      0x0422
+#define MAC_CSR17_SET_STATE            FIELD16(0x0001)
+#define MAC_CSR17_BBP_DESIRE_STATE     FIELD16(0x0006)
+#define MAC_CSR17_RF_DESIRE_STATE      FIELD16(0x0018)
+#define MAC_CSR17_BBP_CURR_STATE       FIELD16(0x0060)
+#define MAC_CSR17_RF_CURR_STATE                FIELD16(0x0180)
+#define MAC_CSR17_PUT_TO_SLEEP         FIELD16(0x0200)
+
+/*
+ * MAC_CSR18: Wakeup timer register.
+ * DELAY_AFTER_BEACON: Delay after Tbcn expired in units of 1/16 TU.
+ * BEACONS_BEFORE_WAKEUP: Number of beacon before wakeup.
+ * AUTO_WAKE: Enable auto wakeup / sleep mechanism.
+ */
+#define MAC_CSR18                      0x0424
+#define MAC_CSR18_DELAY_AFTER_BEACON   FIELD16(0x00ff)
+#define MAC_CSR18_BEACONS_BEFORE_WAKEUP        FIELD16(0x7f00)
+#define MAC_CSR18_AUTO_WAKE            FIELD16(0x8000)
+
+/*
+ * MAC_CSR19: GPIO control register.
+ *     MAC_CSR19_VALx: GPIO value
+ *     MAC_CSR19_DIRx: GPIO direction: 0 = input; 1 = output
+ */
+#define MAC_CSR19                      0x0426
+#define MAC_CSR19_VAL0                 FIELD16(0x0001)
+#define MAC_CSR19_VAL1                 FIELD16(0x0002)
+#define MAC_CSR19_VAL2                 FIELD16(0x0004)
+#define MAC_CSR19_VAL3                 FIELD16(0x0008)
+#define MAC_CSR19_VAL4                 FIELD16(0x0010)
+#define MAC_CSR19_VAL5                 FIELD16(0x0020)
+#define MAC_CSR19_VAL6                 FIELD16(0x0040)
+#define MAC_CSR19_VAL7                 FIELD16(0x0080)
+#define MAC_CSR19_DIR0                 FIELD16(0x0100)
+#define MAC_CSR19_DIR1                 FIELD16(0x0200)
+#define MAC_CSR19_DIR2                 FIELD16(0x0400)
+#define MAC_CSR19_DIR3                 FIELD16(0x0800)
+#define MAC_CSR19_DIR4                 FIELD16(0x1000)
+#define MAC_CSR19_DIR5                 FIELD16(0x2000)
+#define MAC_CSR19_DIR6                 FIELD16(0x4000)
+#define MAC_CSR19_DIR7                 FIELD16(0x8000)
+
+/*
+ * MAC_CSR20: LED control register.
+ * ACTIVITY: 0: idle, 1: active.
+ * LINK: 0: linkoff, 1: linkup.
+ * ACTIVITY_POLARITY: 0: active low, 1: active high.
+ */
+#define MAC_CSR20                      0x0428
+#define MAC_CSR20_ACTIVITY             FIELD16(0x0001)
+#define MAC_CSR20_LINK                 FIELD16(0x0002)
+#define MAC_CSR20_ACTIVITY_POLARITY    FIELD16(0x0004)
+
+/*
+ * MAC_CSR21: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ */
+#define MAC_CSR21                      0x042a
+#define MAC_CSR21_ON_PERIOD            FIELD16(0x00ff)
+#define MAC_CSR21_OFF_PERIOD           FIELD16(0xff00)
+
+/*
+ * MAC_CSR22: Collision window control register.
+ */
+#define MAC_CSR22                      0x042c
+
+/*
+ * Transmit related CSRs.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * TXRX_CSR0: Security control register.
+ */
+#define TXRX_CSR0                      0x0440
+#define TXRX_CSR0_ALGORITHM            FIELD16(0x0007)
+#define TXRX_CSR0_IV_OFFSET            FIELD16(0x01f8)
+#define TXRX_CSR0_KEY_ID               FIELD16(0x1e00)
+
+/*
+ * TXRX_CSR1: TX configuration.
+ * ACK_TIMEOUT: ACK Timeout in unit of 1-us.
+ * TSF_OFFSET: TSF offset in MAC header.
+ * AUTO_SEQUENCE: Let ASIC control frame sequence number.
+ */
+#define TXRX_CSR1                      0x0442
+#define TXRX_CSR1_ACK_TIMEOUT          FIELD16(0x00ff)
+#define TXRX_CSR1_TSF_OFFSET           FIELD16(0x7f00)
+#define TXRX_CSR1_AUTO_SEQUENCE                FIELD16(0x8000)
+
+/*
+ * TXRX_CSR2: RX control.
+ * DISABLE_RX: Disable rx engine.
+ * DROP_CRC: Drop crc error.
+ * DROP_PHYSICAL: Drop physical error.
+ * DROP_CONTROL: Drop control frame.
+ * DROP_NOT_TO_ME: Drop not to me unicast frame.
+ * DROP_TODS: Drop frame tods bit is true.
+ * DROP_VERSION_ERROR: Drop version error frame.
+ * DROP_MCAST: Drop multicast frames.
+ * DROP_BCAST: Drop broadcast frames.
+ */
+#define TXRX_CSR2                      0x0444
+#define        TXRX_CSR2_DISABLE_RX            FIELD16(0x0001)
+#define TXRX_CSR2_DROP_CRC             FIELD16(0x0002)
+#define TXRX_CSR2_DROP_PHYSICAL                FIELD16(0x0004)
+#define TXRX_CSR2_DROP_CONTROL         FIELD16(0x0008)
+#define TXRX_CSR2_DROP_NOT_TO_ME       FIELD16(0x0010)
+#define TXRX_CSR2_DROP_TODS            FIELD16(0x0020)
+#define TXRX_CSR2_DROP_VERSION_ERROR   FIELD16(0x0040)
+#define TXRX_CSR2_DROP_MULTICAST       FIELD16(0x0200)
+#define TXRX_CSR2_DROP_BROADCAST       FIELD16(0x0400)
+
+/*
+ * RX BBP ID registers
+ * TXRX_CSR3: CCK RX BBP ID.
+ * TXRX_CSR4: OFDM RX BBP ID.
+ */
+#define TXRX_CSR3                      0x0446
+#define TXRX_CSR4                      0x0448
+
+/*
+ * TXRX_CSR5: CCK TX BBP ID0.
+ */
+#define TXRX_CSR5                      0x044a
+#define TXRX_CSR5_BBP_ID0              FIELD16(0x007f)
+#define TXRX_CSR5_BBP_ID0_VALID                FIELD16(0x0080)
+#define TXRX_CSR5_BBP_ID1              FIELD16(0x7f00)
+#define TXRX_CSR5_BBP_ID1_VALID                FIELD16(0x8000)
+
+/*
+ * TXRX_CSR6: CCK TX BBP ID1.
+ */
+#define TXRX_CSR6                      0x044c
+#define TXRX_CSR6_BBP_ID0              FIELD16(0x007f)
+#define TXRX_CSR6_BBP_ID0_VALID                FIELD16(0x0080)
+#define TXRX_CSR6_BBP_ID1              FIELD16(0x7f00)
+#define TXRX_CSR6_BBP_ID1_VALID                FIELD16(0x8000)
+
+/*
+ * TXRX_CSR7: OFDM TX BBP ID0.
+ */
+#define TXRX_CSR7                      0x044e
+#define TXRX_CSR7_BBP_ID0              FIELD16(0x007f)
+#define TXRX_CSR7_BBP_ID0_VALID                FIELD16(0x0080)
+#define TXRX_CSR7_BBP_ID1              FIELD16(0x7f00)
+#define TXRX_CSR7_BBP_ID1_VALID                FIELD16(0x8000)
+
+/*
+ * TXRX_CSR8: OFDM TX BBP ID1.
+ */
+#define TXRX_CSR8                      0x0450
+#define TXRX_CSR8_BBP_ID0              FIELD16(0x007f)
+#define TXRX_CSR8_BBP_ID0_VALID                FIELD16(0x0080)
+#define TXRX_CSR8_BBP_ID1              FIELD16(0x7f00)
+#define TXRX_CSR8_BBP_ID1_VALID                FIELD16(0x8000)
+
+/*
+ * TXRX_CSR9: TX ACK time-out.
+ */
+#define TXRX_CSR9                      0x0452
+
+/*
+ * TXRX_CSR10: Auto responder control.
+ */
+#define TXRX_CSR10                     0x0454
+#define TXRX_CSR10_AUTORESPOND_PREAMBLE FIELD16(0x0004)
+
+/*
+ * TXRX_CSR11: Auto responder basic rate.
+ */
+#define TXRX_CSR11                     0x0456
+
+/*
+ * ACK/CTS time registers.
+ */
+#define TXRX_CSR12                     0x0458
+#define TXRX_CSR13                     0x045a
+#define TXRX_CSR14                     0x045c
+#define TXRX_CSR15                     0x045e
+#define TXRX_CSR16                     0x0460
+#define TXRX_CSR17                     0x0462
+
+/*
+ * TXRX_CSR18: Synchronization control register.
+ */
+#define TXRX_CSR18                     0x0464
+#define TXRX_CSR18_OFFSET              FIELD16(0x000f)
+#define TXRX_CSR18_INTERVAL            FIELD16(0xfff0)
+
+/*
+ * TXRX_CSR19: Synchronization control register.
+ * TSF_COUNT: Enable TSF auto counting.
+ * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
+ * TBCN: Enable Tbcn with reload value.
+ * BEACON_GEN: Enable beacon generator.
+ */
+#define TXRX_CSR19                     0x0466
+#define TXRX_CSR19_TSF_COUNT           FIELD16(0x0001)
+#define TXRX_CSR19_TSF_SYNC            FIELD16(0x0006)
+#define TXRX_CSR19_TBCN                        FIELD16(0x0008)
+#define TXRX_CSR19_BEACON_GEN          FIELD16(0x0010)
+
+/*
+ * TXRX_CSR20: Tx BEACON offset time control register.
+ * OFFSET: In units of usec.
+ * BCN_EXPECT_WINDOW: Default: 2^CWmin
+ */
+#define TXRX_CSR20                     0x0468
+#define TXRX_CSR20_OFFSET              FIELD16(0x1fff)
+#define TXRX_CSR20_BCN_EXPECT_WINDOW   FIELD16(0xe000)
+
+/*
+ * TXRX_CSR21
+ */
+#define TXRX_CSR21                     0x046a
+
+/*
+ * Encryption related CSRs.
+ *
+ */
+
+/*
+ * SEC_CSR0: Shared key 0, word 0
+ * SEC_CSR1: Shared key 0, word 1
+ * SEC_CSR2: Shared key 0, word 2
+ * SEC_CSR3: Shared key 0, word 3
+ * SEC_CSR4: Shared key 0, word 4
+ * SEC_CSR5: Shared key 0, word 5
+ * SEC_CSR6: Shared key 0, word 6
+ * SEC_CSR7: Shared key 0, word 7
+ */
+#define SEC_CSR0                       0x0480
+#define SEC_CSR1                       0x0482
+#define SEC_CSR2                       0x0484
+#define SEC_CSR3                       0x0486
+#define SEC_CSR4                       0x0488
+#define SEC_CSR5                       0x048a
+#define SEC_CSR6                       0x048c
+#define SEC_CSR7                       0x048e
+
+/*
+ * SEC_CSR8: Shared key 1, word 0
+ * SEC_CSR9: Shared key 1, word 1
+ * SEC_CSR10: Shared key 1, word 2
+ * SEC_CSR11: Shared key 1, word 3
+ * SEC_CSR12: Shared key 1, word 4
+ * SEC_CSR13: Shared key 1, word 5
+ * SEC_CSR14: Shared key 1, word 6
+ * SEC_CSR15: Shared key 1, word 7
+ */
+#define SEC_CSR8                       0x0490
+#define SEC_CSR9                       0x0492
+#define SEC_CSR10                      0x0494
+#define SEC_CSR11                      0x0496
+#define SEC_CSR12                      0x0498
+#define SEC_CSR13                      0x049a
+#define SEC_CSR14                      0x049c
+#define SEC_CSR15                      0x049e
+
+/*
+ * SEC_CSR16: Shared key 2, word 0
+ * SEC_CSR17: Shared key 2, word 1
+ * SEC_CSR18: Shared key 2, word 2
+ * SEC_CSR19: Shared key 2, word 3
+ * SEC_CSR20: Shared key 2, word 4
+ * SEC_CSR21: Shared key 2, word 5
+ * SEC_CSR22: Shared key 2, word 6
+ * SEC_CSR23: Shared key 2, word 7
+ */
+#define SEC_CSR16                      0x04a0
+#define SEC_CSR17                      0x04a2
+#define SEC_CSR18                      0X04A4
+#define SEC_CSR19                      0x04a6
+#define SEC_CSR20                      0x04a8
+#define SEC_CSR21                      0x04aa
+#define SEC_CSR22                      0x04ac
+#define SEC_CSR23                      0x04ae
+
+/*
+ * SEC_CSR24: Shared key 3, word 0
+ * SEC_CSR25: Shared key 3, word 1
+ * SEC_CSR26: Shared key 3, word 2
+ * SEC_CSR27: Shared key 3, word 3
+ * SEC_CSR28: Shared key 3, word 4
+ * SEC_CSR29: Shared key 3, word 5
+ * SEC_CSR30: Shared key 3, word 6
+ * SEC_CSR31: Shared key 3, word 7
+ */
+#define SEC_CSR24                      0x04b0
+#define SEC_CSR25                      0x04b2
+#define SEC_CSR26                      0x04b4
+#define SEC_CSR27                      0x04b6
+#define SEC_CSR28                      0x04b8
+#define SEC_CSR29                      0x04ba
+#define SEC_CSR30                      0x04bc
+#define SEC_CSR31                      0x04be
+
+#define KEY_ENTRY(__idx) \
+       ( SEC_CSR0 + ((__idx) * 16) )
+
+/*
+ * PHY control registers.
+ */
+
+/*
+ * PHY_CSR0: RF switching timing control.
+ */
+#define PHY_CSR0                       0x04c0
+
+/*
+ * PHY_CSR1: TX PA configuration.
+ */
+#define PHY_CSR1                       0x04c2
+
+/*
+ * MAC configuration registers.
+ */
+
+/*
+ * PHY_CSR2: TX MAC configuration.
+ * NOTE: Both register fields are complete dummy,
+ * documentation and legacy drivers are unclear un
+ * what this register means or what fields exists.
+ */
+#define PHY_CSR2                       0x04c4
+#define PHY_CSR2_LNA                   FIELD16(0x0002)
+#define PHY_CSR2_LNA_MODE              FIELD16(0x3000)
+
+/*
+ * PHY_CSR3: RX MAC configuration.
+ */
+#define PHY_CSR3                       0x04c6
+
+/*
+ * PHY_CSR4: Interface configuration.
+ */
+#define PHY_CSR4                       0x04c8
+#define PHY_CSR4_LOW_RF_LE             FIELD16(0x0001)
+
+/*
+ * BBP pre-TX registers.
+ * PHY_CSR5: BBP pre-TX CCK.
+ */
+#define PHY_CSR5                       0x04ca
+#define PHY_CSR5_CCK                   FIELD16(0x0003)
+#define PHY_CSR5_CCK_FLIP              FIELD16(0x0004)
+
+/*
+ * BBP pre-TX registers.
+ * PHY_CSR6: BBP pre-TX OFDM.
+ */
+#define PHY_CSR6                       0x04cc
+#define PHY_CSR6_OFDM                  FIELD16(0x0003)
+#define PHY_CSR6_OFDM_FLIP             FIELD16(0x0004)
+
+/*
+ * PHY_CSR7: BBP access register 0.
+ * BBP_DATA: BBP data.
+ * BBP_REG_ID: BBP register ID.
+ * BBP_READ_CONTROL: 0: write, 1: read.
+ */
+#define PHY_CSR7                       0x04ce
+#define PHY_CSR7_DATA                  FIELD16(0x00ff)
+#define PHY_CSR7_REG_ID                        FIELD16(0x7f00)
+#define PHY_CSR7_READ_CONTROL          FIELD16(0x8000)
+
+/*
+ * PHY_CSR8: BBP access register 1.
+ * BBP_BUSY: ASIC is busy execute BBP programming.
+ */
+#define PHY_CSR8                       0x04d0
+#define PHY_CSR8_BUSY                  FIELD16(0x0001)
+
+/*
+ * PHY_CSR9: RF access register.
+ * RF_VALUE: Register value + id to program into rf/if.
+ */
+#define PHY_CSR9                       0x04d2
+#define PHY_CSR9_RF_VALUE              FIELD16(0xffff)
+
+/*
+ * PHY_CSR10: RF access register.
+ * RF_VALUE: Register value + id to program into rf/if.
+ * RF_NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
+ * RF_IF_SELECT: Chip to program: 0: rf, 1: if.
+ * RF_PLL_LD: Rf pll_ld status.
+ * RF_BUSY: 1: asic is busy execute rf programming.
+ */
+#define PHY_CSR10                      0x04d4
+#define PHY_CSR10_RF_VALUE             FIELD16(0x00ff)
+#define PHY_CSR10_RF_NUMBER_OF_BITS    FIELD16(0x1f00)
+#define PHY_CSR10_RF_IF_SELECT         FIELD16(0x2000)
+#define PHY_CSR10_RF_PLL_LD            FIELD16(0x4000)
+#define PHY_CSR10_RF_BUSY              FIELD16(0x8000)
+
+/*
+ * STA_CSR0: FCS error count.
+ * FCS_ERROR: FCS error count, cleared when read.
+ */
+#define STA_CSR0                       0x04e0
+#define STA_CSR0_FCS_ERROR             FIELD16(0xffff)
+
+/*
+ * STA_CSR1: PLCP error count.
+ */
+#define STA_CSR1                       0x04e2
+
+/*
+ * STA_CSR2: LONG error count.
+ */
+#define STA_CSR2                       0x04e4
+
+/*
+ * STA_CSR3: CCA false alarm.
+ * FALSE_CCA_ERROR: False CCA error count, cleared when read.
+ */
+#define STA_CSR3                       0x04e6
+#define STA_CSR3_FALSE_CCA_ERROR       FIELD16(0xffff)
+
+/*
+ * STA_CSR4: RX FIFO overflow.
+ */
+#define STA_CSR4                       0x04e8
+
+/*
+ * STA_CSR5: Beacon sent counter.
+ */
+#define STA_CSR5                       0x04ea
+
+/*
+ *  Statistics registers
+ */
+#define STA_CSR6                       0x04ec
+#define STA_CSR7                       0x04ee
+#define STA_CSR8                       0x04f0
+#define STA_CSR9                       0x04f2
+#define STA_CSR10                      0x04f4
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2: TX antenna control
+ */
+#define BBP_R2_TX_ANTENNA              FIELD8(0x03)
+#define BBP_R2_TX_IQ_FLIP              FIELD8(0x04)
+
+/*
+ * R14: RX antenna control
+ */
+#define BBP_R14_RX_ANTENNA             FIELD8(0x03)
+#define BBP_R14_RX_IQ_FLIP             FIELD8(0x04)
+
+/*
+ * RF registers.
+ */
+
+/*
+ * RF 1
+ */
+#define RF1_TUNER                      FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TUNER                      FIELD32(0x00000100)
+#define RF3_TXPOWER                    FIELD32(0x00003e00)
+
+/*
+ * EEPROM contents.
+ */
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0              0x0002
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1               0x0003
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2              0x0004
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM antenna.
+ * ANTENNA_NUM: Number of antenna's.
+ * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * LED_MODE: 0: default, 1: TX/RX activity, 2: Single (ignore link), 3: rsvd.
+ * DYN_TXAGC: Dynamic TX AGC control.
+ * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
+ * RF_TYPE: Rf_type of this adapter.
+ */
+#define EEPROM_ANTENNA                 0x000b
+#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
+#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
+#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
+#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x01c0)
+#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
+#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
+#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
+
+/*
+ * EEPROM NIC config.
+ * CARDBUS_ACCEL: 0: enable, 1: disable.
+ * DYN_BBP_TUNE: 0: enable, 1: disable.
+ * CCK_TX_POWER: CCK TX power compensation.
+ */
+#define EEPROM_NIC                     0x000c
+#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0001)
+#define EEPROM_NIC_DYN_BBP_TUNE                FIELD16(0x0002)
+#define EEPROM_NIC_CCK_TX_POWER                FIELD16(0x000c)
+
+/*
+ * EEPROM geography.
+ * GEO: Default geography setting for device.
+ */
+#define EEPROM_GEOGRAPHY               0x000d
+#define EEPROM_GEOGRAPHY_GEO           FIELD16(0x0f00)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START               0x000e
+#define EEPROM_BBP_SIZE                        16
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER
+ */
+#define EEPROM_TXPOWER_START           0x001e
+#define EEPROM_TXPOWER_SIZE            7
+#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
+#define EEPROM_TXPOWER_2               FIELD16(0xff00)
+
+/*
+ * EEPROM Tuning threshold
+ */
+#define EEPROM_BBPTUNE                 0x0030
+#define EEPROM_BBPTUNE_THRESHOLD       FIELD16(0x00ff)
+
+/*
+ * EEPROM BBP R24 Tuning.
+ */
+#define EEPROM_BBPTUNE_R24             0x0031
+#define EEPROM_BBPTUNE_R24_LOW         FIELD16(0x00ff)
+#define EEPROM_BBPTUNE_R24_HIGH                FIELD16(0xff00)
+
+/*
+ * EEPROM BBP R25 Tuning.
+ */
+#define EEPROM_BBPTUNE_R25             0x0032
+#define EEPROM_BBPTUNE_R25_LOW         FIELD16(0x00ff)
+#define EEPROM_BBPTUNE_R25_HIGH                FIELD16(0xff00)
+
+/*
+ * EEPROM BBP R24 Tuning.
+ */
+#define EEPROM_BBPTUNE_R61             0x0033
+#define EEPROM_BBPTUNE_R61_LOW         FIELD16(0x00ff)
+#define EEPROM_BBPTUNE_R61_HIGH                FIELD16(0xff00)
+
+/*
+ * EEPROM BBP VGC Tuning.
+ */
+#define EEPROM_BBPTUNE_VGC             0x0034
+#define EEPROM_BBPTUNE_VGCUPPER                FIELD16(0x00ff)
+#define EEPROM_BBPTUNE_VGCLOWER                FIELD16(0xff00)
+
+/*
+ * EEPROM BBP R17 Tuning.
+ */
+#define EEPROM_BBPTUNE_R17             0x0035
+#define EEPROM_BBPTUNE_R17_LOW         FIELD16(0x00ff)
+#define EEPROM_BBPTUNE_R17_HIGH                FIELD16(0xff00)
+
+/*
+ * RSSI <-> dBm offset calibration
+ */
+#define EEPROM_CALIBRATE_OFFSET                0x0036
+#define EEPROM_CALIBRATE_OFFSET_RSSI   FIELD16(0x00ff)
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  ( 5 * sizeof(__le32) )
+#define RXD_DESC_SIZE                  ( 4 * sizeof(__le32) )
+
+/*
+ * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_PACKET_ID               FIELD32(0x0000000f)
+#define TXD_W0_RETRY_LIMIT             FIELD32(0x000000f0)
+#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
+#define TXD_W0_ACK                     FIELD32(0x00000200)
+#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
+#define TXD_W0_OFDM                    FIELD32(0x00000800)
+#define TXD_W0_NEW_SEQ                 FIELD32(0x00001000)
+#define TXD_W0_IFS                     FIELD32(0x00006000)
+#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define TXD_W0_CIPHER                  FIELD32(0x20000000)
+#define TXD_W0_KEY_ID                  FIELD32(0xc0000000)
+
+/*
+ * Word1
+ */
+#define TXD_W1_IV_OFFSET               FIELD32(0x0000003f)
+#define TXD_W1_AIFS                    FIELD32(0x000000c0)
+#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
+#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
+
+/*
+ * Word2: PLCP information
+ */
+#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
+#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
+#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
+#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
+
+/*
+ * Word3
+ */
+#define TXD_W3_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word4
+ */
+#define TXD_W4_EIV                     FIELD32(0xffffffff)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ */
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
+#define RXD_W0_MULTICAST               FIELD32(0x00000004)
+#define RXD_W0_BROADCAST               FIELD32(0x00000008)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
+#define RXD_W0_OFDM                    FIELD32(0x00000040)
+#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
+#define RXD_W0_CIPHER                  FIELD32(0x00000100)
+#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000200)
+#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+
+/*
+ * Word1
+ */
+#define RXD_W1_RSSI                    FIELD32(0x000000ff)
+#define RXD_W1_SIGNAL                  FIELD32(0x0000ff00)
+
+/*
+ * Word2
+ */
+#define RXD_W2_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word3
+ */
+#define RXD_W3_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_TXPOWER    0
+#define MAX_TXPOWER    31
+#define DEFAULT_TXPOWER        24
+
+#define TXPOWER_FROM_DEV(__txpower) \
+       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
+
+#endif /* RT2500USB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800.h b/drivers/net/wireless/ralink/rt2x00/rt2800.h
new file mode 100644 (file)
index 0000000..95c1d7c
--- /dev/null
@@ -0,0 +1,2986 @@
+/*
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800
+       Abstract: Data structures and registers for the rt2800 modules.
+       Supported chipsets: RT2800E, RT2800ED & RT2800U.
+ */
+
+#ifndef RT2800_H
+#define RT2800_H
+
+/*
+ * RF chip defines.
+ *
+ * RF2820 2.4G 2T3R
+ * RF2850 2.4G/5G 2T3R
+ * RF2720 2.4G 1T2R
+ * RF2750 2.4G/5G 1T2R
+ * RF3020 2.4G 1T1R
+ * RF2020 2.4G B/G
+ * RF3021 2.4G 1T2R
+ * RF3022 2.4G 2T2R
+ * RF3052 2.4G/5G 2T2R
+ * 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)
+ * RF5592 2.4G/5G 2T2R
+ * RF3070 2.4G 1T1R
+ * RF5360 2.4G 1T1R
+ * RF5362 2.4G 1T1R
+ * RF5370 2.4G 1T1R
+ * RF5390 2.4G 1T1R
+ */
+#define RF2820                         0x0001
+#define RF2850                         0x0002
+#define RF2720                         0x0003
+#define RF2750                         0x0004
+#define RF3020                         0x0005
+#define RF2020                         0x0006
+#define RF3021                         0x0007
+#define RF3022                         0x0008
+#define RF3052                         0x0009
+#define RF2853                         0x000a
+#define RF3320                         0x000b
+#define RF3322                         0x000c
+#define RF3053                         0x000d
+#define RF5592                         0x000f
+#define RF3070                         0x3070
+#define RF3290                         0x3290
+#define RF5360                         0x5360
+#define RF5362                         0x5362
+#define RF5370                         0x5370
+#define RF5372                         0x5372
+#define RF5390                         0x5390
+#define RF5392                         0x5392
+
+/*
+ * Chipset revisions.
+ */
+#define REV_RT2860C                    0x0100
+#define REV_RT2860D                    0x0101
+#define REV_RT2872E                    0x0200
+#define REV_RT3070E                    0x0200
+#define REV_RT3070F                    0x0201
+#define REV_RT3071E                    0x0211
+#define REV_RT3090E                    0x0211
+#define REV_RT3390E                    0x0211
+#define REV_RT3593E                    0x0211
+#define REV_RT5390F                    0x0502
+#define REV_RT5390R                    0x1502
+#define REV_RT5592C                    0x0221
+
+#define DEFAULT_RSSI_OFFSET            120
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x1000
+#define CSR_REG_SIZE                   0x0800
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x0200
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x00ff
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x0010
+#define RFCSR_BASE                     0x0000
+#define RFCSR_SIZE                     0x0040
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  4
+
+/*
+ * Registers.
+ */
+
+
+/*
+ * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number.
+ */
+#define MAC_CSR0_3290                  0x0000
+
+/*
+ * E2PROM_CSR: PCI EEPROM control register.
+ * RELOAD: Write 1 to reload eeprom content.
+ * TYPE: 0: 93c46, 1:93c66.
+ * LOAD_STATUS: 1:loading, 0:done.
+ */
+#define E2PROM_CSR                     0x0004
+#define E2PROM_CSR_DATA_CLOCK          FIELD32(0x00000001)
+#define E2PROM_CSR_CHIP_SELECT         FIELD32(0x00000002)
+#define E2PROM_CSR_DATA_IN             FIELD32(0x00000004)
+#define E2PROM_CSR_DATA_OUT            FIELD32(0x00000008)
+#define E2PROM_CSR_TYPE                        FIELD32(0x00000030)
+#define E2PROM_CSR_LOAD_STATUS         FIELD32(0x00000040)
+#define E2PROM_CSR_RELOAD              FIELD32(0x00000080)
+
+/*
+ * CMB_CTRL_CFG
+ */
+#define CMB_CTRL               0x0020
+#define AUX_OPT_BIT0           FIELD32(0x00000001)
+#define AUX_OPT_BIT1           FIELD32(0x00000002)
+#define AUX_OPT_BIT2           FIELD32(0x00000004)
+#define AUX_OPT_BIT3           FIELD32(0x00000008)
+#define AUX_OPT_BIT4           FIELD32(0x00000010)
+#define AUX_OPT_BIT5           FIELD32(0x00000020)
+#define AUX_OPT_BIT6           FIELD32(0x00000040)
+#define AUX_OPT_BIT7           FIELD32(0x00000080)
+#define AUX_OPT_BIT8           FIELD32(0x00000100)
+#define AUX_OPT_BIT9           FIELD32(0x00000200)
+#define AUX_OPT_BIT10          FIELD32(0x00000400)
+#define AUX_OPT_BIT11          FIELD32(0x00000800)
+#define AUX_OPT_BIT12          FIELD32(0x00001000)
+#define AUX_OPT_BIT13          FIELD32(0x00002000)
+#define AUX_OPT_BIT14          FIELD32(0x00004000)
+#define AUX_OPT_BIT15          FIELD32(0x00008000)
+#define LDO25_LEVEL            FIELD32(0x00030000)
+#define LDO25_LARGEA           FIELD32(0x00040000)
+#define LDO25_FRC_ON           FIELD32(0x00080000)
+#define CMB_RSV                        FIELD32(0x00300000)
+#define XTAL_RDY               FIELD32(0x00400000)
+#define PLL_LD                 FIELD32(0x00800000)
+#define LDO_CORE_LEVEL         FIELD32(0x0F000000)
+#define LDO_BGSEL              FIELD32(0x30000000)
+#define LDO3_EN                        FIELD32(0x40000000)
+#define LDO0_EN                        FIELD32(0x80000000)
+
+/*
+ * EFUSE_CSR_3290: RT3290 EEPROM
+ */
+#define EFUSE_CTRL_3290                        0x0024
+
+/*
+ * EFUSE_DATA3 of 3290
+ */
+#define EFUSE_DATA3_3290               0x0028
+
+/*
+ * EFUSE_DATA2 of 3290
+ */
+#define EFUSE_DATA2_3290               0x002c
+
+/*
+ * EFUSE_DATA1 of 3290
+ */
+#define EFUSE_DATA1_3290               0x0030
+
+/*
+ * EFUSE_DATA0 of 3290
+ */
+#define EFUSE_DATA0_3290               0x0034
+
+/*
+ * OSC_CTRL_CFG
+ * Ring oscillator configuration
+ */
+#define OSC_CTRL               0x0038
+#define OSC_REF_CYCLE          FIELD32(0x00001fff)
+#define OSC_RSV                        FIELD32(0x0000e000)
+#define OSC_CAL_CNT            FIELD32(0x0fff0000)
+#define OSC_CAL_ACK            FIELD32(0x10000000)
+#define OSC_CLK_32K_VLD                FIELD32(0x20000000)
+#define OSC_CAL_REQ            FIELD32(0x40000000)
+#define OSC_ROSC_EN            FIELD32(0x80000000)
+
+/*
+ * COEX_CFG_0
+ */
+#define COEX_CFG0              0x0040
+#define COEX_CFG_ANT           FIELD32(0xff000000)
+/*
+ * COEX_CFG_1
+ */
+#define COEX_CFG1              0x0044
+
+/*
+ * COEX_CFG_2
+ */
+#define COEX_CFG2              0x0048
+#define BT_COEX_CFG1           FIELD32(0xff000000)
+#define BT_COEX_CFG0           FIELD32(0x00ff0000)
+#define WL_COEX_CFG1           FIELD32(0x0000ff00)
+#define WL_COEX_CFG0           FIELD32(0x000000ff)
+/*
+ * PLL_CTRL_CFG
+ * PLL configuration register
+ */
+#define PLL_CTRL               0x0050
+#define PLL_RESERVED_INPUT1    FIELD32(0x000000ff)
+#define PLL_RESERVED_INPUT2    FIELD32(0x0000ff00)
+#define PLL_CONTROL            FIELD32(0x00070000)
+#define PLL_LPF_R1             FIELD32(0x00080000)
+#define PLL_LPF_C1_CTRL                FIELD32(0x00300000)
+#define PLL_LPF_C2_CTRL                FIELD32(0x00c00000)
+#define PLL_CP_CURRENT_CTRL    FIELD32(0x03000000)
+#define PLL_PFD_DELAY_CTRL     FIELD32(0x0c000000)
+#define PLL_LOCK_CTRL          FIELD32(0x70000000)
+#define PLL_VBGBK_EN           FIELD32(0x80000000)
+
+
+/*
+ * WLAN_CTRL_CFG
+ * RT3290 wlan configuration
+ */
+#define WLAN_FUN_CTRL                  0x0080
+#define WLAN_EN                                FIELD32(0x00000001)
+#define WLAN_CLK_EN                    FIELD32(0x00000002)
+#define WLAN_RSV1                      FIELD32(0x00000004)
+#define WLAN_RESET                     FIELD32(0x00000008)
+#define PCIE_APP0_CLK_REQ              FIELD32(0x00000010)
+#define FRC_WL_ANT_SET                 FIELD32(0x00000020)
+#define INV_TR_SW0                     FIELD32(0x00000040)
+#define WLAN_GPIO_IN_BIT0              FIELD32(0x00000100)
+#define WLAN_GPIO_IN_BIT1              FIELD32(0x00000200)
+#define WLAN_GPIO_IN_BIT2              FIELD32(0x00000400)
+#define WLAN_GPIO_IN_BIT3              FIELD32(0x00000800)
+#define WLAN_GPIO_IN_BIT4              FIELD32(0x00001000)
+#define WLAN_GPIO_IN_BIT5              FIELD32(0x00002000)
+#define WLAN_GPIO_IN_BIT6              FIELD32(0x00004000)
+#define WLAN_GPIO_IN_BIT7              FIELD32(0x00008000)
+#define WLAN_GPIO_IN_BIT_ALL           FIELD32(0x0000ff00)
+#define WLAN_GPIO_OUT_BIT0             FIELD32(0x00010000)
+#define WLAN_GPIO_OUT_BIT1             FIELD32(0x00020000)
+#define WLAN_GPIO_OUT_BIT2             FIELD32(0x00040000)
+#define WLAN_GPIO_OUT_BIT3             FIELD32(0x00050000)
+#define WLAN_GPIO_OUT_BIT4             FIELD32(0x00100000)
+#define WLAN_GPIO_OUT_BIT5             FIELD32(0x00200000)
+#define WLAN_GPIO_OUT_BIT6             FIELD32(0x00400000)
+#define WLAN_GPIO_OUT_BIT7             FIELD32(0x00800000)
+#define WLAN_GPIO_OUT_BIT_ALL          FIELD32(0x00ff0000)
+#define WLAN_GPIO_OUT_OE_BIT0          FIELD32(0x01000000)
+#define WLAN_GPIO_OUT_OE_BIT1          FIELD32(0x02000000)
+#define WLAN_GPIO_OUT_OE_BIT2          FIELD32(0x04000000)
+#define WLAN_GPIO_OUT_OE_BIT3          FIELD32(0x08000000)
+#define WLAN_GPIO_OUT_OE_BIT4          FIELD32(0x10000000)
+#define WLAN_GPIO_OUT_OE_BIT5          FIELD32(0x20000000)
+#define WLAN_GPIO_OUT_OE_BIT6          FIELD32(0x40000000)
+#define WLAN_GPIO_OUT_OE_BIT7          FIELD32(0x80000000)
+#define WLAN_GPIO_OUT_OE_BIT_ALL       FIELD32(0xff000000)
+
+/*
+ * AUX_CTRL: Aux/PCI-E related configuration
+ */
+#define AUX_CTRL                       0x10c
+#define AUX_CTRL_WAKE_PCIE_EN          FIELD32(0x00000002)
+#define AUX_CTRL_FORCE_PCIE_CLK                FIELD32(0x00000400)
+
+/*
+ * OPT_14: Unknown register used by rt3xxx devices.
+ */
+#define OPT_14_CSR                     0x0114
+#define OPT_14_CSR_BIT0                        FIELD32(0x00000001)
+
+/*
+ * INT_SOURCE_CSR: Interrupt source register.
+ * Write one to clear corresponding bit.
+ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO
+ */
+#define INT_SOURCE_CSR                 0x0200
+#define INT_SOURCE_CSR_RXDELAYINT      FIELD32(0x00000001)
+#define INT_SOURCE_CSR_TXDELAYINT      FIELD32(0x00000002)
+#define INT_SOURCE_CSR_RX_DONE         FIELD32(0x00000004)
+#define INT_SOURCE_CSR_AC0_DMA_DONE    FIELD32(0x00000008)
+#define INT_SOURCE_CSR_AC1_DMA_DONE    FIELD32(0x00000010)
+#define INT_SOURCE_CSR_AC2_DMA_DONE    FIELD32(0x00000020)
+#define INT_SOURCE_CSR_AC3_DMA_DONE    FIELD32(0x00000040)
+#define INT_SOURCE_CSR_HCCA_DMA_DONE   FIELD32(0x00000080)
+#define INT_SOURCE_CSR_MGMT_DMA_DONE   FIELD32(0x00000100)
+#define INT_SOURCE_CSR_MCU_COMMAND     FIELD32(0x00000200)
+#define INT_SOURCE_CSR_RXTX_COHERENT   FIELD32(0x00000400)
+#define INT_SOURCE_CSR_TBTT            FIELD32(0x00000800)
+#define INT_SOURCE_CSR_PRE_TBTT                FIELD32(0x00001000)
+#define INT_SOURCE_CSR_TX_FIFO_STATUS  FIELD32(0x00002000)
+#define INT_SOURCE_CSR_AUTO_WAKEUP     FIELD32(0x00004000)
+#define INT_SOURCE_CSR_GPTIMER         FIELD32(0x00008000)
+#define INT_SOURCE_CSR_RX_COHERENT     FIELD32(0x00010000)
+#define INT_SOURCE_CSR_TX_COHERENT     FIELD32(0x00020000)
+
+/*
+ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
+ */
+#define INT_MASK_CSR                   0x0204
+#define INT_MASK_CSR_RXDELAYINT                FIELD32(0x00000001)
+#define INT_MASK_CSR_TXDELAYINT                FIELD32(0x00000002)
+#define INT_MASK_CSR_RX_DONE           FIELD32(0x00000004)
+#define INT_MASK_CSR_AC0_DMA_DONE      FIELD32(0x00000008)
+#define INT_MASK_CSR_AC1_DMA_DONE      FIELD32(0x00000010)
+#define INT_MASK_CSR_AC2_DMA_DONE      FIELD32(0x00000020)
+#define INT_MASK_CSR_AC3_DMA_DONE      FIELD32(0x00000040)
+#define INT_MASK_CSR_HCCA_DMA_DONE     FIELD32(0x00000080)
+#define INT_MASK_CSR_MGMT_DMA_DONE     FIELD32(0x00000100)
+#define INT_MASK_CSR_MCU_COMMAND       FIELD32(0x00000200)
+#define INT_MASK_CSR_RXTX_COHERENT     FIELD32(0x00000400)
+#define INT_MASK_CSR_TBTT              FIELD32(0x00000800)
+#define INT_MASK_CSR_PRE_TBTT          FIELD32(0x00001000)
+#define INT_MASK_CSR_TX_FIFO_STATUS    FIELD32(0x00002000)
+#define INT_MASK_CSR_AUTO_WAKEUP       FIELD32(0x00004000)
+#define INT_MASK_CSR_GPTIMER           FIELD32(0x00008000)
+#define INT_MASK_CSR_RX_COHERENT       FIELD32(0x00010000)
+#define INT_MASK_CSR_TX_COHERENT       FIELD32(0x00020000)
+
+/*
+ * WPDMA_GLO_CFG
+ */
+#define WPDMA_GLO_CFG                  0x0208
+#define WPDMA_GLO_CFG_ENABLE_TX_DMA    FIELD32(0x00000001)
+#define WPDMA_GLO_CFG_TX_DMA_BUSY      FIELD32(0x00000002)
+#define WPDMA_GLO_CFG_ENABLE_RX_DMA    FIELD32(0x00000004)
+#define WPDMA_GLO_CFG_RX_DMA_BUSY      FIELD32(0x00000008)
+#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE        FIELD32(0x00000030)
+#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE        FIELD32(0x00000040)
+#define WPDMA_GLO_CFG_BIG_ENDIAN       FIELD32(0x00000080)
+#define WPDMA_GLO_CFG_RX_HDR_SCATTER   FIELD32(0x0000ff00)
+#define WPDMA_GLO_CFG_HDR_SEG_LEN      FIELD32(0xffff0000)
+
+/*
+ * WPDMA_RST_IDX
+ */
+#define WPDMA_RST_IDX                  0x020c
+#define WPDMA_RST_IDX_DTX_IDX0         FIELD32(0x00000001)
+#define WPDMA_RST_IDX_DTX_IDX1         FIELD32(0x00000002)
+#define WPDMA_RST_IDX_DTX_IDX2         FIELD32(0x00000004)
+#define WPDMA_RST_IDX_DTX_IDX3         FIELD32(0x00000008)
+#define WPDMA_RST_IDX_DTX_IDX4         FIELD32(0x00000010)
+#define WPDMA_RST_IDX_DTX_IDX5         FIELD32(0x00000020)
+#define WPDMA_RST_IDX_DRX_IDX0         FIELD32(0x00010000)
+
+/*
+ * DELAY_INT_CFG
+ */
+#define DELAY_INT_CFG                  0x0210
+#define DELAY_INT_CFG_RXMAX_PTIME      FIELD32(0x000000ff)
+#define DELAY_INT_CFG_RXMAX_PINT       FIELD32(0x00007f00)
+#define DELAY_INT_CFG_RXDLY_INT_EN     FIELD32(0x00008000)
+#define DELAY_INT_CFG_TXMAX_PTIME      FIELD32(0x00ff0000)
+#define DELAY_INT_CFG_TXMAX_PINT       FIELD32(0x7f000000)
+#define DELAY_INT_CFG_TXDLY_INT_EN     FIELD32(0x80000000)
+
+/*
+ * WMM_AIFSN_CFG: Aifsn for each EDCA AC
+ * AIFSN0: AC_VO
+ * AIFSN1: AC_VI
+ * AIFSN2: AC_BE
+ * AIFSN3: AC_BK
+ */
+#define WMM_AIFSN_CFG                  0x0214
+#define WMM_AIFSN_CFG_AIFSN0           FIELD32(0x0000000f)
+#define WMM_AIFSN_CFG_AIFSN1           FIELD32(0x000000f0)
+#define WMM_AIFSN_CFG_AIFSN2           FIELD32(0x00000f00)
+#define WMM_AIFSN_CFG_AIFSN3           FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMIN_CSR: CWmin for each EDCA AC
+ * CWMIN0: AC_VO
+ * CWMIN1: AC_VI
+ * CWMIN2: AC_BE
+ * CWMIN3: AC_BK
+ */
+#define WMM_CWMIN_CFG                  0x0218
+#define WMM_CWMIN_CFG_CWMIN0           FIELD32(0x0000000f)
+#define WMM_CWMIN_CFG_CWMIN1           FIELD32(0x000000f0)
+#define WMM_CWMIN_CFG_CWMIN2           FIELD32(0x00000f00)
+#define WMM_CWMIN_CFG_CWMIN3           FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMAX_CSR: CWmax for each EDCA AC
+ * CWMAX0: AC_VO
+ * CWMAX1: AC_VI
+ * CWMAX2: AC_BE
+ * CWMAX3: AC_BK
+ */
+#define WMM_CWMAX_CFG                  0x021c
+#define WMM_CWMAX_CFG_CWMAX0           FIELD32(0x0000000f)
+#define WMM_CWMAX_CFG_CWMAX1           FIELD32(0x000000f0)
+#define WMM_CWMAX_CFG_CWMAX2           FIELD32(0x00000f00)
+#define WMM_CWMAX_CFG_CWMAX3           FIELD32(0x0000f000)
+
+/*
+ * AC_TXOP0: AC_VO/AC_VI TXOP register
+ * AC0TXOP: AC_VO in unit of 32us
+ * AC1TXOP: AC_VI in unit of 32us
+ */
+#define WMM_TXOP0_CFG                  0x0220
+#define WMM_TXOP0_CFG_AC0TXOP          FIELD32(0x0000ffff)
+#define WMM_TXOP0_CFG_AC1TXOP          FIELD32(0xffff0000)
+
+/*
+ * AC_TXOP1: AC_BE/AC_BK TXOP register
+ * AC2TXOP: AC_BE in unit of 32us
+ * AC3TXOP: AC_BK in unit of 32us
+ */
+#define WMM_TXOP1_CFG                  0x0224
+#define WMM_TXOP1_CFG_AC2TXOP          FIELD32(0x0000ffff)
+#define WMM_TXOP1_CFG_AC3TXOP          FIELD32(0xffff0000)
+
+/*
+ * GPIO_CTRL:
+ *     GPIO_CTRL_VALx: GPIO value
+ *     GPIO_CTRL_DIRx: GPIO direction: 0 = output; 1 = input
+ */
+#define GPIO_CTRL                      0x0228
+#define GPIO_CTRL_VAL0                 FIELD32(0x00000001)
+#define GPIO_CTRL_VAL1                 FIELD32(0x00000002)
+#define GPIO_CTRL_VAL2                 FIELD32(0x00000004)
+#define GPIO_CTRL_VAL3                 FIELD32(0x00000008)
+#define GPIO_CTRL_VAL4                 FIELD32(0x00000010)
+#define GPIO_CTRL_VAL5                 FIELD32(0x00000020)
+#define GPIO_CTRL_VAL6                 FIELD32(0x00000040)
+#define GPIO_CTRL_VAL7                 FIELD32(0x00000080)
+#define GPIO_CTRL_DIR0                 FIELD32(0x00000100)
+#define GPIO_CTRL_DIR1                 FIELD32(0x00000200)
+#define GPIO_CTRL_DIR2                 FIELD32(0x00000400)
+#define GPIO_CTRL_DIR3                 FIELD32(0x00000800)
+#define GPIO_CTRL_DIR4                 FIELD32(0x00001000)
+#define GPIO_CTRL_DIR5                 FIELD32(0x00002000)
+#define GPIO_CTRL_DIR6                 FIELD32(0x00004000)
+#define GPIO_CTRL_DIR7                 FIELD32(0x00008000)
+#define GPIO_CTRL_VAL8                 FIELD32(0x00010000)
+#define GPIO_CTRL_VAL9                 FIELD32(0x00020000)
+#define GPIO_CTRL_VAL10                        FIELD32(0x00040000)
+#define GPIO_CTRL_DIR8                 FIELD32(0x01000000)
+#define GPIO_CTRL_DIR9                 FIELD32(0x02000000)
+#define GPIO_CTRL_DIR10                        FIELD32(0x04000000)
+
+/*
+ * MCU_CMD_CFG
+ */
+#define MCU_CMD_CFG                    0x022c
+
+/*
+ * AC_VO register offsets
+ */
+#define TX_BASE_PTR0                   0x0230
+#define TX_MAX_CNT0                    0x0234
+#define TX_CTX_IDX0                    0x0238
+#define TX_DTX_IDX0                    0x023c
+
+/*
+ * AC_VI register offsets
+ */
+#define TX_BASE_PTR1                   0x0240
+#define TX_MAX_CNT1                    0x0244
+#define TX_CTX_IDX1                    0x0248
+#define TX_DTX_IDX1                    0x024c
+
+/*
+ * AC_BE register offsets
+ */
+#define TX_BASE_PTR2                   0x0250
+#define TX_MAX_CNT2                    0x0254
+#define TX_CTX_IDX2                    0x0258
+#define TX_DTX_IDX2                    0x025c
+
+/*
+ * AC_BK register offsets
+ */
+#define TX_BASE_PTR3                   0x0260
+#define TX_MAX_CNT3                    0x0264
+#define TX_CTX_IDX3                    0x0268
+#define TX_DTX_IDX3                    0x026c
+
+/*
+ * HCCA register offsets
+ */
+#define TX_BASE_PTR4                   0x0270
+#define TX_MAX_CNT4                    0x0274
+#define TX_CTX_IDX4                    0x0278
+#define TX_DTX_IDX4                    0x027c
+
+/*
+ * MGMT register offsets
+ */
+#define TX_BASE_PTR5                   0x0280
+#define TX_MAX_CNT5                    0x0284
+#define TX_CTX_IDX5                    0x0288
+#define TX_DTX_IDX5                    0x028c
+
+/*
+ * RX register offsets
+ */
+#define RX_BASE_PTR                    0x0290
+#define RX_MAX_CNT                     0x0294
+#define RX_CRX_IDX                     0x0298
+#define RX_DRX_IDX                     0x029c
+
+/*
+ * USB_DMA_CFG
+ * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns.
+ * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes.
+ * PHY_CLEAR: phy watch dog enable.
+ * TX_CLEAR: Clear USB DMA TX path.
+ * TXOP_HALT: Halt TXOP count down when TX buffer is full.
+ * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation.
+ * RX_BULK_EN: Enable USB DMA Rx.
+ * TX_BULK_EN: Enable USB DMA Tx.
+ * EP_OUT_VALID: OUT endpoint data valid.
+ * RX_BUSY: USB DMA RX FSM busy.
+ * TX_BUSY: USB DMA TX FSM busy.
+ */
+#define USB_DMA_CFG                    0x02a0
+#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT        FIELD32(0x000000ff)
+#define USB_DMA_CFG_RX_BULK_AGG_LIMIT  FIELD32(0x0000ff00)
+#define USB_DMA_CFG_PHY_CLEAR          FIELD32(0x00010000)
+#define USB_DMA_CFG_TX_CLEAR           FIELD32(0x00080000)
+#define USB_DMA_CFG_TXOP_HALT          FIELD32(0x00100000)
+#define USB_DMA_CFG_RX_BULK_AGG_EN     FIELD32(0x00200000)
+#define USB_DMA_CFG_RX_BULK_EN         FIELD32(0x00400000)
+#define USB_DMA_CFG_TX_BULK_EN         FIELD32(0x00800000)
+#define USB_DMA_CFG_EP_OUT_VALID       FIELD32(0x3f000000)
+#define USB_DMA_CFG_RX_BUSY            FIELD32(0x40000000)
+#define USB_DMA_CFG_TX_BUSY            FIELD32(0x80000000)
+
+/*
+ * US_CYC_CNT
+ * BT_MODE_EN: Bluetooth mode enable
+ * CLOCK CYCLE: Clock cycle count in 1us.
+ * PCI:0x21, PCIE:0x7d, USB:0x1e
+ */
+#define US_CYC_CNT                     0x02a4
+#define US_CYC_CNT_BT_MODE_EN          FIELD32(0x00000100)
+#define US_CYC_CNT_CLOCK_CYCLE         FIELD32(0x000000ff)
+
+/*
+ * PBF_SYS_CTRL
+ * HOST_RAM_WRITE: enable Host program ram write selection
+ */
+#define PBF_SYS_CTRL                   0x0400
+#define PBF_SYS_CTRL_READY             FIELD32(0x00000080)
+#define PBF_SYS_CTRL_HOST_RAM_WRITE    FIELD32(0x00010000)
+
+/*
+ * HOST-MCU shared memory
+ */
+#define HOST_CMD_CSR                   0x0404
+#define HOST_CMD_CSR_HOST_COMMAND      FIELD32(0x000000ff)
+
+/*
+ * PBF registers
+ * Most are for debug. Driver doesn't touch PBF register.
+ */
+#define PBF_CFG                                0x0408
+#define PBF_MAX_PCNT                   0x040c
+#define PBF_CTRL                       0x0410
+#define PBF_INT_STA                    0x0414
+#define PBF_INT_ENA                    0x0418
+
+/*
+ * BCN_OFFSET0:
+ */
+#define BCN_OFFSET0                    0x042c
+#define BCN_OFFSET0_BCN0               FIELD32(0x000000ff)
+#define BCN_OFFSET0_BCN1               FIELD32(0x0000ff00)
+#define BCN_OFFSET0_BCN2               FIELD32(0x00ff0000)
+#define BCN_OFFSET0_BCN3               FIELD32(0xff000000)
+
+/*
+ * BCN_OFFSET1:
+ */
+#define BCN_OFFSET1                    0x0430
+#define BCN_OFFSET1_BCN4               FIELD32(0x000000ff)
+#define BCN_OFFSET1_BCN5               FIELD32(0x0000ff00)
+#define BCN_OFFSET1_BCN6               FIELD32(0x00ff0000)
+#define BCN_OFFSET1_BCN7               FIELD32(0xff000000)
+
+/*
+ * TXRXQ_PCNT: PBF register
+ * PCNT_TX0Q: Page count for TX hardware queue 0
+ * PCNT_TX1Q: Page count for TX hardware queue 1
+ * PCNT_TX2Q: Page count for TX hardware queue 2
+ * PCNT_RX0Q: Page count for RX hardware queue
+ */
+#define TXRXQ_PCNT                     0x0438
+#define TXRXQ_PCNT_TX0Q                        FIELD32(0x000000ff)
+#define TXRXQ_PCNT_TX1Q                        FIELD32(0x0000ff00)
+#define TXRXQ_PCNT_TX2Q                        FIELD32(0x00ff0000)
+#define TXRXQ_PCNT_RX0Q                        FIELD32(0xff000000)
+
+/*
+ * PBF register
+ * Debug. Driver doesn't touch PBF register.
+ */
+#define PBF_DBG                                0x043c
+
+/*
+ * RF registers
+ */
+#define        RF_CSR_CFG                      0x0500
+#define RF_CSR_CFG_DATA                        FIELD32(0x000000ff)
+#define RF_CSR_CFG_REGNUM              FIELD32(0x00003f00)
+#define RF_CSR_CFG_WRITE               FIELD32(0x00010000)
+#define RF_CSR_CFG_BUSY                        FIELD32(0x00020000)
+
+/*
+ * EFUSE_CSR: RT30x0 EEPROM
+ */
+#define EFUSE_CTRL                     0x0580
+#define EFUSE_CTRL_ADDRESS_IN          FIELD32(0x03fe0000)
+#define EFUSE_CTRL_MODE                        FIELD32(0x000000c0)
+#define EFUSE_CTRL_KICK                        FIELD32(0x40000000)
+#define EFUSE_CTRL_PRESENT             FIELD32(0x80000000)
+
+/*
+ * EFUSE_DATA0
+ */
+#define EFUSE_DATA0                    0x0590
+
+/*
+ * EFUSE_DATA1
+ */
+#define EFUSE_DATA1                    0x0594
+
+/*
+ * EFUSE_DATA2
+ */
+#define EFUSE_DATA2                    0x0598
+
+/*
+ * EFUSE_DATA3
+ */
+#define EFUSE_DATA3                    0x059c
+
+/*
+ * LDO_CFG0
+ */
+#define LDO_CFG0                       0x05d4
+#define LDO_CFG0_DELAY3                        FIELD32(0x000000ff)
+#define LDO_CFG0_DELAY2                        FIELD32(0x0000ff00)
+#define LDO_CFG0_DELAY1                        FIELD32(0x00ff0000)
+#define LDO_CFG0_BGSEL                 FIELD32(0x03000000)
+#define LDO_CFG0_LDO_CORE_VLEVEL       FIELD32(0x1c000000)
+#define LD0_CFG0_LDO25_LEVEL           FIELD32(0x60000000)
+#define LDO_CFG0_LDO25_LARGEA          FIELD32(0x80000000)
+
+/*
+ * GPIO_SWITCH
+ */
+#define GPIO_SWITCH                    0x05dc
+#define GPIO_SWITCH_0                  FIELD32(0x00000001)
+#define GPIO_SWITCH_1                  FIELD32(0x00000002)
+#define GPIO_SWITCH_2                  FIELD32(0x00000004)
+#define GPIO_SWITCH_3                  FIELD32(0x00000008)
+#define GPIO_SWITCH_4                  FIELD32(0x00000010)
+#define GPIO_SWITCH_5                  FIELD32(0x00000020)
+#define GPIO_SWITCH_6                  FIELD32(0x00000040)
+#define GPIO_SWITCH_7                  FIELD32(0x00000080)
+
+/*
+ * FIXME: where the DEBUG_INDEX name come from?
+ */
+#define MAC_DEBUG_INDEX                        0x05e8
+#define MAC_DEBUG_INDEX_XTAL           FIELD32(0x80000000)
+
+/*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ * ASIC_REV: 0
+ * ASIC_VER: 2860 or 2870
+ */
+#define MAC_CSR0                       0x1000
+#define MAC_CSR0_REVISION              FIELD32(0x0000ffff)
+#define MAC_CSR0_CHIPSET               FIELD32(0xffff0000)
+
+/*
+ * MAC_SYS_CTRL:
+ */
+#define MAC_SYS_CTRL                   0x1004
+#define MAC_SYS_CTRL_RESET_CSR         FIELD32(0x00000001)
+#define MAC_SYS_CTRL_RESET_BBP         FIELD32(0x00000002)
+#define MAC_SYS_CTRL_ENABLE_TX         FIELD32(0x00000004)
+#define MAC_SYS_CTRL_ENABLE_RX         FIELD32(0x00000008)
+#define MAC_SYS_CTRL_CONTINUOUS_TX     FIELD32(0x00000010)
+#define MAC_SYS_CTRL_LOOPBACK          FIELD32(0x00000020)
+#define MAC_SYS_CTRL_WLAN_HALT         FIELD32(0x00000040)
+#define MAC_SYS_CTRL_RX_TIMESTAMP      FIELD32(0x00000080)
+
+/*
+ * MAC_ADDR_DW0: STA MAC register 0
+ */
+#define MAC_ADDR_DW0                   0x1008
+#define MAC_ADDR_DW0_BYTE0             FIELD32(0x000000ff)
+#define MAC_ADDR_DW0_BYTE1             FIELD32(0x0000ff00)
+#define MAC_ADDR_DW0_BYTE2             FIELD32(0x00ff0000)
+#define MAC_ADDR_DW0_BYTE3             FIELD32(0xff000000)
+
+/*
+ * MAC_ADDR_DW1: STA MAC register 1
+ * UNICAST_TO_ME_MASK:
+ * Used to mask off bits from byte 5 of the MAC address
+ * to determine the UNICAST_TO_ME bit for RX frames.
+ * The full mask is complemented by BSS_ID_MASK:
+ *    MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+#define MAC_ADDR_DW1                   0x100c
+#define MAC_ADDR_DW1_BYTE4             FIELD32(0x000000ff)
+#define MAC_ADDR_DW1_BYTE5             FIELD32(0x0000ff00)
+#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK        FIELD32(0x00ff0000)
+
+/*
+ * MAC_BSSID_DW0: BSSID register 0
+ */
+#define MAC_BSSID_DW0                  0x1010
+#define MAC_BSSID_DW0_BYTE0            FIELD32(0x000000ff)
+#define MAC_BSSID_DW0_BYTE1            FIELD32(0x0000ff00)
+#define MAC_BSSID_DW0_BYTE2            FIELD32(0x00ff0000)
+#define MAC_BSSID_DW0_BYTE3            FIELD32(0xff000000)
+
+/*
+ * MAC_BSSID_DW1: BSSID register 1
+ * BSS_ID_MASK:
+ *     0: 1-BSSID mode (BSS index = 0)
+ *     1: 2-BSSID mode (BSS index: Byte5, bit 0)
+ *     2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ *     3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
+ * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
+ * BSSID. This will make sure that those bits will be ignored
+ * when determining the MY_BSS of RX frames.
+ */
+#define MAC_BSSID_DW1                  0x1014
+#define MAC_BSSID_DW1_BYTE4            FIELD32(0x000000ff)
+#define MAC_BSSID_DW1_BYTE5            FIELD32(0x0000ff00)
+#define MAC_BSSID_DW1_BSS_ID_MASK      FIELD32(0x00030000)
+#define MAC_BSSID_DW1_BSS_BCN_NUM      FIELD32(0x001c0000)
+
+/*
+ * MAX_LEN_CFG: Maximum frame length register.
+ * MAX_MPDU: rt2860b max 16k bytes
+ * MAX_PSDU: Maximum PSDU length
+ *     (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
+ */
+#define MAX_LEN_CFG                    0x1018
+#define MAX_LEN_CFG_MAX_MPDU           FIELD32(0x00000fff)
+#define MAX_LEN_CFG_MAX_PSDU           FIELD32(0x00003000)
+#define MAX_LEN_CFG_MIN_PSDU           FIELD32(0x0000c000)
+#define MAX_LEN_CFG_MIN_MPDU           FIELD32(0x000f0000)
+
+/*
+ * BBP_CSR_CFG: BBP serial control register
+ * VALUE: Register value to program into BBP
+ * REG_NUM: Selected BBP register
+ * READ_CONTROL: 0 write BBP, 1 read BBP
+ * BUSY: ASIC is busy executing BBP commands
+ * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
+ * BBP_RW_MODE: 0 serial, 1 parallel
+ */
+#define BBP_CSR_CFG                    0x101c
+#define BBP_CSR_CFG_VALUE              FIELD32(0x000000ff)
+#define BBP_CSR_CFG_REGNUM             FIELD32(0x0000ff00)
+#define BBP_CSR_CFG_READ_CONTROL       FIELD32(0x00010000)
+#define BBP_CSR_CFG_BUSY               FIELD32(0x00020000)
+#define BBP_CSR_CFG_BBP_PAR_DUR                FIELD32(0x00040000)
+#define BBP_CSR_CFG_BBP_RW_MODE                FIELD32(0x00080000)
+
+/*
+ * RF_CSR_CFG0: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * BITWIDTH: Selected RF register
+ * STANDBYMODE: 0 high when standby, 1 low when standby
+ * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
+ * BUSY: ASIC is busy executing RF commands
+ */
+#define RF_CSR_CFG0                    0x1020
+#define RF_CSR_CFG0_REGID_AND_VALUE    FIELD32(0x00ffffff)
+#define RF_CSR_CFG0_BITWIDTH           FIELD32(0x1f000000)
+#define RF_CSR_CFG0_REG_VALUE_BW       FIELD32(0x1fffffff)
+#define RF_CSR_CFG0_STANDBYMODE                FIELD32(0x20000000)
+#define RF_CSR_CFG0_SEL                        FIELD32(0x40000000)
+#define RF_CSR_CFG0_BUSY               FIELD32(0x80000000)
+
+/*
+ * RF_CSR_CFG1: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * RFGAP: Gap between BB_CONTROL_RF and RF_LE
+ *        0: 3 system clock cycle (37.5usec)
+ *        1: 5 system clock cycle (62.5usec)
+ */
+#define RF_CSR_CFG1                    0x1024
+#define RF_CSR_CFG1_REGID_AND_VALUE    FIELD32(0x00ffffff)
+#define RF_CSR_CFG1_RFGAP              FIELD32(0x1f000000)
+
+/*
+ * RF_CSR_CFG2: RF control register
+ * VALUE: Register value to program into RF
+ */
+#define RF_CSR_CFG2                    0x1028
+#define RF_CSR_CFG2_VALUE              FIELD32(0x00ffffff)
+
+/*
+ * LED_CFG: LED control
+ * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
+ * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
+ * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
+ * color LED's:
+ *   0: off
+ *   1: blinking upon TX2
+ *   2: periodic slow blinking
+ *   3: always on
+ * LED polarity:
+ *   0: active low
+ *   1: active high
+ */
+#define LED_CFG                                0x102c
+#define LED_CFG_ON_PERIOD              FIELD32(0x000000ff)
+#define LED_CFG_OFF_PERIOD             FIELD32(0x0000ff00)
+#define LED_CFG_SLOW_BLINK_PERIOD      FIELD32(0x003f0000)
+#define LED_CFG_R_LED_MODE             FIELD32(0x03000000)
+#define LED_CFG_G_LED_MODE             FIELD32(0x0c000000)
+#define LED_CFG_Y_LED_MODE             FIELD32(0x30000000)
+#define LED_CFG_LED_POLAR              FIELD32(0x40000000)
+
+/*
+ * AMPDU_BA_WINSIZE: Force BlockAck window size
+ * FORCE_WINSIZE_ENABLE:
+ *   0: Disable forcing of BlockAck window size
+ *   1: Enable forcing of BlockAck window size, overwrites values BlockAck
+ *      window size values in the TXWI
+ * FORCE_WINSIZE: BlockAck window size
+ */
+#define AMPDU_BA_WINSIZE               0x1040
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE FIELD32(0x00000020)
+#define AMPDU_BA_WINSIZE_FORCE_WINSIZE FIELD32(0x0000001f)
+
+/*
+ * XIFS_TIME_CFG: MAC timing
+ * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
+ * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
+ * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
+ *     when MAC doesn't reference BBP signal BBRXEND
+ * EIFS: unit 1us
+ * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
+ *
+ */
+#define XIFS_TIME_CFG                  0x1100
+#define XIFS_TIME_CFG_CCKM_SIFS_TIME   FIELD32(0x000000ff)
+#define XIFS_TIME_CFG_OFDM_SIFS_TIME   FIELD32(0x0000ff00)
+#define XIFS_TIME_CFG_OFDM_XIFS_TIME   FIELD32(0x000f0000)
+#define XIFS_TIME_CFG_EIFS             FIELD32(0x1ff00000)
+#define XIFS_TIME_CFG_BB_RXEND_ENABLE  FIELD32(0x20000000)
+
+/*
+ * BKOFF_SLOT_CFG:
+ */
+#define BKOFF_SLOT_CFG                 0x1104
+#define BKOFF_SLOT_CFG_SLOT_TIME       FIELD32(0x000000ff)
+#define BKOFF_SLOT_CFG_CC_DELAY_TIME   FIELD32(0x0000ff00)
+
+/*
+ * NAV_TIME_CFG:
+ */
+#define NAV_TIME_CFG                   0x1108
+#define NAV_TIME_CFG_SIFS              FIELD32(0x000000ff)
+#define NAV_TIME_CFG_SLOT_TIME         FIELD32(0x0000ff00)
+#define NAV_TIME_CFG_EIFS              FIELD32(0x01ff0000)
+#define NAV_TIME_ZERO_SIFS             FIELD32(0x02000000)
+
+/*
+ * CH_TIME_CFG: count as channel busy
+ * EIFS_BUSY: Count EIFS as channel busy
+ * NAV_BUSY: Count NAS as channel busy
+ * RX_BUSY: Count RX as channel busy
+ * TX_BUSY: Count TX as channel busy
+ * TMR_EN: Enable channel statistics timer
+ */
+#define CH_TIME_CFG                    0x110c
+#define CH_TIME_CFG_EIFS_BUSY          FIELD32(0x00000010)
+#define CH_TIME_CFG_NAV_BUSY           FIELD32(0x00000008)
+#define CH_TIME_CFG_RX_BUSY            FIELD32(0x00000004)
+#define CH_TIME_CFG_TX_BUSY            FIELD32(0x00000002)
+#define CH_TIME_CFG_TMR_EN             FIELD32(0x00000001)
+
+/*
+ * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
+ */
+#define PBF_LIFE_TIMER                 0x1110
+
+/*
+ * BCN_TIME_CFG:
+ * BEACON_INTERVAL: in unit of 1/16 TU
+ * TSF_TICKING: Enable TSF auto counting
+ * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+ * BEACON_GEN: Enable beacon generator
+ */
+#define BCN_TIME_CFG                   0x1114
+#define BCN_TIME_CFG_BEACON_INTERVAL   FIELD32(0x0000ffff)
+#define BCN_TIME_CFG_TSF_TICKING       FIELD32(0x00010000)
+#define BCN_TIME_CFG_TSF_SYNC          FIELD32(0x00060000)
+#define BCN_TIME_CFG_TBTT_ENABLE       FIELD32(0x00080000)
+#define BCN_TIME_CFG_BEACON_GEN                FIELD32(0x00100000)
+#define BCN_TIME_CFG_TX_TIME_COMPENSATE        FIELD32(0xf0000000)
+
+/*
+ * TBTT_SYNC_CFG:
+ * BCN_AIFSN: Beacon AIFSN after TBTT interrupt in slots
+ * BCN_CWMIN: Beacon CWMin after TBTT interrupt in slots
+ */
+#define TBTT_SYNC_CFG                  0x1118
+#define TBTT_SYNC_CFG_TBTT_ADJUST      FIELD32(0x000000ff)
+#define TBTT_SYNC_CFG_BCN_EXP_WIN      FIELD32(0x0000ff00)
+#define TBTT_SYNC_CFG_BCN_AIFSN                FIELD32(0x000f0000)
+#define TBTT_SYNC_CFG_BCN_CWMIN                FIELD32(0x00f00000)
+
+/*
+ * TSF_TIMER_DW0: Local lsb TSF timer, read-only
+ */
+#define TSF_TIMER_DW0                  0x111c
+#define TSF_TIMER_DW0_LOW_WORD         FIELD32(0xffffffff)
+
+/*
+ * TSF_TIMER_DW1: Local msb TSF timer, read-only
+ */
+#define TSF_TIMER_DW1                  0x1120
+#define TSF_TIMER_DW1_HIGH_WORD                FIELD32(0xffffffff)
+
+/*
+ * TBTT_TIMER: TImer remains till next TBTT, read-only
+ */
+#define TBTT_TIMER                     0x1124
+
+/*
+ * INT_TIMER_CFG: timer configuration
+ * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU
+ * GP_TIMER: period of general purpose timer in units of 1/16 TU
+ */
+#define INT_TIMER_CFG                  0x1128
+#define INT_TIMER_CFG_PRE_TBTT_TIMER   FIELD32(0x0000ffff)
+#define INT_TIMER_CFG_GP_TIMER         FIELD32(0xffff0000)
+
+/*
+ * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
+ */
+#define INT_TIMER_EN                   0x112c
+#define INT_TIMER_EN_PRE_TBTT_TIMER    FIELD32(0x00000001)
+#define INT_TIMER_EN_GP_TIMER          FIELD32(0x00000002)
+
+/*
+ * CH_IDLE_STA: channel idle time (in us)
+ */
+#define CH_IDLE_STA                    0x1130
+
+/*
+ * CH_BUSY_STA: channel busy time on primary channel (in us)
+ */
+#define CH_BUSY_STA                    0x1134
+
+/*
+ * CH_BUSY_STA_SEC: channel busy time on secondary channel in HT40 mode (in us)
+ */
+#define CH_BUSY_STA_SEC                        0x1138
+
+/*
+ * MAC_STATUS_CFG:
+ * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
+ *     if 1 or higher one of the 2 registers is busy.
+ */
+#define MAC_STATUS_CFG                 0x1200
+#define MAC_STATUS_CFG_BBP_RF_BUSY     FIELD32(0x00000003)
+
+/*
+ * PWR_PIN_CFG:
+ */
+#define PWR_PIN_CFG                    0x1204
+
+/*
+ * AUTOWAKEUP_CFG: Manual power control / status register
+ * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
+ * AUTOWAKE: 0:sleep, 1:awake
+ */
+#define AUTOWAKEUP_CFG                 0x1208
+#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME  FIELD32(0x000000ff)
+#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE        FIELD32(0x00007f00)
+#define AUTOWAKEUP_CFG_AUTOWAKE                FIELD32(0x00008000)
+
+/*
+ * EDCA_AC0_CFG:
+ */
+#define EDCA_AC0_CFG                   0x1300
+#define EDCA_AC0_CFG_TX_OP             FIELD32(0x000000ff)
+#define EDCA_AC0_CFG_AIFSN             FIELD32(0x00000f00)
+#define EDCA_AC0_CFG_CWMIN             FIELD32(0x0000f000)
+#define EDCA_AC0_CFG_CWMAX             FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC1_CFG:
+ */
+#define EDCA_AC1_CFG                   0x1304
+#define EDCA_AC1_CFG_TX_OP             FIELD32(0x000000ff)
+#define EDCA_AC1_CFG_AIFSN             FIELD32(0x00000f00)
+#define EDCA_AC1_CFG_CWMIN             FIELD32(0x0000f000)
+#define EDCA_AC1_CFG_CWMAX             FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC2_CFG:
+ */
+#define EDCA_AC2_CFG                   0x1308
+#define EDCA_AC2_CFG_TX_OP             FIELD32(0x000000ff)
+#define EDCA_AC2_CFG_AIFSN             FIELD32(0x00000f00)
+#define EDCA_AC2_CFG_CWMIN             FIELD32(0x0000f000)
+#define EDCA_AC2_CFG_CWMAX             FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC3_CFG:
+ */
+#define EDCA_AC3_CFG                   0x130c
+#define EDCA_AC3_CFG_TX_OP             FIELD32(0x000000ff)
+#define EDCA_AC3_CFG_AIFSN             FIELD32(0x00000f00)
+#define EDCA_AC3_CFG_CWMIN             FIELD32(0x0000f000)
+#define EDCA_AC3_CFG_CWMAX             FIELD32(0x000f0000)
+
+/*
+ * EDCA_TID_AC_MAP:
+ */
+#define EDCA_TID_AC_MAP                        0x1310
+
+/*
+ * TX_PWR_CFG:
+ */
+#define TX_PWR_CFG_RATE0               FIELD32(0x0000000f)
+#define TX_PWR_CFG_RATE1               FIELD32(0x000000f0)
+#define TX_PWR_CFG_RATE2               FIELD32(0x00000f00)
+#define TX_PWR_CFG_RATE3               FIELD32(0x0000f000)
+#define TX_PWR_CFG_RATE4               FIELD32(0x000f0000)
+#define TX_PWR_CFG_RATE5               FIELD32(0x00f00000)
+#define TX_PWR_CFG_RATE6               FIELD32(0x0f000000)
+#define TX_PWR_CFG_RATE7               FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_0:
+ */
+#define TX_PWR_CFG_0                   0x1314
+#define TX_PWR_CFG_0_1MBS              FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_2MBS              FIELD32(0x000000f0)
+#define TX_PWR_CFG_0_55MBS             FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_11MBS             FIELD32(0x0000f000)
+#define TX_PWR_CFG_0_6MBS              FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_9MBS              FIELD32(0x00f00000)
+#define TX_PWR_CFG_0_12MBS             FIELD32(0x0f000000)
+#define TX_PWR_CFG_0_18MBS             FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_0_CCK1_CH0          FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_CCK1_CH1          FIELD32(0x000000f0)
+#define TX_PWR_CFG_0_CCK5_CH0          FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_CCK5_CH1          FIELD32(0x0000f000)
+#define TX_PWR_CFG_0_OFDM6_CH0         FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_OFDM6_CH1         FIELD32(0x00f00000)
+#define TX_PWR_CFG_0_OFDM12_CH0                FIELD32(0x0f000000)
+#define TX_PWR_CFG_0_OFDM12_CH1                FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_1:
+ */
+#define TX_PWR_CFG_1                   0x1318
+#define TX_PWR_CFG_1_24MBS             FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_36MBS             FIELD32(0x000000f0)
+#define TX_PWR_CFG_1_48MBS             FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_54MBS             FIELD32(0x0000f000)
+#define TX_PWR_CFG_1_MCS0              FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_MCS1              FIELD32(0x00f00000)
+#define TX_PWR_CFG_1_MCS2              FIELD32(0x0f000000)
+#define TX_PWR_CFG_1_MCS3              FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_1_OFDM24_CH0                FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_OFDM24_CH1                FIELD32(0x000000f0)
+#define TX_PWR_CFG_1_OFDM48_CH0                FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_OFDM48_CH1                FIELD32(0x0000f000)
+#define TX_PWR_CFG_1_MCS0_CH0          FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_MCS0_CH1          FIELD32(0x00f00000)
+#define TX_PWR_CFG_1_MCS2_CH0          FIELD32(0x0f000000)
+#define TX_PWR_CFG_1_MCS2_CH1          FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_2:
+ */
+#define TX_PWR_CFG_2                   0x131c
+#define TX_PWR_CFG_2_MCS4              FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_MCS5              FIELD32(0x000000f0)
+#define TX_PWR_CFG_2_MCS6              FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_MCS7              FIELD32(0x0000f000)
+#define TX_PWR_CFG_2_MCS8              FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_MCS9              FIELD32(0x00f00000)
+#define TX_PWR_CFG_2_MCS10             FIELD32(0x0f000000)
+#define TX_PWR_CFG_2_MCS11             FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_2_MCS4_CH0          FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_MCS4_CH1          FIELD32(0x000000f0)
+#define TX_PWR_CFG_2_MCS6_CH0          FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_MCS6_CH1          FIELD32(0x0000f000)
+#define TX_PWR_CFG_2_MCS8_CH0          FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_MCS8_CH1          FIELD32(0x00f00000)
+#define TX_PWR_CFG_2_MCS10_CH0         FIELD32(0x0f000000)
+#define TX_PWR_CFG_2_MCS10_CH1         FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_3:
+ */
+#define TX_PWR_CFG_3                   0x1320
+#define TX_PWR_CFG_3_MCS12             FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_MCS13             FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_MCS14             FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_MCS15             FIELD32(0x0000f000)
+#define TX_PWR_CFG_3_UKNOWN1           FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_UKNOWN2           FIELD32(0x00f00000)
+#define TX_PWR_CFG_3_UKNOWN3           FIELD32(0x0f000000)
+#define TX_PWR_CFG_3_UKNOWN4           FIELD32(0xf0000000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_3_MCS12_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_MCS12_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_MCS14_CH0         FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_MCS14_CH1         FIELD32(0x0000f000)
+#define TX_PWR_CFG_3_STBC0_CH0         FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_STBC0_CH1         FIELD32(0x00f00000)
+#define TX_PWR_CFG_3_STBC2_CH0         FIELD32(0x0f000000)
+#define TX_PWR_CFG_3_STBC2_CH1         FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_4:
+ */
+#define TX_PWR_CFG_4                   0x1324
+#define TX_PWR_CFG_4_UKNOWN5           FIELD32(0x0000000f)
+#define TX_PWR_CFG_4_UKNOWN6           FIELD32(0x000000f0)
+#define TX_PWR_CFG_4_UKNOWN7           FIELD32(0x00000f00)
+#define TX_PWR_CFG_4_UKNOWN8           FIELD32(0x0000f000)
+/* bits for 3T devices */
+#define TX_PWR_CFG_3_STBC4_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_STBC4_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_STBC6_CH0         FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_STBC6_CH1         FIELD32(0x0000f000)
+
+/*
+ * TX_PIN_CFG:
+ */
+#define TX_PIN_CFG                     0x1328
+#define TX_PIN_CFG_PA_PE_DISABLE       0xfcfffff0
+#define TX_PIN_CFG_PA_PE_A0_EN         FIELD32(0x00000001)
+#define TX_PIN_CFG_PA_PE_G0_EN         FIELD32(0x00000002)
+#define TX_PIN_CFG_PA_PE_A1_EN         FIELD32(0x00000004)
+#define TX_PIN_CFG_PA_PE_G1_EN         FIELD32(0x00000008)
+#define TX_PIN_CFG_PA_PE_A0_POL                FIELD32(0x00000010)
+#define TX_PIN_CFG_PA_PE_G0_POL                FIELD32(0x00000020)
+#define TX_PIN_CFG_PA_PE_A1_POL                FIELD32(0x00000040)
+#define TX_PIN_CFG_PA_PE_G1_POL                FIELD32(0x00000080)
+#define TX_PIN_CFG_LNA_PE_A0_EN                FIELD32(0x00000100)
+#define TX_PIN_CFG_LNA_PE_G0_EN                FIELD32(0x00000200)
+#define TX_PIN_CFG_LNA_PE_A1_EN                FIELD32(0x00000400)
+#define TX_PIN_CFG_LNA_PE_G1_EN                FIELD32(0x00000800)
+#define TX_PIN_CFG_LNA_PE_A0_POL       FIELD32(0x00001000)
+#define TX_PIN_CFG_LNA_PE_G0_POL       FIELD32(0x00002000)
+#define TX_PIN_CFG_LNA_PE_A1_POL       FIELD32(0x00004000)
+#define TX_PIN_CFG_LNA_PE_G1_POL       FIELD32(0x00008000)
+#define TX_PIN_CFG_RFTR_EN             FIELD32(0x00010000)
+#define TX_PIN_CFG_RFTR_POL            FIELD32(0x00020000)
+#define TX_PIN_CFG_TRSW_EN             FIELD32(0x00040000)
+#define TX_PIN_CFG_TRSW_POL            FIELD32(0x00080000)
+#define TX_PIN_CFG_PA_PE_A2_EN         FIELD32(0x01000000)
+#define TX_PIN_CFG_PA_PE_G2_EN         FIELD32(0x02000000)
+#define TX_PIN_CFG_PA_PE_A2_POL                FIELD32(0x04000000)
+#define TX_PIN_CFG_PA_PE_G2_POL                FIELD32(0x08000000)
+#define TX_PIN_CFG_LNA_PE_A2_EN                FIELD32(0x10000000)
+#define TX_PIN_CFG_LNA_PE_G2_EN                FIELD32(0x20000000)
+#define TX_PIN_CFG_LNA_PE_A2_POL       FIELD32(0x40000000)
+#define TX_PIN_CFG_LNA_PE_G2_POL       FIELD32(0x80000000)
+
+/*
+ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
+ */
+#define TX_BAND_CFG                    0x132c
+#define TX_BAND_CFG_HT40_MINUS         FIELD32(0x00000001)
+#define TX_BAND_CFG_A                  FIELD32(0x00000002)
+#define TX_BAND_CFG_BG                 FIELD32(0x00000004)
+
+/*
+ * TX_SW_CFG0:
+ */
+#define TX_SW_CFG0                     0x1330
+
+/*
+ * TX_SW_CFG1:
+ */
+#define TX_SW_CFG1                     0x1334
+
+/*
+ * TX_SW_CFG2:
+ */
+#define TX_SW_CFG2                     0x1338
+
+/*
+ * TXOP_THRES_CFG:
+ */
+#define TXOP_THRES_CFG                 0x133c
+
+/*
+ * TXOP_CTRL_CFG:
+ * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation
+ * AC_TRUN_EN: Enable/Disable truncation for AC change
+ * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change
+ * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode
+ * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS
+ * RESERVED_TRUN_EN: Reserved
+ * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection
+ * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz
+ *            transmissions if extension CCA is clear).
+ * EXT_CCA_DLY: Extension CCA signal delay time (unit: us)
+ * EXT_CWMIN: CwMin for extension channel backoff
+ *           0: Disabled
+ *
+ */
+#define TXOP_CTRL_CFG                  0x1340
+#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN  FIELD32(0x00000001)
+#define TXOP_CTRL_CFG_AC_TRUN_EN       FIELD32(0x00000002)
+#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN        FIELD32(0x00000004)
+#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN        FIELD32(0x00000008)
+#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN  FIELD32(0x00000010)
+#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020)
+#define TXOP_CTRL_CFG_LSIG_TXOP_EN     FIELD32(0x00000040)
+#define TXOP_CTRL_CFG_EXT_CCA_EN       FIELD32(0x00000080)
+#define TXOP_CTRL_CFG_EXT_CCA_DLY      FIELD32(0x0000ff00)
+#define TXOP_CTRL_CFG_EXT_CWMIN                FIELD32(0x000f0000)
+
+/*
+ * TX_RTS_CFG:
+ * RTS_THRES: unit:byte
+ * RTS_FBK_EN: enable rts rate fallback
+ */
+#define TX_RTS_CFG                     0x1344
+#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT        FIELD32(0x000000ff)
+#define TX_RTS_CFG_RTS_THRES           FIELD32(0x00ffff00)
+#define TX_RTS_CFG_RTS_FBK_EN          FIELD32(0x01000000)
+
+/*
+ * TX_TIMEOUT_CFG:
+ * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
+ * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
+ * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
+ *                it is recommended that:
+ *                (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+ */
+#define TX_TIMEOUT_CFG                 0x1348
+#define TX_TIMEOUT_CFG_MPDU_LIFETIME   FIELD32(0x000000f0)
+#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT  FIELD32(0x0000ff00)
+#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT   FIELD32(0x00ff0000)
+
+/*
+ * TX_RTY_CFG:
+ * SHORT_RTY_LIMIT: short retry limit
+ * LONG_RTY_LIMIT: long retry limit
+ * LONG_RTY_THRE: Long retry threshoold
+ * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
+ *                   0:expired by retry limit, 1: expired by mpdu life timer
+ * AGG_RTY_MODE: Aggregate MPDU retry mode
+ *               0:expired by retry limit, 1: expired by mpdu life timer
+ * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
+ */
+#define TX_RTY_CFG                     0x134c
+#define TX_RTY_CFG_SHORT_RTY_LIMIT     FIELD32(0x000000ff)
+#define TX_RTY_CFG_LONG_RTY_LIMIT      FIELD32(0x0000ff00)
+#define TX_RTY_CFG_LONG_RTY_THRE       FIELD32(0x0fff0000)
+#define TX_RTY_CFG_NON_AGG_RTY_MODE    FIELD32(0x10000000)
+#define TX_RTY_CFG_AGG_RTY_MODE                FIELD32(0x20000000)
+#define TX_RTY_CFG_TX_AUTO_FB_ENABLE   FIELD32(0x40000000)
+
+/*
+ * TX_LINK_CFG:
+ * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
+ * MFB_ENABLE: TX apply remote MFB 1:enable
+ * REMOTE_UMFS_ENABLE: remote unsolicit  MFB enable
+ *                     0: not apply remote remote unsolicit (MFS=7)
+ * TX_MRQ_EN: MCS request TX enable
+ * TX_RDG_EN: RDG TX enable
+ * TX_CF_ACK_EN: Piggyback CF-ACK enable
+ * REMOTE_MFB: remote MCS feedback
+ * REMOTE_MFS: remote MCS feedback sequence number
+ */
+#define TX_LINK_CFG                    0x1350
+#define TX_LINK_CFG_REMOTE_MFB_LIFETIME        FIELD32(0x000000ff)
+#define TX_LINK_CFG_MFB_ENABLE         FIELD32(0x00000100)
+#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200)
+#define TX_LINK_CFG_TX_MRQ_EN          FIELD32(0x00000400)
+#define TX_LINK_CFG_TX_RDG_EN          FIELD32(0x00000800)
+#define TX_LINK_CFG_TX_CF_ACK_EN       FIELD32(0x00001000)
+#define TX_LINK_CFG_REMOTE_MFB         FIELD32(0x00ff0000)
+#define TX_LINK_CFG_REMOTE_MFS         FIELD32(0xff000000)
+
+/*
+ * HT_FBK_CFG0:
+ */
+#define HT_FBK_CFG0                    0x1354
+#define HT_FBK_CFG0_HTMCS0FBK          FIELD32(0x0000000f)
+#define HT_FBK_CFG0_HTMCS1FBK          FIELD32(0x000000f0)
+#define HT_FBK_CFG0_HTMCS2FBK          FIELD32(0x00000f00)
+#define HT_FBK_CFG0_HTMCS3FBK          FIELD32(0x0000f000)
+#define HT_FBK_CFG0_HTMCS4FBK          FIELD32(0x000f0000)
+#define HT_FBK_CFG0_HTMCS5FBK          FIELD32(0x00f00000)
+#define HT_FBK_CFG0_HTMCS6FBK          FIELD32(0x0f000000)
+#define HT_FBK_CFG0_HTMCS7FBK          FIELD32(0xf0000000)
+
+/*
+ * HT_FBK_CFG1:
+ */
+#define HT_FBK_CFG1                    0x1358
+#define HT_FBK_CFG1_HTMCS8FBK          FIELD32(0x0000000f)
+#define HT_FBK_CFG1_HTMCS9FBK          FIELD32(0x000000f0)
+#define HT_FBK_CFG1_HTMCS10FBK         FIELD32(0x00000f00)
+#define HT_FBK_CFG1_HTMCS11FBK         FIELD32(0x0000f000)
+#define HT_FBK_CFG1_HTMCS12FBK         FIELD32(0x000f0000)
+#define HT_FBK_CFG1_HTMCS13FBK         FIELD32(0x00f00000)
+#define HT_FBK_CFG1_HTMCS14FBK         FIELD32(0x0f000000)
+#define HT_FBK_CFG1_HTMCS15FBK         FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG0:
+ */
+#define LG_FBK_CFG0                    0x135c
+#define LG_FBK_CFG0_OFDMMCS0FBK                FIELD32(0x0000000f)
+#define LG_FBK_CFG0_OFDMMCS1FBK                FIELD32(0x000000f0)
+#define LG_FBK_CFG0_OFDMMCS2FBK                FIELD32(0x00000f00)
+#define LG_FBK_CFG0_OFDMMCS3FBK                FIELD32(0x0000f000)
+#define LG_FBK_CFG0_OFDMMCS4FBK                FIELD32(0x000f0000)
+#define LG_FBK_CFG0_OFDMMCS5FBK                FIELD32(0x00f00000)
+#define LG_FBK_CFG0_OFDMMCS6FBK                FIELD32(0x0f000000)
+#define LG_FBK_CFG0_OFDMMCS7FBK                FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG1:
+ */
+#define LG_FBK_CFG1                    0x1360
+#define LG_FBK_CFG0_CCKMCS0FBK         FIELD32(0x0000000f)
+#define LG_FBK_CFG0_CCKMCS1FBK         FIELD32(0x000000f0)
+#define LG_FBK_CFG0_CCKMCS2FBK         FIELD32(0x00000f00)
+#define LG_FBK_CFG0_CCKMCS3FBK         FIELD32(0x0000f000)
+
+/*
+ * CCK_PROT_CFG: CCK Protection
+ * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
+ * PROTECT_CTRL: Protection control frame type for CCK TX
+ *               0:none, 1:RTS/CTS, 2:CTS-to-self
+ * PROTECT_NAV_SHORT: TXOP protection type for CCK TX with short NAV
+ * PROTECT_NAV_LONG: TXOP protection type for CCK TX with long NAV
+ * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
+ * RTS_TH_EN: RTS threshold enable on CCK TX
+ */
+#define CCK_PROT_CFG                   0x1364
+#define CCK_PROT_CFG_PROTECT_RATE      FIELD32(0x0000ffff)
+#define CCK_PROT_CFG_PROTECT_CTRL      FIELD32(0x00030000)
+#define CCK_PROT_CFG_PROTECT_NAV_SHORT FIELD32(0x00040000)
+#define CCK_PROT_CFG_PROTECT_NAV_LONG  FIELD32(0x00080000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_CCK   FIELD32(0x00100000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM  FIELD32(0x00200000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM20  FIELD32(0x00400000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM40  FIELD32(0x00800000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF20  FIELD32(0x01000000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF40  FIELD32(0x02000000)
+#define CCK_PROT_CFG_RTS_TH_EN         FIELD32(0x04000000)
+
+/*
+ * OFDM_PROT_CFG: OFDM Protection
+ */
+#define OFDM_PROT_CFG                  0x1368
+#define OFDM_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
+#define OFDM_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
+#define OFDM_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
+#define OFDM_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define OFDM_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
+
+/*
+ * MM20_PROT_CFG: MM20 Protection
+ */
+#define MM20_PROT_CFG                  0x136c
+#define MM20_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
+#define MM20_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
+#define MM20_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
+#define MM20_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define MM20_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
+
+/*
+ * MM40_PROT_CFG: MM40 Protection
+ */
+#define MM40_PROT_CFG                  0x1370
+#define MM40_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
+#define MM40_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
+#define MM40_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
+#define MM40_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define MM40_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
+
+/*
+ * GF20_PROT_CFG: GF20 Protection
+ */
+#define GF20_PROT_CFG                  0x1374
+#define GF20_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
+#define GF20_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
+#define GF20_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
+#define GF20_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define GF20_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
+
+/*
+ * GF40_PROT_CFG: GF40 Protection
+ */
+#define GF40_PROT_CFG                  0x1378
+#define GF40_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
+#define GF40_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
+#define GF40_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
+#define GF40_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define GF40_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
+
+/*
+ * EXP_CTS_TIME:
+ */
+#define EXP_CTS_TIME                   0x137c
+
+/*
+ * EXP_ACK_TIME:
+ */
+#define EXP_ACK_TIME                   0x1380
+
+/* TX_PWR_CFG_5 */
+#define TX_PWR_CFG_5                   0x1384
+#define TX_PWR_CFG_5_MCS16_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_5_MCS16_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_5_MCS16_CH2         FIELD32(0x00000f00)
+#define TX_PWR_CFG_5_MCS18_CH0         FIELD32(0x000f0000)
+#define TX_PWR_CFG_5_MCS18_CH1         FIELD32(0x00f00000)
+#define TX_PWR_CFG_5_MCS18_CH2         FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_6 */
+#define TX_PWR_CFG_6                   0x1388
+#define TX_PWR_CFG_6_MCS20_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_6_MCS20_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_6_MCS20_CH2         FIELD32(0x00000f00)
+#define TX_PWR_CFG_6_MCS22_CH0         FIELD32(0x000f0000)
+#define TX_PWR_CFG_6_MCS22_CH1         FIELD32(0x00f00000)
+#define TX_PWR_CFG_6_MCS22_CH2         FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_0_EXT */
+#define TX_PWR_CFG_0_EXT               0x1390
+#define TX_PWR_CFG_0_EXT_CCK1_CH2      FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_EXT_CCK5_CH2      FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_EXT_OFDM6_CH2     FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_EXT_OFDM12_CH2    FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_1_EXT */
+#define TX_PWR_CFG_1_EXT               0x1394
+#define TX_PWR_CFG_1_EXT_OFDM24_CH2    FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_EXT_OFDM48_CH2    FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_EXT_MCS0_CH2      FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_EXT_MCS2_CH2      FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_2_EXT */
+#define TX_PWR_CFG_2_EXT               0x1398
+#define TX_PWR_CFG_2_EXT_MCS4_CH2      FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_EXT_MCS6_CH2      FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_EXT_MCS8_CH2      FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_EXT_MCS10_CH2     FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_3_EXT */
+#define TX_PWR_CFG_3_EXT               0x139c
+#define TX_PWR_CFG_3_EXT_MCS12_CH2     FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_EXT_MCS14_CH2     FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_EXT_STBC0_CH2     FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_EXT_STBC2_CH2     FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_4_EXT */
+#define TX_PWR_CFG_4_EXT               0x13a0
+#define TX_PWR_CFG_4_EXT_STBC4_CH2     FIELD32(0x0000000f)
+#define TX_PWR_CFG_4_EXT_STBC6_CH2     FIELD32(0x00000f00)
+
+/* TX_PWR_CFG_7 */
+#define TX_PWR_CFG_7                   0x13d4
+#define TX_PWR_CFG_7_OFDM54_CH0                FIELD32(0x0000000f)
+#define TX_PWR_CFG_7_OFDM54_CH1                FIELD32(0x000000f0)
+#define TX_PWR_CFG_7_OFDM54_CH2                FIELD32(0x00000f00)
+#define TX_PWR_CFG_7_MCS7_CH0          FIELD32(0x000f0000)
+#define TX_PWR_CFG_7_MCS7_CH1          FIELD32(0x00f00000)
+#define TX_PWR_CFG_7_MCS7_CH2          FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_8 */
+#define TX_PWR_CFG_8                   0x13d8
+#define TX_PWR_CFG_8_MCS15_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_8_MCS15_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_8_MCS15_CH2         FIELD32(0x00000f00)
+#define TX_PWR_CFG_8_MCS23_CH0         FIELD32(0x000f0000)
+#define TX_PWR_CFG_8_MCS23_CH1         FIELD32(0x00f00000)
+#define TX_PWR_CFG_8_MCS23_CH2         FIELD32(0x0f000000)
+
+/* TX_PWR_CFG_9 */
+#define TX_PWR_CFG_9                   0x13dc
+#define TX_PWR_CFG_9_STBC7_CH0         FIELD32(0x0000000f)
+#define TX_PWR_CFG_9_STBC7_CH1         FIELD32(0x000000f0)
+#define TX_PWR_CFG_9_STBC7_CH2         FIELD32(0x00000f00)
+
+/*
+ * RX_FILTER_CFG: RX configuration register.
+ */
+#define RX_FILTER_CFG                  0x1400
+#define RX_FILTER_CFG_DROP_CRC_ERROR   FIELD32(0x00000001)
+#define RX_FILTER_CFG_DROP_PHY_ERROR   FIELD32(0x00000002)
+#define RX_FILTER_CFG_DROP_NOT_TO_ME   FIELD32(0x00000004)
+#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008)
+#define RX_FILTER_CFG_DROP_VER_ERROR   FIELD32(0x00000010)
+#define RX_FILTER_CFG_DROP_MULTICAST   FIELD32(0x00000020)
+#define RX_FILTER_CFG_DROP_BROADCAST   FIELD32(0x00000040)
+#define RX_FILTER_CFG_DROP_DUPLICATE   FIELD32(0x00000080)
+#define RX_FILTER_CFG_DROP_CF_END_ACK  FIELD32(0x00000100)
+#define RX_FILTER_CFG_DROP_CF_END      FIELD32(0x00000200)
+#define RX_FILTER_CFG_DROP_ACK         FIELD32(0x00000400)
+#define RX_FILTER_CFG_DROP_CTS         FIELD32(0x00000800)
+#define RX_FILTER_CFG_DROP_RTS         FIELD32(0x00001000)
+#define RX_FILTER_CFG_DROP_PSPOLL      FIELD32(0x00002000)
+#define RX_FILTER_CFG_DROP_BA          FIELD32(0x00004000)
+#define RX_FILTER_CFG_DROP_BAR         FIELD32(0x00008000)
+#define RX_FILTER_CFG_DROP_CNTL                FIELD32(0x00010000)
+
+/*
+ * AUTO_RSP_CFG:
+ * AUTORESPONDER: 0: disable, 1: enable
+ * BAC_ACK_POLICY: 0:long, 1:short preamble
+ * CTS_40_MMODE: Response CTS 40MHz duplicate mode
+ * CTS_40_MREF: Response CTS 40MHz duplicate mode
+ * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
+ * DUAL_CTS_EN: Power bit value in control frame
+ * ACK_CTS_PSM_BIT:Power bit value in control frame
+ */
+#define AUTO_RSP_CFG                   0x1404
+#define AUTO_RSP_CFG_AUTORESPONDER     FIELD32(0x00000001)
+#define AUTO_RSP_CFG_BAC_ACK_POLICY    FIELD32(0x00000002)
+#define AUTO_RSP_CFG_CTS_40_MMODE      FIELD32(0x00000004)
+#define AUTO_RSP_CFG_CTS_40_MREF       FIELD32(0x00000008)
+#define AUTO_RSP_CFG_AR_PREAMBLE       FIELD32(0x00000010)
+#define AUTO_RSP_CFG_DUAL_CTS_EN       FIELD32(0x00000040)
+#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT   FIELD32(0x00000080)
+
+/*
+ * LEGACY_BASIC_RATE:
+ */
+#define LEGACY_BASIC_RATE              0x1408
+
+/*
+ * HT_BASIC_RATE:
+ */
+#define HT_BASIC_RATE                  0x140c
+
+/*
+ * HT_CTRL_CFG:
+ */
+#define HT_CTRL_CFG                    0x1410
+
+/*
+ * SIFS_COST_CFG:
+ */
+#define SIFS_COST_CFG                  0x1414
+
+/*
+ * RX_PARSER_CFG:
+ * Set NAV for all received frames
+ */
+#define RX_PARSER_CFG                  0x1418
+
+/*
+ * TX_SEC_CNT0:
+ */
+#define TX_SEC_CNT0                    0x1500
+
+/*
+ * RX_SEC_CNT0:
+ */
+#define RX_SEC_CNT0                    0x1504
+
+/*
+ * CCMP_FC_MUTE:
+ */
+#define CCMP_FC_MUTE                   0x1508
+
+/*
+ * TXOP_HLDR_ADDR0:
+ */
+#define TXOP_HLDR_ADDR0                        0x1600
+
+/*
+ * TXOP_HLDR_ADDR1:
+ */
+#define TXOP_HLDR_ADDR1                        0x1604
+
+/*
+ * TXOP_HLDR_ET:
+ */
+#define TXOP_HLDR_ET                   0x1608
+
+/*
+ * QOS_CFPOLL_RA_DW0:
+ */
+#define QOS_CFPOLL_RA_DW0              0x160c
+
+/*
+ * QOS_CFPOLL_RA_DW1:
+ */
+#define QOS_CFPOLL_RA_DW1              0x1610
+
+/*
+ * QOS_CFPOLL_QC:
+ */
+#define QOS_CFPOLL_QC                  0x1614
+
+/*
+ * RX_STA_CNT0: RX PLCP error count & RX CRC error count
+ */
+#define RX_STA_CNT0                    0x1700
+#define RX_STA_CNT0_CRC_ERR            FIELD32(0x0000ffff)
+#define RX_STA_CNT0_PHY_ERR            FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT1: RX False CCA count & RX LONG frame count
+ */
+#define RX_STA_CNT1                    0x1704
+#define RX_STA_CNT1_FALSE_CCA          FIELD32(0x0000ffff)
+#define RX_STA_CNT1_PLCP_ERR           FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT2:
+ */
+#define RX_STA_CNT2                    0x1708
+#define RX_STA_CNT2_RX_DUPLI_COUNT     FIELD32(0x0000ffff)
+#define RX_STA_CNT2_RX_FIFO_OVERFLOW   FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT0: TX Beacon count
+ */
+#define TX_STA_CNT0                    0x170c
+#define TX_STA_CNT0_TX_FAIL_COUNT      FIELD32(0x0000ffff)
+#define TX_STA_CNT0_TX_BEACON_COUNT    FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT1: TX tx count
+ */
+#define TX_STA_CNT1                    0x1710
+#define TX_STA_CNT1_TX_SUCCESS         FIELD32(0x0000ffff)
+#define TX_STA_CNT1_TX_RETRANSMIT      FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT2: TX tx count
+ */
+#define TX_STA_CNT2                    0x1714
+#define TX_STA_CNT2_TX_ZERO_LEN_COUNT  FIELD32(0x0000ffff)
+#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT        FIELD32(0xffff0000)
+
+/*
+ * TX_STA_FIFO: TX Result for specific PID status fifo register.
+ *
+ * This register is implemented as FIFO with 16 entries in the HW. Each
+ * register read fetches the next tx result. If the FIFO is full because
+ * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS)
+ * triggered, the hw seems to simply drop further tx results.
+ *
+ * VALID: 1: this tx result is valid
+ *        0: no valid tx result -> driver should stop reading
+ * PID_TYPE: The PID latched from the PID field in the TXWI, can be used
+ *           to match a frame with its tx result (even though the PID is
+ *           only 4 bits wide).
+ * PID_QUEUE: Part of PID_TYPE, this is the queue index number (0-3)
+ * PID_ENTRY: Part of PID_TYPE, this is the queue entry index number (1-3)
+ *            This identification number is calculated by ((idx % 3) + 1).
+ * TX_SUCCESS: Indicates tx success (1) or failure (0)
+ * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0)
+ * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0)
+ * WCID: The wireless client ID.
+ * MCS: The tx rate used during the last transmission of this frame, be it
+ *      successful or not.
+ * PHYMODE: The phymode used for the transmission.
+ */
+#define TX_STA_FIFO                    0x1718
+#define TX_STA_FIFO_VALID              FIELD32(0x00000001)
+#define TX_STA_FIFO_PID_TYPE           FIELD32(0x0000001e)
+#define TX_STA_FIFO_PID_QUEUE          FIELD32(0x00000006)
+#define TX_STA_FIFO_PID_ENTRY          FIELD32(0x00000018)
+#define TX_STA_FIFO_TX_SUCCESS         FIELD32(0x00000020)
+#define TX_STA_FIFO_TX_AGGRE           FIELD32(0x00000040)
+#define TX_STA_FIFO_TX_ACK_REQUIRED    FIELD32(0x00000080)
+#define TX_STA_FIFO_WCID               FIELD32(0x0000ff00)
+#define TX_STA_FIFO_SUCCESS_RATE       FIELD32(0xffff0000)
+#define TX_STA_FIFO_MCS                        FIELD32(0x007f0000)
+#define TX_STA_FIFO_PHYMODE            FIELD32(0xc0000000)
+
+/*
+ * TX_AGG_CNT: Debug counter
+ */
+#define TX_AGG_CNT                     0x171c
+#define TX_AGG_CNT_NON_AGG_TX_COUNT    FIELD32(0x0000ffff)
+#define TX_AGG_CNT_AGG_TX_COUNT                FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT0:
+ */
+#define TX_AGG_CNT0                    0x1720
+#define TX_AGG_CNT0_AGG_SIZE_1_COUNT   FIELD32(0x0000ffff)
+#define TX_AGG_CNT0_AGG_SIZE_2_COUNT   FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT1:
+ */
+#define TX_AGG_CNT1                    0x1724
+#define TX_AGG_CNT1_AGG_SIZE_3_COUNT   FIELD32(0x0000ffff)
+#define TX_AGG_CNT1_AGG_SIZE_4_COUNT   FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT2:
+ */
+#define TX_AGG_CNT2                    0x1728
+#define TX_AGG_CNT2_AGG_SIZE_5_COUNT   FIELD32(0x0000ffff)
+#define TX_AGG_CNT2_AGG_SIZE_6_COUNT   FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT3:
+ */
+#define TX_AGG_CNT3                    0x172c
+#define TX_AGG_CNT3_AGG_SIZE_7_COUNT   FIELD32(0x0000ffff)
+#define TX_AGG_CNT3_AGG_SIZE_8_COUNT   FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT4:
+ */
+#define TX_AGG_CNT4                    0x1730
+#define TX_AGG_CNT4_AGG_SIZE_9_COUNT   FIELD32(0x0000ffff)
+#define TX_AGG_CNT4_AGG_SIZE_10_COUNT  FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT5:
+ */
+#define TX_AGG_CNT5                    0x1734
+#define TX_AGG_CNT5_AGG_SIZE_11_COUNT  FIELD32(0x0000ffff)
+#define TX_AGG_CNT5_AGG_SIZE_12_COUNT  FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT6:
+ */
+#define TX_AGG_CNT6                    0x1738
+#define TX_AGG_CNT6_AGG_SIZE_13_COUNT  FIELD32(0x0000ffff)
+#define TX_AGG_CNT6_AGG_SIZE_14_COUNT  FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT7:
+ */
+#define TX_AGG_CNT7                    0x173c
+#define TX_AGG_CNT7_AGG_SIZE_15_COUNT  FIELD32(0x0000ffff)
+#define TX_AGG_CNT7_AGG_SIZE_16_COUNT  FIELD32(0xffff0000)
+
+/*
+ * MPDU_DENSITY_CNT:
+ * TX_ZERO_DEL: TX zero length delimiter count
+ * RX_ZERO_DEL: RX zero length delimiter count
+ */
+#define MPDU_DENSITY_CNT               0x1740
+#define MPDU_DENSITY_CNT_TX_ZERO_DEL   FIELD32(0x0000ffff)
+#define MPDU_DENSITY_CNT_RX_ZERO_DEL   FIELD32(0xffff0000)
+
+/*
+ * Security key table memory.
+ *
+ * The pairwise key table shares some memory with the beacon frame
+ * buffers 6 and 7. That basically means that when beacon 6 & 7
+ * are used we should only use the reduced pairwise key table which
+ * has a maximum of 222 entries.
+ *
+ * ---------------------------------------------
+ * |0x4000 | Pairwise Key   | Reduced Pairwise |
+ * |       | Table          | Key Table        |
+ * |       | Size: 256 * 32 | Size: 222 * 32   |
+ * |0x5BC0 |                |-------------------
+ * |       |                | Beacon 6         |
+ * |0x5DC0 |                |-------------------
+ * |       |                | Beacon 7         |
+ * |0x5FC0 |                |-------------------
+ * |0x5FFF |                |
+ * --------------------------
+ *
+ * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
+ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
+ * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
+ * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
+ * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry
+ * SHARED_KEY_MODE_BASE: 4-byte * 16-entry
+ */
+#define MAC_WCID_BASE                  0x1800
+#define PAIRWISE_KEY_TABLE_BASE                0x4000
+#define MAC_IVEIV_TABLE_BASE           0x6000
+#define MAC_WCID_ATTRIBUTE_BASE                0x6800
+#define SHARED_KEY_TABLE_BASE          0x6c00
+#define SHARED_KEY_MODE_BASE           0x7000
+
+#define MAC_WCID_ENTRY(__idx) \
+       (MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)))
+#define PAIRWISE_KEY_ENTRY(__idx) \
+       (PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
+#define MAC_IVEIV_ENTRY(__idx) \
+       (MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)))
+#define MAC_WCID_ATTR_ENTRY(__idx) \
+       (MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)))
+#define SHARED_KEY_ENTRY(__idx) \
+       (SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
+#define SHARED_KEY_MODE_ENTRY(__idx) \
+       (SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)))
+
+struct mac_wcid_entry {
+       u8 mac[6];
+       u8 reserved[2];
+} __packed;
+
+struct hw_key_entry {
+       u8 key[16];
+       u8 tx_mic[8];
+       u8 rx_mic[8];
+} __packed;
+
+struct mac_iveiv_entry {
+       u8 iv[8];
+} __packed;
+
+/*
+ * MAC_WCID_ATTRIBUTE:
+ */
+#define MAC_WCID_ATTRIBUTE_KEYTAB      FIELD32(0x00000001)
+#define MAC_WCID_ATTRIBUTE_CIPHER      FIELD32(0x0000000e)
+#define MAC_WCID_ATTRIBUTE_BSS_IDX     FIELD32(0x00000070)
+#define MAC_WCID_ATTRIBUTE_RX_WIUDF    FIELD32(0x00000380)
+#define MAC_WCID_ATTRIBUTE_CIPHER_EXT  FIELD32(0x00000400)
+#define MAC_WCID_ATTRIBUTE_BSS_IDX_EXT FIELD32(0x00000800)
+#define MAC_WCID_ATTRIBUTE_WAPI_MCBC   FIELD32(0x00008000)
+#define MAC_WCID_ATTRIBUTE_WAPI_KEY_IDX        FIELD32(0xff000000)
+
+/*
+ * SHARED_KEY_MODE:
+ */
+#define SHARED_KEY_MODE_BSS0_KEY0      FIELD32(0x00000007)
+#define SHARED_KEY_MODE_BSS0_KEY1      FIELD32(0x00000070)
+#define SHARED_KEY_MODE_BSS0_KEY2      FIELD32(0x00000700)
+#define SHARED_KEY_MODE_BSS0_KEY3      FIELD32(0x00007000)
+#define SHARED_KEY_MODE_BSS1_KEY0      FIELD32(0x00070000)
+#define SHARED_KEY_MODE_BSS1_KEY1      FIELD32(0x00700000)
+#define SHARED_KEY_MODE_BSS1_KEY2      FIELD32(0x07000000)
+#define SHARED_KEY_MODE_BSS1_KEY3      FIELD32(0x70000000)
+
+/*
+ * HOST-MCU communication
+ */
+
+/*
+ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
+ * CMD_TOKEN: Command id, 0xff disable status reporting.
+ */
+#define H2M_MAILBOX_CSR                        0x7010
+#define H2M_MAILBOX_CSR_ARG0           FIELD32(0x000000ff)
+#define H2M_MAILBOX_CSR_ARG1           FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CSR_CMD_TOKEN      FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CSR_OWNER          FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_CID:
+ * Free slots contain 0xff. MCU will store command's token to lowest free slot.
+ * If all slots are occupied status will be dropped.
+ */
+#define H2M_MAILBOX_CID                        0x7014
+#define H2M_MAILBOX_CID_CMD0           FIELD32(0x000000ff)
+#define H2M_MAILBOX_CID_CMD1           FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CID_CMD2           FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CID_CMD3           FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_STATUS:
+ * Command status will be saved to same slot as command id.
+ */
+#define H2M_MAILBOX_STATUS             0x701c
+
+/*
+ * H2M_INT_SRC:
+ */
+#define H2M_INT_SRC                    0x7024
+
+/*
+ * H2M_BBP_AGENT:
+ */
+#define H2M_BBP_AGENT                  0x7028
+
+/*
+ * MCU_LEDCS: LED control for MCU Mailbox.
+ */
+#define MCU_LEDCS_LED_MODE             FIELD8(0x1f)
+#define MCU_LEDCS_POLARITY             FIELD8(0x01)
+
+/*
+ * HW_CS_CTS_BASE:
+ * Carrier-sense CTS frame base address.
+ * It's where mac stores carrier-sense frame for carrier-sense function.
+ */
+#define HW_CS_CTS_BASE                 0x7700
+
+/*
+ * HW_DFS_CTS_BASE:
+ * DFS CTS frame base address. It's where mac stores CTS frame for DFS.
+ */
+#define HW_DFS_CTS_BASE                        0x7780
+
+/*
+ * TXRX control registers - base address 0x3000
+ */
+
+/*
+ * TXRX_CSR1:
+ * rt2860b  UNKNOWN reg use R/O Reg Addr 0x77d0 first..
+ */
+#define TXRX_CSR1                      0x77d0
+
+/*
+ * HW_DEBUG_SETTING_BASE:
+ * since NULL frame won't be that long (256 byte)
+ * We steal 16 tail bytes to save debugging settings
+ */
+#define HW_DEBUG_SETTING_BASE          0x77f0
+#define HW_DEBUG_SETTING_BASE2         0x7770
+
+/*
+ * HW_BEACON_BASE
+ * In order to support maximum 8 MBSS and its maximum length
+ * is 512 bytes for each beacon
+ * Three section discontinue memory segments will be used.
+ * 1. The original region for BCN 0~3
+ * 2. Extract memory from FCE table for BCN 4~5
+ * 3. Extract memory from Pair-wise key table for BCN 6~7
+ *    It occupied those memory of wcid 238~253 for BCN 6
+ *    and wcid 222~237 for BCN 7 (see Security key table memory
+ *    for more info).
+ *
+ * IMPORTANT NOTE: Not sure why legacy driver does this,
+ * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
+ */
+#define HW_BEACON_BASE0                        0x7800
+#define HW_BEACON_BASE1                        0x7a00
+#define HW_BEACON_BASE2                        0x7c00
+#define HW_BEACON_BASE3                        0x7e00
+#define HW_BEACON_BASE4                        0x7200
+#define HW_BEACON_BASE5                        0x7400
+#define HW_BEACON_BASE6                        0x5dc0
+#define HW_BEACON_BASE7                        0x5bc0
+
+#define HW_BEACON_BASE(__index) \
+       (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \
+         (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
+         (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
+
+#define BEACON_BASE_TO_OFFSET(_base)   (((_base) - 0x4000) / 64)
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * BBP 1: TX Antenna & Power Control
+ * POWER_CTRL:
+ * 0 - normal,
+ * 1 - drop tx power by 6dBm,
+ * 2 - drop tx power by 12dBm,
+ * 3 - increase tx power by 6dBm
+ */
+#define BBP1_TX_POWER_CTRL             FIELD8(0x03)
+#define BBP1_TX_ANTENNA                        FIELD8(0x18)
+
+/*
+ * BBP 3: RX Antenna
+ */
+#define BBP3_RX_ADC                    FIELD8(0x03)
+#define BBP3_RX_ANTENNA                        FIELD8(0x18)
+#define BBP3_HT40_MINUS                        FIELD8(0x20)
+#define BBP3_ADC_MODE_SWITCH           FIELD8(0x40)
+#define BBP3_ADC_INIT_MODE             FIELD8(0x80)
+
+/*
+ * BBP 4: Bandwidth
+ */
+#define BBP4_TX_BF                     FIELD8(0x01)
+#define BBP4_BANDWIDTH                 FIELD8(0x18)
+#define BBP4_MAC_IF_CTRL               FIELD8(0x40)
+
+/* BBP27 */
+#define BBP27_RX_CHAIN_SEL             FIELD8(0x60)
+
+/*
+ * BBP 47: Bandwidth
+ */
+#define BBP47_TSSI_REPORT_SEL          FIELD8(0x03)
+#define BBP47_TSSI_UPDATE_REQ          FIELD8(0x04)
+#define BBP47_TSSI_TSSI_MODE           FIELD8(0x18)
+#define BBP47_TSSI_ADC6                        FIELD8(0x80)
+
+/*
+ * BBP 49
+ */
+#define BBP49_UPDATE_FLAG              FIELD8(0x01)
+
+/*
+ * BBP 105:
+ * - bit0: detect SIG on primary channel only (on 40MHz bandwidth)
+ * - bit1: FEQ (Feed Forward Compensation) for independend streams
+ * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single
+ *        stream)
+ * - bit4: channel estimation updates based on remodulation of
+ *        L-SIG and HT-SIG symbols
+ */
+#define BBP105_DETECT_SIG_ON_PRIMARY   FIELD8(0x01)
+#define BBP105_FEQ                     FIELD8(0x02)
+#define BBP105_MLD                     FIELD8(0x04)
+#define BBP105_SIG_REMODULATION                FIELD8(0x08)
+
+/*
+ * BBP 109
+ */
+#define BBP109_TX0_POWER               FIELD8(0x0f)
+#define BBP109_TX1_POWER               FIELD8(0xf0)
+
+/* BBP 110 */
+#define BBP110_TX2_POWER               FIELD8(0x0f)
+
+
+/*
+ * BBP 138: Unknown
+ */
+#define BBP138_RX_ADC1                 FIELD8(0x02)
+#define BBP138_RX_ADC2                 FIELD8(0x04)
+#define BBP138_TX_DAC1                 FIELD8(0x20)
+#define BBP138_TX_DAC2                 FIELD8(0x40)
+
+/*
+ * BBP 152: Rx Ant
+ */
+#define BBP152_RX_DEFAULT_ANT          FIELD8(0x80)
+
+/*
+ * BBP 254: unknown
+ */
+#define BBP254_BIT7                    FIELD8(0x80)
+
+/*
+ * RFCSR registers
+ * The wordsize of the RFCSR is 8 bits.
+ */
+
+/*
+ * RFCSR 1:
+ */
+#define RFCSR1_RF_BLOCK_EN             FIELD8(0x01)
+#define RFCSR1_PLL_PD                  FIELD8(0x02)
+#define RFCSR1_RX0_PD                  FIELD8(0x04)
+#define RFCSR1_TX0_PD                  FIELD8(0x08)
+#define RFCSR1_RX1_PD                  FIELD8(0x10)
+#define RFCSR1_TX1_PD                  FIELD8(0x20)
+#define RFCSR1_RX2_PD                  FIELD8(0x40)
+#define RFCSR1_TX2_PD                  FIELD8(0x80)
+
+/*
+ * RFCSR 2:
+ */
+#define RFCSR2_RESCAL_EN               FIELD8(0x80)
+
+/*
+ * RFCSR 3:
+ */
+#define RFCSR3_K                       FIELD8(0x0f)
+/* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */
+#define RFCSR3_PA1_BIAS_CCK            FIELD8(0x70)
+#define RFCSR3_PA2_CASCODE_BIAS_CCKK   FIELD8(0x80)
+/* Bits for RF3290/RF5360/RF5362/RF5370/RF5372/RF5390/RF5392 */
+#define RFCSR3_VCOCAL_EN               FIELD8(0x80)
+/* Bits for RF3050 */
+#define RFCSR3_BIT1                    FIELD8(0x02)
+#define RFCSR3_BIT2                    FIELD8(0x04)
+#define RFCSR3_BIT3                    FIELD8(0x08)
+#define RFCSR3_BIT4                    FIELD8(0x10)
+#define RFCSR3_BIT5                    FIELD8(0x20)
+
+/*
+ * FRCSR 5:
+ */
+#define RFCSR5_R1                      FIELD8(0x0c)
+
+/*
+ * RFCSR 6:
+ */
+#define RFCSR6_R1                      FIELD8(0x03)
+#define RFCSR6_R2                      FIELD8(0x40)
+#define RFCSR6_TXDIV                   FIELD8(0x0c)
+/* bits for RF3053 */
+#define RFCSR6_VCO_IC                  FIELD8(0xc0)
+
+/*
+ * RFCSR 7:
+ */
+#define RFCSR7_RF_TUNING               FIELD8(0x01)
+#define RFCSR7_BIT1                    FIELD8(0x02)
+#define RFCSR7_BIT2                    FIELD8(0x04)
+#define RFCSR7_BIT3                    FIELD8(0x08)
+#define RFCSR7_BIT4                    FIELD8(0x10)
+#define RFCSR7_BIT5                    FIELD8(0x20)
+#define RFCSR7_BITS67                  FIELD8(0xc0)
+
+/*
+ * RFCSR 9:
+ */
+#define RFCSR9_K                       FIELD8(0x0f)
+#define RFCSR9_N                       FIELD8(0x10)
+#define RFCSR9_UNKNOWN                 FIELD8(0x60)
+#define RFCSR9_MOD                     FIELD8(0x80)
+
+/*
+ * RFCSR 11:
+ */
+#define RFCSR11_R                      FIELD8(0x03)
+#define RFCSR11_PLL_MOD                        FIELD8(0x0c)
+#define RFCSR11_MOD                    FIELD8(0xc0)
+/* bits for RF3053 */
+/* TODO: verify RFCSR11_MOD usage on other chips */
+#define RFCSR11_PLL_IDOH               FIELD8(0x40)
+
+
+/*
+ * RFCSR 12:
+ */
+#define RFCSR12_TX_POWER               FIELD8(0x1f)
+#define RFCSR12_DR0                    FIELD8(0xe0)
+
+/*
+ * RFCSR 13:
+ */
+#define RFCSR13_TX_POWER               FIELD8(0x1f)
+#define RFCSR13_DR0                    FIELD8(0xe0)
+
+/*
+ * RFCSR 15:
+ */
+#define RFCSR15_TX_LO2_EN              FIELD8(0x08)
+
+/*
+ * RFCSR 16:
+ */
+#define RFCSR16_TXMIXER_GAIN           FIELD8(0x07)
+
+/*
+ * RFCSR 17:
+ */
+#define RFCSR17_TXMIXER_GAIN           FIELD8(0x07)
+#define RFCSR17_TX_LO1_EN              FIELD8(0x08)
+#define RFCSR17_R                      FIELD8(0x20)
+#define RFCSR17_CODE                   FIELD8(0x7f)
+
+/* RFCSR 18 */
+#define RFCSR18_XO_TUNE_BYPASS         FIELD8(0x40)
+
+
+/*
+ * RFCSR 20:
+ */
+#define RFCSR20_RX_LO1_EN              FIELD8(0x08)
+
+/*
+ * RFCSR 21:
+ */
+#define RFCSR21_RX_LO2_EN              FIELD8(0x08)
+
+/*
+ * RFCSR 22:
+ */
+#define RFCSR22_BASEBAND_LOOPBACK      FIELD8(0x01)
+
+/*
+ * RFCSR 23:
+ */
+#define RFCSR23_FREQ_OFFSET            FIELD8(0x7f)
+
+/*
+ * RFCSR 24:
+ */
+#define RFCSR24_TX_AGC_FC              FIELD8(0x1f)
+#define RFCSR24_TX_H20M                        FIELD8(0x20)
+#define RFCSR24_TX_CALIB               FIELD8(0x7f)
+
+/*
+ * RFCSR 27:
+ */
+#define RFCSR27_R1                     FIELD8(0x03)
+#define RFCSR27_R2                     FIELD8(0x04)
+#define RFCSR27_R3                     FIELD8(0x30)
+#define RFCSR27_R4                     FIELD8(0x40)
+
+/*
+ * RFCSR 29:
+ */
+#define RFCSR29_ADC6_TEST              FIELD8(0x01)
+#define RFCSR29_ADC6_INT_TEST          FIELD8(0x02)
+#define RFCSR29_RSSI_RESET             FIELD8(0x04)
+#define RFCSR29_RSSI_ON                        FIELD8(0x08)
+#define RFCSR29_RSSI_RIP_CTRL          FIELD8(0x30)
+#define RFCSR29_RSSI_GAIN              FIELD8(0xc0)
+
+/*
+ * RFCSR 30:
+ */
+#define RFCSR30_TX_H20M                        FIELD8(0x02)
+#define RFCSR30_RX_H20M                        FIELD8(0x04)
+#define RFCSR30_RX_VCM                 FIELD8(0x18)
+#define RFCSR30_RF_CALIBRATION         FIELD8(0x80)
+
+/*
+ * RFCSR 31:
+ */
+#define RFCSR31_RX_AGC_FC              FIELD8(0x1f)
+#define RFCSR31_RX_H20M                        FIELD8(0x20)
+#define RFCSR31_RX_CALIB               FIELD8(0x7f)
+
+/* RFCSR 32 bits for RF3053 */
+#define RFCSR32_TX_AGC_FC              FIELD8(0xf8)
+
+/* RFCSR 36 bits for RF3053 */
+#define RFCSR36_RF_BS                  FIELD8(0x80)
+
+/*
+ * RFCSR 38:
+ */
+#define RFCSR38_RX_LO1_EN              FIELD8(0x20)
+
+/*
+ * RFCSR 39:
+ */
+#define RFCSR39_RX_DIV                 FIELD8(0x40)
+#define RFCSR39_RX_LO2_EN              FIELD8(0x80)
+
+/*
+ * RFCSR 49:
+ */
+#define RFCSR49_TX                     FIELD8(0x3f)
+#define RFCSR49_EP                     FIELD8(0xc0)
+/* bits for RT3593 */
+#define RFCSR49_TX_LO1_IC              FIELD8(0x1c)
+#define RFCSR49_TX_DIV                 FIELD8(0x20)
+
+/*
+ * RFCSR 50:
+ */
+#define RFCSR50_TX                     FIELD8(0x3f)
+#define RFCSR50_EP                     FIELD8(0xc0)
+/* bits for RT3593 */
+#define RFCSR50_TX_LO1_EN              FIELD8(0x20)
+#define RFCSR50_TX_LO2_EN              FIELD8(0x10)
+
+/* RFCSR 51 */
+/* bits for RT3593 */
+#define RFCSR51_BITS01                 FIELD8(0x03)
+#define RFCSR51_BITS24                 FIELD8(0x1c)
+#define RFCSR51_BITS57                 FIELD8(0xe0)
+
+#define RFCSR53_TX_POWER               FIELD8(0x3f)
+#define RFCSR53_UNKNOWN                        FIELD8(0xc0)
+
+#define RFCSR54_TX_POWER               FIELD8(0x3f)
+#define RFCSR54_UNKNOWN                        FIELD8(0xc0)
+
+#define RFCSR55_TX_POWER               FIELD8(0x3f)
+#define RFCSR55_UNKNOWN                        FIELD8(0xc0)
+
+#define RFCSR57_DRV_CC                 FIELD8(0xfc)
+
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 2
+ */
+#define RF2_ANTENNA_RX2                        FIELD32(0x00000040)
+#define RF2_ANTENNA_TX1                        FIELD32(0x00004000)
+#define RF2_ANTENNA_RX1                        FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TXPOWER_G                  FIELD32(0x00003e00)
+#define RF3_TXPOWER_A_7DBM_BOOST       FIELD32(0x00000200)
+#define RF3_TXPOWER_A                  FIELD32(0x00003c00)
+
+/*
+ * RF 4
+ */
+#define RF4_TXPOWER_G                  FIELD32(0x000007c0)
+#define RF4_TXPOWER_A_7DBM_BOOST       FIELD32(0x00000040)
+#define RF4_TXPOWER_A                  FIELD32(0x00000780)
+#define RF4_FREQ_OFFSET                        FIELD32(0x001f8000)
+#define RF4_HT40                       FIELD32(0x00200000)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+enum rt2800_eeprom_word {
+       EEPROM_CHIP_ID = 0,
+       EEPROM_VERSION,
+       EEPROM_MAC_ADDR_0,
+       EEPROM_MAC_ADDR_1,
+       EEPROM_MAC_ADDR_2,
+       EEPROM_NIC_CONF0,
+       EEPROM_NIC_CONF1,
+       EEPROM_FREQ,
+       EEPROM_LED_AG_CONF,
+       EEPROM_LED_ACT_CONF,
+       EEPROM_LED_POLARITY,
+       EEPROM_NIC_CONF2,
+       EEPROM_LNA,
+       EEPROM_RSSI_BG,
+       EEPROM_RSSI_BG2,
+       EEPROM_TXMIXER_GAIN_BG,
+       EEPROM_RSSI_A,
+       EEPROM_RSSI_A2,
+       EEPROM_TXMIXER_GAIN_A,
+       EEPROM_EIRP_MAX_TX_POWER,
+       EEPROM_TXPOWER_DELTA,
+       EEPROM_TXPOWER_BG1,
+       EEPROM_TXPOWER_BG2,
+       EEPROM_TSSI_BOUND_BG1,
+       EEPROM_TSSI_BOUND_BG2,
+       EEPROM_TSSI_BOUND_BG3,
+       EEPROM_TSSI_BOUND_BG4,
+       EEPROM_TSSI_BOUND_BG5,
+       EEPROM_TXPOWER_A1,
+       EEPROM_TXPOWER_A2,
+       EEPROM_TSSI_BOUND_A1,
+       EEPROM_TSSI_BOUND_A2,
+       EEPROM_TSSI_BOUND_A3,
+       EEPROM_TSSI_BOUND_A4,
+       EEPROM_TSSI_BOUND_A5,
+       EEPROM_TXPOWER_BYRATE,
+       EEPROM_BBP_START,
+
+       /* IDs for extended EEPROM format used by three-chain devices */
+       EEPROM_EXT_LNA2,
+       EEPROM_EXT_TXPOWER_BG3,
+       EEPROM_EXT_TXPOWER_A3,
+
+       /* New values must be added before this */
+       EEPROM_WORD_COUNT
+};
+
+/*
+ * EEPROM Version
+ */
+#define EEPROM_VERSION_FAE             FIELD16(0x00ff)
+#define EEPROM_VERSION_VERSION         FIELD16(0xff00)
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM NIC Configuration 0
+ * RXPATH: 1: 1R, 2: 2R, 3: 3R
+ * TXPATH: 1: 1T, 2: 2T, 3: 3T
+ * RF_TYPE: RFIC type
+ */
+#define EEPROM_NIC_CONF0_RXPATH                FIELD16(0x000f)
+#define EEPROM_NIC_CONF0_TXPATH                FIELD16(0x00f0)
+#define EEPROM_NIC_CONF0_RF_TYPE       FIELD16(0x0f00)
+
+/*
+ * EEPROM NIC Configuration 1
+ * HW_RADIO: 0: disable, 1: enable
+ * EXTERNAL_TX_ALC: 0: disable, 1: enable
+ * EXTERNAL_LNA_2G: 0: disable, 1: enable
+ * EXTERNAL_LNA_5G: 0: disable, 1: enable
+ * CARDBUS_ACCEL: 0: enable, 1: disable
+ * BW40M_SB_2G: 0: disable, 1: enable
+ * BW40M_SB_5G: 0: disable, 1: enable
+ * WPS_PBC: 0: disable, 1: enable
+ * BW40M_2G: 0: enable, 1: disable
+ * BW40M_5G: 0: enable, 1: disable
+ * BROADBAND_EXT_LNA: 0: disable, 1: enable
+ * ANT_DIVERSITY: 00: Disable, 01: Diversity,
+ *                               10: Main antenna, 11: Aux antenna
+ * INTERNAL_TX_ALC: 0: disable, 1: enable
+ * BT_COEXIST: 0: disable, 1: enable
+ * DAC_TEST: 0: disable, 1: enable
+ */
+#define EEPROM_NIC_CONF1_HW_RADIO              FIELD16(0x0001)
+#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC       FIELD16(0x0002)
+#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G       FIELD16(0x0004)
+#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G       FIELD16(0x0008)
+#define EEPROM_NIC_CONF1_CARDBUS_ACCEL         FIELD16(0x0010)
+#define EEPROM_NIC_CONF1_BW40M_SB_2G           FIELD16(0x0020)
+#define EEPROM_NIC_CONF1_BW40M_SB_5G           FIELD16(0x0040)
+#define EEPROM_NIC_CONF1_WPS_PBC               FIELD16(0x0080)
+#define EEPROM_NIC_CONF1_BW40M_2G              FIELD16(0x0100)
+#define EEPROM_NIC_CONF1_BW40M_5G              FIELD16(0x0200)
+#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA     FIELD16(0x400)
+#define EEPROM_NIC_CONF1_ANT_DIVERSITY         FIELD16(0x1800)
+#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)
+
+/*
+ * EEPROM frequency
+ */
+#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
+#define EEPROM_FREQ_LED_MODE           FIELD16(0x7f00)
+#define EEPROM_FREQ_LED_POLARITY       FIELD16(0x1000)
+
+/*
+ * EEPROM LED
+ * POLARITY_RDY_G: Polarity RDY_G setting.
+ * POLARITY_RDY_A: Polarity RDY_A setting.
+ * POLARITY_ACT: Polarity ACT setting.
+ * POLARITY_GPIO_0: Polarity GPIO0 setting.
+ * POLARITY_GPIO_1: Polarity GPIO1 setting.
+ * POLARITY_GPIO_2: Polarity GPIO2 setting.
+ * POLARITY_GPIO_3: Polarity GPIO3 setting.
+ * POLARITY_GPIO_4: Polarity GPIO4 setting.
+ * LED_MODE: Led mode.
+ */
+#define EEPROM_LED_POLARITY_RDY_BG     FIELD16(0x0001)
+#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
+#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
+#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
+#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
+#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
+#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
+#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
+#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
+
+/*
+ * EEPROM NIC Configuration 2
+ * RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
+ * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
+ * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved
+ */
+#define EEPROM_NIC_CONF2_RX_STREAM     FIELD16(0x000f)
+#define EEPROM_NIC_CONF2_TX_STREAM     FIELD16(0x00f0)
+#define EEPROM_NIC_CONF2_CRYSTAL       FIELD16(0x0600)
+
+/*
+ * EEPROM LNA
+ */
+#define EEPROM_LNA_BG                  FIELD16(0x00ff)
+#define EEPROM_LNA_A0                  FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG offset
+ */
+#define EEPROM_RSSI_BG_OFFSET0         FIELD16(0x00ff)
+#define EEPROM_RSSI_BG_OFFSET1         FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG2 offset
+ */
+#define EEPROM_RSSI_BG2_OFFSET2                FIELD16(0x00ff)
+#define EEPROM_RSSI_BG2_LNA_A1         FIELD16(0xff00)
+
+/*
+ * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2).
+ */
+#define EEPROM_TXMIXER_GAIN_BG_VAL     FIELD16(0x0007)
+
+/*
+ * EEPROM RSSI A offset
+ */
+#define EEPROM_RSSI_A_OFFSET0          FIELD16(0x00ff)
+#define EEPROM_RSSI_A_OFFSET1          FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI A2 offset
+ */
+#define EEPROM_RSSI_A2_OFFSET2         FIELD16(0x00ff)
+#define EEPROM_RSSI_A2_LNA_A2          FIELD16(0xff00)
+
+/*
+ * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2).
+ */
+#define EEPROM_TXMIXER_GAIN_A_VAL      FIELD16(0x0007)
+
+/*
+ * EEPROM EIRP Maximum TX power values(unit: dbm)
+ */
+#define EEPROM_EIRP_MAX_TX_POWER_2GHZ  FIELD16(0x00ff)
+#define EEPROM_EIRP_MAX_TX_POWER_5GHZ  FIELD16(0xff00)
+
+/*
+ * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
+ * This is delta in 40MHZ.
+ * VALUE: Tx Power dalta value, MAX=4(unit: dbm)
+ * TYPE: 1: Plus the delta value, 0: minus the delta value
+ * ENABLE: enable tx power compensation for 40BW
+ */
+#define EEPROM_TXPOWER_DELTA_VALUE_2G  FIELD16(0x003f)
+#define EEPROM_TXPOWER_DELTA_TYPE_2G   FIELD16(0x0040)
+#define EEPROM_TXPOWER_DELTA_ENABLE_2G FIELD16(0x0080)
+#define EEPROM_TXPOWER_DELTA_VALUE_5G  FIELD16(0x3f00)
+#define EEPROM_TXPOWER_DELTA_TYPE_5G   FIELD16(0x4000)
+#define EEPROM_TXPOWER_DELTA_ENABLE_5G FIELD16(0x8000)
+
+/*
+ * EEPROM TXPOWER 802.11BG
+ */
+#define EEPROM_TXPOWER_BG_SIZE         7
+#define EEPROM_TXPOWER_BG_1            FIELD16(0x00ff)
+#define EEPROM_TXPOWER_BG_2            FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -4)
+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -3)
+ */
+#define EEPROM_TSSI_BOUND_BG1_MINUS4   FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG1_MINUS3   FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -2)
+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -1)
+ */
+#define EEPROM_TSSI_BOUND_BG2_MINUS2   FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG2_MINUS1   FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * REF: Reference TSSI value, no tx power changes needed
+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 1)
+ */
+#define EEPROM_TSSI_BOUND_BG3_REF      FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG3_PLUS1    FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 2)
+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 3)
+ */
+#define EEPROM_TSSI_BOUND_BG4_PLUS2    FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG4_PLUS3    FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 4)
+ * AGC_STEP: Temperature compensation step.
+ */
+#define EEPROM_TSSI_BOUND_BG5_PLUS4    FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER 802.11A
+ */
+#define EEPROM_TXPOWER_A_SIZE          6
+#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
+#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
+
+/* EEPROM_TXPOWER_{A,G} fields for RT3593 */
+#define EEPROM_TXPOWER_ALC             FIELD8(0x1f)
+#define EEPROM_TXPOWER_FINE_CTRL       FIELD8(0xe0)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -4)
+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -3)
+ */
+#define EEPROM_TSSI_BOUND_A1_MINUS4    FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A1_MINUS3    FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -2)
+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
+ *         reduced by (agc_step * -1)
+ */
+#define EEPROM_TSSI_BOUND_A2_MINUS2    FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A2_MINUS1    FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * REF: Reference TSSI value, no tx power changes needed
+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 1)
+ */
+#define EEPROM_TSSI_BOUND_A3_REF       FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A3_PLUS1     FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 2)
+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 3)
+ */
+#define EEPROM_TSSI_BOUND_A4_PLUS2     FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A4_PLUS3     FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
+ *        increased by (agc_step * 4)
+ * AGC_STEP: Temperature compensation step.
+ */
+#define EEPROM_TSSI_BOUND_A5_PLUS4     FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A5_AGC_STEP  FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode
+ */
+#define EEPROM_TXPOWER_BYRATE_SIZE     9
+
+#define EEPROM_TXPOWER_BYRATE_RATE0    FIELD16(0x000f)
+#define EEPROM_TXPOWER_BYRATE_RATE1    FIELD16(0x00f0)
+#define EEPROM_TXPOWER_BYRATE_RATE2    FIELD16(0x0f00)
+#define EEPROM_TXPOWER_BYRATE_RATE3    FIELD16(0xf000)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_SIZE                        16
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/* EEPROM_EXT_LNA2 */
+#define EEPROM_EXT_LNA2_A1             FIELD16(0x00ff)
+#define EEPROM_EXT_LNA2_A2             FIELD16(0xff00)
+
+/*
+ * EEPROM IQ Calibration, unlike other entries those are byte addresses.
+ */
+
+#define EEPROM_IQ_GAIN_CAL_TX0_2G                      0x130
+#define EEPROM_IQ_PHASE_CAL_TX0_2G                     0x131
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G                        0x132
+#define EEPROM_IQ_GAIN_CAL_TX1_2G                      0x133
+#define EEPROM_IQ_PHASE_CAL_TX1_2G                     0x134
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G                        0x135
+#define EEPROM_IQ_GAIN_CAL_RX0_2G                      0x136
+#define EEPROM_IQ_PHASE_CAL_RX0_2G                     0x137
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G                        0x138
+#define EEPROM_IQ_GAIN_CAL_RX1_2G                      0x139
+#define EEPROM_IQ_PHASE_CAL_RX1_2G                     0x13A
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G                        0x13B
+#define EEPROM_RF_IQ_COMPENSATION_CONTROL              0x13C
+#define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL    0x13D
+#define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G         0x144
+#define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G                0x145
+#define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G       0X146
+#define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G      0x147
+#define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G       0x148
+#define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G      0x149
+#define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G         0x14A
+#define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G                0x14B
+#define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G       0X14C
+#define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G      0x14D
+#define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G       0x14E
+#define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G      0x14F
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G   0x150
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G   0x151
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G 0x152
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G 0x153
+#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G 0x154
+#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G 0x155
+#define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G         0x156
+#define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G                0x157
+#define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G       0X158
+#define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G      0x159
+#define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G       0x15A
+#define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G      0x15B
+#define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G         0x15C
+#define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G                0x15D
+#define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G       0X15E
+#define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G      0x15F
+#define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G       0x160
+#define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G      0x161
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G   0x162
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G   0x163
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G 0x164
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G 0x165
+#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G 0x166
+#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G 0x167
+
+/*
+ * MCU mailbox commands.
+ * MCU_SLEEP - go to power-save mode.
+ *             arg1: 1: save as much power as possible, 0: save less power.
+ *             status: 1: success, 2: already asleep,
+ *                     3: maybe MAC is busy so can't finish this task.
+ * MCU_RADIO_OFF
+ *             arg0: 0: do power-saving, NOT turn off radio.
+ */
+#define MCU_SLEEP                      0x30
+#define MCU_WAKEUP                     0x31
+#define MCU_RADIO_OFF                  0x35
+#define MCU_CURRENT                    0x36
+#define MCU_LED                                0x50
+#define MCU_LED_STRENGTH               0x51
+#define MCU_LED_AG_CONF                        0x52
+#define MCU_LED_ACT_CONF               0x53
+#define MCU_LED_LED_POLARITY           0x54
+#define MCU_RADAR                      0x60
+#define MCU_BOOT_SIGNAL                        0x72
+#define MCU_ANT_SELECT                 0X73
+#define MCU_FREQ_OFFSET                        0x74
+#define MCU_BBP_SIGNAL                 0x80
+#define MCU_POWER_SAVE                 0x83
+#define MCU_BAND_SELECT                        0x91
+
+/*
+ * MCU mailbox tokens
+ */
+#define TOKEN_SLEEP                    1
+#define TOKEN_RADIO_OFF                        2
+#define TOKEN_WAKEUP                   3
+
+
+/*
+ * DMA descriptor defines.
+ */
+
+#define TXWI_DESC_SIZE_4WORDS          (4 * sizeof(__le32))
+#define TXWI_DESC_SIZE_5WORDS          (5 * sizeof(__le32))
+
+#define RXWI_DESC_SIZE_4WORDS          (4 * sizeof(__le32))
+#define RXWI_DESC_SIZE_5WORDS          (5 * sizeof(__le32))
+#define RXWI_DESC_SIZE_6WORDS          (6 * sizeof(__le32))
+
+/*
+ * TX WI structure
+ */
+
+/*
+ * Word0
+ * FRAG: 1 To inform TKIP engine this is a fragment.
+ * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
+ * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
+ * BW: Channel bandwidth 0:20MHz, 1:40 MHz (for legacy rates this will
+ *     duplicate the frame to both channels).
+ * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
+ * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will
+ *        aggregate consecutive frames with the same RA and QoS TID. If
+ *        a frame A with the same RA and QoS TID but AMPDU=0 is queued
+ *        directly after a frame B with AMPDU=1, frame A might still
+ *        get aggregated into the AMPDU started by frame B. So, setting
+ *        AMPDU to 0 does _not_ necessarily mean the frame is sent as
+ *        MPDU, it can still end up in an AMPDU if the previous frame
+ *        was tagged as AMPDU.
+ */
+#define TXWI_W0_FRAG                   FIELD32(0x00000001)
+#define TXWI_W0_MIMO_PS                        FIELD32(0x00000002)
+#define TXWI_W0_CF_ACK                 FIELD32(0x00000004)
+#define TXWI_W0_TS                     FIELD32(0x00000008)
+#define TXWI_W0_AMPDU                  FIELD32(0x00000010)
+#define TXWI_W0_MPDU_DENSITY           FIELD32(0x000000e0)
+#define TXWI_W0_TX_OP                  FIELD32(0x00000300)
+#define TXWI_W0_MCS                    FIELD32(0x007f0000)
+#define TXWI_W0_BW                     FIELD32(0x00800000)
+#define TXWI_W0_SHORT_GI               FIELD32(0x01000000)
+#define TXWI_W0_STBC                   FIELD32(0x06000000)
+#define TXWI_W0_IFS                    FIELD32(0x08000000)
+#define TXWI_W0_PHYMODE                        FIELD32(0xc0000000)
+
+/*
+ * Word1
+ * ACK: 0: No Ack needed, 1: Ack needed
+ * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number
+ * BW_WIN_SIZE: BA windows size of the recipient
+ * WIRELESS_CLI_ID: Client ID for WCID table access
+ * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame
+ * PACKETID: Will be latched into the TX_STA_FIFO register once the according
+ *           frame was processed. If multiple frames are aggregated together
+ *           (AMPDU==1) the reported tx status will always contain the packet
+ *           id of the first frame. 0: Don't report tx status for this frame.
+ * PACKETID_QUEUE: Part of PACKETID, This is the queue index (0-3)
+ * PACKETID_ENTRY: Part of PACKETID, THis is the queue entry index (1-3)
+ *                 This identification number is calculated by ((idx % 3) + 1).
+ *                The (+1) is required to prevent PACKETID to become 0.
+ */
+#define TXWI_W1_ACK                    FIELD32(0x00000001)
+#define TXWI_W1_NSEQ                   FIELD32(0x00000002)
+#define TXWI_W1_BW_WIN_SIZE            FIELD32(0x000000fc)
+#define TXWI_W1_WIRELESS_CLI_ID                FIELD32(0x0000ff00)
+#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT  FIELD32(0x0fff0000)
+#define TXWI_W1_PACKETID               FIELD32(0xf0000000)
+#define TXWI_W1_PACKETID_QUEUE         FIELD32(0x30000000)
+#define TXWI_W1_PACKETID_ENTRY         FIELD32(0xc0000000)
+
+/*
+ * Word2
+ */
+#define TXWI_W2_IV                     FIELD32(0xffffffff)
+
+/*
+ * Word3
+ */
+#define TXWI_W3_EIV                    FIELD32(0xffffffff)
+
+/*
+ * RX WI structure
+ */
+
+/*
+ * Word0
+ */
+#define RXWI_W0_WIRELESS_CLI_ID                FIELD32(0x000000ff)
+#define RXWI_W0_KEY_INDEX              FIELD32(0x00000300)
+#define RXWI_W0_BSSID                  FIELD32(0x00001c00)
+#define RXWI_W0_UDF                    FIELD32(0x0000e000)
+#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT  FIELD32(0x0fff0000)
+#define RXWI_W0_TID                    FIELD32(0xf0000000)
+
+/*
+ * Word1
+ */
+#define RXWI_W1_FRAG                   FIELD32(0x0000000f)
+#define RXWI_W1_SEQUENCE               FIELD32(0x0000fff0)
+#define RXWI_W1_MCS                    FIELD32(0x007f0000)
+#define RXWI_W1_BW                     FIELD32(0x00800000)
+#define RXWI_W1_SHORT_GI               FIELD32(0x01000000)
+#define RXWI_W1_STBC                   FIELD32(0x06000000)
+#define RXWI_W1_PHYMODE                        FIELD32(0xc0000000)
+
+/*
+ * Word2
+ */
+#define RXWI_W2_RSSI0                  FIELD32(0x000000ff)
+#define RXWI_W2_RSSI1                  FIELD32(0x0000ff00)
+#define RXWI_W2_RSSI2                  FIELD32(0x00ff0000)
+
+/*
+ * Word3
+ */
+#define RXWI_W3_SNR0                   FIELD32(0x000000ff)
+#define RXWI_W3_SNR1                   FIELD32(0x0000ff00)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_G_TXPOWER  0
+#define MIN_A_TXPOWER  -7
+#define MAX_G_TXPOWER  31
+#define MAX_A_TXPOWER  15
+#define DEFAULT_TXPOWER        5
+
+#define MIN_A_TXPOWER_3593     0
+#define MAX_A_TXPOWER_3593     31
+
+#define TXPOWER_G_FROM_DEV(__txpower) \
+       ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_A_FROM_DEV(__txpower) \
+       ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+/*
+ *  Board's maximun TX power limitation
+ */
+#define EIRP_MAX_TX_POWER_LIMIT        0x50
+
+/*
+ * Number of TBTT intervals after which we have to adjust
+ * the hw beacon timer.
+ */
+#define BCN_TBTT_OFFSET 64
+
+/*
+ * Hardware has 255 WCID table entries. First 32 entries are reserved for
+ * shared keys. Since parts of the pairwise key table might be shared with
+ * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
+ */
+#define WCID_START     33
+#define WCID_END       222
+#define STA_IDS_SIZE   (WCID_END - WCID_START + 2)
+
+/*
+ * RT2800 driver data structure
+ */
+struct rt2800_drv_data {
+       u8 calibration_bw20;
+       u8 calibration_bw40;
+       u8 bbp25;
+       u8 bbp26;
+       u8 txmixer_gain_24g;
+       u8 txmixer_gain_5g;
+       unsigned int tbtt_tick;
+       DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
+};
+
+#endif /* RT2800_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
new file mode 100644 (file)
index 0000000..9733b31
--- /dev/null
@@ -0,0 +1,8021 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+       Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+
+       Based on the original rt2800pci.c and rt2800usb.c.
+         Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+         Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+         Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+         Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+         Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+         Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+         <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800lib
+       Abstract: rt2800 generic device routines.
+ */
+
+#include <linux/crc-ccitt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2800lib.h"
+#include "rt2800.h"
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2800_register_read and rt2800_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ * The _lock versions must be used if you already hold the csr_mutex
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RFCSR(__dev, __reg) \
+       rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+       rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+                           H2M_MAILBOX_CSR_OWNER, (__reg))
+
+static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
+{
+       /* check for rt2872 on SoC */
+       if (!rt2x00_is_soc(rt2x00dev) ||
+           !rt2x00_rt(rt2x00dev, RT2872))
+               return false;
+
+       /* we know for sure that these rf chipsets are used on rt305x boards */
+       if (rt2x00_rf(rt2x00dev, RF3020) ||
+           rt2x00_rf(rt2x00dev, RF3021) ||
+           rt2x00_rf(rt2x00dev, RF3022))
+               return true;
+
+       rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");
+       return false;
+}
+
+static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+
+               rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
+               rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+
+               rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RFCSR becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
+               rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+               rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
+               rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RFCSR becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+               rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
+               rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+
+               WAIT_FOR_RFCSR(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int word, const u32 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
+               rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
+               rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
+               rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
+
+               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
+       [EEPROM_CHIP_ID]                = 0x0000,
+       [EEPROM_VERSION]                = 0x0001,
+       [EEPROM_MAC_ADDR_0]             = 0x0002,
+       [EEPROM_MAC_ADDR_1]             = 0x0003,
+       [EEPROM_MAC_ADDR_2]             = 0x0004,
+       [EEPROM_NIC_CONF0]              = 0x001a,
+       [EEPROM_NIC_CONF1]              = 0x001b,
+       [EEPROM_FREQ]                   = 0x001d,
+       [EEPROM_LED_AG_CONF]            = 0x001e,
+       [EEPROM_LED_ACT_CONF]           = 0x001f,
+       [EEPROM_LED_POLARITY]           = 0x0020,
+       [EEPROM_NIC_CONF2]              = 0x0021,
+       [EEPROM_LNA]                    = 0x0022,
+       [EEPROM_RSSI_BG]                = 0x0023,
+       [EEPROM_RSSI_BG2]               = 0x0024,
+       [EEPROM_TXMIXER_GAIN_BG]        = 0x0024, /* overlaps with RSSI_BG2 */
+       [EEPROM_RSSI_A]                 = 0x0025,
+       [EEPROM_RSSI_A2]                = 0x0026,
+       [EEPROM_TXMIXER_GAIN_A]         = 0x0026, /* overlaps with RSSI_A2 */
+       [EEPROM_EIRP_MAX_TX_POWER]      = 0x0027,
+       [EEPROM_TXPOWER_DELTA]          = 0x0028,
+       [EEPROM_TXPOWER_BG1]            = 0x0029,
+       [EEPROM_TXPOWER_BG2]            = 0x0030,
+       [EEPROM_TSSI_BOUND_BG1]         = 0x0037,
+       [EEPROM_TSSI_BOUND_BG2]         = 0x0038,
+       [EEPROM_TSSI_BOUND_BG3]         = 0x0039,
+       [EEPROM_TSSI_BOUND_BG4]         = 0x003a,
+       [EEPROM_TSSI_BOUND_BG5]         = 0x003b,
+       [EEPROM_TXPOWER_A1]             = 0x003c,
+       [EEPROM_TXPOWER_A2]             = 0x0053,
+       [EEPROM_TSSI_BOUND_A1]          = 0x006a,
+       [EEPROM_TSSI_BOUND_A2]          = 0x006b,
+       [EEPROM_TSSI_BOUND_A3]          = 0x006c,
+       [EEPROM_TSSI_BOUND_A4]          = 0x006d,
+       [EEPROM_TSSI_BOUND_A5]          = 0x006e,
+       [EEPROM_TXPOWER_BYRATE]         = 0x006f,
+       [EEPROM_BBP_START]              = 0x0078,
+};
+
+static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = {
+       [EEPROM_CHIP_ID]                = 0x0000,
+       [EEPROM_VERSION]                = 0x0001,
+       [EEPROM_MAC_ADDR_0]             = 0x0002,
+       [EEPROM_MAC_ADDR_1]             = 0x0003,
+       [EEPROM_MAC_ADDR_2]             = 0x0004,
+       [EEPROM_NIC_CONF0]              = 0x001a,
+       [EEPROM_NIC_CONF1]              = 0x001b,
+       [EEPROM_NIC_CONF2]              = 0x001c,
+       [EEPROM_EIRP_MAX_TX_POWER]      = 0x0020,
+       [EEPROM_FREQ]                   = 0x0022,
+       [EEPROM_LED_AG_CONF]            = 0x0023,
+       [EEPROM_LED_ACT_CONF]           = 0x0024,
+       [EEPROM_LED_POLARITY]           = 0x0025,
+       [EEPROM_LNA]                    = 0x0026,
+       [EEPROM_EXT_LNA2]               = 0x0027,
+       [EEPROM_RSSI_BG]                = 0x0028,
+       [EEPROM_RSSI_BG2]               = 0x0029,
+       [EEPROM_RSSI_A]                 = 0x002a,
+       [EEPROM_RSSI_A2]                = 0x002b,
+       [EEPROM_TXPOWER_BG1]            = 0x0030,
+       [EEPROM_TXPOWER_BG2]            = 0x0037,
+       [EEPROM_EXT_TXPOWER_BG3]        = 0x003e,
+       [EEPROM_TSSI_BOUND_BG1]         = 0x0045,
+       [EEPROM_TSSI_BOUND_BG2]         = 0x0046,
+       [EEPROM_TSSI_BOUND_BG3]         = 0x0047,
+       [EEPROM_TSSI_BOUND_BG4]         = 0x0048,
+       [EEPROM_TSSI_BOUND_BG5]         = 0x0049,
+       [EEPROM_TXPOWER_A1]             = 0x004b,
+       [EEPROM_TXPOWER_A2]             = 0x0065,
+       [EEPROM_EXT_TXPOWER_A3]         = 0x007f,
+       [EEPROM_TSSI_BOUND_A1]          = 0x009a,
+       [EEPROM_TSSI_BOUND_A2]          = 0x009b,
+       [EEPROM_TSSI_BOUND_A3]          = 0x009c,
+       [EEPROM_TSSI_BOUND_A4]          = 0x009d,
+       [EEPROM_TSSI_BOUND_A5]          = 0x009e,
+       [EEPROM_TXPOWER_BYRATE]         = 0x00a0,
+};
+
+static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev,
+                                            const enum rt2800_eeprom_word word)
+{
+       const unsigned int *map;
+       unsigned int index;
+
+       if (WARN_ONCE(word >= EEPROM_WORD_COUNT,
+                     "%s: invalid EEPROM word %d\n",
+                     wiphy_name(rt2x00dev->hw->wiphy), word))
+               return 0;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               map = rt2800_eeprom_map_ext;
+       else
+               map = rt2800_eeprom_map;
+
+       index = map[word];
+
+       /* Index 0 is valid only for EEPROM_CHIP_ID.
+        * Otherwise it means that the offset of the
+        * given word is not initialized in the map,
+        * or that the field is not usable on the
+        * actual chipset.
+        */
+       WARN_ONCE(word != EEPROM_CHIP_ID && index == 0,
+                 "%s: invalid access of EEPROM word %d\n",
+                 wiphy_name(rt2x00dev->hw->wiphy), word);
+
+       return index;
+}
+
+static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev,
+                               const enum rt2800_eeprom_word word)
+{
+       unsigned int index;
+
+       index = rt2800_eeprom_word_index(rt2x00dev, word);
+       return rt2x00_eeprom_addr(rt2x00dev, index);
+}
+
+static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
+                              const enum rt2800_eeprom_word word, u16 *data)
+{
+       unsigned int index;
+
+       index = rt2800_eeprom_word_index(rt2x00dev, word);
+       rt2x00_eeprom_read(rt2x00dev, index, data);
+}
+
+static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
+                               const enum rt2800_eeprom_word word, u16 data)
+{
+       unsigned int index;
+
+       index = rt2800_eeprom_word_index(rt2x00dev, word);
+       rt2x00_eeprom_write(rt2x00dev, index, data);
+}
+
+static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
+                                         const enum rt2800_eeprom_word array,
+                                         unsigned int offset,
+                                         u16 *data)
+{
+       unsigned int index;
+
+       index = rt2800_eeprom_word_index(rt2x00dev, array);
+       rt2x00_eeprom_read(rt2x00dev, index + offset, data);
+}
+
+static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       int i, count;
+
+       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+       if (rt2x00_get_field32(reg, WLAN_EN))
+               return 0;
+
+       rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
+       rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
+       rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
+       rt2x00_set_field32(&reg, WLAN_EN, 1);
+       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+
+       udelay(REGISTER_BUSY_DELAY);
+
+       count = 0;
+       do {
+               /*
+                * Check PLL_LD & XTAL_RDY.
+                */
+               for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+                       rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+                       if (rt2x00_get_field32(reg, PLL_LD) &&
+                           rt2x00_get_field32(reg, XTAL_RDY))
+                               break;
+                       udelay(REGISTER_BUSY_DELAY);
+               }
+
+               if (i >= REGISTER_BUSY_COUNT) {
+
+                       if (count >= 10)
+                               return -EIO;
+
+                       rt2800_register_write(rt2x00dev, 0x58, 0x018);
+                       udelay(REGISTER_BUSY_DELAY);
+                       rt2800_register_write(rt2x00dev, 0x58, 0x418);
+                       udelay(REGISTER_BUSY_DELAY);
+                       rt2800_register_write(rt2x00dev, 0x58, 0x618);
+                       udelay(REGISTER_BUSY_DELAY);
+                       count++;
+               } else {
+                       count = 0;
+               }
+
+               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
+               rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
+               rt2x00_set_field32(&reg, WLAN_RESET, 1);
+               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+               udelay(10);
+               rt2x00_set_field32(&reg, WLAN_RESET, 0);
+               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+               udelay(10);
+               rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);
+       } while (count != 0);
+
+       return 0;
+}
+
+void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
+                       const u8 command, const u8 token,
+                       const u8 arg0, const u8 arg1)
+{
+       u32 reg;
+
+       /*
+        * SOC devices don't support MCU requests.
+        */
+       if (rt2x00_is_soc(rt2x00dev))
+               return;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the MCU becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+               rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+               reg = 0;
+               rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+               rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+EXPORT_SYMBOL_GPL(rt2800_mcu_request);
+
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i = 0;
+       u32 reg;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+               if (reg && reg != ~0)
+                       return 0;
+               msleep(1);
+       }
+
+       rt2x00_err(rt2x00dev, "Unstable hardware\n");
+       return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
+
+int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u32 reg;
+
+       /*
+        * Some devices are really slow to respond here. Wait a whole second
+        * before timing out.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+               if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
+                   !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
+                       return 0;
+
+               msleep(10);
+       }
+
+       rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);
+       return -EACCES;
+}
+EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
+
+void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_disable_wpdma);
+
+void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
+                              unsigned short *txwi_size,
+                              unsigned short *rxwi_size)
+{
+       switch (rt2x00dev->chip.rt) {
+       case RT3593:
+               *txwi_size = TXWI_DESC_SIZE_4WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_5WORDS;
+               break;
+
+       case RT5592:
+               *txwi_size = TXWI_DESC_SIZE_5WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_6WORDS;
+               break;
+
+       default:
+               *txwi_size = TXWI_DESC_SIZE_4WORDS;
+               *rxwi_size = RXWI_DESC_SIZE_4WORDS;
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size);
+
+static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)
+{
+       u16 fw_crc;
+       u16 crc;
+
+       /*
+        * The last 2 bytes in the firmware array are the crc checksum itself,
+        * this means that we should never pass those 2 bytes to the crc
+        * algorithm.
+        */
+       fw_crc = (data[len - 2] << 8 | data[len - 1]);
+
+       /*
+        * Use the crc ccitt algorithm.
+        * This will return the same value as the legacy driver which
+        * used bit ordering reversion on the both the firmware bytes
+        * before input input as well as on the final output.
+        * Obviously using crc ccitt directly is much more efficient.
+        */
+       crc = crc_ccitt(~0, data, len - 2);
+
+       /*
+        * There is a small difference between the crc-itu-t + bitrev and
+        * the crc-ccitt crc calculation. In the latter method the 2 bytes
+        * will be swapped, use swab16 to convert the crc to the correct
+        * value.
+        */
+       crc = swab16(crc);
+
+       return fw_crc == crc;
+}
+
+int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
+                         const u8 *data, const size_t len)
+{
+       size_t offset = 0;
+       size_t fw_len;
+       bool multiple;
+
+       /*
+        * PCI(e) & SOC devices require firmware with a length
+        * of 8kb. USB devices require firmware files with a length
+        * of 4kb. Certain USB chipsets however require different firmware,
+        * which Ralink only provides attached to the original firmware
+        * file. Thus for USB devices, firmware files have a length
+        * which is a multiple of 4kb. The firmware for rt3290 chip also
+        * have a length which is a multiple of 4kb.
+        */
+       if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))
+               fw_len = 4096;
+       else
+               fw_len = 8192;
+
+       multiple = true;
+       /*
+        * Validate the firmware length
+        */
+       if (len != fw_len && (!multiple || (len % fw_len) != 0))
+               return FW_BAD_LENGTH;
+
+       /*
+        * Check if the chipset requires one of the upper parts
+        * of the firmware.
+        */
+       if (rt2x00_is_usb(rt2x00dev) &&
+           !rt2x00_rt(rt2x00dev, RT2860) &&
+           !rt2x00_rt(rt2x00dev, RT2872) &&
+           !rt2x00_rt(rt2x00dev, RT3070) &&
+           ((len / fw_len) == 1))
+               return FW_BAD_VERSION;
+
+       /*
+        * 8kb firmware files must be checked as if it were
+        * 2 separate firmware files.
+        */
+       while (offset < len) {
+               if (!rt2800_check_firmware_crc(data + offset, fw_len))
+                       return FW_BAD_CRC;
+
+               offset += fw_len;
+       }
+
+       return FW_OK;
+}
+EXPORT_SYMBOL_GPL(rt2800_check_firmware);
+
+int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
+                        const u8 *data, const size_t len)
+{
+       unsigned int i;
+       u32 reg;
+       int retval;
+
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               retval = rt2800_enable_wlan_rt3290(rt2x00dev);
+               if (retval)
+                       return -EBUSY;
+       }
+
+       /*
+        * If driver doesn't wake up firmware here,
+        * rt2800_load_firmware will hang forever when interface is up again.
+        */
+       rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
+
+       /*
+        * Wait for stable hardware.
+        */
+       if (rt2800_wait_csr_ready(rt2x00dev))
+               return -EBUSY;
+
+       if (rt2x00_is_pci(rt2x00dev)) {
+               if (rt2x00_rt(rt2x00dev, RT3290) ||
+                   rt2x00_rt(rt2x00dev, RT3572) ||
+                   rt2x00_rt(rt2x00dev, RT5390) ||
+                   rt2x00_rt(rt2x00dev, RT5392)) {
+                       rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+                       rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+                       rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+                       rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+               }
+               rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
+       }
+
+       rt2800_disable_wpdma(rt2x00dev);
+
+       /*
+        * Write firmware to the device.
+        */
+       rt2800_drv_write_firmware(rt2x00dev, data, len);
+
+       /*
+        * Wait for device to stabilize.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+               if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
+                       break;
+               msleep(1);
+       }
+
+       if (i == REGISTER_BUSY_COUNT) {
+               rt2x00_err(rt2x00dev, "PBF system register not ready\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Disable DMA, will be reenabled later when enabling
+        * the radio.
+        */
+       rt2800_disable_wpdma(rt2x00dev);
+
+       /*
+        * Initialize firmware.
+        */
+       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       if (rt2x00_is_usb(rt2x00dev)) {
+               rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+               rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+       }
+       msleep(1);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_load_firmware);
+
+void rt2800_write_tx_data(struct queue_entry *entry,
+                         struct txentry_desc *txdesc)
+{
+       __le32 *txwi = rt2800_drv_get_txwi(entry);
+       u32 word;
+       int i;
+
+       /*
+        * Initialize TX Info descriptor
+        */
+       rt2x00_desc_read(txwi, 0, &word);
+       rt2x00_set_field32(&word, TXWI_W0_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
+                          test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
+       rt2x00_set_field32(&word, TXWI_W0_TS,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_AMPDU,
+                          test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,
+                          txdesc->u.ht.mpdu_density);
+       rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);
+       rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);
+       rt2x00_set_field32(&word, TXWI_W0_BW,
+                          test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
+                          test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);
+       rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
+       rt2x00_desc_write(txwi, 0, word);
+
+       rt2x00_desc_read(txwi, 1, &word);
+       rt2x00_set_field32(&word, TXWI_W1_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W1_NSEQ,
+                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
+       rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
+       rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
+                          test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
+                          txdesc->key_idx : txdesc->u.ht.wcid);
+       rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
+                          txdesc->length);
+       rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
+       rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
+       rt2x00_desc_write(txwi, 1, word);
+
+       /*
+        * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert
+        * the IV from the IVEIV register when TXD_W3_WIV is set to 0.
+        * When TXD_W3_WIV is set to 1 it will use the IV data
+        * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
+        * crypto entry in the registers should be used to encrypt the frame.
+        *
+        * Nulify all remaining words as well, we don't know how to program them.
+        */
+       for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++)
+               _rt2x00_desc_write(txwi, i, 0);
+}
+EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
+
+static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
+{
+       s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
+       s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
+       s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
+       u16 eeprom;
+       u8 offset0;
+       u8 offset1;
+       u8 offset2;
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
+               offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
+               offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
+               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+               offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
+       } else {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
+               offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
+               offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
+               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+               offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
+       }
+
+       /*
+        * Convert the value from the descriptor into the RSSI value
+        * If the value in the descriptor is 0, it is considered invalid
+        * and the default (extremely low) rssi value is assumed
+        */
+       rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
+       rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
+       rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
+
+       /*
+        * mac80211 only accepts a single RSSI value. Calculating the
+        * average doesn't deliver a fair answer either since -60:-60 would
+        * be considered equally good as -50:-70 while the second is the one
+        * which gives less energy...
+        */
+       rssi0 = max(rssi0, rssi1);
+       return (int)max(rssi0, rssi2);
+}
+
+void rt2800_process_rxwi(struct queue_entry *entry,
+                        struct rxdone_entry_desc *rxdesc)
+{
+       __le32 *rxwi = (__le32 *) entry->skb->data;
+       u32 word;
+
+       rt2x00_desc_read(rxwi, 0, &word);
+
+       rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);
+       rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+
+       rt2x00_desc_read(rxwi, 1, &word);
+
+       if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))
+               rxdesc->flags |= RX_FLAG_SHORT_GI;
+
+       if (rt2x00_get_field32(word, RXWI_W1_BW))
+               rxdesc->flags |= RX_FLAG_40MHZ;
+
+       /*
+        * Detect RX rate, always use MCS as signal type.
+        */
+       rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
+       rxdesc->signal = rt2x00_get_field32(word, RXWI_W1_MCS);
+       rxdesc->rate_mode = rt2x00_get_field32(word, RXWI_W1_PHYMODE);
+
+       /*
+        * Mask of 0x8 bit to remove the short preamble flag.
+        */
+       if (rxdesc->rate_mode == RATE_MODE_CCK)
+               rxdesc->signal &= ~0x8;
+
+       rt2x00_desc_read(rxwi, 2, &word);
+
+       /*
+        * Convert descriptor AGC value to RSSI value.
+        */
+       rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
+       /*
+        * Remove RXWI descriptor from start of the buffer.
+        */
+       skb_pull(entry->skb, entry->queue->winfo_size);
+}
+EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
+
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct txdone_entry_desc txdesc;
+       u32 word;
+       u16 mcs, real_mcs;
+       int aggr, ampdu;
+
+       /*
+        * Obtain the status about this packet.
+        */
+       txdesc.flags = 0;
+       rt2x00_desc_read(txwi, 0, &word);
+
+       mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
+       ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
+
+       real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
+       aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
+
+       /*
+        * If a frame was meant to be sent as a single non-aggregated MPDU
+        * but ended up in an aggregate the used tx rate doesn't correlate
+        * with the one specified in the TXWI as the whole aggregate is sent
+        * with the same rate.
+        *
+        * For example: two frames are sent to rt2x00, the first one sets
+        * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0
+        * and requests MCS15. If the hw aggregates both frames into one
+        * AMDPU the tx status for both frames will contain MCS7 although
+        * the frame was sent successfully.
+        *
+        * Hence, replace the requested rate with the real tx rate to not
+        * confuse the rate control algortihm by providing clearly wrong
+        * data.
+        */
+       if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
+               skbdesc->tx_rate_idx = real_mcs;
+               mcs = real_mcs;
+       }
+
+       if (aggr == 1 || ampdu == 1)
+               __set_bit(TXDONE_AMPDU, &txdesc.flags);
+
+       /*
+        * Ralink has a retry mechanism using a global fallback
+        * table. We setup this fallback table to try the immediate
+        * lower rate for all rates. In the TX_STA_FIFO, the MCS field
+        * always contains the MCS used for the last transmission, be
+        * it successful or not.
+        */
+       if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) {
+               /*
+                * Transmission succeeded. The number of retries is
+                * mcs - real_mcs
+                */
+               __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+               txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
+       } else {
+               /*
+                * Transmission failed. The number of retries is
+                * always 7 in this case (for a total number of 8
+                * frames sent).
+                */
+               __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               txdesc.retry = rt2x00dev->long_retry;
+       }
+
+       /*
+        * the frame was retried at least once
+        * -> hw used fallback rates
+        */
+       if (txdesc.retry)
+               __set_bit(TXDONE_FALLBACK, &txdesc.flags);
+
+       rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+
+static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+                                         unsigned int index)
+{
+       return HW_BEACON_BASE(index);
+}
+
+static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev,
+                                         unsigned int index)
+{
+       return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
+}
+
+static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue = rt2x00dev->bcn;
+       struct queue_entry *entry;
+       int i, bcn_num = 0;
+       u64 off, reg = 0;
+       u32 bssid_dw1;
+
+       /*
+        * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
+        */
+       for (i = 0; i < queue->limit; i++) {
+               entry = &queue->entries[i];
+               if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
+                       continue;
+               off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
+               reg |= off << (8 * bcn_num);
+               bcn_num++;
+       }
+
+       WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+
+       rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
+       rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
+
+       /*
+        * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
+        */
+       rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+       rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
+                          bcn_num > 0 ? bcn_num - 1 : 0);
+       rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
+}
+
+void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int beacon_base;
+       unsigned int padding_len;
+       u32 orig_reg, reg;
+       const int txwi_desc_size = entry->queue->winfo_size;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+       orig_reg = reg;
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+       /*
+        * Add space for the TXWI in front of the skb.
+        */
+       memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
+       skbdesc->desc = entry->skb->data;
+       skbdesc->desc_len = txwi_desc_size;
+
+       /*
+        * Add the TXWI for the beacon to the skb.
+        */
+       rt2800_write_tx_data(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
+       /*
+        * Write entire beacon with TXWI and padding to register.
+        */
+       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
+       if (padding_len && skb_pad(entry->skb, padding_len)) {
+               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
+               /* skb freed by skb_pad() on failure */
+               entry->skb = NULL;
+               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+               return;
+       }
+
+       beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
+
+       rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
+                                  entry->skb->len + padding_len);
+       __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+       /*
+        * Change global beacons settings.
+        */
+       rt2800_update_beacons_setup(rt2x00dev);
+
+       /*
+        * Restore beaconing state.
+        */
+       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+
+       /*
+        * Clean up beacon skb.
+        */
+       dev_kfree_skb_any(entry->skb);
+       entry->skb = NULL;
+}
+EXPORT_SYMBOL_GPL(rt2800_write_beacon);
+
+static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
+                                               unsigned int index)
+{
+       int i;
+       const int txwi_desc_size = rt2x00dev->bcn->winfo_size;
+       unsigned int beacon_base;
+
+       beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
+
+       /*
+        * For the Beacon base registers we only need to clear
+        * the whole TXWI which (when set to 0) will invalidate
+        * the entire beacon.
+        */
+       for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
+               rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+}
+
+void rt2800_clear_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       u32 orig_reg, reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg);
+       reg = orig_reg;
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+       /*
+        * Clear beacon.
+        */
+       rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
+       __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
+
+       /*
+        * Change global beacons settings.
+        */
+       rt2800_update_beacons_setup(rt2x00dev);
+       /*
+        * Restore beaconing state.
+        */
+       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_clear_beacon);
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+const struct rt2x00debug rt2800_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = rt2800_register_read,
+               .write          = rt2800_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = CSR_REG_SIZE / sizeof(u32),
+       },
+       .eeprom = {
+               /* NOTE: The local EEPROM access functions can't
+                * be used here, use the generic versions instead.
+                */
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt2800_bbp_read,
+               .write          = rt2800_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt2800_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+       .rfcsr  = {
+               .read           = rt2800_rfcsr_read,
+               .write          = rt2800_rfcsr_write,
+               .word_base      = RFCSR_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = RFCSR_SIZE / sizeof(u8),
+       },
+};
+EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
+       } else {
+               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+               return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2800_brightness_set(struct led_classdev *led_cdev,
+                                 enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       unsigned int bg_mode =
+           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+       unsigned int polarity =
+               rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+                                  EEPROM_FREQ_LED_POLARITY);
+       unsigned int ledmode =
+               rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+                                  EEPROM_FREQ_LED_MODE);
+       u32 reg;
+
+       /* Check for SoC (SOC devices don't support MCU requests) */
+       if (rt2x00_is_soc(led->rt2x00dev)) {
+               rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+
+               /* Set LED Polarity */
+               rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
+
+               /* Set LED Mode */
+               if (led->type == LED_TYPE_RADIO) {
+                       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
+                                          enabled ? 3 : 0);
+               } else if (led->type == LED_TYPE_ASSOC) {
+                       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
+                                          enabled ? 3 : 0);
+               } else if (led->type == LED_TYPE_QUALITY) {
+                       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
+                                          enabled ? 3 : 0);
+               }
+
+               rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+       } else {
+               if (led->type == LED_TYPE_RADIO) {
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+                                             enabled ? 0x20 : 0);
+               } else if (led->type == LED_TYPE_ASSOC) {
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+                                             enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+               } else if (led->type == LED_TYPE_QUALITY) {
+                       /*
+                        * The brightness is divided into 6 levels (0 - 5),
+                        * The specs tell us the following levels:
+                        *      0, 1 ,3, 7, 15, 31
+                        * to determine the level in a simple way we can simply
+                        * work with bitshifting:
+                        *      (1 << level) - 1
+                        */
+                       rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+                                             (1 << brightness / (LED_FULL / 6)) - 1,
+                                             polarity);
+               }
+       }
+}
+
+static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
+                    struct rt2x00_led *led, enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt2800_brightness_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
+                              const u8 *address,
+                              int wcid)
+{
+       struct mac_wcid_entry wcid_entry;
+       u32 offset;
+
+       offset = MAC_WCID_ENTRY(wcid);
+
+       memset(&wcid_entry, 0xff, sizeof(wcid_entry));
+       if (address)
+               memcpy(wcid_entry.mac, address, ETH_ALEN);
+
+       rt2800_register_multiwrite(rt2x00dev, offset,
+                                     &wcid_entry, sizeof(wcid_entry));
+}
+
+static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+       u32 offset;
+       offset = MAC_WCID_ATTR_ENTRY(wcid);
+       rt2800_register_write(rt2x00dev, offset, 0);
+}
+
+static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
+                                          int wcid, u32 bssidx)
+{
+       u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
+       u32 reg;
+
+       /*
+        * 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_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
+       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
+                          (bssidx & 0x8) >> 3);
+       rt2800_register_write(rt2x00dev, offset, reg);
+}
+
+static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
+                                          struct rt2x00lib_crypto *crypto,
+                                          struct ieee80211_key_conf *key)
+{
+       struct mac_iveiv_entry iveiv_entry;
+       u32 offset;
+       u32 reg;
+
+       offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
+
+       if (crypto->cmd == SET_KEY) {
+               rt2800_register_read(rt2x00dev, offset, &reg);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
+                                  !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+               /*
+                * Both the cipher as the BSS Idx numbers are split in a main
+                * value of 3 bits, and a extended field for adding one additional
+                * bit to the value.
+                */
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
+                                  (crypto->cipher & 0x7));
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
+                                  (crypto->cipher & 0x8) >> 3);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
+               rt2800_register_write(rt2x00dev, offset, reg);
+       } else {
+               /* Delete the cipher without touching the bssidx */
+               rt2800_register_read(rt2x00dev, offset, &reg);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
+               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
+               rt2800_register_write(rt2x00dev, offset, reg);
+       }
+
+       offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+
+       memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+       if ((crypto->cipher == CIPHER_TKIP) ||
+           (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+           (crypto->cipher == CIPHER_AES))
+               iveiv_entry.iv[3] |= 0x20;
+       iveiv_entry.iv[3] |= key->keyidx << 6;
+       rt2800_register_multiwrite(rt2x00dev, offset,
+                                     &iveiv_entry, sizeof(iveiv_entry));
+}
+
+int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_crypto *crypto,
+                            struct ieee80211_key_conf *key)
+{
+       struct hw_key_entry key_entry;
+       struct rt2x00_field32 field;
+       u32 offset;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
+
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+               rt2800_register_multiwrite(rt2x00dev, offset,
+                                             &key_entry, sizeof(key_entry));
+       }
+
+       /*
+        * The cipher types are stored over multiple registers
+        * starting with SHARED_KEY_MODE_BASE each word will have
+        * 32 bits and contains the cipher types for 2 bssidx each.
+        * Using the correct defines correctly will cause overhead,
+        * so just calculate the correct offset.
+        */
+       field.bit_offset = 4 * (key->hw_key_idx % 8);
+       field.bit_mask = 0x7 << field.bit_offset;
+
+       offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
+
+       rt2800_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field,
+                          (crypto->cmd == SET_KEY) * crypto->cipher);
+       rt2800_register_write(rt2x00dev, offset, reg);
+
+       /*
+        * Update WCID information
+        */
+       rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
+       rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
+                                      crypto->bssidx);
+       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
+
+int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00lib_crypto *crypto,
+                              struct ieee80211_key_conf *key)
+{
+       struct hw_key_entry key_entry;
+       u32 offset;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * Allow key configuration only for STAs that are
+                * known by the hw.
+                */
+               if (crypto->wcid > WCID_END)
+                       return -ENOSPC;
+               key->hw_key_idx = crypto->wcid;
+
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+               rt2800_register_multiwrite(rt2x00dev, offset,
+                                             &key_entry, sizeof(key_entry));
+       }
+
+       /*
+        * Update WCID information
+        */
+       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
+
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta)
+{
+       int wcid;
+       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+       /*
+        * Search for the first free WCID entry and return the corresponding
+        * index.
+        */
+       wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START;
+
+       /*
+        * Store selected wcid even if it is invalid so that we can
+        * later decide if the STA is uploaded into the hw.
+        */
+       sta_priv->wcid = wcid;
+
+       /*
+        * No space left in the device, however, we can still communicate
+        * with the STA -> No error.
+        */
+       if (wcid > WCID_END)
+               return 0;
+
+       __set_bit(wcid - WCID_START, drv_data->sta_ids);
+
+       /*
+        * Clean up WCID attributes and write STA address to the device.
+        */
+       rt2800_delete_wcid_attr(rt2x00dev, wcid);
+       rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
+       rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
+                                      rt2x00lib_get_bssidx(rt2x00dev, vif));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_add);
+
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+       if (wcid > WCID_END)
+               return 0;
+       /*
+        * Remove WCID entry, no need to clean the attributes as they will
+        * get renewed when the WCID is reused.
+        */
+       rt2800_config_wcid(rt2x00dev, NULL, wcid);
+       __clear_bit(wcid - WCID_START, drv_data->sta_ids);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_sta_remove);
+
+void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
+                         const unsigned int filter_flags)
+{
+       u32 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
+                          !(filter_flags & FIF_ALLMULTI));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
+                          !(filter_flags & FIF_PSPOLL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 0);
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
+                          !(filter_flags & FIF_CONTROL));
+       rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_config_filter);
+
+void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
+                       struct rt2x00intf_conf *conf, const unsigned int flags)
+{
+       u32 reg;
+       bool update_bssid = false;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable synchronisation.
+                */
+               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
+               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+               if (conf->sync == TSF_SYNC_AP_NONE) {
+                       /*
+                        * Tune beacon queue transmit parameters for AP mode
+                        */
+                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
+                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+               } else {
+                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
+                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+               }
+       }
+
+       if (flags & CONFIG_UPDATE_MAC) {
+               if (flags & CONFIG_UPDATE_TYPE &&
+                   conf->sync == TSF_SYNC_AP_NONE) {
+                       /*
+                        * The BSSID register has to be set to our own mac
+                        * address in AP mode.
+                        */
+                       memcpy(conf->bssid, conf->mac, sizeof(conf->mac));
+                       update_bssid = true;
+               }
+
+               if (!is_zero_ether_addr((const u8 *)conf->mac)) {
+                       reg = le32_to_cpu(conf->mac[1]);
+                       rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
+                       conf->mac[1] = cpu_to_le32(reg);
+               }
+
+               rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
+                                             conf->mac, sizeof(conf->mac));
+       }
+
+       if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {
+               if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
+                       reg = le32_to_cpu(conf->bssid[1]);
+                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
+                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
+                       conf->bssid[1] = cpu_to_le32(reg);
+               }
+
+               rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
+                                             conf->bssid, sizeof(conf->bssid));
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800_config_intf);
+
+static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
+                                   struct rt2x00lib_erp *erp)
+{
+       bool any_sta_nongf = !!(erp->ht_opmode &
+                               IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+       u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION;
+       u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode;
+       u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate;
+       u32 reg;
+
+       /* default protection rate for HT20: OFDM 24M */
+       mm20_rate = gf20_rate = 0x4004;
+
+       /* default protection rate for HT40: duplicate OFDM 24M */
+       mm40_rate = gf40_rate = 0x4084;
+
+       switch (protection) {
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+               /*
+                * All STAs in this BSS are HT20/40 but there might be
+                * STAs not supporting greenfield mode.
+                * => Disable protection for HT transmissions.
+                */
+               mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0;
+
+               break;
+       case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+               /*
+                * All STAs in this BSS are HT20 or HT20/40 but there
+                * might be STAs not supporting greenfield mode.
+                * => Protect all HT40 transmissions.
+                */
+               mm20_mode = gf20_mode = 0;
+               mm40_mode = gf40_mode = 2;
+
+               break;
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+               /*
+                * Nonmember protection:
+                * According to 802.11n we _should_ protect all
+                * HT transmissions (but we don't have to).
+                *
+                * But if cts_protection is enabled we _shall_ protect
+                * all HT transmissions using a CCK rate.
+                *
+                * And if any station is non GF we _shall_ protect
+                * GF transmissions.
+                *
+                * We decide to protect everything
+                * -> fall through to mixed mode.
+                */
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+               /*
+                * Legacy STAs are present
+                * => Protect all HT transmissions.
+                */
+               mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;
+
+               /*
+                * If erp protection is needed we have to protect HT
+                * transmissions with CCK 11M long preamble.
+                */
+               if (erp->cts_protection) {
+                       /* don't duplicate RTS/CTS in CCK mode */
+                       mm20_rate = mm40_rate = 0x0003;
+                       gf20_rate = gf40_rate = 0x0003;
+               }
+               break;
+       }
+
+       /* check for STAs not supporting greenfield mode */
+       if (any_sta_nongf)
+               gf20_mode = gf40_mode = 2;
+
+       /* Update HT protection config */
+       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
+       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
+       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
+       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
+       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+}
+
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+                      u32 changed)
+{
+       u32 reg;
+
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+               rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
+                                  !!erp->short_preamble);
+               rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
+                                  !!erp->short_preamble);
+               rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+       }
+
+       if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+               rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+               rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
+                                  erp->cts_protection ? 2 : 0);
+               rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES) {
+               rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
+                                        erp->basic_rates);
+               rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+       }
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+               rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
+                                  erp->slot_time);
+               rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+
+               rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
+               rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+       }
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+       }
+
+       if (changed & BSS_CHANGED_HT)
+               rt2800_config_ht_opmode(rt2x00dev, erp);
+}
+EXPORT_SYMBOL_GPL(rt2800_config_erp);
+
+static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 eeprom;
+       u8 led_ctrl, led_g_mode, led_r_mode;
+
+       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
+               rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
+       } else {
+               rt2x00_set_field32(&reg, GPIO_SWITCH_0, 0);
+               rt2x00_set_field32(&reg, GPIO_SWITCH_1, 0);
+       }
+       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+       led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
+       led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
+       if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
+           led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+               led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
+               if (led_ctrl == 0 || led_ctrl > 0x40) {
+                       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
+                       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, led_r_mode);
+                       rt2800_register_write(rt2x00dev, LED_CFG, reg);
+               } else {
+                       rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
+                                          (led_g_mode << 2) | led_r_mode, 1);
+               }
+       }
+}
+
+static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
+                                    enum antenna ant)
+{
+       u32 reg;
+       u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0;
+       u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
+
+       if (rt2x00_is_pci(rt2x00dev)) {
+               rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+               rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
+               rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+       } else if (rt2x00_is_usb(rt2x00dev))
+               rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
+                                  eesk_pin, 0);
+
+       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
+       rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
+       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+}
+
+void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
+{
+       u8 r1;
+       u8 r3;
+       u16 eeprom;
+
+       rt2800_bbp_read(rt2x00dev, 1, &r1);
+       rt2800_bbp_read(rt2x00dev, 3, &r3);
+
+       if (rt2x00_rt(rt2x00dev, RT3572) &&
+           rt2x00_has_cap_bt_coexist(rt2x00dev))
+               rt2800_config_3572bt_ant(rt2x00dev);
+
+       /*
+        * Configure the TX antenna.
+        */
+       switch (ant->tx_chain_num) {
+       case 1:
+               rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
+               break;
+       case 2:
+               if (rt2x00_rt(rt2x00dev, RT3572) &&
+                   rt2x00_has_cap_bt_coexist(rt2x00dev))
+                       rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
+               else
+                       rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+               break;
+       case 3:
+               rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+               break;
+       }
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx_chain_num) {
+       case 1:
+               if (rt2x00_rt(rt2x00dev, RT3070) ||
+                   rt2x00_rt(rt2x00dev, RT3090) ||
+                   rt2x00_rt(rt2x00dev, RT3352) ||
+                   rt2x00_rt(rt2x00dev, RT3390)) {
+                       rt2800_eeprom_read(rt2x00dev,
+                                          EEPROM_NIC_CONF1, &eeprom);
+                       if (rt2x00_get_field16(eeprom,
+                                               EEPROM_NIC_CONF1_ANT_DIVERSITY))
+                               rt2800_set_ant_diversity(rt2x00dev,
+                                               rt2x00dev->default_ant.rx);
+               }
+               rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
+               break;
+       case 2:
+               if (rt2x00_rt(rt2x00dev, RT3572) &&
+                   rt2x00_has_cap_bt_coexist(rt2x00dev)) {
+                       rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
+                       rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
+                               rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+                       rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
+               } else {
+                       rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+               }
+               break;
+       case 3:
+               rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
+               break;
+       }
+
+       rt2800_bbp_write(rt2x00dev, 3, r3);
+       rt2800_bbp_write(rt2x00dev, 1, r1);
+
+       if (rt2x00_rt(rt2x00dev, RT3593)) {
+               if (ant->rx_chain_num == 1)
+                       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+               else
+                       rt2800_bbp_write(rt2x00dev, 86, 0x46);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800_config_ant);
+
+static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+                                  struct rt2x00lib_conf *libconf)
+{
+       u16 eeprom;
+       short lna_gain;
+
+       if (libconf->rf.channel <= 14) {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+               lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
+       } else if (libconf->rf.channel <= 64) {
+               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)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_EXT_LNA2_A1);
+               } else {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_RSSI_BG2_LNA_A1);
+               }
+       } else {
+               if (rt2x00_rt(rt2x00dev, RT3593)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_EXT_LNA2_A2);
+               } else {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+                       lna_gain = rt2x00_get_field16(eeprom,
+                                                     EEPROM_RSSI_A2_LNA_A2);
+               }
+       }
+
+       rt2x00dev->lna_gain = lna_gain;
+}
+
+#define FREQ_OFFSET_BOUND      0x5f
+
+static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
+{
+       u8 freq_offset, prev_freq_offset;
+       u8 rfcsr, prev_rfcsr;
+
+       freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
+       freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
+
+       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+       prev_rfcsr = rfcsr;
+
+       rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
+       if (rfcsr == prev_rfcsr)
+               return;
+
+       if (rt2x00_is_usb(rt2x00dev)) {
+               rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
+                                  freq_offset, prev_rfcsr);
+               return;
+       }
+
+       prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
+       while (prev_freq_offset != freq_offset) {
+               if (prev_freq_offset < freq_offset)
+                       prev_freq_offset++;
+               else
+                       prev_freq_offset--;
+
+               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
+               rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+               usleep_range(1000, 1500);
+       }
+}
+
+static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+       if (rt2x00dev->default_ant.tx_chain_num == 1)
+               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
+
+       if (rt2x00dev->default_ant.rx_chain_num == 1) {
+               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
+               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+       } else if (rt2x00dev->default_ant.rx_chain_num == 2)
+               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+
+       if (rf->channel > 14) {
+               /*
+                * When TX power is below 0, we should increase it by 7 to
+                * make it a positive value (Minimum value is -7).
+                * However this means that values between 0 and 7 have
+                * double meaning, and we should set a 7DBm boost flag.
+                */
+               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
+                                  (info->default_power1 >= 0));
+
+               if (info->default_power1 < 0)
+                       info->default_power1 += 7;
+
+               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
+
+               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
+                                  (info->default_power2 >= 0));
+
+               if (info->default_power2 < 0)
+                       info->default_power2 += 7;
+
+               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
+       } else {
+               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
+               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
+       }
+
+       rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
+
+       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+
+       udelay(200);
+
+       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+
+       udelay(200);
+
+       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+       rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 rfcsr, calib_tx, calib_rx;
+
+       rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+
+       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3);
+       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
+       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
+       rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
+                         rt2x00dev->default_ant.rx_chain_num <= 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD,
+                         rt2x00dev->default_ant.rx_chain_num <= 2);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,
+                         rt2x00dev->default_ant.tx_chain_num <= 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD,
+                         rt2x00dev->default_ant.tx_chain_num <= 2);
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+       rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+       if (rt2x00_rt(rt2x00dev, RT3390)) {
+               calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f;
+               calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f;
+       } else {
+               if (conf_is_ht40(conf)) {
+                       calib_tx = drv_data->calibration_bw40;
+                       calib_rx = drv_data->calibration_bw40;
+               } else {
+                       calib_tx = drv_data->calibration_bw20;
+                       calib_rx = drv_data->calibration_bw20;
+               }
+       }
+
+       rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx);
+       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx);
+       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+       rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+       msleep(1);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+}
+
+static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 rfcsr;
+       u32 reg;
+
+       if (rf->channel <= 14) {
+               rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
+               rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
+       } else {
+               rt2800_bbp_write(rt2x00dev, 25, 0x09);
+               rt2800_bbp_write(rt2x00dev, 26, 0xff);
+       }
+
+       rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
+
+       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
+       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
+       rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
+               rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+                                 info->default_power1);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
+               rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+                               (info->default_power1 & 0x3) |
+                               ((info->default_power1 & 0xC) << 1));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
+               rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+                                 info->default_power2);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
+               rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+                               (info->default_power2 & 0x3) |
+                               ((info->default_power2 & 0xC) << 1));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
+       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);
+       if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
+               if (rf->channel <= 14) {
+                       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+                       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+               }
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+       } else {
+               switch (rt2x00dev->default_ant.tx_chain_num) {
+               case 1:
+                       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+               case 2:
+                       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+                       break;
+               }
+
+               switch (rt2x00dev->default_ant.rx_chain_num) {
+               case 1:
+                       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+               case 2:
+                       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+                       break;
+               }
+       }
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+       rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+       if (conf_is_ht40(conf)) {
+               rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40);
+               rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40);
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20);
+               rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20);
+       }
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+               rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+               rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+               rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+               rfcsr = 0x4c;
+               rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,
+                                 drv_data->txmixer_gain_24g);
+               rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
+               rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+               rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+               rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+               rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+               rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+       } else {
+               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0);
+               rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+               rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+               rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
+               rfcsr = 0x7a;
+               rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,
+                                 drv_data->txmixer_gain_5g);
+               rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
+               rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+               if (rf->channel <= 64) {
+                       rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
+                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
+                       rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+               } else if (rf->channel <= 128) {
+                       rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
+                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
+                       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+               } else {
+                       rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
+                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
+                       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+               }
+               rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
+               rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
+       }
+
+       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
+       if (rf->channel <= 14)
+               rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
+       else
+               rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
+       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+
+       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+       rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+}
+
+static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 txrx_agc_fc;
+       u8 txrx_h20m;
+       u8 rfcsr;
+       u8 bbp;
+       const bool txbf_enabled = false; /* TODO */
+
+       /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
+       rt2800_bbp_read(rt2x00dev, 109, &bbp);
+       rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
+       rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
+       rt2800_bbp_write(rt2x00dev, 109, bbp);
+
+       rt2800_bbp_read(rt2x00dev, 110, &bbp);
+       rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
+       rt2800_bbp_write(rt2x00dev, 110, bbp);
+
+       if (rf->channel <= 14) {
+               /* Restore BBP 25 & 26 for 2.4 GHz */
+               rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
+               rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
+       } else {
+               /* Hard code BBP 25 & 26 for 5GHz */
+
+               /* Enable IQ Phase correction */
+               rt2800_bbp_write(rt2x00dev, 25, 0x09);
+               /* Setup IQ Phase correction value */
+               rt2800_bbp_write(rt2x00dev, 26, 0xff);
+       }
+
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
+
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+                                 info->default_power1 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
+                                 ((info->default_power1 & 0x18) << 1) |
+                                 (info->default_power1 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+                                 info->default_power2 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
+                                 ((info->default_power2 & 0x18) << 1) |
+                                 (info->default_power2 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
+       if (rf->channel <= 14) {
+               rfcsr = 0;
+               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+                                 info->default_power3 & 0x1f);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rfcsr = 0x40;
+
+               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
+                                 ((info->default_power3 & 0x18) << 1) |
+                                 (info->default_power3 & 7));
+       }
+       rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
+
+       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);
+
+       if (conf_is_ht40(conf)) {
+               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
+                                               RFCSR24_TX_AGC_FC);
+               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40,
+                                             RFCSR24_TX_H20M);
+       } else {
+               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20,
+                                               RFCSR24_TX_AGC_FC);
+               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20,
+                                             RFCSR24_TX_H20M);
+       }
+
+       /* NOTE: the reference driver does not writes the new value
+        * back to RFCSR 32
+        */
+       rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
+
+       if (rf->channel <= 14)
+               rfcsr = 0xa0;
+       else
+               rfcsr = 0x80;
+       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+       /* Band selection */
+       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);
+
+       rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
+       if (rf->channel <= 14)
+               rfcsr = 0x3c;
+       else
+               rfcsr = 0x20;
+       rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+       if (rf->channel <= 14)
+               rfcsr = 0x1a;
+       else
+               rfcsr = 0x12;
+       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       if (rf->channel >= 1 && rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+       else if (rf->channel >= 36 && rf->channel <= 64)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+       else if (rf->channel >= 100 && rf->channel <= 128)
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
+       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+       rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0xd8);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
+       }
+
+       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
+       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4);
+               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2);
+       }
+       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2);
+
+       if (txbf_enabled)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1);
+
+       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+       if (rf->channel <= 14)
+               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 57, rfcsr);
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+               rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
+               rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+       }
+
+       /* Initiate VCO calibration */
+       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       if (rf->channel <= 14) {
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+       } else {
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+       }
+       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+       if (rf->channel >= 1 && rf->channel <= 14) {
+               rfcsr = 0x23;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+       } else if (rf->channel >= 36 && rf->channel <= 64) {
+               rfcsr = 0x36;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, 0x36);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xeb);
+       } else if (rf->channel >= 100 && rf->channel <= 128) {
+               rfcsr = 0x32;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xb3);
+       } else {
+               rfcsr = 0x30;
+               if (txbf_enabled)
+                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
+               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+               rt2800_rfcsr_write(rt2x00dev, 45, 0x9b);
+       }
+}
+
+#define POWER_BOUND            0x27
+#define POWER_BOUND_5G         0x2b
+
+static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       u8 rfcsr;
+
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       if (info->default_power1 > POWER_BOUND)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       if (rf->channel <= 14) {
+               if (rf->channel == 6)
+                       rt2800_bbp_write(rt2x00dev, 68, 0x0c);
+               else
+                       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+               if (rf->channel >= 1 && rf->channel <= 6)
+                       rt2800_bbp_write(rt2x00dev, 59, 0x0f);
+               else if (rf->channel >= 7 && rf->channel <= 11)
+                       rt2800_bbp_write(rt2x00dev, 59, 0x0e);
+               else if (rf->channel >= 12 && rf->channel <= 14)
+                       rt2800_bbp_write(rt2x00dev, 59, 0x0d);
+       }
+}
+
+static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       u8 rfcsr;
+
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
+
+       if (info->default_power1 > POWER_BOUND)
+               rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1);
+
+       if (info->default_power2 > POWER_BOUND)
+               rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+
+       if ( rt2x00dev->default_ant.tx_chain_num == 2 )
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+
+       if ( rt2x00dev->default_ant.rx_chain_num == 2 )
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_rfcsr_write(rt2x00dev, 31, 80);
+}
+
+static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       u8 rfcsr;
+
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       if (info->default_power1 > POWER_BOUND)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+       if (rt2x00_rt(rt2x00dev, RT5392)) {
+               rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+               if (info->default_power2 > POWER_BOUND)
+                       rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
+               else
+                       rt2x00_set_field8(&rfcsr, RFCSR50_TX,
+                                         info->default_power2);
+               rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+       }
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       if (rt2x00_rt(rt2x00dev, RT5392)) {
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+       }
+       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       if (rf->channel <= 14) {
+               int idx = rf->channel-1;
+
+               if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
+                       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+                               /* r55/r59 value array of channel 1~14 */
+                               static const char r55_bt_rev[] = {0x83, 0x83,
+                                       0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
+                                       0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
+                               static const char r59_bt_rev[] = {0x0e, 0x0e,
+                                       0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
+                                       0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
+
+                               rt2800_rfcsr_write(rt2x00dev, 55,
+                                                  r55_bt_rev[idx]);
+                               rt2800_rfcsr_write(rt2x00dev, 59,
+                                                  r59_bt_rev[idx]);
+                       } else {
+                               static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
+                                       0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
+                                       0x88, 0x88, 0x86, 0x85, 0x84};
+
+                               rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
+                       }
+               } else {
+                       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+                               static const char r55_nonbt_rev[] = {0x23, 0x23,
+                                       0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
+                                       0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+                               static const char r59_nonbt_rev[] = {0x07, 0x07,
+                                       0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+                                       0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
+
+                               rt2800_rfcsr_write(rt2x00dev, 55,
+                                                  r55_nonbt_rev[idx]);
+                               rt2800_rfcsr_write(rt2x00dev, 59,
+                                                  r59_nonbt_rev[idx]);
+                       } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+                                  rt2x00_rt(rt2x00dev, RT5392)) {
+                               static const char r59_non_bt[] = {0x8f, 0x8f,
+                                       0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
+                                       0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
+
+                               rt2800_rfcsr_write(rt2x00dev, 59,
+                                                  r59_non_bt[idx]);
+                       }
+               }
+       }
+}
+
+static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_conf *conf,
+                                        struct rf_channel *rf,
+                                        struct channel_info *info)
+{
+       u8 rfcsr, ep_reg;
+       u32 reg;
+       int power_bound;
+
+       /* TODO */
+       const bool is_11b = false;
+       const bool is_type_ep = false;
+
+       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL,
+                          (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);
+       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+       /* Order of values on rf_channel entry: N, K, mod, R */
+       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);
+
+       rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);
+       rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);
+       rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);
+       rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);
+       rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);
+       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+       if (rf->channel <= 14) {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0x90);
+               /* FIXME: RF11 owerwrite ? */
+               rt2800_rfcsr_write(rt2x00dev, 11, 0x4A);
+               rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
+               rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
+               rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
+               rt2800_rfcsr_write(rt2x00dev, 24, 0x4A);
+               rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
+               rt2800_rfcsr_write(rt2x00dev, 36, 0x80);
+               rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+               rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
+               rt2800_rfcsr_write(rt2x00dev, 39, 0x1B);
+               rt2800_rfcsr_write(rt2x00dev, 40, 0x0D);
+               rt2800_rfcsr_write(rt2x00dev, 41, 0x9B);
+               rt2800_rfcsr_write(rt2x00dev, 42, 0xD5);
+               rt2800_rfcsr_write(rt2x00dev, 43, 0x72);
+               rt2800_rfcsr_write(rt2x00dev, 44, 0x0E);
+               rt2800_rfcsr_write(rt2x00dev, 45, 0xA2);
+               rt2800_rfcsr_write(rt2x00dev, 46, 0x6B);
+               rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+               rt2800_rfcsr_write(rt2x00dev, 51, 0x3E);
+               rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
+               rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
+               rt2800_rfcsr_write(rt2x00dev, 56, 0xA1);
+               rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
+               rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+               rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
+               rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
+
+               /* TODO RF27 <- tssi */
+
+               rfcsr = rf->channel <= 10 ? 0x07 : 0x06;
+               rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+               rt2800_rfcsr_write(rt2x00dev, 59, rfcsr);
+
+               if (is_11b) {
+                       /* CCK */
+                       rt2800_rfcsr_write(rt2x00dev, 31, 0xF8);
+                       rt2800_rfcsr_write(rt2x00dev, 32, 0xC0);
+                       if (is_type_ep)
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x06);
+                       else
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x47);
+               } else {
+                       /* OFDM */
+                       if (is_type_ep)
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x03);
+                       else
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+               }
+
+               power_bound = POWER_BOUND;
+               ep_reg = 0x2;
+       } else {
+               rt2800_rfcsr_write(rt2x00dev, 10, 0x97);
+               /* FIMXE: RF11 overwrite */
+               rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
+               rt2800_rfcsr_write(rt2x00dev, 25, 0xBF);
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
+               rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 37, 0x04);
+               rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+               rt2800_rfcsr_write(rt2x00dev, 40, 0x42);
+               rt2800_rfcsr_write(rt2x00dev, 41, 0xBB);
+               rt2800_rfcsr_write(rt2x00dev, 42, 0xD7);
+               rt2800_rfcsr_write(rt2x00dev, 45, 0x41);
+               rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
+               rt2800_rfcsr_write(rt2x00dev, 57, 0x77);
+               rt2800_rfcsr_write(rt2x00dev, 60, 0x05);
+               rt2800_rfcsr_write(rt2x00dev, 61, 0x01);
+
+               /* TODO RF27 <- tssi */
+
+               if (rf->channel >= 36 && rf->channel <= 64) {
+
+                       rt2800_rfcsr_write(rt2x00dev, 12, 0x2E);
+                       rt2800_rfcsr_write(rt2x00dev, 13, 0x22);
+                       rt2800_rfcsr_write(rt2x00dev, 22, 0x60);
+                       rt2800_rfcsr_write(rt2x00dev, 23, 0x7F);
+                       if (rf->channel <= 50)
+                               rt2800_rfcsr_write(rt2x00dev, 24, 0x09);
+                       else if (rf->channel >= 52)
+                               rt2800_rfcsr_write(rt2x00dev, 24, 0x07);
+                       rt2800_rfcsr_write(rt2x00dev, 39, 0x1C);
+                       rt2800_rfcsr_write(rt2x00dev, 43, 0x5B);
+                       rt2800_rfcsr_write(rt2x00dev, 44, 0X40);
+                       rt2800_rfcsr_write(rt2x00dev, 46, 0X00);
+                       rt2800_rfcsr_write(rt2x00dev, 51, 0xFE);
+                       rt2800_rfcsr_write(rt2x00dev, 52, 0x0C);
+                       rt2800_rfcsr_write(rt2x00dev, 54, 0xF8);
+                       if (rf->channel <= 50) {
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x06),
+                               rt2800_rfcsr_write(rt2x00dev, 56, 0xD3);
+                       } else if (rf->channel >= 52) {
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x04);
+                               rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
+                       }
+
+                       rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
+                       rt2800_rfcsr_write(rt2x00dev, 59, 0x7F);
+                       rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
+
+               } else if (rf->channel >= 100 && rf->channel <= 165) {
+
+                       rt2800_rfcsr_write(rt2x00dev, 12, 0x0E);
+                       rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
+                       rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
+                       if (rf->channel <= 153) {
+                               rt2800_rfcsr_write(rt2x00dev, 23, 0x3C);
+                               rt2800_rfcsr_write(rt2x00dev, 24, 0x06);
+                       } else if (rf->channel >= 155) {
+                               rt2800_rfcsr_write(rt2x00dev, 23, 0x38);
+                               rt2800_rfcsr_write(rt2x00dev, 24, 0x05);
+                       }
+                       if (rf->channel <= 138) {
+                               rt2800_rfcsr_write(rt2x00dev, 39, 0x1A);
+                               rt2800_rfcsr_write(rt2x00dev, 43, 0x3B);
+                               rt2800_rfcsr_write(rt2x00dev, 44, 0x20);
+                               rt2800_rfcsr_write(rt2x00dev, 46, 0x18);
+                       } else if (rf->channel >= 140) {
+                               rt2800_rfcsr_write(rt2x00dev, 39, 0x18);
+                               rt2800_rfcsr_write(rt2x00dev, 43, 0x1B);
+                               rt2800_rfcsr_write(rt2x00dev, 44, 0x10);
+                               rt2800_rfcsr_write(rt2x00dev, 46, 0X08);
+                       }
+                       if (rf->channel <= 124)
+                               rt2800_rfcsr_write(rt2x00dev, 51, 0xFC);
+                       else if (rf->channel >= 126)
+                               rt2800_rfcsr_write(rt2x00dev, 51, 0xEC);
+                       if (rf->channel <= 138)
+                               rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
+                       else if (rf->channel >= 140)
+                               rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
+                       rt2800_rfcsr_write(rt2x00dev, 54, 0xEB);
+                       if (rf->channel <= 138)
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x01);
+                       else if (rf->channel >= 140)
+                               rt2800_rfcsr_write(rt2x00dev, 55, 0x00);
+                       if (rf->channel <= 128)
+                               rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
+                       else if (rf->channel >= 130)
+                               rt2800_rfcsr_write(rt2x00dev, 56, 0xAB);
+                       if (rf->channel <= 116)
+                               rt2800_rfcsr_write(rt2x00dev, 58, 0x1D);
+                       else if (rf->channel >= 118)
+                               rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
+                       if (rf->channel <= 138)
+                               rt2800_rfcsr_write(rt2x00dev, 59, 0x3F);
+                       else if (rf->channel >= 140)
+                               rt2800_rfcsr_write(rt2x00dev, 59, 0x7C);
+                       if (rf->channel <= 116)
+                               rt2800_rfcsr_write(rt2x00dev, 62, 0x1D);
+                       else if (rf->channel >= 118)
+                               rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
+               }
+
+               power_bound = POWER_BOUND_5G;
+               ep_reg = 0x3;
+       }
+
+       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+       if (info->default_power1 > power_bound)
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+       if (is_type_ep)
+               rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);
+       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       if (info->default_power2 > power_bound)
+               rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
+       else
+               rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2);
+       if (is_type_ep)
+               rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);
+       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD,
+                         rt2x00dev->default_ant.tx_chain_num >= 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,
+                         rt2x00dev->default_ant.tx_chain_num == 2);
+       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD,
+                         rt2x00dev->default_ant.rx_chain_num >= 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
+                         rt2x00dev->default_ant.rx_chain_num == 2);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0xe4);
+
+       if (conf_is_ht40(conf))
+               rt2800_rfcsr_write(rt2x00dev, 30, 0x16);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+
+       if (!is_11b) {
+               rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+               rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+       }
+
+       /* TODO proper frequency adjustment */
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       /* TODO merge with others */
+       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+       /* 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);
+
+       rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18);
+       rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08);
+       rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38);
+       rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92);
+
+       /* GLRT band configuration */
+       rt2800_bbp_write(rt2x00dev, 195, 128);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0);
+       rt2800_bbp_write(rt2x00dev, 195, 129);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E);
+       rt2800_bbp_write(rt2x00dev, 195, 130);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28);
+       rt2800_bbp_write(rt2x00dev, 195, 131);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20);
+       rt2800_bbp_write(rt2x00dev, 195, 133);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F);
+       rt2800_bbp_write(rt2x00dev, 195, 124);
+       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);
+}
+
+static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
+                                          const unsigned int word,
+                                          const u8 value)
+{
+       u8 chain, reg;
+
+       for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {
+               rt2800_bbp_read(rt2x00dev, 27, &reg);
+               rt2x00_set_field8(&reg,  BBP27_RX_CHAIN_SEL, chain);
+               rt2800_bbp_write(rt2x00dev, 27, reg);
+
+               rt2800_bbp_write(rt2x00dev, word, value);
+       }
+}
+
+static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)
+{
+       u8 cal;
+
+       /* TX0 IQ Gain */
+       rt2800_bbp_write(rt2x00dev, 158, 0x2c);
+       if (channel <= 14)
+               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G);
+       else if (channel >= 36 && channel <= 64)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G);
+       else if (channel >= 100 && channel <= 138)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G);
+       else if (channel >= 140 && channel <= 165)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G);
+       else
+               cal = 0;
+       rt2800_bbp_write(rt2x00dev, 159, cal);
+
+       /* TX0 IQ Phase */
+       rt2800_bbp_write(rt2x00dev, 158, 0x2d);
+       if (channel <= 14)
+               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G);
+       else if (channel >= 36 && channel <= 64)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G);
+       else if (channel >= 100 && channel <= 138)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G);
+       else if (channel >= 140 && channel <= 165)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G);
+       else
+               cal = 0;
+       rt2800_bbp_write(rt2x00dev, 159, cal);
+
+       /* TX1 IQ Gain */
+       rt2800_bbp_write(rt2x00dev, 158, 0x4a);
+       if (channel <= 14)
+               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G);
+       else if (channel >= 36 && channel <= 64)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G);
+       else if (channel >= 100 && channel <= 138)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G);
+       else if (channel >= 140 && channel <= 165)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G);
+       else
+               cal = 0;
+       rt2800_bbp_write(rt2x00dev, 159, cal);
+
+       /* TX1 IQ Phase */
+       rt2800_bbp_write(rt2x00dev, 158, 0x4b);
+       if (channel <= 14)
+               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G);
+       else if (channel >= 36 && channel <= 64)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G);
+       else if (channel >= 100 && channel <= 138)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G);
+       else if (channel >= 140 && channel <= 165)
+               cal = rt2x00_eeprom_byte(rt2x00dev,
+                                        EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G);
+       else
+               cal = 0;
+       rt2800_bbp_write(rt2x00dev, 159, cal);
+
+       /* FIXME: possible RX0, RX1 callibration ? */
+
+       /* RF IQ compensation control */
+       rt2800_bbp_write(rt2x00dev, 158, 0x04);
+       cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL);
+       rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
+
+       /* RF IQ imbalance compensation control */
+       rt2800_bbp_write(rt2x00dev, 158, 0x03);
+       cal = rt2x00_eeprom_byte(rt2x00dev,
+                                EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL);
+       rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
+}
+
+static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev,
+                                 unsigned int channel,
+                                 char txpower)
+{
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               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))
+               return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
+                              MAX_A_TXPOWER_3593);
+       else
+               return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+}
+
+static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+                                 struct ieee80211_conf *conf,
+                                 struct rf_channel *rf,
+                                 struct channel_info *info)
+{
+       u32 reg;
+       unsigned int tx_pin;
+       u8 bbp, rfcsr;
+
+       info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+                                                    info->default_power1);
+       info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+                                                    info->default_power2);
+       if (rt2x00dev->default_ant.tx_chain_num > 2)
+               info->default_power3 =
+                       rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+                                             info->default_power3);
+
+       switch (rt2x00dev->chip.rf) {
+       case RF2020:
+       case RF3020:
+       case RF3021:
+       case RF3022:
+       case RF3320:
+               rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+               break;
+       case RF3052:
+               rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
+               break;
+       case RF3053:
+               rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info);
+               break;
+       case RF3290:
+               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+               break;
+       case RF3322:
+               rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
+               break;
+       case RF3070:
+       case RF5360:
+       case RF5362:
+       case RF5370:
+       case RF5372:
+       case RF5390:
+       case RF5392:
+               rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
+               break;
+       case RF5592:
+               rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);
+               break;
+       default:
+               rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
+       }
+
+       if (rt2x00_rf(rt2x00dev, RF3070) ||
+           rt2x00_rf(rt2x00dev, RF3290) ||
+           rt2x00_rf(rt2x00dev, RF3322) ||
+           rt2x00_rf(rt2x00dev, RF5360) ||
+           rt2x00_rf(rt2x00dev, RF5362) ||
+           rt2x00_rf(rt2x00dev, RF5370) ||
+           rt2x00_rf(rt2x00dev, RF5372) ||
+           rt2x00_rf(rt2x00dev, RF5390) ||
+           rt2x00_rf(rt2x00dev, RF5392)) {
+               rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+               rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+               rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+       }
+
+       /*
+        * Change BBP settings
+        */
+       if (rt2x00_rt(rt2x00dev, RT3352)) {
+               rt2800_bbp_write(rt2x00dev, 27, 0x0);
+               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 27, 0x20);
+               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
+       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rf->channel > 14) {
+                       /* Disable CCK Packet detection on 5GHz */
+                       rt2800_bbp_write(rt2x00dev, 70, 0x00);
+               } else {
+                       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+               }
+
+               if (conf_is_ht40(conf))
+                       rt2800_bbp_write(rt2x00dev, 105, 0x04);
+               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);
+       }
+
+       if (rf->channel <= 14) {
+               if (!rt2x00_rt(rt2x00dev, RT5390) &&
+                   !rt2x00_rt(rt2x00dev, RT5392)) {
+                       if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+                               rt2800_bbp_write(rt2x00dev, 82, 0x62);
+                               rt2800_bbp_write(rt2x00dev, 75, 0x46);
+                       } else {
+                               if (rt2x00_rt(rt2x00dev, RT3593))
+                                       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+                               else
+                                       rt2800_bbp_write(rt2x00dev, 82, 0x84);
+                               rt2800_bbp_write(rt2x00dev, 75, 0x50);
+                       }
+                       if (rt2x00_rt(rt2x00dev, RT3593))
+                               rt2800_bbp_write(rt2x00dev, 83, 0x8a);
+               }
+
+       } else {
+               if (rt2x00_rt(rt2x00dev, RT3572))
+                       rt2800_bbp_write(rt2x00dev, 82, 0x94);
+               else if (rt2x00_rt(rt2x00dev, RT3593))
+                       rt2800_bbp_write(rt2x00dev, 82, 0x82);
+               else
+                       rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+
+               if (rt2x00_rt(rt2x00dev, RT3593))
+                       rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+
+               if (rt2x00_has_cap_external_lna_a(rt2x00dev))
+                       rt2800_bbp_write(rt2x00dev, 75, 0x46);
+               else
+                       rt2800_bbp_write(rt2x00dev, 75, 0x50);
+       }
+
+       rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
+       rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
+       rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
+       rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
+
+       if (rt2x00_rt(rt2x00dev, RT3572))
+               rt2800_rfcsr_write(rt2x00dev, 8, 0);
+
+       tx_pin = 0;
+
+       switch (rt2x00dev->default_ant.tx_chain_num) {
+       case 3:
+               /* Turn on tertiary PAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN,
+                                  rf->channel > 14);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN,
+                                  rf->channel <= 14);
+               /* fall-through */
+       case 2:
+               /* Turn on secondary PAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
+                                  rf->channel > 14);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
+                                  rf->channel <= 14);
+               /* fall-through */
+       case 1:
+               /* Turn on primary PAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN,
+                                  rf->channel > 14);
+               if (rt2x00_has_cap_bt_coexist(rt2x00dev))
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+               else
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
+                                          rf->channel <= 14);
+               break;
+       }
+
+       switch (rt2x00dev->default_ant.rx_chain_num) {
+       case 3:
+               /* Turn on tertiary LNAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
+               /* fall-through */
+       case 2:
+               /* Turn on secondary LNAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
+               /* fall-through */
+       case 1:
+               /* Turn on primary LNAs */
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
+               break;
+       }
+
+       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
+
+       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+       if (rt2x00_rt(rt2x00dev, RT3572)) {
+               rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
+
+               /* AGC init */
+               if (rf->channel <= 14)
+                       reg = 0x1c + (2 * rt2x00dev->lna_gain);
+               else
+                       reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3);
+
+               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+       }
+
+       if (rt2x00_rt(rt2x00dev, RT3593)) {
+               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+
+               /* Band selection */
+               if (rt2x00_is_usb(rt2x00dev) ||
+                   rt2x00_is_pcie(rt2x00dev)) {
+                       /* GPIO #8 controls all paths */
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR8, 0);
+                       if (rf->channel <= 14)
+                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 1);
+                       else
+                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 0);
+               }
+
+               /* LNA PE control. */
+               if (rt2x00_is_usb(rt2x00dev)) {
+                       /* GPIO #4 controls PE0 and PE1,
+                        * GPIO #7 controls PE2
+                        */
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
+
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
+               } else if (rt2x00_is_pcie(rt2x00dev)) {
+                       /* GPIO #4 controls PE0, PE1 and PE2 */
+                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
+               }
+
+               rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+
+               /* AGC init */
+               if (rf->channel <= 14)
+                       reg = 0x1c + 2 * rt2x00dev->lna_gain;
+               else
+                       reg = 0x22 + ((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);
+
+               /* AGC init */
+               reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain;
+               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
+               rt2800_iq_calibrate(rt2x00dev, rf->channel);
+       }
+
+       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
+       rt2800_bbp_write(rt2x00dev, 4, bbp);
+
+       rt2800_bbp_read(rt2x00dev, 3, &bbp);
+       rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
+       rt2800_bbp_write(rt2x00dev, 3, bbp);
+
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
+               if (conf_is_ht40(conf)) {
+                       rt2800_bbp_write(rt2x00dev, 69, 0x1a);
+                       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+                       rt2800_bbp_write(rt2x00dev, 73, 0x16);
+               } else {
+                       rt2800_bbp_write(rt2x00dev, 69, 0x16);
+                       rt2800_bbp_write(rt2x00dev, 70, 0x08);
+                       rt2800_bbp_write(rt2x00dev, 73, 0x11);
+               }
+       }
+
+       msleep(1);
+
+       /*
+        * Clear channel statistic counters
+        */
+       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
+       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
+       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
+
+       /*
+        * Clear update flag
+        */
+       if (rt2x00_rt(rt2x00dev, RT3352)) {
+               rt2800_bbp_read(rt2x00dev, 49, &bbp);
+               rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
+               rt2800_bbp_write(rt2x00dev, 49, bbp);
+       }
+}
+
+static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
+{
+       u8 tssi_bounds[9];
+       u8 current_tssi;
+       u16 eeprom;
+       u8 step;
+       int i;
+
+       /*
+        * First check if temperature compensation is supported.
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC))
+               return 0;
+
+       /*
+        * Read TSSI boundaries for temperature compensation from
+        * the EEPROM.
+        *
+        * Array idx               0    1    2    3    4    5    6    7    8
+        * Matching Delta value   -4   -3   -2   -1    0   +1   +2   +3   +4
+        * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
+        */
+       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
+               tssi_bounds[0] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG1_MINUS4);
+               tssi_bounds[1] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG1_MINUS3);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
+               tssi_bounds[2] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG2_MINUS2);
+               tssi_bounds[3] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG2_MINUS1);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
+               tssi_bounds[4] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG3_REF);
+               tssi_bounds[5] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG3_PLUS1);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
+               tssi_bounds[6] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG4_PLUS2);
+               tssi_bounds[7] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG4_PLUS3);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
+               tssi_bounds[8] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_BG5_PLUS4);
+
+               step = rt2x00_get_field16(eeprom,
+                                         EEPROM_TSSI_BOUND_BG5_AGC_STEP);
+       } else {
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
+               tssi_bounds[0] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A1_MINUS4);
+               tssi_bounds[1] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A1_MINUS3);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
+               tssi_bounds[2] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A2_MINUS2);
+               tssi_bounds[3] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A2_MINUS1);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
+               tssi_bounds[4] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A3_REF);
+               tssi_bounds[5] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A3_PLUS1);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
+               tssi_bounds[6] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A4_PLUS2);
+               tssi_bounds[7] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A4_PLUS3);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
+               tssi_bounds[8] = rt2x00_get_field16(eeprom,
+                                       EEPROM_TSSI_BOUND_A5_PLUS4);
+
+               step = rt2x00_get_field16(eeprom,
+                                         EEPROM_TSSI_BOUND_A5_AGC_STEP);
+       }
+
+       /*
+        * Check if temperature compensation is supported.
+        */
+       if (tssi_bounds[4] == 0xff || step == 0xff)
+               return 0;
+
+       /*
+        * Read current TSSI (BBP 49).
+        */
+       rt2800_bbp_read(rt2x00dev, 49, &current_tssi);
+
+       /*
+        * Compare TSSI value (BBP49) with the compensation boundaries
+        * from the EEPROM and increase or decrease tx power.
+        */
+       for (i = 0; i <= 3; i++) {
+               if (current_tssi > tssi_bounds[i])
+                       break;
+       }
+
+       if (i == 4) {
+               for (i = 8; i >= 5; i--) {
+                       if (current_tssi < tssi_bounds[i])
+                               break;
+               }
+       }
+
+       return (i - 4) * step;
+}
+
+static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
+                                     enum ieee80211_band band)
+{
+       u16 eeprom;
+       u8 comp_en;
+       u8 comp_type;
+       int comp_value = 0;
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+
+       /*
+        * HT40 compensation not required.
+        */
+       if (eeprom == 0xffff ||
+           !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+               return 0;
+
+       if (band == IEEE80211_BAND_2GHZ) {
+               comp_en = rt2x00_get_field16(eeprom,
+                                EEPROM_TXPOWER_DELTA_ENABLE_2G);
+               if (comp_en) {
+                       comp_type = rt2x00_get_field16(eeprom,
+                                          EEPROM_TXPOWER_DELTA_TYPE_2G);
+                       comp_value = rt2x00_get_field16(eeprom,
+                                           EEPROM_TXPOWER_DELTA_VALUE_2G);
+                       if (!comp_type)
+                               comp_value = -comp_value;
+               }
+       } else {
+               comp_en = rt2x00_get_field16(eeprom,
+                                EEPROM_TXPOWER_DELTA_ENABLE_5G);
+               if (comp_en) {
+                       comp_type = rt2x00_get_field16(eeprom,
+                                          EEPROM_TXPOWER_DELTA_TYPE_5G);
+                       comp_value = rt2x00_get_field16(eeprom,
+                                           EEPROM_TXPOWER_DELTA_VALUE_5G);
+                       if (!comp_type)
+                               comp_value = -comp_value;
+               }
+       }
+
+       return comp_value;
+}
+
+static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
+                                       int power_level, int max_power)
+{
+       int delta;
+
+       if (rt2x00_has_cap_power_limit(rt2x00dev))
+               return 0;
+
+       /*
+        * XXX: We don't know the maximum transmit power of our hardware since
+        * the EEPROM doesn't expose it. We only know that we are calibrated
+        * to 100% tx power.
+        *
+        * Hence, we assume the regulatory limit that cfg80211 calulated for
+        * the current channel is our maximum and if we are requested to lower
+        * the value we just reduce our tx power accordingly.
+        */
+       delta = power_level - max_power;
+       return min(delta, 0);
+}
+
+static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
+                                  enum ieee80211_band band, int power_level,
+                                  u8 txpower, int delta)
+{
+       u16 eeprom;
+       u8 criterion;
+       u8 eirp_txpower;
+       u8 eirp_txpower_criterion;
+       u8 reg_limit;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return min_t(u8, txpower, 0xc);
+
+       if (rt2x00_has_cap_power_limit(rt2x00dev)) {
+               /*
+                * Check if eirp txpower exceed txpower_limit.
+                * We use OFDM 6M as criterion and its eirp txpower
+                * is stored at EEPROM_EIRP_MAX_TX_POWER.
+                * .11b data rate need add additional 4dbm
+                * when calculating eirp txpower.
+                */
+               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                             1, &eeprom);
+               criterion = rt2x00_get_field16(eeprom,
+                                              EEPROM_TXPOWER_BYRATE_RATE0);
+
+               rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
+                                  &eeprom);
+
+               if (band == IEEE80211_BAND_2GHZ)
+                       eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+                                                EEPROM_EIRP_MAX_TX_POWER_2GHZ);
+               else
+                       eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+                                                EEPROM_EIRP_MAX_TX_POWER_5GHZ);
+
+               eirp_txpower = eirp_txpower_criterion + (txpower - criterion) +
+                              (is_rate_b ? 4 : 0) + delta;
+
+               reg_limit = (eirp_txpower > power_level) ?
+                                       (eirp_txpower - power_level) : 0;
+       } else
+               reg_limit = 0;
+
+       txpower = max(0, txpower + delta - reg_limit);
+       return min_t(u8, txpower, 0xc);
+}
+
+
+enum {
+       TX_PWR_CFG_0_IDX,
+       TX_PWR_CFG_1_IDX,
+       TX_PWR_CFG_2_IDX,
+       TX_PWR_CFG_3_IDX,
+       TX_PWR_CFG_4_IDX,
+       TX_PWR_CFG_5_IDX,
+       TX_PWR_CFG_6_IDX,
+       TX_PWR_CFG_7_IDX,
+       TX_PWR_CFG_8_IDX,
+       TX_PWR_CFG_9_IDX,
+       TX_PWR_CFG_0_EXT_IDX,
+       TX_PWR_CFG_1_EXT_IDX,
+       TX_PWR_CFG_2_EXT_IDX,
+       TX_PWR_CFG_3_EXT_IDX,
+       TX_PWR_CFG_4_EXT_IDX,
+       TX_PWR_CFG_IDX_COUNT,
+};
+
+static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_channel *chan,
+                                        int power_level)
+{
+       u8 txpower;
+       u16 eeprom;
+       u32 regs[TX_PWR_CFG_IDX_COUNT];
+       unsigned int offset;
+       enum ieee80211_band band = chan->band;
+       int delta;
+       int i;
+
+       memset(regs, '\0', sizeof(regs));
+
+       /* TODO: adapt TX power reduction from the rt28xx code */
+
+       /* calculate temperature compensation delta */
+       delta = rt2800_get_gain_calibration_delta(rt2x00dev);
+
+       if (band == IEEE80211_BAND_5GHZ)
+               offset = 16;
+       else
+               offset = 0;
+
+       if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+               offset += 8;
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset, &eeprom);
+
+       /* CCK 1MBS,2MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_CCK1_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_CCK1_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+                          TX_PWR_CFG_0_EXT_CCK1_CH2, txpower);
+
+       /* CCK 5.5MBS,11MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_CCK5_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_CCK5_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+                          TX_PWR_CFG_0_EXT_CCK5_CH2, txpower);
+
+       /* OFDM 6MBS,9MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_OFDM6_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_OFDM6_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+                          TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower);
+
+       /* OFDM 12MBS,18MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_OFDM12_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
+                          TX_PWR_CFG_0_OFDM12_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
+                          TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 1, &eeprom);
+
+       /* OFDM 24MBS,36MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_OFDM24_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_OFDM24_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+                          TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower);
+
+       /* OFDM 48MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_OFDM48_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_OFDM48_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+                          TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower);
+
+       /* OFDM 54MBS */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_OFDM54_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_OFDM54_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_OFDM54_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 2, &eeprom);
+
+       /* MCS 0,1 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_MCS0_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_MCS0_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+                          TX_PWR_CFG_1_EXT_MCS0_CH2, txpower);
+
+       /* MCS 2,3 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_MCS2_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
+                          TX_PWR_CFG_1_MCS2_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
+                          TX_PWR_CFG_1_EXT_MCS2_CH2, txpower);
+
+       /* MCS 4,5 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS4_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS4_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+                          TX_PWR_CFG_2_EXT_MCS4_CH2, txpower);
+
+       /* MCS 6 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS6_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS6_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+                          TX_PWR_CFG_2_EXT_MCS6_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 3, &eeprom);
+
+       /* MCS 7 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_MCS7_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_MCS7_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
+                          TX_PWR_CFG_7_MCS7_CH2, txpower);
+
+       /* MCS 8,9 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS8_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS8_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+                          TX_PWR_CFG_2_EXT_MCS8_CH2, txpower);
+
+       /* MCS 10,11 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS10_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
+                          TX_PWR_CFG_2_MCS10_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
+                          TX_PWR_CFG_2_EXT_MCS10_CH2, txpower);
+
+       /* MCS 12,13 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_MCS12_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_MCS12_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+                          TX_PWR_CFG_3_EXT_MCS12_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 4, &eeprom);
+
+       /* MCS 14 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_MCS14_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_MCS14_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+                          TX_PWR_CFG_3_EXT_MCS14_CH2, txpower);
+
+       /* MCS 15 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS15_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS15_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS15_CH2, txpower);
+
+       /* MCS 16,17 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS16_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS16_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS16_CH2, txpower);
+
+       /* MCS 18,19 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS18_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS18_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
+                          TX_PWR_CFG_5_MCS18_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 5, &eeprom);
+
+       /* MCS 20,21 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS20_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS20_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS20_CH2, txpower);
+
+       /* MCS 22 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS22_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS22_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
+                          TX_PWR_CFG_6_MCS22_CH2, txpower);
+
+       /* MCS 23 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS23_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS23_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
+                          TX_PWR_CFG_8_MCS23_CH2, txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 6, &eeprom);
+
+       /* STBC, MCS 0,1 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_STBC0_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_STBC0_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+                          TX_PWR_CFG_3_EXT_STBC0_CH2, txpower);
+
+       /* STBC, MCS 2,3 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_STBC2_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
+                          TX_PWR_CFG_3_STBC2_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
+                          TX_PWR_CFG_3_EXT_STBC2_CH2, txpower);
+
+       /* STBC, MCS 4,5 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0,
+                          txpower);
+
+       /* STBC, MCS 6 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2,
+                          txpower);
+
+       /* read the next four txpower values */
+       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                     offset + 7, &eeprom);
+
+       /* STBC, MCS 7 */
+       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
+       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
+                                           txpower, delta);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+                          TX_PWR_CFG_9_STBC7_CH0, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+                          TX_PWR_CFG_9_STBC7_CH1, txpower);
+       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
+                          TX_PWR_CFG_9_STBC7_CH2, txpower);
+
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]);
+
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT,
+                             regs[TX_PWR_CFG_0_EXT_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT,
+                             regs[TX_PWR_CFG_1_EXT_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT,
+                             regs[TX_PWR_CFG_2_EXT_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT,
+                             regs[TX_PWR_CFG_3_EXT_IDX]);
+       rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT,
+                             regs[TX_PWR_CFG_4_EXT_IDX]);
+
+       for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++)
+               rt2x00_dbg(rt2x00dev,
+                          "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n",
+                          (band == IEEE80211_BAND_5GHZ) ? '5' : '2',
+                          (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ?
+                                                               '4' : '2',
+                          (i > TX_PWR_CFG_9_IDX) ?
+                                       (i - TX_PWR_CFG_9_IDX - 1) : i,
+                          (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "",
+                          (unsigned long) regs[i]);
+}
+
+/*
+ * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
+ * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
+ * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
+ * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
+ * Reference per rate transmit power values are located in the EEPROM at
+ * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
+ * current conditions (i.e. band, bandwidth, temperature, user settings).
+ */
+static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
+                                        struct ieee80211_channel *chan,
+                                        int power_level)
+{
+       u8 txpower, r1;
+       u16 eeprom;
+       u32 reg, offset;
+       int i, is_rate_b, delta, power_ctrl;
+       enum ieee80211_band band = chan->band;
+
+       /*
+        * Calculate HT40 compensation. For 40MHz we need to add or subtract
+        * value read from EEPROM (different for 2GHz and for 5GHz).
+        */
+       delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
+
+       /*
+        * Calculate temperature compensation. Depends on measurement of current
+        * TSSI (Transmitter Signal Strength Indication) we know TX power (due
+        * to temperature or maybe other factors) is smaller or bigger than
+        * expected. We adjust it, based on TSSI reference and boundaries values
+        * provided in EEPROM.
+        */
+       switch (rt2x00dev->chip.rt) {
+       case RT2860:
+       case RT2872:
+       case RT2883:
+       case RT3070:
+       case RT3071:
+       case RT3090:
+       case RT3572:
+               delta += rt2800_get_gain_calibration_delta(rt2x00dev);
+               break;
+       default:
+               /* TODO: temperature compensation code for other chips. */
+               break;
+       }
+
+       /*
+        * Decrease power according to user settings, on devices with unknown
+        * maximum tx power. For other devices we take user power_level into
+        * consideration on rt2800_compensate_txpower().
+        */
+       delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
+                                             chan->max_power);
+
+       /*
+        * BBP_R1 controls TX power for all rates, it allow to set the following
+        * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
+        *
+        * TODO: we do not use +6 dBm option to do not increase power beyond
+        * regulatory limit, however this could be utilized for devices with
+        * CAPABILITY_POWER_LIMIT.
+        */
+       if (delta <= -12) {
+               power_ctrl = 2;
+               delta += 12;
+       } else if (delta <= -6) {
+               power_ctrl = 1;
+               delta += 6;
+       } else {
+               power_ctrl = 0;
+       }
+       rt2800_bbp_read(rt2x00dev, 1, &r1);
+       rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
+       rt2800_bbp_write(rt2x00dev, 1, r1);
+
+       offset = TX_PWR_CFG_0;
+
+       for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
+               /* just to be safe */
+               if (offset > TX_PWR_CFG_4)
+                       break;
+
+               rt2800_register_read(rt2x00dev, offset, &reg);
+
+               /* read the next four txpower values */
+               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                             i, &eeprom);
+
+               is_rate_b = i ? 0 : 1;
+               /*
+                * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
+                * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE0);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
+                * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE1);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,
+                * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE2);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
+                * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE3);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
+
+               /* read the next four txpower values */
+               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
+                                             i + 1, &eeprom);
+
+               is_rate_b = 0;
+               /*
+                * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
+                * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE0);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
+                * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE1);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
+                * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE2);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
+
+               /*
+                * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
+                * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown,
+                * TX_PWR_CFG_4: unknown
+                */
+               txpower = rt2x00_get_field16(eeprom,
+                                            EEPROM_TXPOWER_BYRATE_RATE3);
+               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+                                            power_level, txpower, delta);
+               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
+
+               rt2800_register_write(rt2x00dev, offset, reg);
+
+               /* next TX_PWR_CFG register */
+               offset += 4;
+       }
+}
+
+static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
+                                 struct ieee80211_channel *chan,
+                                 int power_level)
+{
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
+       else
+               rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
+}
+
+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,
+                             rt2x00dev->tx_power);
+}
+EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
+
+void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
+{
+       u32     tx_pin;
+       u8      rfcsr;
+
+       /*
+        * A voltage-controlled oscillator(VCO) is an electronic oscillator
+        * designed to be controlled in oscillation frequency by a voltage
+        * input. Maybe the temperature will affect the frequency of
+        * oscillation to be shifted. The VCO calibration will be called
+        * periodically to adjust the frequency to be precision.
+       */
+
+       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+       tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;
+       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+       switch (rt2x00dev->chip.rf) {
+       case RF2020:
+       case RF3020:
+       case RF3021:
+       case RF3022:
+       case RF3320:
+       case RF3052:
+               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+               rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
+               break;
+       case RF3053:
+       case RF3070:
+       case RF3290:
+       case RF5360:
+       case RF5362:
+       case RF5370:
+       case RF5372:
+       case RF5390:
+       case RF5392:
+               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+               rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+               break;
+       default:
+               return;
+       }
+
+       mdelay(1);
+
+       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
+       if (rt2x00dev->rf_channel <= 14) {
+               switch (rt2x00dev->default_ant.tx_chain_num) {
+               case 3:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1);
+                       /* fall through */
+               case 2:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+                       /* fall through */
+               case 1:
+               default:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
+                       break;
+               }
+       } else {
+               switch (rt2x00dev->default_ant.tx_chain_num) {
+               case 3:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1);
+                       /* fall through */
+               case 2:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
+                       /* fall through */
+               case 1:
+               default:
+                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);
+                       break;
+               }
+       }
+       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+}
+EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
+
+static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+                                     struct rt2x00lib_conf *libconf)
+{
+       u32 reg;
+
+       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
+                          libconf->conf->short_frame_max_tx_count);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
+                          libconf->conf->long_frame_max_tx_count);
+       rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
+}
+
+static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
+
+               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
+                                  libconf->conf->listen_interval - 1);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
+               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+
+               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+       } else {
+               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
+               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
+               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+
+               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+       }
+}
+
+void rt2800_config(struct rt2x00_dev *rt2x00dev,
+                  struct rt2x00lib_conf *libconf,
+                  const unsigned int flags)
+{
+       /* Always recalculate LNA gain before changing configuration */
+       rt2800_config_lna_gain(rt2x00dev, libconf);
+
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
+               rt2800_config_channel(rt2x00dev, libconf->conf,
+                                     &libconf->rf, &libconf->channel);
+               rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
+                                     libconf->conf->power_level);
+       }
+       if (flags & IEEE80211_CONF_CHANGE_POWER)
+               rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
+                                     libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt2800_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt2800_config_ps(rt2x00dev, libconf);
+}
+EXPORT_SYMBOL_GPL(rt2800_config);
+
+/*
+ * Link tuning
+ */
+void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
+{
+       u32 reg;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+       qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
+}
+EXPORT_SYMBOL_GPL(rt2800_link_stats);
+
+static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
+{
+       u8 vgc;
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+               if (rt2x00_rt(rt2x00dev, RT3070) ||
+                   rt2x00_rt(rt2x00dev, RT3071) ||
+                   rt2x00_rt(rt2x00dev, RT3090) ||
+                   rt2x00_rt(rt2x00dev, RT3290) ||
+                   rt2x00_rt(rt2x00dev, RT3390) ||
+                   rt2x00_rt(rt2x00dev, RT3572) ||
+                   rt2x00_rt(rt2x00dev, RT3593) ||
+                   rt2x00_rt(rt2x00dev, RT5390) ||
+                   rt2x00_rt(rt2x00dev, RT5392) ||
+                   rt2x00_rt(rt2x00dev, RT5592))
+                       vgc = 0x1c + (2 * rt2x00dev->lna_gain);
+               else
+                       vgc = 0x2e + rt2x00dev->lna_gain;
+       } else { /* 5GHZ band */
+               if (rt2x00_rt(rt2x00dev, RT3593))
+                       vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
+               else if (rt2x00_rt(rt2x00dev, RT5592))
+                       vgc = 0x24 + (2 * rt2x00dev->lna_gain);
+               else {
+                       if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+                               vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3;
+                       else
+                               vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3;
+               }
+       }
+
+       return vgc;
+}
+
+static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                 struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level != vgc_level) {
+               if (rt2x00_rt(rt2x00dev, RT3572) ||
+                   rt2x00_rt(rt2x00dev, RT3593)) {
+                       rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
+                                                      vgc_level);
+               } else if (rt2x00_rt(rt2x00dev, RT5592)) {
+                       rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a);
+                       rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level);
+               } else {
+                       rt2800_bbp_write(rt2x00dev, 66, vgc_level);
+               }
+
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
+{
+       rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev));
+}
+EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
+
+void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
+                      const u32 count)
+{
+       u8 vgc;
+
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))
+               return;
+
+       /* When RSSI is better than a certain threshold, increase VGC
+        * with a chip specific value in order to improve the balance
+        * between sensibility and noise isolation.
+        */
+
+       vgc = rt2800_get_default_vgc(rt2x00dev);
+
+       switch (rt2x00dev->chip.rt) {
+       case RT3572:
+       case RT3593:
+               if (qual->rssi > -65) {
+                       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)
+                               vgc += 0x20;
+                       else
+                               vgc += 0x10;
+               }
+               break;
+
+       case RT5592:
+               if (qual->rssi > -65)
+                       vgc += 0x20;
+               break;
+
+       default:
+               if (qual->rssi > -80)
+                       vgc += 0x10;
+               break;
+       }
+
+       rt2800_set_vgc(rt2x00dev, qual, vgc);
+}
+EXPORT_SYMBOL_GPL(rt2800_link_tuner);
+
+/*
+ * Initialization functions.
+ */
+static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 eeprom;
+       unsigned int i;
+       int ret;
+
+       rt2800_disable_wpdma(rt2x00dev);
+
+       ret = rt2800_drv_init_registers(rt2x00dev);
+       if (ret)
+               return ret;
+
+       rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+       rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1600);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
+       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+       rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);
+
+       rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, 9);
+       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
+       rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+               if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
+                       rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
+                       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+               }
+
+               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+               if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
+                       rt2x00_set_field32(&reg, LDO0_EN, 1);
+                       rt2x00_set_field32(&reg, LDO_BGSEL, 3);
+                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
+               }
+
+               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+               rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
+               rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
+               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+
+               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+               rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
+               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
+
+               rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
+               rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
+               rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
+               rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
+               rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
+               rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
+
+               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+               rt2x00_set_field32(&reg, PLL_CONTROL, 1);
+               rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
+       }
+
+       if (rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
+
+               if (rt2x00_rt(rt2x00dev, RT3290))
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+                                             0x00000404);
+               else
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+                                             0x00000400);
+
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+                                          &eeprom);
+                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000002c);
+                       else
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000000f);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+               }
+       } else if (rt2x00_rt(rt2x00dev, RT3070)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+               }
+       } else if (rt2800_is_305x_soc(rt2x00dev)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
+       } else if (rt2x00_rt(rt2x00dev, RT3352)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+       } else if (rt2x00_rt(rt2x00dev, RT3572)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+                                          &eeprom);
+                       if (rt2x00_get_field16(eeprom,
+                                              EEPROM_NIC_CONF1_DAC_TEST))
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000001f);
+                       else
+                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                                     0x0000000f);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+                                             0x00000000);
+               }
+       } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+                  rt2x00_rt(rt2x00dev, RT5392) ||
+                  rt2x00_rt(rt2x00dev, RT5592)) {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+       } else {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+       }
+
+       rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
+       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
+       rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
+       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
+       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
+       rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+       rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
+           rt2x00_rt(rt2x00dev, RT2883) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
+               rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
+       else
+               rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
+       rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
+       rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
+       rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
+       rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
+       rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
+       rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
+       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
+       rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
+       rt2800_register_write(rt2x00dev, LED_CFG, reg);
+
+       rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
+
+       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 31);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
+       rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
+       rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 1);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
+       rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
+       rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
+       rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
+       rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
+       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
+       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
+       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, 0);
+       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+       if (rt2x00_is_usb(rt2x00dev)) {
+               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+
+               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
+               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
+               rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+       }
+
+       /*
+        * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
+        * although it is reserved.
+        */
+       rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
+       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
+       rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
+
+       reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+       rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
+
+       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
+       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
+                          IEEE80211_MAX_RTS_THRESHOLD);
+       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
+       rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+       rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
+
+       /*
+        * Usually the CCK SIFS time should be set to 10 and the OFDM SIFS
+        * time should be set to 16. However, the original Ralink driver uses
+        * 16 for both and indeed using a value of 10 for CCK SIFS results in
+        * connection problems with 11g + CTS protection. Hence, use the same
+        * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
+        */
+       rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 314);
+       rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
+       rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+
+       rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
+       /*
+        * ASIC will keep garbage value after boot, clear encryption keys.
+        */
+       for (i = 0; i < 4; i++)
+               rt2800_register_write(rt2x00dev,
+                                        SHARED_KEY_MODE_ENTRY(i), 0);
+
+       for (i = 0; i < 256; i++) {
+               rt2800_config_wcid(rt2x00dev, NULL, i);
+               rt2800_delete_wcid_attr(rt2x00dev, i);
+               rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+       }
+
+       /*
+        * Clear all beacons
+        */
+       for (i = 0; i < 8; i++)
+               rt2800_clear_beacon_register(rt2x00dev, i);
+
+       if (rt2x00_is_usb(rt2x00dev)) {
+               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+               rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
+               rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+       } else if (rt2x00_is_pcie(rt2x00dev)) {
+               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+               rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
+               rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+       }
+
+       rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
+       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
+       rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);
+
+       rt2800_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
+       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
+       rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);
+
+       rt2800_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
+       rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);
+
+       rt2800_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
+       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
+       rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);
+
+       /*
+        * Do not force the BA window size, we use the TXWI to set it
+        */
+       rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
+       rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
+       rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
+       rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
+
+       /*
+        * We must clear the error counters.
+        * These registers are cleared on read,
+        * so we may pass a useless variable to store the value.
+        */
+       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+       rt2800_register_read(rt2x00dev, RX_STA_CNT1, &reg);
+       rt2800_register_read(rt2x00dev, RX_STA_CNT2, &reg);
+       rt2800_register_read(rt2x00dev, TX_STA_CNT0, &reg);
+       rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
+       rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
+
+       /*
+        * Setup leadtime for pre tbtt interrupt to 6ms
+        */
+       rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
+       rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
+       rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
+
+       /*
+        * Set up channel statistics timer
+        */
+       rt2800_register_read(rt2x00dev, CH_TIME_CFG, &reg);
+       rt2x00_set_field32(&reg, CH_TIME_CFG_EIFS_BUSY, 1);
+       rt2x00_set_field32(&reg, CH_TIME_CFG_NAV_BUSY, 1);
+       rt2x00_set_field32(&reg, CH_TIME_CFG_RX_BUSY, 1);
+       rt2x00_set_field32(&reg, CH_TIME_CFG_TX_BUSY, 1);
+       rt2x00_set_field32(&reg, CH_TIME_CFG_TMR_EN, 1);
+       rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg);
+
+       return 0;
+}
+
+static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u32 reg;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
+               if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
+                       return 0;
+
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       /*
+        * BBP was enabled after firmware was loaded,
+        * but we need to reactivate it now.
+        */
+       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       msleep(1);
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2800_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
+{
+       u8 value;
+
+       rt2800_bbp_read(rt2x00dev, 4, &value);
+       rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
+       rt2800_bbp_write(rt2x00dev, 4, value);
+}
+
+static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 142, 1);
+       rt2800_bbp_write(rt2x00dev, 143, 57);
+}
+
+static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)
+{
+       const u8 glrt_table[] = {
+               0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */
+               0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */
+               0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */
+               0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */
+               0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */
+               0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */
+               0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */
+               0x2E, 0x36, 0x30, 0x6E,                                     /* 208 ~ 211 */
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(glrt_table); i++) {
+               rt2800_bbp_write(rt2x00dev, 195, 128 + i);
+               rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]);
+       }
+};
+
+static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 65, 0x2C);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+       rt2800_bbp_write(rt2x00dev, 68, 0x0B);
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+       rt2800_bbp_write(rt2x00dev, 73, 0x10);
+       rt2800_bbp_write(rt2x00dev, 81, 0x37);
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+       rt2800_bbp_write(rt2x00dev, 83, 0x6A);
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+       rt2800_bbp_write(rt2x00dev, 103, 0x00);
+       rt2800_bbp_write(rt2x00dev, 105, 0x05);
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+}
+
+static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)
+{
+       u16 eeprom;
+       u8 value;
+
+       rt2800_bbp_read(rt2x00dev, 138, &value);
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+               value |= 0x20;
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+               value &= ~0x02;
+       rt2800_bbp_write(rt2x00dev, 138, value);
+}
+
+static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x10);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 78, 0x0e);
+       rt2800_bbp_write(rt2x00dev, 80, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x01);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+}
+
+static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
+               rt2800_bbp_write(rt2x00dev, 69, 0x16);
+               rt2800_bbp_write(rt2x00dev, 73, 0x12);
+       } else {
+               rt2800_bbp_write(rt2x00dev, 69, 0x12);
+               rt2800_bbp_write(rt2x00dev, 73, 0x10);
+       }
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 81, 0x37);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
+               rt2800_bbp_write(rt2x00dev, 84, 0x19);
+       else
+               rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 103, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+}
+
+static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x10);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 79, 0x13);
+       rt2800_bbp_write(rt2x00dev, 80, 0x05);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
+           rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+       else
+               rt2800_bbp_write(rt2x00dev, 103, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+       if (rt2x00_rt(rt2x00dev, RT3071) ||
+           rt2x00_rt(rt2x00dev, RT3090))
+               rt2800_disable_unused_dac_adc(rt2x00dev);
+}
+
+static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev)
+{
+       u8 value;
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x13);
+       rt2800_bbp_write(rt2x00dev, 75, 0x46);
+       rt2800_bbp_write(rt2x00dev, 76, 0x28);
+
+       rt2800_bbp_write(rt2x00dev, 77, 0x58);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 74, 0x0b);
+       rt2800_bbp_write(rt2x00dev, 79, 0x18);
+       rt2800_bbp_write(rt2x00dev, 80, 0x09);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x7a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x9a);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x02);
+
+       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x1c);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x03);
+
+       rt2800_bbp_write(rt2x00dev, 128, 0x12);
+
+       rt2800_bbp_write(rt2x00dev, 67, 0x24);
+       rt2800_bbp_write(rt2x00dev, 143, 0x04);
+       rt2800_bbp_write(rt2x00dev, 142, 0x99);
+       rt2800_bbp_write(rt2x00dev, 150, 0x30);
+       rt2800_bbp_write(rt2x00dev, 151, 0x2e);
+       rt2800_bbp_write(rt2x00dev, 152, 0x20);
+       rt2800_bbp_write(rt2x00dev, 153, 0x34);
+       rt2800_bbp_write(rt2x00dev, 154, 0x40);
+       rt2800_bbp_write(rt2x00dev, 155, 0x3b);
+       rt2800_bbp_write(rt2x00dev, 253, 0x04);
+
+       rt2800_bbp_read(rt2x00dev, 47, &value);
+       rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
+       rt2800_bbp_write(rt2x00dev, 47, value);
+
+       /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
+       rt2800_bbp_read(rt2x00dev, 3, &value);
+       rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
+       rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
+       rt2800_bbp_write(rt2x00dev, 3, value);
+}
+
+static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 3, 0x00);
+       rt2800_bbp_write(rt2x00dev, 4, 0x50);
+
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 47, 0x48);
+
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x13);
+       rt2800_bbp_write(rt2x00dev, 75, 0x46);
+       rt2800_bbp_write(rt2x00dev, 76, 0x28);
+
+       rt2800_bbp_write(rt2x00dev, 77, 0x59);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 78, 0x0e);
+       rt2800_bbp_write(rt2x00dev, 80, 0x08);
+       rt2800_bbp_write(rt2x00dev, 81, 0x37);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 88, 0x90);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x02);
+
+       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x34);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x05);
+
+       rt2800_bbp_write(rt2x00dev, 120, 0x50);
+
+       rt2800_bbp_write(rt2x00dev, 137, 0x0f);
+
+       rt2800_bbp_write(rt2x00dev, 163, 0xbd);
+       /* 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_3390(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x10);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 79, 0x13);
+       rt2800_bbp_write(rt2x00dev, 80, 0x05);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+       else
+               rt2800_bbp_write(rt2x00dev, 103, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+       rt2800_disable_unused_dac_adc(rt2x00dev);
+}
+
+static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x10);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 79, 0x13);
+       rt2800_bbp_write(rt2x00dev, 80, 0x05);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x99);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+       rt2800_disable_unused_dac_adc(rt2x00dev);
+}
+
+static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_init_bbp_early(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 79, 0x13);
+       rt2800_bbp_write(rt2x00dev, 80, 0x05);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+       rt2800_bbp_write(rt2x00dev, 137, 0x0f);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x19);
+
+       /* Enable DC filter */
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+}
+
+static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
+{
+       int ant, div_mode;
+       u16 eeprom;
+       u8 value;
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+       rt2800_bbp_write(rt2x00dev, 66, 0x38);
+
+       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 73, 0x13);
+       rt2800_bbp_write(rt2x00dev, 75, 0x46);
+       rt2800_bbp_write(rt2x00dev, 76, 0x28);
+
+       rt2800_bbp_write(rt2x00dev, 77, 0x59);
+
+       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+
+       rt2800_bbp_write(rt2x00dev, 79, 0x13);
+       rt2800_bbp_write(rt2x00dev, 80, 0x05);
+       rt2800_bbp_write(rt2x00dev, 81, 0x33);
+
+       rt2800_bbp_write(rt2x00dev, 82, 0x62);
+
+       rt2800_bbp_write(rt2x00dev, 83, 0x7a);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x9a);
+
+       rt2800_bbp_write(rt2x00dev, 86, 0x38);
+
+       if (rt2x00_rt(rt2x00dev, RT5392))
+               rt2800_bbp_write(rt2x00dev, 88, 0x90);
+
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x02);
+
+       if (rt2x00_rt(rt2x00dev, RT5392)) {
+               rt2800_bbp_write(rt2x00dev, 95, 0x9a);
+               rt2800_bbp_write(rt2x00dev, 98, 0x12);
+       }
+
+       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
+       rt2800_bbp_write(rt2x00dev, 105, 0x3c);
+
+       if (rt2x00_rt(rt2x00dev, RT5390))
+               rt2800_bbp_write(rt2x00dev, 106, 0x03);
+       else if (rt2x00_rt(rt2x00dev, RT5392))
+               rt2800_bbp_write(rt2x00dev, 106, 0x12);
+       else
+               WARN_ON(1);
+
+       rt2800_bbp_write(rt2x00dev, 128, 0x12);
+
+       if (rt2x00_rt(rt2x00dev, RT5392)) {
+               rt2800_bbp_write(rt2x00dev, 134, 0xd0);
+               rt2800_bbp_write(rt2x00dev, 135, 0xf6);
+       }
+
+       rt2800_disable_unused_dac_adc(rt2x00dev);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       div_mode = rt2x00_get_field16(eeprom,
+                                     EEPROM_NIC_CONF1_ANT_DIVERSITY);
+       ant = (div_mode == 3) ? 1 : 0;
+
+       /* check if this is a Bluetooth combo card */
+       if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
+               u32 reg;
+
+               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+               rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
+               rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
+               rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
+               rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 0);
+               if (ant == 0)
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 1);
+               else if (ant == 1)
+                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 1);
+               rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+       }
+
+       /* This chip has hardware antenna diversity*/
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {
+               rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */
+               rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */
+               rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */
+       }
+
+       rt2800_bbp_read(rt2x00dev, 152, &value);
+       if (ant == 0)
+               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
+       else
+               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
+       rt2800_bbp_write(rt2x00dev, 152, value);
+
+       rt2800_init_freq_calibration(rt2x00dev);
+}
+
+static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
+{
+       int ant, div_mode;
+       u16 eeprom;
+       u8 value;
+
+       rt2800_init_bbp_early(rt2x00dev);
+
+       rt2800_bbp_read(rt2x00dev, 105, &value);
+       rt2x00_set_field8(&value, BBP105_MLD,
+                         rt2x00dev->default_ant.rx_chain_num == 2);
+       rt2800_bbp_write(rt2x00dev, 105, value);
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 20, 0x06);
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+       rt2800_bbp_write(rt2x00dev, 65, 0x2C);
+       rt2800_bbp_write(rt2x00dev, 68, 0xDD);
+       rt2800_bbp_write(rt2x00dev, 69, 0x1A);
+       rt2800_bbp_write(rt2x00dev, 70, 0x05);
+       rt2800_bbp_write(rt2x00dev, 73, 0x13);
+       rt2800_bbp_write(rt2x00dev, 74, 0x0F);
+       rt2800_bbp_write(rt2x00dev, 75, 0x4F);
+       rt2800_bbp_write(rt2x00dev, 76, 0x28);
+       rt2800_bbp_write(rt2x00dev, 77, 0x59);
+       rt2800_bbp_write(rt2x00dev, 84, 0x9A);
+       rt2800_bbp_write(rt2x00dev, 86, 0x38);
+       rt2800_bbp_write(rt2x00dev, 88, 0x90);
+       rt2800_bbp_write(rt2x00dev, 91, 0x04);
+       rt2800_bbp_write(rt2x00dev, 92, 0x02);
+       rt2800_bbp_write(rt2x00dev, 95, 0x9a);
+       rt2800_bbp_write(rt2x00dev, 98, 0x12);
+       rt2800_bbp_write(rt2x00dev, 103, 0xC0);
+       rt2800_bbp_write(rt2x00dev, 104, 0x92);
+       /* FIXME BBP105 owerwrite */
+       rt2800_bbp_write(rt2x00dev, 105, 0x3C);
+       rt2800_bbp_write(rt2x00dev, 106, 0x35);
+       rt2800_bbp_write(rt2x00dev, 128, 0x12);
+       rt2800_bbp_write(rt2x00dev, 134, 0xD0);
+       rt2800_bbp_write(rt2x00dev, 135, 0xF6);
+       rt2800_bbp_write(rt2x00dev, 137, 0x0F);
+
+       /* Initialize GLRT (Generalized Likehood Radio Test) */
+       rt2800_init_bbp_5592_glrt(rt2x00dev);
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+       div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
+       ant = (div_mode == 3) ? 1 : 0;
+       rt2800_bbp_read(rt2x00dev, 152, &value);
+       if (ant == 0) {
+               /* Main antenna */
+               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
+       } else {
+               /* Auxiliary antenna */
+               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
+       }
+       rt2800_bbp_write(rt2x00dev, 152, value);
+
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {
+               rt2800_bbp_read(rt2x00dev, 254, &value);
+               rt2x00_set_field8(&value, BBP254_BIT7, 1);
+               rt2800_bbp_write(rt2x00dev, 254, value);
+       }
+
+       rt2800_init_freq_calibration(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 84, 0x19);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+}
+
+static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (rt2800_is_305x_soc(rt2x00dev))
+               rt2800_init_bbp_305x_soc(rt2x00dev);
+
+       switch (rt2x00dev->chip.rt) {
+       case RT2860:
+       case RT2872:
+       case RT2883:
+               rt2800_init_bbp_28xx(rt2x00dev);
+               break;
+       case RT3070:
+       case RT3071:
+       case RT3090:
+               rt2800_init_bbp_30xx(rt2x00dev);
+               break;
+       case RT3290:
+               rt2800_init_bbp_3290(rt2x00dev);
+               break;
+       case RT3352:
+               rt2800_init_bbp_3352(rt2x00dev);
+               break;
+       case RT3390:
+               rt2800_init_bbp_3390(rt2x00dev);
+               break;
+       case RT3572:
+               rt2800_init_bbp_3572(rt2x00dev);
+               break;
+       case RT3593:
+               rt2800_init_bbp_3593(rt2x00dev);
+               return;
+       case RT5390:
+       case RT5392:
+               rt2800_init_bbp_53xx(rt2x00dev);
+               break;
+       case RT5592:
+               rt2800_init_bbp_5592(rt2x00dev);
+               return;
+       }
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i,
+                                             &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt2800_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+}
+
+static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+       rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
+       rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
+}
+
+static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
+                               u8 filter_target)
+{
+       unsigned int i;
+       u8 bbp;
+       u8 rfcsr;
+       u8 passband;
+       u8 stopband;
+       u8 overtuned = 0;
+       u8 rfcsr24 = (bw40) ? 0x27 : 0x07;
+
+       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+
+       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
+       rt2800_bbp_write(rt2x00dev, 4, bbp);
+
+       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
+       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
+       rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+       /*
+        * Set power & frequency of passband test tone
+        */
+       rt2800_bbp_write(rt2x00dev, 24, 0);
+
+       for (i = 0; i < 100; i++) {
+               rt2800_bbp_write(rt2x00dev, 25, 0x90);
+               msleep(1);
+
+               rt2800_bbp_read(rt2x00dev, 55, &passband);
+               if (passband)
+                       break;
+       }
+
+       /*
+        * Set power & frequency of stopband test tone
+        */
+       rt2800_bbp_write(rt2x00dev, 24, 0x06);
+
+       for (i = 0; i < 100; i++) {
+               rt2800_bbp_write(rt2x00dev, 25, 0x90);
+               msleep(1);
+
+               rt2800_bbp_read(rt2x00dev, 55, &stopband);
+
+               if ((passband - stopband) <= filter_target) {
+                       rfcsr24++;
+                       overtuned += ((passband - stopband) == filter_target);
+               } else
+                       break;
+
+               rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+       }
+
+       rfcsr24 -= !!overtuned;
+
+       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+       return rfcsr24;
+}
+
+static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
+                                      const unsigned int rf_reg)
+{
+       u8 rfcsr;
+
+       rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
+       rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
+       rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+       msleep(1);
+       rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0);
+       rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+}
+
+static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 filter_tgt_bw20;
+       u8 filter_tgt_bw40;
+       u8 rfcsr, bbp;
+
+       /*
+        * TODO: sync filter_tgt values with vendor driver
+        */
+       if (rt2x00_rt(rt2x00dev, RT3070)) {
+               filter_tgt_bw20 = 0x16;
+               filter_tgt_bw40 = 0x19;
+       } else {
+               filter_tgt_bw20 = 0x13;
+               filter_tgt_bw40 = 0x15;
+       }
+
+       drv_data->calibration_bw20 =
+               rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20);
+       drv_data->calibration_bw40 =
+               rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);
+
+       /*
+        * Save BBP 25 & 26 values for later use in channel switching (for 3052)
+        */
+       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
+       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+
+       /*
+        * Set back to initial state
+        */
+       rt2800_bbp_write(rt2x00dev, 24, 0);
+
+       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+       rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+       /*
+        * Set BBP back to BW20
+        */
+       rt2800_bbp_read(rt2x00dev, 4, &bbp);
+       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+       rt2800_bbp_write(rt2x00dev, 4, bbp);
+}
+
+static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 min_gain, rfcsr, bbp;
+       u16 eeprom;
+
+       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+
+       rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+       if (rt2x00_rt(rt2x00dev, RT3070) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+               if (!rt2x00_has_cap_external_lna_bg(rt2x00dev))
+                       rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+       }
+
+       min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;
+       if (drv_data->txmixer_gain_24g >= min_gain) {
+               rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+                                 drv_data->txmixer_gain_24g);
+       }
+
+       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+       if (rt2x00_rt(rt2x00dev, RT3090)) {
+               /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
+               rt2800_bbp_read(rt2x00dev, 138, &bbp);
+               rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+                       rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+                       rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
+               rt2800_bbp_write(rt2x00dev, 138, bbp);
+       }
+
+       if (rt2x00_rt(rt2x00dev, RT3070)) {
+               rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
+                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
+               else
+                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
+               rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
+       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+                  rt2x00_rt(rt2x00dev, RT3090) ||
+                  rt2x00_rt(rt2x00dev, RT3390)) {
+               rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+               rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+               rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
+
+               rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+
+               rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
+               rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
+       }
+}
+
+static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u8 rfcsr;
+       u8 tx_gain;
+
+       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+       tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g,
+                                   RFCSR17_TXMIXER_GAIN);
+       rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain);
+       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+       /* TODO: enable stream mode */
+}
+
+static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
+{
+       u8 reg;
+       u16 eeprom;
+
+       /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
+       rt2800_bbp_read(rt2x00dev, 138, &reg);
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+               rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+               rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
+       rt2800_bbp_write(rt2x00dev, 138, reg);
+
+       rt2800_rfcsr_read(rt2x00dev, 38, &reg);
+       rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 38, reg);
+
+       rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+       rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
+       rt2800_rfcsr_write(rt2x00dev, 39, reg);
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_rfcsr_read(rt2x00dev, 30, &reg);
+       rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
+       rt2800_rfcsr_write(rt2x00dev, 30, reg);
+}
+
+static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
+       rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
+       rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
+}
+
+static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
+{
+       u8 rfcsr;
+       u16 eeprom;
+       u32 reg;
+
+       /* XXX vendor driver do this only for 3070 */
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x60);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x41);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x7b);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
+       rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+                  rt2x00_rt(rt2x00dev, RT3090)) {
+               rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+
+               rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+               rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+               rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
+                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
+                                          &eeprom);
+                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
+                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+                       else
+                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+               }
+               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+               rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+               rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+               rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+       }
+
+       rt2800_rx_filter_calibration(rt2x00dev);
+
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E))
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
+{
+       u8 rfcsr;
+
+       rt2800_rf_init_calibration(rt2x00dev, 2);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+       rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+       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, 0x05);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+       rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
+       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
+       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+       rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+       rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+       rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
+       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+       rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
+
+       rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
+       rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x18);
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x33);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0xd2);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x5a);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0x01);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x45);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x03);
+       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, 0x01);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
+       rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
+       rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
+       rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
+       rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
+       rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
+       rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
+       rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 46, 0xdd);
+       rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
+       rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
+       rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
+       rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
+       rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
+       rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
+       rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
+       rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
+       rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
+       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);
+
+       rt2800_rx_filter_calibration(rt2x00dev);
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
+       rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x62);
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x8b);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x42);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x34);
+       rt2800_rfcsr_write(rt2x00dev, 8, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x61);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x3b);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0xe0);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0xe0);
+       rt2800_rfcsr_write(rt2x00dev, 17, 0x94);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x5c);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x4a);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0xb2);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0xf6);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x14);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x41);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+
+       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+       rt2800_rx_filter_calibration(rt2x00dev);
+
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
+{
+       u8 rfcsr;
+       u32 reg;
+
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
+       rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
+
+       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+       msleep(1);
+       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+       rt2800_rx_filter_calibration(rt2x00dev);
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+}
+
+static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
+{
+       u8 bbp;
+       bool txbf_enabled = false; /* FIXME */
+
+       rt2800_bbp_read(rt2x00dev, 105, &bbp);
+       if (rt2x00dev->default_ant.rx_chain_num == 1)
+               rt2x00_set_field8(&bbp, BBP105_MLD, 0);
+       else
+               rt2x00_set_field8(&bbp, BBP105_MLD, 1);
+       rt2800_bbp_write(rt2x00dev, 105, bbp);
+
+       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+       rt2800_bbp_write(rt2x00dev, 92, 0x02);
+       rt2800_bbp_write(rt2x00dev, 82, 0x82);
+       rt2800_bbp_write(rt2x00dev, 106, 0x05);
+       rt2800_bbp_write(rt2x00dev, 104, 0x92);
+       rt2800_bbp_write(rt2x00dev, 88, 0x90);
+       rt2800_bbp_write(rt2x00dev, 148, 0xc8);
+       rt2800_bbp_write(rt2x00dev, 47, 0x48);
+       rt2800_bbp_write(rt2x00dev, 120, 0x50);
+
+       if (txbf_enabled)
+               rt2800_bbp_write(rt2x00dev, 163, 0xbd);
+       else
+               rt2800_bbp_write(rt2x00dev, 163, 0x9d);
+
+       /* SNR mapping */
+       rt2800_bbp_write(rt2x00dev, 142, 6);
+       rt2800_bbp_write(rt2x00dev, 143, 160);
+       rt2800_bbp_write(rt2x00dev, 142, 7);
+       rt2800_bbp_write(rt2x00dev, 143, 161);
+       rt2800_bbp_write(rt2x00dev, 142, 8);
+       rt2800_bbp_write(rt2x00dev, 143, 162);
+
+       /* ADC/DAC control */
+       rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
+       /* RX AGC energy lower bound in log2 */
+       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+       /* FIXME: BBP 105 owerwrite? */
+       rt2800_bbp_write(rt2x00dev, 105, 0x04);
+
+}
+
+static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u32 reg;
+       u8 rfcsr;
+
+       /* Disable GPIO #4 and #7 function for LAN PE control */
+       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+       rt2x00_set_field32(&reg, GPIO_SWITCH_4, 0);
+       rt2x00_set_field32(&reg, GPIO_SWITCH_7, 0);
+       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+       /* Initialize default register values */
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
+       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x4e);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 32, 0x78);
+       rt2800_rfcsr_write(rt2x00dev, 33, 0x3b);
+       rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0xe0);
+       rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
+       rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
+       rt2800_rfcsr_write(rt2x00dev, 44, 0xd3);
+       rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
+       rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
+       rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
+       rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
+       rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
+       rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+       rt2800_rfcsr_write(rt2x00dev, 53, 0x18);
+       rt2800_rfcsr_write(rt2x00dev, 54, 0x18);
+       rt2800_rfcsr_write(rt2x00dev, 55, 0x18);
+       rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
+       rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
+
+       /* Initiate calibration */
+       /* TODO: use rt2800_rf_init_calibration ? */
+       rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
+       rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
+       rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1);
+       rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
+
+       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+       usleep_range(1000, 1500);
+       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+       /* Set initial values for RX filter calibration */
+       drv_data->calibration_bw20 = 0x1f;
+       drv_data->calibration_bw40 = 0x2f;
+
+       /* Save BBP 25 & 26 values for later use in channel switching */
+       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
+       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+       rt2800_normal_mode_setup_3593(rt2x00dev);
+
+       rt3593_post_bbp_init(rt2x00dev);
+
+       /* TODO: enable stream mode support */
+}
+
+static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_rf_init_calibration(rt2x00dev, 2);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
+
+       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+       if (rt2x00_is_usb(rt2x00dev) &&
+           rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+
+       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+       rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);
+       rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);
+       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 46, 0x7b);
+       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
+
+       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 53, 0x84);
+       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+       rt2800_rfcsr_write(rt2x00dev, 55, 0x44);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 56, 0x42);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
+       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+       rt2800_rfcsr_write(rt2x00dev, 59, 0x8f);
+
+       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
+               else
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd5);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
+               else
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xb5);
+       }
+       rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+       rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_rf_init_calibration(rt2x00dev, 2);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x4d);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0x8d);
+       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 23, 0x0b);
+       rt2800_rfcsr_write(rt2x00dev, 24, 0x44);
+       rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+       rt2800_rfcsr_write(rt2x00dev, 32, 0x20);
+       rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
+       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
+       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+       rt2800_rfcsr_write(rt2x00dev, 40, 0x0f);
+       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+       rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
+       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+       rt2800_rfcsr_write(rt2x00dev, 47, 0x0c);
+       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
+       rt2800_rfcsr_write(rt2x00dev, 50, 0x94);
+       rt2800_rfcsr_write(rt2x00dev, 51, 0x3a);
+       rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
+       rt2800_rfcsr_write(rt2x00dev, 53, 0x44);
+       rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
+       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+       rt2800_rfcsr_write(rt2x00dev, 56, 0xa1);
+       rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
+       rt2800_rfcsr_write(rt2x00dev, 59, 0x07);
+       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+       rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
+       rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
+       rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+
+       rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_rf_init_calibration(rt2x00dev, 30);
+
+       rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
+       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 6, 0xE4);
+       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+       rt2800_rfcsr_write(rt2x00dev, 19, 0x4D);
+       rt2800_rfcsr_write(rt2x00dev, 20, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 21, 0x8D);
+       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+       rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
+       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+       rt2800_rfcsr_write(rt2x00dev, 47, 0x0C);
+       rt2800_rfcsr_write(rt2x00dev, 53, 0x22);
+       rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+
+       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+       msleep(1);
+
+       rt2800_adjust_freq_offset(rt2x00dev);
+
+       /* Enable DC filter */
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+
+       rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+       if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
+               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+       rt2800_led_open_drain_enable(rt2x00dev);
+}
+
+static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+{
+       if (rt2800_is_305x_soc(rt2x00dev)) {
+               rt2800_init_rfcsr_305x_soc(rt2x00dev);
+               return;
+       }
+
+       switch (rt2x00dev->chip.rt) {
+       case RT3070:
+       case RT3071:
+       case RT3090:
+               rt2800_init_rfcsr_30xx(rt2x00dev);
+               break;
+       case RT3290:
+               rt2800_init_rfcsr_3290(rt2x00dev);
+               break;
+       case RT3352:
+               rt2800_init_rfcsr_3352(rt2x00dev);
+               break;
+       case RT3390:
+               rt2800_init_rfcsr_3390(rt2x00dev);
+               break;
+       case RT3572:
+               rt2800_init_rfcsr_3572(rt2x00dev);
+               break;
+       case RT3593:
+               rt2800_init_rfcsr_3593(rt2x00dev);
+               break;
+       case RT5390:
+               rt2800_init_rfcsr_5390(rt2x00dev);
+               break;
+       case RT5392:
+               rt2800_init_rfcsr_5392(rt2x00dev);
+               break;
+       case RT5592:
+               rt2800_init_rfcsr_5592(rt2x00dev);
+               break;
+       }
+}
+
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 word;
+
+       /*
+        * Initialize MAC registers.
+        */
+       if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
+                    rt2800_init_registers(rt2x00dev)))
+               return -EIO;
+
+       /*
+        * Wait BBP/RF to wake up.
+        */
+       if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
+               return -EIO;
+
+       /*
+        * Send signal during boot time to initialize firmware.
+        */
+       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       if (rt2x00_is_usb(rt2x00dev))
+               rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+       rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+       msleep(1);
+
+       /*
+        * Make sure BBP is up and running.
+        */
+       if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))
+               return -EIO;
+
+       /*
+        * Initialize BBP/RF registers.
+        */
+       rt2800_init_bbp(rt2x00dev);
+       rt2800_init_rfcsr(rt2x00dev);
+
+       if (rt2x00_is_usb(rt2x00dev) &&
+           (rt2x00_rt(rt2x00dev, RT3070) ||
+            rt2x00_rt(rt2x00dev, RT3071) ||
+            rt2x00_rt(rt2x00dev, RT3572))) {
+               udelay(200);
+               rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
+               udelay(10);
+       }
+
+       /*
+        * Enable RX.
+        */
+       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+       udelay(50);
+
+       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
+       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+       /*
+        * Initialize LED control
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
+       rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
+                          word & 0xff, (word >> 8) & 0xff);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
+       rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
+                          word & 0xff, (word >> 8) & 0xff);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
+       rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
+                          word & 0xff, (word >> 8) & 0xff);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_enable_radio);
+
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2800_disable_wpdma(rt2x00dev);
+
+       /* Wait for DMA, ignore error */
+       rt2800_wait_wpdma_ready(rt2x00dev);
+
+       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_disable_radio);
+
+int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 efuse_ctrl_reg;
+
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               efuse_ctrl_reg = EFUSE_CTRL_3290;
+       else
+               efuse_ctrl_reg = EFUSE_CTRL;
+
+       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
+       return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
+}
+EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
+
+static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
+{
+       u32 reg;
+       u16 efuse_ctrl_reg;
+       u16 efuse_data0_reg;
+       u16 efuse_data1_reg;
+       u16 efuse_data2_reg;
+       u16 efuse_data3_reg;
+
+       if (rt2x00_rt(rt2x00dev, RT3290)) {
+               efuse_ctrl_reg = EFUSE_CTRL_3290;
+               efuse_data0_reg = EFUSE_DATA0_3290;
+               efuse_data1_reg = EFUSE_DATA1_3290;
+               efuse_data2_reg = EFUSE_DATA2_3290;
+               efuse_data3_reg = EFUSE_DATA3_3290;
+       } else {
+               efuse_ctrl_reg = EFUSE_CTRL;
+               efuse_data0_reg = EFUSE_DATA0;
+               efuse_data1_reg = EFUSE_DATA1;
+               efuse_data2_reg = EFUSE_DATA2;
+               efuse_data3_reg = EFUSE_DATA3;
+       }
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
+       rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
+       rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
+       rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
+       rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
+
+       /* Wait until the EEPROM has been loaded */
+       rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
+       /* Apparently the data is read from end to start */
+       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
+       /* The returned value is in CPU order, but eeprom is le */
+       *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
+       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
+       *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+
+       for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
+               rt2800_efuse_read(rt2x00dev, i);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
+
+static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return 0;
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
+       if ((word & 0x00ff) != 0x00ff)
+               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
+
+       return 0;
+}
+
+static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+
+       if (rt2x00_rt(rt2x00dev, RT3593))
+               return 0;
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
+       if ((word & 0x00ff) != 0x00ff)
+               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
+
+       return 0;
+}
+
+static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u16 word;
+       u8 *mac;
+       u8 default_lna_gain;
+       int retval;
+
+       /*
+        * Read the EEPROM.
+        */
+       retval = rt2800_read_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+       } else if (rt2x00_rt(rt2x00dev, RT2860) ||
+                  rt2x00_rt(rt2x00dev, RT2872)) {
+               /*
+                * There is a max of 2 RX streams for RT28x0 series
+                */
+               if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2)
+                       rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+       }
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
+       }
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       if ((word & 0x00ff) == 0x00ff) {
+               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
+       }
+       if ((word & 0xff00) == 0xff00) {
+               rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
+                                  LED_MODE_TXRX_ACTIVITY);
+               rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
+               rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);
+       }
+
+       /*
+        * During the LNA validation we are going to use
+        * lna0 as correct value. Note that EEPROM_LNA
+        * is never validated.
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+       default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
+               rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
+       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
+               rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
+       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
+
+       drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
+
+       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_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,
+                                          default_lna_gain);
+       }
+       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
+
+       drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
+               rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
+       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
+               rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
+       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
+
+       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_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,
+                                          default_lna_gain);
+       }
+       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+       if (rt2x00_rt(rt2x00dev, RT3593)) {
+               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)
+                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+                                          default_lna_gain);
+               if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 ||
+                   rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff)
+                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
+                                          default_lna_gain);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word);
+       }
+
+       return 0;
+}
+
+static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u16 value;
+       u16 eeprom;
+       u16 rf;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+
+       /*
+        * Identify RF chipset by EEPROM value
+        * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
+        * RT53xx: defined in "EEPROM_CHIP_ID" field
+        */
+       if (rt2x00_rt(rt2x00dev, RT3290) ||
+           rt2x00_rt(rt2x00dev, RT5390) ||
+           rt2x00_rt(rt2x00dev, RT5392))
+               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+       else
+               rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
+
+       switch (rf) {
+       case RF2820:
+       case RF2850:
+       case RF2720:
+       case RF2750:
+       case RF3020:
+       case RF2020:
+       case RF3021:
+       case RF3022:
+       case RF3052:
+       case RF3053:
+       case RF3070:
+       case RF3290:
+       case RF3320:
+       case RF3322:
+       case RF5360:
+       case RF5362:
+       case RF5370:
+       case RF5372:
+       case RF5390:
+       case RF5392:
+       case RF5592:
+               break;
+       default:
+               rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
+                          rf);
+               return -ENODEV;
+       }
+
+       rt2x00_set_rf(rt2x00dev, rf);
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx_chain_num =
+           rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);
+       rt2x00dev->default_ant.rx_chain_num =
+           rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
+
+       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+
+       if (rt2x00_rt(rt2x00dev, RT3070) ||
+           rt2x00_rt(rt2x00dev, RT3090) ||
+           rt2x00_rt(rt2x00dev, RT3352) ||
+           rt2x00_rt(rt2x00dev, RT3390)) {
+               value = rt2x00_get_field16(eeprom,
+                               EEPROM_NIC_CONF1_ANT_DIVERSITY);
+               switch (value) {
+               case 0:
+               case 1:
+               case 2:
+                       rt2x00dev->default_ant.tx = ANTENNA_A;
+                       rt2x00dev->default_ant.rx = ANTENNA_A;
+                       break;
+               case 3:
+                       rt2x00dev->default_ant.tx = ANTENNA_A;
+                       rt2x00dev->default_ant.rx = ANTENNA_B;
+                       break;
+               }
+       } else {
+               rt2x00dev->default_ant.tx = ANTENNA_A;
+               rt2x00dev->default_ant.rx = ANTENNA_A;
+       }
+
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {
+               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */
+               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */
+       }
+
+       /*
+        * Determine external LNA informations.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
+
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+
+       /*
+        * Detect if this device has Bluetooth co-existence.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
+               __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
+
+       /*
+        * Read frequency offset and RF programming sequence.
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
+
+       /*
+        * Store led settings, for correct led behaviour.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+       rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
+       rt2x00dev->led_mcu_reg = eeprom;
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       /*
+        * Check if support EIRP tx power limit feature.
+        */
+       rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+
+       if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
+                                       EIRP_MAX_TX_POWER_LIMIT)
+               __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
+
+       return 0;
+}
+
+/*
+ * RF value list for rt28xx
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
+ */
+static const struct rf_channel rf_vals[] = {
+       { 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
+       { 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
+       { 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
+       { 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
+       { 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
+       { 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
+       { 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
+       { 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
+       { 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
+       { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
+       { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
+       { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
+       { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
+       { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
+       { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
+       { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
+       { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
+       { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
+       { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
+       { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
+       { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
+       { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
+       { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
+       { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
+       { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
+       { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
+       { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
+       { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
+       { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
+       { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
+       { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
+       { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
+       { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
+       { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
+       { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
+       { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
+       { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
+       { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
+       { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
+       { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
+
+       /* 802.11 UNII */
+       { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
+       { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
+       { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
+       { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
+       { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
+       { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
+       { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
+       { 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
+       { 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
+       { 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
+       { 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
+
+       /* 802.11 Japan */
+       { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
+       { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
+       { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
+       { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
+       { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
+       { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
+       { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
+};
+
+/*
+ * RF value list for rt3xxx
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053)
+ */
+static const struct rf_channel rf_vals_3x[] = {
+       {1,  241, 2, 2 },
+       {2,  241, 2, 7 },
+       {3,  242, 2, 2 },
+       {4,  242, 2, 7 },
+       {5,  243, 2, 2 },
+       {6,  243, 2, 7 },
+       {7,  244, 2, 2 },
+       {8,  244, 2, 7 },
+       {9,  245, 2, 2 },
+       {10, 245, 2, 7 },
+       {11, 246, 2, 2 },
+       {12, 246, 2, 7 },
+       {13, 247, 2, 2 },
+       {14, 248, 2, 4 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       {36, 0x56, 0, 4},
+       {38, 0x56, 0, 6},
+       {40, 0x56, 0, 8},
+       {44, 0x57, 0, 0},
+       {46, 0x57, 0, 2},
+       {48, 0x57, 0, 4},
+       {52, 0x57, 0, 8},
+       {54, 0x57, 0, 10},
+       {56, 0x58, 0, 0},
+       {60, 0x58, 0, 4},
+       {62, 0x58, 0, 6},
+       {64, 0x58, 0, 8},
+
+       /* 802.11 HyperLan 2 */
+       {100, 0x5b, 0, 8},
+       {102, 0x5b, 0, 10},
+       {104, 0x5c, 0, 0},
+       {108, 0x5c, 0, 4},
+       {110, 0x5c, 0, 6},
+       {112, 0x5c, 0, 8},
+       {116, 0x5d, 0, 0},
+       {118, 0x5d, 0, 2},
+       {120, 0x5d, 0, 4},
+       {124, 0x5d, 0, 8},
+       {126, 0x5d, 0, 10},
+       {128, 0x5e, 0, 0},
+       {132, 0x5e, 0, 4},
+       {134, 0x5e, 0, 6},
+       {136, 0x5e, 0, 8},
+       {140, 0x5f, 0, 0},
+
+       /* 802.11 UNII */
+       {149, 0x5f, 0, 9},
+       {151, 0x5f, 0, 11},
+       {153, 0x60, 0, 1},
+       {157, 0x60, 0, 5},
+       {159, 0x60, 0, 7},
+       {161, 0x60, 0, 9},
+       {165, 0x61, 0, 1},
+       {167, 0x61, 0, 3},
+       {169, 0x61, 0, 5},
+       {171, 0x61, 0, 7},
+       {173, 0x61, 0, 9},
+};
+
+static const struct rf_channel rf_vals_5592_xtal20[] = {
+       /* Channel, N, K, mod, R */
+       {1, 482, 4, 10, 3},
+       {2, 483, 4, 10, 3},
+       {3, 484, 4, 10, 3},
+       {4, 485, 4, 10, 3},
+       {5, 486, 4, 10, 3},
+       {6, 487, 4, 10, 3},
+       {7, 488, 4, 10, 3},
+       {8, 489, 4, 10, 3},
+       {9, 490, 4, 10, 3},
+       {10, 491, 4, 10, 3},
+       {11, 492, 4, 10, 3},
+       {12, 493, 4, 10, 3},
+       {13, 494, 4, 10, 3},
+       {14, 496, 8, 10, 3},
+       {36, 172, 8, 12, 1},
+       {38, 173, 0, 12, 1},
+       {40, 173, 4, 12, 1},
+       {42, 173, 8, 12, 1},
+       {44, 174, 0, 12, 1},
+       {46, 174, 4, 12, 1},
+       {48, 174, 8, 12, 1},
+       {50, 175, 0, 12, 1},
+       {52, 175, 4, 12, 1},
+       {54, 175, 8, 12, 1},
+       {56, 176, 0, 12, 1},
+       {58, 176, 4, 12, 1},
+       {60, 176, 8, 12, 1},
+       {62, 177, 0, 12, 1},
+       {64, 177, 4, 12, 1},
+       {100, 183, 4, 12, 1},
+       {102, 183, 8, 12, 1},
+       {104, 184, 0, 12, 1},
+       {106, 184, 4, 12, 1},
+       {108, 184, 8, 12, 1},
+       {110, 185, 0, 12, 1},
+       {112, 185, 4, 12, 1},
+       {114, 185, 8, 12, 1},
+       {116, 186, 0, 12, 1},
+       {118, 186, 4, 12, 1},
+       {120, 186, 8, 12, 1},
+       {122, 187, 0, 12, 1},
+       {124, 187, 4, 12, 1},
+       {126, 187, 8, 12, 1},
+       {128, 188, 0, 12, 1},
+       {130, 188, 4, 12, 1},
+       {132, 188, 8, 12, 1},
+       {134, 189, 0, 12, 1},
+       {136, 189, 4, 12, 1},
+       {138, 189, 8, 12, 1},
+       {140, 190, 0, 12, 1},
+       {149, 191, 6, 12, 1},
+       {151, 191, 10, 12, 1},
+       {153, 192, 2, 12, 1},
+       {155, 192, 6, 12, 1},
+       {157, 192, 10, 12, 1},
+       {159, 193, 2, 12, 1},
+       {161, 193, 6, 12, 1},
+       {165, 194, 2, 12, 1},
+       {184, 164, 0, 12, 1},
+       {188, 164, 4, 12, 1},
+       {192, 165, 8, 12, 1},
+       {196, 166, 0, 12, 1},
+};
+
+static const struct rf_channel rf_vals_5592_xtal40[] = {
+       /* Channel, N, K, mod, R */
+       {1, 241, 2, 10, 3},
+       {2, 241, 7, 10, 3},
+       {3, 242, 2, 10, 3},
+       {4, 242, 7, 10, 3},
+       {5, 243, 2, 10, 3},
+       {6, 243, 7, 10, 3},
+       {7, 244, 2, 10, 3},
+       {8, 244, 7, 10, 3},
+       {9, 245, 2, 10, 3},
+       {10, 245, 7, 10, 3},
+       {11, 246, 2, 10, 3},
+       {12, 246, 7, 10, 3},
+       {13, 247, 2, 10, 3},
+       {14, 248, 4, 10, 3},
+       {36, 86, 4, 12, 1},
+       {38, 86, 6, 12, 1},
+       {40, 86, 8, 12, 1},
+       {42, 86, 10, 12, 1},
+       {44, 87, 0, 12, 1},
+       {46, 87, 2, 12, 1},
+       {48, 87, 4, 12, 1},
+       {50, 87, 6, 12, 1},
+       {52, 87, 8, 12, 1},
+       {54, 87, 10, 12, 1},
+       {56, 88, 0, 12, 1},
+       {58, 88, 2, 12, 1},
+       {60, 88, 4, 12, 1},
+       {62, 88, 6, 12, 1},
+       {64, 88, 8, 12, 1},
+       {100, 91, 8, 12, 1},
+       {102, 91, 10, 12, 1},
+       {104, 92, 0, 12, 1},
+       {106, 92, 2, 12, 1},
+       {108, 92, 4, 12, 1},
+       {110, 92, 6, 12, 1},
+       {112, 92, 8, 12, 1},
+       {114, 92, 10, 12, 1},
+       {116, 93, 0, 12, 1},
+       {118, 93, 2, 12, 1},
+       {120, 93, 4, 12, 1},
+       {122, 93, 6, 12, 1},
+       {124, 93, 8, 12, 1},
+       {126, 93, 10, 12, 1},
+       {128, 94, 0, 12, 1},
+       {130, 94, 2, 12, 1},
+       {132, 94, 4, 12, 1},
+       {134, 94, 6, 12, 1},
+       {136, 94, 8, 12, 1},
+       {138, 94, 10, 12, 1},
+       {140, 95, 0, 12, 1},
+       {149, 95, 9, 12, 1},
+       {151, 95, 11, 12, 1},
+       {153, 96, 1, 12, 1},
+       {155, 96, 3, 12, 1},
+       {157, 96, 5, 12, 1},
+       {159, 96, 7, 12, 1},
+       {161, 96, 9, 12, 1},
+       {165, 97, 1, 12, 1},
+       {184, 82, 0, 12, 1},
+       {188, 82, 4, 12, 1},
+       {192, 82, 8, 12, 1},
+       {196, 83, 0, 12, 1},
+};
+
+static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *default_power1;
+       char *default_power2;
+       char *default_power3;
+       unsigned int i;
+       u32 reg;
+
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       /*
+        * Initialize all hw fields.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_HT_CCK_RATES);
+       ieee80211_hw_set(rt2x00dev->hw, REPORTS_TX_ACK_STATUS);
+       ieee80211_hw_set(rt2x00dev->hw, AMPDU_AGGREGATION);
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+
+       /*
+        * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
+        * unless we are capable of sending the buffered frames out after the
+        * DTIM transmission using rt2x00lib_beacondone. This will send out
+        * multicast and broadcast traffic immediately instead of buffering it
+        * infinitly and thus dropping it after some time.
+        */
+       if (!rt2x00_is_usb(rt2x00dev))
+               ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2800_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * As rt2800 has a global fallback table we cannot specify
+        * more then one tx rate per frame but since the hw will
+        * try several rates (based on the fallback table) we should
+        * initialize max_report_rates to the maximum number of rates
+        * we are going to try. Otherwise mac80211 will truncate our
+        * reported tx rates and the rc algortihm will end up with
+        * incorrect data.
+        */
+       rt2x00dev->hw->max_rates = 1;
+       rt2x00dev->hw->max_report_rates = 7;
+       rt2x00dev->hw->max_rate_tries = 1;
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+       switch (rt2x00dev->chip.rf) {
+       case RF2720:
+       case RF2820:
+               spec->num_channels = 14;
+               spec->channels = rf_vals;
+               break;
+
+       case RF2750:
+       case RF2850:
+               spec->num_channels = ARRAY_SIZE(rf_vals);
+               spec->channels = rf_vals;
+               break;
+
+       case RF2020:
+       case RF3020:
+       case RF3021:
+       case RF3022:
+       case RF3070:
+       case RF3290:
+       case RF3320:
+       case RF3322:
+       case RF5360:
+       case RF5362:
+       case RF5370:
+       case RF5372:
+       case RF5390:
+       case RF5392:
+               spec->num_channels = 14;
+               spec->channels = rf_vals_3x;
+               break;
+
+       case RF3052:
+       case RF3053:
+               spec->num_channels = ARRAY_SIZE(rf_vals_3x);
+               spec->channels = rf_vals_3x;
+               break;
+
+       case RF5592:
+               rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
+               if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
+                       spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
+                       spec->channels = rf_vals_5592_xtal40;
+               } else {
+                       spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);
+                       spec->channels = rf_vals_5592_xtal20;
+               }
+               break;
+       }
+
+       if (WARN_ON_ONCE(!spec->channels))
+               return -ENODEV;
+
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       if (spec->num_channels > 14)
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+
+       /*
+        * Initialize HT information.
+        */
+       if (!rt2x00_rf(rt2x00dev, RF2020))
+               spec->ht.ht_supported = true;
+       else
+               spec->ht.ht_supported = false;
+
+       spec->ht.cap =
+           IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+           IEEE80211_HT_CAP_GRN_FLD |
+           IEEE80211_HT_CAP_SGI_20 |
+           IEEE80211_HT_CAP_SGI_40;
+
+       if (rt2x00dev->default_ant.tx_chain_num >= 2)
+               spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
+
+       spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num <<
+                       IEEE80211_HT_CAP_RX_STBC_SHIFT;
+
+       spec->ht.ampdu_factor = 3;
+       spec->ht.ampdu_density = 4;
+       spec->ht.mcs.tx_params =
+           IEEE80211_HT_MCS_TX_DEFINED |
+           IEEE80211_HT_MCS_TX_RX_DIFF |
+           ((rt2x00dev->default_ant.tx_chain_num - 1) <<
+            IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+
+       switch (rt2x00dev->default_ant.rx_chain_num) {
+       case 3:
+               spec->ht.mcs.rx_mask[2] = 0xff;
+       case 2:
+               spec->ht.mcs.rx_mask[1] = 0xff;
+       case 1:
+               spec->ht.mcs.rx_mask[0] = 0xff;
+               spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
+               break;
+       }
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
+       default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+
+       if (rt2x00dev->default_ant.tx_chain_num > 2)
+               default_power3 = rt2800_eeprom_addr(rt2x00dev,
+                                                   EEPROM_EXT_TXPOWER_BG3);
+       else
+               default_power3 = NULL;
+
+       for (i = 0; i < 14; i++) {
+               info[i].default_power1 = default_power1[i];
+               info[i].default_power2 = default_power2[i];
+               if (default_power3)
+                       info[i].default_power3 = default_power3[i];
+       }
+
+       if (spec->num_channels > 14) {
+               default_power1 = rt2800_eeprom_addr(rt2x00dev,
+                                                   EEPROM_TXPOWER_A1);
+               default_power2 = rt2800_eeprom_addr(rt2x00dev,
+                                                   EEPROM_TXPOWER_A2);
+
+               if (rt2x00dev->default_ant.tx_chain_num > 2)
+                       default_power3 =
+                               rt2800_eeprom_addr(rt2x00dev,
+                                                  EEPROM_EXT_TXPOWER_A3);
+               else
+                       default_power3 = NULL;
+
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].default_power1 = default_power1[i - 14];
+                       info[i].default_power2 = default_power2[i - 14];
+                       if (default_power3)
+                               info[i].default_power3 = default_power3[i - 14];
+               }
+       }
+
+       switch (rt2x00dev->chip.rf) {
+       case RF2020:
+       case RF3020:
+       case RF3021:
+       case RF3022:
+       case RF3320:
+       case RF3052:
+       case RF3053:
+       case RF3070:
+       case RF3290:
+       case RF5360:
+       case RF5362:
+       case RF5370:
+       case RF5372:
+       case RF5390:
+       case RF5392:
+               __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
+               break;
+       }
+
+       return 0;
+}
+
+static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u32 rt;
+       u32 rev;
+
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+       else
+               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+
+       rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);
+       rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);
+
+       switch (rt) {
+       case RT2860:
+       case RT2872:
+       case RT2883:
+       case RT3070:
+       case RT3071:
+       case RT3090:
+       case RT3290:
+       case RT3352:
+       case RT3390:
+       case RT3572:
+       case RT3593:
+       case RT5390:
+       case RT5392:
+       case RT5592:
+               break;
+       default:
+               rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n",
+                          rt, rev);
+               return -ENODEV;
+       }
+
+       rt2x00_set_rt(rt2x00dev, rt, rev);
+
+       return 0;
+}
+
+int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u32 reg;
+
+       retval = rt2800_probe_rt(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt2800_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt2800_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_DIR2, 1);
+       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt2800_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Set device capabilities.
+        */
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
+       if (!rt2x00_is_usb(rt2x00dev))
+               __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
+
+       /*
+        * Set device requirements.
+        */
+       if (!rt2x00_is_soc(rt2x00dev))
+               __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+       if (!rt2800_hwcrypt_disabled(rt2x00dev))
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
+       if (rt2x00_is_usb(rt2x00dev))
+               __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
+       else {
+               __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+               __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
+       }
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_probe_hw);
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+void rt2800_get_key_seq(struct ieee80211_hw *hw,
+                       struct ieee80211_key_conf *key,
+                       struct ieee80211_key_seq *seq)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct mac_iveiv_entry iveiv_entry;
+       u32 offset;
+
+       if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
+               return;
+
+       offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+       rt2800_register_multiread(rt2x00dev, offset,
+                                     &iveiv_entry, sizeof(iveiv_entry));
+
+       memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2);
+       memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4);
+}
+EXPORT_SYMBOL_GPL(rt2800_get_key_seq);
+
+int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u32 reg;
+       bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
+
+       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
+       rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+       rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
+       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);
+
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+                  struct ieee80211_vif *vif, u16 queue_idx,
+                  const struct ieee80211_tx_queue_params *params)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+       struct rt2x00_field32 field;
+       int retval;
+       u32 reg;
+       u32 offset;
+
+       /*
+        * First pass the configuration through rt2x00lib, that will
+        * update the queue settings and validate the input. After that
+        * we are free to update the registers based on the value
+        * in the queue parameter.
+        */
+       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
+       if (retval)
+               return retval;
+
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues/
+        */
+       if (queue_idx >= 4)
+               return 0;
+
+       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+
+       /* Update WMM TXOP register */
+       offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
+       field.bit_offset = (queue_idx & 1) * 16;
+       field.bit_mask = 0xffff << field.bit_offset;
+
+       rt2800_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field, queue->txop);
+       rt2800_register_write(rt2x00dev, offset, reg);
+
+       /* Update WMM registers */
+       field.bit_offset = queue_idx * 4;
+       field.bit_mask = 0xf << field.bit_offset;
+
+       rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
+       rt2x00_set_field32(&reg, field, queue->aifs);
+       rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_min);
+       rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
+
+       rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_max);
+       rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
+
+       /* Update EDCA registers */
+       offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
+
+       rt2800_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
+       rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
+       rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
+       rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
+       rt2800_register_write(rt2x00dev, offset, reg);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_conf_tx);
+
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u64 tsf;
+       u32 reg;
+
+       rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
+       tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
+       rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
+       tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
+
+       return tsf;
+}
+EXPORT_SYMBOL_GPL(rt2800_get_tsf);
+
+int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       enum ieee80211_ampdu_mlme_action action,
+                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+                       u8 buf_size, bool amsdu)
+{
+       struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
+       int ret = 0;
+
+       /*
+        * Don't allow aggregation for stations the hardware isn't aware
+        * of because tx status reports for frames to an unknown station
+        * always contain wcid=WCID_END+1 and thus we can't distinguish
+        * between multiple stations which leads to unwanted situations
+        * when the hw reorders frames due to aggregation.
+        */
+       if (sta_priv->wcid > WCID_END)
+               return 1;
+
+       switch (action) {
+       case IEEE80211_AMPDU_RX_START:
+       case IEEE80211_AMPDU_RX_STOP:
+               /*
+                * The hw itself takes care of setting up BlockAck mechanisms.
+                * So, we only have to allow mac80211 to nagotiate a BlockAck
+                * agreement. Once that is done, the hw will BlockAck incoming
+                * AMPDUs without further setup.
+                */
+               break;
+       case IEEE80211_AMPDU_TX_START:
+               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               break;
+       case IEEE80211_AMPDU_TX_STOP_CONT:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               break;
+       case IEEE80211_AMPDU_TX_OPERATIONAL:
+               break;
+       default:
+               rt2x00_warn((struct rt2x00_dev *)hw->priv,
+                           "Unknown AMPDU action\n");
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(rt2800_ampdu_action);
+
+int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
+                     struct survey_info *survey)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+       u32 idle, busy, busy_ext;
+
+       if (idx != 0)
+               return -ENOENT;
+
+       survey->channel = conf->chandef.chan;
+
+       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
+       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
+       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
+
+       if (idle || busy) {
+               survey->filled = SURVEY_INFO_TIME |
+                                SURVEY_INFO_TIME_BUSY |
+                                SURVEY_INFO_TIME_EXT_BUSY;
+
+               survey->time = (idle + busy) / 1000;
+               survey->time_busy = busy / 1000;
+               survey->time_ext_busy = busy_ext / 1000;
+       }
+
+       if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+               survey->filled |= SURVEY_INFO_IN_USE;
+
+       return 0;
+
+}
+EXPORT_SYMBOL_GPL(rt2800_get_survey);
+
+MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2800 library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
new file mode 100644 (file)
index 0000000..440790b
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Bartlomiej Zolnierkiewicz
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RT2800LIB_H
+#define RT2800LIB_H
+
+struct rt2800_ops {
+       void (*register_read)(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int offset, u32 *value);
+       void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset, u32 *value);
+       void (*register_write)(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int offset, u32 value);
+       void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int offset, u32 value);
+
+       void (*register_multiread)(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset,
+                                  void *value, const u32 length);
+       void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int offset,
+                                   const void *value, const u32 length);
+
+       int (*regbusy_read)(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int offset,
+                           const struct rt2x00_field32 field, u32 *reg);
+
+       int (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
+       bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
+
+       int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
+                                 const u8 *data, const size_t len);
+       int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
+       __le32 *(*drv_get_txwi)(struct queue_entry *entry);
+};
+
+static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
+                                       const unsigned int offset,
+                                       u32 *value)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_read(rt2x00dev, offset, value);
+}
+
+static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                            const unsigned int offset,
+                                            u32 *value)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_read_lock(rt2x00dev, offset, value);
+}
+
+static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
+                                        const unsigned int offset,
+                                        u32 value)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_write(rt2x00dev, offset, value);
+}
+
+static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
+                                             const unsigned int offset,
+                                             u32 value)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_write_lock(rt2x00dev, offset, value);
+}
+
+static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
+                                            const unsigned int offset,
+                                            void *value, const u32 length)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_multiread(rt2x00dev, offset, value, length);
+}
+
+static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+                                             const unsigned int offset,
+                                             const void *value,
+                                             const u32 length)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
+}
+
+static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                                     const unsigned int offset,
+                                     const struct rt2x00_field32 field,
+                                     u32 *reg)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
+}
+
+static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       return rt2800ops->read_eeprom(rt2x00dev);
+}
+
+static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       return rt2800ops->hwcrypt_disabled(rt2x00dev);
+}
+
+static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
+                                           const u8 *data, const size_t len)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
+}
+
+static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
+       return rt2800ops->drv_init_registers(rt2x00dev);
+}
+
+static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry)
+{
+       const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv;
+
+       return rt2800ops->drv_get_txwi(entry);
+}
+
+void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
+                       const u8 command, const u8 token,
+                       const u8 arg0, const u8 arg1);
+
+int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
+int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
+
+int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
+                         const u8 *data, const size_t len);
+int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
+                        const u8 *data, const size_t len);
+
+void rt2800_write_tx_data(struct queue_entry *entry,
+                         struct txentry_desc *txdesc);
+void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
+
+void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
+
+void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
+void rt2800_clear_beacon(struct queue_entry *entry);
+
+extern const struct rt2x00debug rt2800_rt2x00debug;
+
+int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
+int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00lib_crypto *crypto,
+                            struct ieee80211_key_conf *key);
+int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00lib_crypto *crypto,
+                              struct ieee80211_key_conf *key);
+int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
+                  struct ieee80211_sta *sta);
+int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
+void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
+                         const unsigned int filter_flags);
+void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
+                       struct rt2x00intf_conf *conf, const unsigned int flags);
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
+                      u32 changed);
+void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
+void rt2800_config(struct rt2x00_dev *rt2x00dev,
+                  struct rt2x00lib_conf *libconf,
+                  const unsigned int flags);
+void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
+void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
+void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
+                      const u32 count);
+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
+void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
+
+int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
+
+int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
+int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
+
+int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);
+
+void rt2800_get_key_seq(struct ieee80211_hw *hw,
+                       struct ieee80211_key_conf *key,
+                       struct ieee80211_key_seq *seq);
+int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+int rt2800_conf_tx(struct ieee80211_hw *hw,
+                  struct ieee80211_vif *vif, u16 queue_idx,
+                  const struct ieee80211_tx_queue_params *params);
+u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                       enum ieee80211_ampdu_mlme_action action,
+                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+                       u8 buf_size, bool amsdu);
+int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
+                     struct survey_info *survey);
+void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
+
+void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
+                              unsigned short *txwi_size,
+                              unsigned short *rxwi_size);
+
+#endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
new file mode 100644 (file)
index 0000000..de4790b
--- /dev/null
@@ -0,0 +1,871 @@
+/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+ *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+ *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+ *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+ *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+ *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+ *     <http://rt2x00.serialmonkey.com>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*     Module: rt2800mmio
+ *     Abstract: rt2800 MMIO device routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/export.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2800.h"
+#include "rt2800lib.h"
+#include "rt2800mmio.h"
+
+/*
+ * TX descriptor initialization
+ */
+__le32 *rt2800mmio_get_txwi(struct queue_entry *entry)
+{
+       return (__le32 *) entry->skb->data;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi);
+
+void rt2800mmio_write_tx_desc(struct queue_entry *entry,
+                             struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       __le32 *txd = entry_priv->desc;
+       u32 word;
+       const unsigned int txwi_size = entry->queue->winfo_size;
+
+       /*
+        * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1
+        * must contains a TXWI structure + 802.11 header + padding + 802.11
+        * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and
+        * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11
+        * data. It means that LAST_SEC0 is always 0.
+        */
+
+       /*
+        * Initialize TX descriptor
+        */
+       word = 0;
+       rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
+       rt2x00_desc_write(txd, 0, word);
+
+       word = 0;
+       rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
+       rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
+                          !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W1_BURST,
+                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size);
+       rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
+       rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
+       rt2x00_desc_write(txd, 1, word);
+
+       word = 0;
+       rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
+                          skbdesc->skb_dma + txwi_size);
+       rt2x00_desc_write(txd, 2, word);
+
+       word = 0;
+       rt2x00_set_field32(&word, TXD_W3_WIV,
+                          !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
+       rt2x00_desc_write(txd, 3, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->desc = txd;
+       skbdesc->desc_len = TXD_DESC_SIZE;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc);
+
+/*
+ * RX control handlers
+ */
+void rt2800mmio_fill_rxdone(struct queue_entry *entry,
+                           struct rxdone_entry_desc *rxdesc)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       __le32 *rxd = entry_priv->desc;
+       u32 word;
+
+       rt2x00_desc_read(rxd, 3, &word);
+
+       if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+       /*
+        * Unfortunately we don't know the cipher type used during
+        * decryption. This prevents us from correct providing
+        * correct statistics through debugfs.
+        */
+       rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
+
+       if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
+               /*
+                * Hardware has stripped IV/EIV data from 802.11 frame during
+                * decryption. Unfortunately the descriptor doesn't contain
+                * any fields with the EIV/IV data either, so they can't
+                * be restored by rt2x00lib.
+                */
+               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+               /*
+                * The hardware has already checked the Michael Mic and has
+                * stripped it from the frame. Signal this to mac80211.
+                */
+               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+                       rxdesc->flags |= RX_FLAG_DECRYPTED;
+               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+       }
+
+       if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+       if (rt2x00_get_field32(word, RXD_W3_L2PAD))
+               rxdesc->dev_flags |= RXDONE_L2PAD;
+
+       /*
+        * Process the RXWI structure that is at the start of the buffer.
+        */
+       rt2800_process_rxwi(entry, rxdesc);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone);
+
+/*
+ * Interrupt functions.
+ */
+static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev)
+{
+       struct ieee80211_conf conf = { .flags = 0 };
+       struct rt2x00lib_conf libconf = { .conf = &conf };
+
+       rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+}
+
+static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
+{
+       __le32 *txwi;
+       u32 word;
+       int wcid, tx_wcid;
+
+       wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
+
+       txwi = rt2800_drv_get_txwi(entry);
+       rt2x00_desc_read(txwi, 1, &word);
+       tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+
+       return (tx_wcid == wcid);
+}
+
+static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
+{
+       u32 status = *(u32 *)data;
+
+       /*
+        * rt2800pci hardware might reorder frames when exchanging traffic
+        * with multiple BA enabled STAs.
+        *
+        * For example, a tx queue
+        *    [ STA1 | STA2 | STA1 | STA2 ]
+        * can result in tx status reports
+        *    [ STA1 | STA1 | STA2 | STA2 ]
+        * when the hw decides to aggregate the frames for STA1 into one AMPDU.
+        *
+        * To mitigate this effect, associate the tx status to the first frame
+        * in the tx queue with a matching wcid.
+        */
+       if (rt2800mmio_txdone_entry_check(entry, status) &&
+           !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+               /*
+                * Got a matching frame, associate the tx status with
+                * the frame
+                */
+               entry->status = status;
+               set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+               return true;
+       }
+
+       /* Check the next frame */
+       return false;
+}
+
+static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
+{
+       u32 status = *(u32 *)data;
+
+       /*
+        * Find the first frame without tx status and assign this status to it
+        * regardless if it matches or not.
+        */
+       if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+               /*
+                * Got a matching frame, associate the tx status with
+                * the frame
+                */
+               entry->status = status;
+               set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
+               return true;
+       }
+
+       /* Check the next frame */
+       return false;
+}
+static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
+                                             void *data)
+{
+       if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
+               rt2800_txdone_entry(entry, entry->status,
+                                   rt2800mmio_get_txwi(entry));
+               return false;
+       }
+
+       /* No more frames to release */
+       return true;
+}
+
+static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       u32 status;
+       u8 qid;
+       int max_tx_done = 16;
+
+       while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
+               qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
+               if (unlikely(qid >= QID_RX)) {
+                       /*
+                        * Unknown queue, this shouldn't happen. Just drop
+                        * this tx status.
+                        */
+                       rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
+                                   qid);
+                       break;
+               }
+
+               queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+               if (unlikely(queue == NULL)) {
+                       /*
+                        * The queue is NULL, this shouldn't happen. Stop
+                        * processing here and drop the tx status
+                        */
+                       rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
+                                   qid);
+                       break;
+               }
+
+               if (unlikely(rt2x00queue_empty(queue))) {
+                       /*
+                        * The queue is empty. Stop processing here
+                        * and drop the tx status.
+                        */
+                       rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+                                   qid);
+                       break;
+               }
+
+               /*
+                * Let's associate this tx status with the first
+                * matching frame.
+                */
+               if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+                                               Q_INDEX, &status,
+                                               rt2800mmio_txdone_find_entry)) {
+                       /*
+                        * We cannot match the tx status to any frame, so just
+                        * use the first one.
+                        */
+                       if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+                                                       Q_INDEX, &status,
+                                                       rt2800mmio_txdone_match_first)) {
+                               rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
+                                           qid);
+                               break;
+                       }
+               }
+
+               /*
+                * Release all frames with a valid tx status.
+                */
+               rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
+                                          Q_INDEX, NULL,
+                                          rt2800mmio_txdone_release_entries);
+
+               if (--max_tx_done == 0)
+                       break;
+       }
+
+       return !max_tx_done;
+}
+
+static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                              struct rt2x00_field32 irq_field)
+{
+       u32 reg;
+
+       /*
+        * Enable a single interrupt. The interrupt mask register
+        * access needs locking.
+        */
+       spin_lock_irq(&rt2x00dev->irqmask_lock);
+       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, irq_field, 1);
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+void rt2800mmio_txstatus_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       if (rt2800mmio_txdone(rt2x00dev))
+               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+
+       /*
+        * No need to enable the tx status interrupt here as we always
+        * leave it enabled to minimize the possibility of a tx status
+        * register overflow. See comment in interrupt handler.
+        */
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
+
+void rt2800mmio_pretbtt_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt2x00lib_pretbtt(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet);
+
+void rt2800mmio_tbtt_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+       u32 reg;
+
+       rt2x00lib_beacondone(rt2x00dev);
+
+       if (rt2x00dev->intf_ap_count) {
+               /*
+                * The rt2800pci hardware tbtt timer is off by 1us per tbtt
+                * causing beacon skew and as a result causing problems with
+                * some powersaving clients over time. Shorten the beacon
+                * interval every 64 beacons by 64us to mitigate this effect.
+                */
+               if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
+                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+                       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+                                          (rt2x00dev->beacon_int * 16) - 1);
+                       rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
+                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+                       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+                                          (rt2x00dev->beacon_int * 16));
+                       rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               }
+               drv_data->tbtt_tick++;
+               drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
+       }
+
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet);
+
+void rt2800mmio_rxdone_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       if (rt2x00mmio_rxdone(rt2x00dev))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet);
+
+void rt2800mmio_autowake_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt2800mmio_wakeup(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2800mmio_enable_interrupt(rt2x00dev,
+                                           INT_MASK_CSR_AUTO_WAKEUP);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+
+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+{
+       u32 status;
+       int i;
+
+       /*
+        * The TX_FIFO_STATUS interrupt needs special care. We should
+        * read TX_STA_FIFO but we should do it immediately as otherwise
+        * the register can overflow and we would lose status reports.
+        *
+        * Hence, read the TX_STA_FIFO register and copy all tx status
+        * reports into a kernel FIFO which is handled in the txstatus
+        * tasklet. We use a tasklet to process the tx status reports
+        * because we can schedule the tasklet multiple times (when the
+        * interrupt fires again during tx status processing).
+        *
+        * Furthermore we don't disable the TX_FIFO_STATUS
+        * interrupt here but leave it enabled so that the TX_STA_FIFO
+        * can also be read while the tx status tasklet gets executed.
+        *
+        * 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;
+
+               if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
+                       rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
+                       break;
+               }
+       }
+
+       /* Schedule the tasklet for processing the tx status. */
+       tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+}
+
+irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
+{
+       struct rt2x00_dev *rt2x00dev = dev_instance;
+       u32 reg, mask;
+
+       /* Read status and ACK all interrupts */
+       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+       if (!reg)
+               return IRQ_NONE;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return IRQ_HANDLED;
+
+       /*
+        * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+        * for interrupts and interrupt masks we can just use the value of
+        * INT_SOURCE_CSR to create the interrupt mask.
+        */
+       mask = ~reg;
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+               rt2800mmio_txstatus_interrupt(rt2x00dev);
+               /*
+                * Never disable the TX_FIFO_STATUS interrupt.
+                */
+               rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+       }
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+               tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
+               tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+       /*
+        * Disable all interrupts for which a tasklet was scheduled right now,
+        * the tasklet will reenable the appropriate interrupts.
+        */
+       spin_lock(&rt2x00dev->irqmask_lock);
+       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg &= mask;
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       spin_unlock(&rt2x00dev->irqmask_lock);
+
+       return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_interrupt);
+
+void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
+                          enum dev_state state)
+{
+       u32 reg;
+       unsigned long flags;
+
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+       }
+
+       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+       reg = 0;
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+               rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
+       }
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+       if (state == STATE_RADIO_IRQ_OFF) {
+               /*
+                * Wait for possibly running tasklets to finish.
+                */
+               tasklet_kill(&rt2x00dev->txstatus_tasklet);
+               tasklet_kill(&rt2x00dev->rxdone_tasklet);
+               tasklet_kill(&rt2x00dev->autowake_tasklet);
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+               tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq);
+
+/*
+ * Queue handlers.
+ */
+void rt2800mmio_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+               rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
+               rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
+               rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
+               break;
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
+
+void rt2800mmio_kick_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       struct queue_entry *entry;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+                                         entry->entry_idx);
+               break;
+       case QID_MGMT:
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5),
+                                         entry->entry_idx);
+               break;
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue);
+
+void rt2800mmio_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+               rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+               rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+               rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
+               rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
+
+               /*
+                * Wait for current invocation to finish. The tasklet
+                * won't be scheduled anymore afterwards since we disabled
+                * the TBTT and PRE TBTT timer.
+                */
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+               tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+
+               break;
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_stop_queue);
+
+void rt2800mmio_queue_init(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       unsigned short txwi_size, rxwi_size;
+
+       rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
+
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 128;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->winfo_size = rxwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 64;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 8;
+               queue->data_size = 0; /* No DMA required for beacons */
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_ATIM:
+               /* fallthrough */
+       default:
+               BUG();
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_queue_init);
+
+/*
+ * Initialization functions.
+ */
+bool rt2800mmio_get_entry_state(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+
+               return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE));
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+
+               return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE));
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_get_entry_state);
+
+void rt2800mmio_clear_entry(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
+               rt2x00_desc_write(entry_priv->desc, 1, word);
+
+               /*
+                * Set RX IDX in register to inform hardware that we have
+                * handled this entry and it is available for reuse again.
+                */
+               rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+                                         entry->entry_idx);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 1, &word);
+               rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
+               rt2x00_desc_write(entry_priv->desc, 1, word);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
+
+int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct queue_entry_priv_mmio *entry_priv;
+
+       /*
+        * Initialize registers.
+        */
+       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
+                                 entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
+                                 rt2x00dev->tx[0].limit);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+
+       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
+                                 entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
+                                 rt2x00dev->tx[1].limit);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+
+       entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
+                                 entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
+                                 rt2x00dev->tx[2].limit);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+
+       entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
+                                 entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
+                                 rt2x00dev->tx[3].limit);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0);
+
+       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0);
+
+       entry_priv = rt2x00dev->rx->entries[0].priv_data;
+       rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR,
+                                 entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT,
+                                 rt2x00dev->rx[0].limit);
+       rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+                                 rt2x00dev->rx[0].limit - 1);
+       rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0);
+
+       rt2800_disable_wpdma(rt2x00dev);
+
+       rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_init_queues);
+
+int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       /*
+        * Reset DMA indexes
+        */
+       rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
+       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
+       rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+
+       if (rt2x00_is_pcie(rt2x00dev) &&
+           (rt2x00_rt(rt2x00dev, RT3090) ||
+            rt2x00_rt(rt2x00dev, RT3390) ||
+            rt2x00_rt(rt2x00dev, RT3572) ||
+            rt2x00_rt(rt2x00dev, RT3593) ||
+            rt2x00_rt(rt2x00dev, RT5390) ||
+            rt2x00_rt(rt2x00dev, RT5392) ||
+            rt2x00_rt(rt2x00dev, RT5592))) {
+               rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
+               rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+               rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+               rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
+       }
+
+       rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
+       reg = 0;
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_init_registers);
+
+/*
+ * Device state switch handlers.
+ */
+int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /* Wait for DMA, ignore error until we initialize queues. */
+       rt2800_wait_wpdma_ready(rt2x00dev);
+
+       if (unlikely(rt2800mmio_init_queues(rt2x00dev)))
+               return -EIO;
+
+       return rt2800_enable_radio(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2800 MMIO library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
new file mode 100644 (file)
index 0000000..b63312c
--- /dev/null
@@ -0,0 +1,163 @@
+/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+ *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+ *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+ *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+ *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+ *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+ *     <http://rt2x00.serialmonkey.com>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*     Module: rt2800mmio
+ *     Abstract: forward declarations for the rt2800mmio module.
+ */
+
+#ifndef RT2800MMIO_H
+#define RT2800MMIO_H
+
+/*
+ * Queue register offset macros
+ */
+#define TX_QUEUE_REG_OFFSET    0x10
+#define TX_BASE_PTR(__x)       (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET))
+#define TX_MAX_CNT(__x)                (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET))
+#define TX_CTX_IDX(__x)                (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
+#define TX_DTX_IDX(__x)                (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  (4 * sizeof(__le32))
+#define RXD_DESC_SIZE                  (4 * sizeof(__le32))
+
+/*
+ * TX descriptor format for TX, PRIO and Beacon Ring.
+ */
+
+/*
+ * Word0
+ */
+#define TXD_W0_SD_PTR0                 FIELD32(0xffffffff)
+
+/*
+ * Word1
+ */
+#define TXD_W1_SD_LEN1                 FIELD32(0x00003fff)
+#define TXD_W1_LAST_SEC1               FIELD32(0x00004000)
+#define TXD_W1_BURST                   FIELD32(0x00008000)
+#define TXD_W1_SD_LEN0                 FIELD32(0x3fff0000)
+#define TXD_W1_LAST_SEC0               FIELD32(0x40000000)
+#define TXD_W1_DMA_DONE                        FIELD32(0x80000000)
+
+/*
+ * Word2
+ */
+#define TXD_W2_SD_PTR1                 FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
+ * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
+ *       0:MGMT, 1:HCCA 2:EDCA
+ */
+#define TXD_W3_WIV                     FIELD32(0x01000000)
+#define TXD_W3_QSEL                    FIELD32(0x06000000)
+#define TXD_W3_TCO                     FIELD32(0x20000000)
+#define TXD_W3_UCO                     FIELD32(0x40000000)
+#define TXD_W3_ICO                     FIELD32(0x80000000)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ */
+#define RXD_W0_SDP0                    FIELD32(0xffffffff)
+
+/*
+ * Word1
+ */
+#define RXD_W1_SDL1                    FIELD32(0x00003fff)
+#define RXD_W1_SDL0                    FIELD32(0x3fff0000)
+#define RXD_W1_LS0                     FIELD32(0x40000000)
+#define RXD_W1_DMA_DONE                        FIELD32(0x80000000)
+
+/*
+ * Word2
+ */
+#define RXD_W2_SDP1                    FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * AMSDU: RX with 802.3 header, not 802.11 header.
+ * DECRYPTED: This frame is being decrypted.
+ */
+#define RXD_W3_BA                      FIELD32(0x00000001)
+#define RXD_W3_DATA                    FIELD32(0x00000002)
+#define RXD_W3_NULLDATA                        FIELD32(0x00000004)
+#define RXD_W3_FRAG                    FIELD32(0x00000008)
+#define RXD_W3_UNICAST_TO_ME           FIELD32(0x00000010)
+#define RXD_W3_MULTICAST               FIELD32(0x00000020)
+#define RXD_W3_BROADCAST               FIELD32(0x00000040)
+#define RXD_W3_MY_BSS                  FIELD32(0x00000080)
+#define RXD_W3_CRC_ERROR               FIELD32(0x00000100)
+#define RXD_W3_CIPHER_ERROR            FIELD32(0x00000600)
+#define RXD_W3_AMSDU                   FIELD32(0x00000800)
+#define RXD_W3_HTC                     FIELD32(0x00001000)
+#define RXD_W3_RSSI                    FIELD32(0x00002000)
+#define RXD_W3_L2PAD                   FIELD32(0x00004000)
+#define RXD_W3_AMPDU                   FIELD32(0x00008000)
+#define RXD_W3_DECRYPTED               FIELD32(0x00010000)
+#define RXD_W3_PLCP_SIGNAL             FIELD32(0x00020000)
+#define RXD_W3_PLCP_RSSI               FIELD32(0x00040000)
+
+/* TX descriptor initialization */
+__le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
+void rt2800mmio_write_tx_desc(struct queue_entry *entry,
+                             struct txentry_desc *txdesc);
+
+/* RX control handlers */
+void rt2800mmio_fill_rxdone(struct queue_entry *entry,
+                           struct rxdone_entry_desc *rxdesc);
+
+/* Interrupt functions */
+void rt2800mmio_txstatus_tasklet(unsigned long data);
+void rt2800mmio_pretbtt_tasklet(unsigned long data);
+void rt2800mmio_tbtt_tasklet(unsigned long data);
+void rt2800mmio_rxdone_tasklet(unsigned long data);
+void rt2800mmio_autowake_tasklet(unsigned long data);
+irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance);
+void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
+                          enum dev_state state);
+
+/* Queue handlers */
+void rt2800mmio_start_queue(struct data_queue *queue);
+void rt2800mmio_kick_queue(struct data_queue *queue);
+void rt2800mmio_stop_queue(struct data_queue *queue);
+void rt2800mmio_queue_init(struct data_queue *queue);
+
+/* Initialization functions */
+bool rt2800mmio_get_entry_state(struct queue_entry *entry);
+void rt2800mmio_clear_entry(struct queue_entry *entry);
+int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
+int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev);
+
+/* Device state switch handlers. */
+int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
+
+#endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
new file mode 100644 (file)
index 0000000..0af2257
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+       Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800pci
+       Abstract: rt2800pci device specific routines.
+       Supported chipsets: RT2800E & RT2800ED.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/eeprom_93cx6.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00pci.h"
+#include "rt2800lib.h"
+#include "rt2800mmio.h"
+#include "rt2800.h"
+#include "rt2800pci.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static bool modparam_nohwcrypt = false;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+       return modparam_nohwcrypt;
+}
+
+static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
+{
+       unsigned int i;
+       u32 reg;
+
+       /*
+        * SOC devices don't support MCU requests.
+        */
+       if (rt2x00_is_soc(rt2x00dev))
+               return;
+
+       for (i = 0; i < 200; i++) {
+               rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+
+               if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
+                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
+                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) ||
+                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token))
+                       break;
+
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       if (i == 200)
+               rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
+
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+}
+
+static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+
+       eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
+       eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
+       eeprom->reg_data_clock =
+           !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK);
+       eeprom->reg_chip_select =
+           !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT);
+}
+
+static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg = 0;
+
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in);
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out);
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK,
+                          !!eeprom->reg_data_clock);
+       rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
+                          !!eeprom->reg_chip_select);
+
+       rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
+}
+
+static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
+{
+       struct eeprom_93cx6 eeprom;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+
+       eeprom.data = rt2x00dev;
+       eeprom.register_read = rt2800pci_eepromregister_read;
+       eeprom.register_write = rt2800pci_eepromregister_write;
+       switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
+       {
+       case 0:
+               eeprom.width = PCI_EEPROM_WIDTH_93C46;
+               break;
+       case 1:
+               eeprom.width = PCI_EEPROM_WIDTH_93C66;
+               break;
+       default:
+               eeprom.width = PCI_EEPROM_WIDTH_93C86;
+               break;
+       }
+       eeprom.reg_data_in = 0;
+       eeprom.reg_data_out = 0;
+       eeprom.reg_data_clock = 0;
+       eeprom.reg_chip_select = 0;
+
+       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
+                              EEPROM_SIZE / sizeof(u16));
+
+       return 0;
+}
+
+static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2800_efuse_detect(rt2x00dev);
+}
+
+static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2800_read_eeprom_efuse(rt2x00dev);
+}
+
+/*
+ * Firmware functions
+ */
+static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Chip rt3290 use specific 4KB firmware named rt3290.bin.
+        */
+       if (rt2x00_rt(rt2x00dev, RT3290))
+               return FIRMWARE_RT3290;
+       else
+               return FIRMWARE_RT2860;
+}
+
+static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
+                                   const u8 *data, const size_t len)
+{
+       u32 reg;
+
+       /*
+        * enable Host program ram write selection
+        */
+       reg = 0;
+       rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
+       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+
+       /*
+        * Write firmware to device.
+        */
+       rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+                                      data, len);
+
+       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+
+       rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       retval = rt2800mmio_enable_radio(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /* After resume MCU_BOOT_SIGNAL will trash these. */
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+
+       rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
+       rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
+
+       rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0);
+       rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
+
+       return retval;
+}
+
+static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       if (state == STATE_AWAKE) {
+               rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP,
+                                  0, 0x02);
+               rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
+       } else if (state == STATE_SLEEP) {
+               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+                                         0xffffffff);
+               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
+                                         0xffffffff);
+               rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
+                                  0xff, 0x01);
+       }
+
+       return 0;
+}
+
+static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt2800pci_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               /*
+                * After the radio has been disabled, the device should
+                * be put to sleep for powersaving.
+                */
+               rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt2800mmio_toggle_irq(rt2x00dev, state);
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt2800pci_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       if (rt2800pci_efuse_detect(rt2x00dev))
+               retval = rt2800pci_read_eeprom_efuse(rt2x00dev);
+       else
+               retval = rt2800pci_read_eeprom_pci(rt2x00dev);
+
+       return retval;
+}
+
+static const struct ieee80211_ops rt2800pci_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .get_key_seq            = rt2800_get_key_seq,
+       .set_rts_threshold      = rt2800_set_rts_threshold,
+       .sta_add                = rt2x00mac_sta_add,
+       .sta_remove             = rt2x00mac_sta_remove,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2800_conf_tx,
+       .get_tsf                = rt2800_get_tsf,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .ampdu_action           = rt2800_ampdu_action,
+       .flush                  = rt2x00mac_flush,
+       .get_survey             = rt2800_get_survey,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2800_ops rt2800pci_rt2800_ops = {
+       .register_read          = rt2x00mmio_register_read,
+       .register_read_lock     = rt2x00mmio_register_read, /* same for PCI */
+       .register_write         = rt2x00mmio_register_write,
+       .register_write_lock    = rt2x00mmio_register_write, /* same for PCI */
+       .register_multiread     = rt2x00mmio_register_multiread,
+       .register_multiwrite    = rt2x00mmio_register_multiwrite,
+       .regbusy_read           = rt2x00mmio_regbusy_read,
+       .read_eeprom            = rt2800pci_read_eeprom,
+       .hwcrypt_disabled       = rt2800pci_hwcrypt_disabled,
+       .drv_write_firmware     = rt2800pci_write_firmware,
+       .drv_init_registers     = rt2800mmio_init_registers,
+       .drv_get_txwi           = rt2800mmio_get_txwi,
+};
+
+static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
+       .irq_handler            = rt2800mmio_interrupt,
+       .txstatus_tasklet       = rt2800mmio_txstatus_tasklet,
+       .pretbtt_tasklet        = rt2800mmio_pretbtt_tasklet,
+       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
+       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
+       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
+       .probe_hw               = rt2800_probe_hw,
+       .get_firmware_name      = rt2800pci_get_firmware_name,
+       .check_firmware         = rt2800_check_firmware,
+       .load_firmware          = rt2800_load_firmware,
+       .initialize             = rt2x00mmio_initialize,
+       .uninitialize           = rt2x00mmio_uninitialize,
+       .get_entry_state        = rt2800mmio_get_entry_state,
+       .clear_entry            = rt2800mmio_clear_entry,
+       .set_device_state       = rt2800pci_set_device_state,
+       .rfkill_poll            = rt2800_rfkill_poll,
+       .link_stats             = rt2800_link_stats,
+       .reset_tuner            = rt2800_reset_tuner,
+       .link_tuner             = rt2800_link_tuner,
+       .gain_calibration       = rt2800_gain_calibration,
+       .vco_calibration        = rt2800_vco_calibration,
+       .start_queue            = rt2800mmio_start_queue,
+       .kick_queue             = rt2800mmio_kick_queue,
+       .stop_queue             = rt2800mmio_stop_queue,
+       .flush_queue            = rt2x00mmio_flush_queue,
+       .write_tx_desc          = rt2800mmio_write_tx_desc,
+       .write_tx_data          = rt2800_write_tx_data,
+       .write_beacon           = rt2800_write_beacon,
+       .clear_beacon           = rt2800_clear_beacon,
+       .fill_rxdone            = rt2800mmio_fill_rxdone,
+       .config_shared_key      = rt2800_config_shared_key,
+       .config_pairwise_key    = rt2800_config_pairwise_key,
+       .config_filter          = rt2800_config_filter,
+       .config_intf            = rt2800_config_intf,
+       .config_erp             = rt2800_config_erp,
+       .config_ant             = rt2800_config_ant,
+       .config                 = rt2800_config,
+       .sta_add                = rt2800_sta_add,
+       .sta_remove             = rt2800_sta_remove,
+};
+
+static const struct rt2x00_ops rt2800pci_ops = {
+       .name                   = KBUILD_MODNAME,
+       .drv_data_size          = sizeof(struct rt2800_drv_data),
+       .max_ap_intf            = 8,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2800mmio_queue_init,
+       .lib                    = &rt2800pci_rt2x00_ops,
+       .drv                    = &rt2800pci_rt2800_ops,
+       .hw                     = &rt2800pci_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2800_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * RT2800pci module information.
+ */
+static const struct pci_device_id rt2800pci_device_table[] = {
+       { PCI_DEVICE(0x1814, 0x0601) },
+       { PCI_DEVICE(0x1814, 0x0681) },
+       { PCI_DEVICE(0x1814, 0x0701) },
+       { PCI_DEVICE(0x1814, 0x0781) },
+       { PCI_DEVICE(0x1814, 0x3090) },
+       { PCI_DEVICE(0x1814, 0x3091) },
+       { PCI_DEVICE(0x1814, 0x3092) },
+       { PCI_DEVICE(0x1432, 0x7708) },
+       { PCI_DEVICE(0x1432, 0x7727) },
+       { PCI_DEVICE(0x1432, 0x7728) },
+       { PCI_DEVICE(0x1432, 0x7738) },
+       { PCI_DEVICE(0x1432, 0x7748) },
+       { PCI_DEVICE(0x1432, 0x7758) },
+       { PCI_DEVICE(0x1432, 0x7768) },
+       { PCI_DEVICE(0x1462, 0x891a) },
+       { PCI_DEVICE(0x1a3b, 0x1059) },
+#ifdef CONFIG_RT2800PCI_RT3290
+       { PCI_DEVICE(0x1814, 0x3290) },
+#endif
+#ifdef CONFIG_RT2800PCI_RT33XX
+       { PCI_DEVICE(0x1814, 0x3390) },
+#endif
+#ifdef CONFIG_RT2800PCI_RT35XX
+       { PCI_DEVICE(0x1432, 0x7711) },
+       { PCI_DEVICE(0x1432, 0x7722) },
+       { PCI_DEVICE(0x1814, 0x3060) },
+       { PCI_DEVICE(0x1814, 0x3062) },
+       { PCI_DEVICE(0x1814, 0x3562) },
+       { PCI_DEVICE(0x1814, 0x3592) },
+       { PCI_DEVICE(0x1814, 0x3593) },
+       { PCI_DEVICE(0x1814, 0x359f) },
+#endif
+#ifdef CONFIG_RT2800PCI_RT53XX
+       { PCI_DEVICE(0x1814, 0x5360) },
+       { PCI_DEVICE(0x1814, 0x5362) },
+       { PCI_DEVICE(0x1814, 0x5390) },
+       { PCI_DEVICE(0x1814, 0x5392) },
+       { PCI_DEVICE(0x1814, 0x539a) },
+       { PCI_DEVICE(0x1814, 0x539b) },
+       { PCI_DEVICE(0x1814, 0x539f) },
+#endif
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards");
+MODULE_FIRMWARE(FIRMWARE_RT2860);
+MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
+MODULE_LICENSE("GPL");
+
+static int rt2800pci_probe(struct pci_dev *pci_dev,
+                          const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
+}
+
+static struct pci_driver rt2800pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt2800pci_device_table,
+       .probe          = rt2800pci_probe,
+       .remove         = rt2x00pci_remove,
+       .suspend        = rt2x00pci_suspend,
+       .resume         = rt2x00pci_resume,
+};
+
+module_pci_driver(rt2800pci_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.h b/drivers/net/wireless/ralink/rt2x00/rt2800pci.h
new file mode 100644 (file)
index 0000000..9dfef46
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+       Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800pci
+       Abstract: Data structures and registers for the rt2800pci module.
+       Supported chipsets: RT2800E & RT2800ED.
+ */
+
+#ifndef RT2800PCI_H
+#define RT2800PCI_H
+
+/*
+ * 8051 firmware image.
+ */
+#define FIRMWARE_RT2860                        "rt2860.bin"
+#define FIRMWARE_RT3290                        "rt3290.bin"
+#define FIRMWARE_IMAGE_BASE            0x2000
+
+#endif /* RT2800PCI_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
new file mode 100644 (file)
index 0000000..a985a5a
--- /dev/null
@@ -0,0 +1,260 @@
+/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+ *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+ *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+ *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+ *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+ *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+ *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+ *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
+ *     <http://rt2x00.serialmonkey.com>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*     Module: rt2800soc
+ *     Abstract: rt2800 WiSoC specific routines.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00soc.h"
+#include "rt2800.h"
+#include "rt2800lib.h"
+#include "rt2800mmio.h"
+
+/* Allow hardware encryption to be disabled. */
+static bool modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+       return modparam_nohwcrypt;
+}
+
+static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_disable_radio(rt2x00dev);
+       rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+       rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
+}
+
+static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt2800mmio_enable_radio(rt2x00dev);
+               break;
+
+       case STATE_RADIO_OFF:
+               rt2800soc_disable_radio(rt2x00dev);
+               break;
+
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt2800mmio_toggle_irq(rt2x00dev, state);
+               break;
+
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               /* These states are not supported, but don't report an error */
+               retval = 0;
+               break;
+
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+
+       if (!base_addr)
+               return -ENOMEM;
+
+       memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+
+       iounmap(base_addr);
+       return 0;
+}
+
+/* Firmware functions */
+static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+       WARN_ON_ONCE(1);
+       return NULL;
+}
+
+static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev,
+                                  const u8 *data, const size_t len)
+{
+       WARN_ON_ONCE(1);
+       return 0;
+}
+
+static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev,
+                                   const u8 *data, const size_t len)
+{
+       WARN_ON_ONCE(1);
+       return 0;
+}
+
+static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
+                                   const u8 *data, const size_t len)
+{
+       WARN_ON_ONCE(1);
+       return 0;
+}
+
+static const struct ieee80211_ops rt2800soc_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .get_key_seq            = rt2800_get_key_seq,
+       .set_rts_threshold      = rt2800_set_rts_threshold,
+       .sta_add                = rt2x00mac_sta_add,
+       .sta_remove             = rt2x00mac_sta_remove,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2800_conf_tx,
+       .get_tsf                = rt2800_get_tsf,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .ampdu_action           = rt2800_ampdu_action,
+       .flush                  = rt2x00mac_flush,
+       .get_survey             = rt2800_get_survey,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2800_ops rt2800soc_rt2800_ops = {
+       .register_read          = rt2x00mmio_register_read,
+       .register_read_lock     = rt2x00mmio_register_read, /* same for SoCs */
+       .register_write         = rt2x00mmio_register_write,
+       .register_write_lock    = rt2x00mmio_register_write, /* same for SoCs */
+       .register_multiread     = rt2x00mmio_register_multiread,
+       .register_multiwrite    = rt2x00mmio_register_multiwrite,
+       .regbusy_read           = rt2x00mmio_regbusy_read,
+       .read_eeprom            = rt2800soc_read_eeprom,
+       .hwcrypt_disabled       = rt2800soc_hwcrypt_disabled,
+       .drv_write_firmware     = rt2800soc_write_firmware,
+       .drv_init_registers     = rt2800mmio_init_registers,
+       .drv_get_txwi           = rt2800mmio_get_txwi,
+};
+
+static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
+       .irq_handler            = rt2800mmio_interrupt,
+       .txstatus_tasklet       = rt2800mmio_txstatus_tasklet,
+       .pretbtt_tasklet        = rt2800mmio_pretbtt_tasklet,
+       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
+       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
+       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
+       .probe_hw               = rt2800_probe_hw,
+       .get_firmware_name      = rt2800soc_get_firmware_name,
+       .check_firmware         = rt2800soc_check_firmware,
+       .load_firmware          = rt2800soc_load_firmware,
+       .initialize             = rt2x00mmio_initialize,
+       .uninitialize           = rt2x00mmio_uninitialize,
+       .get_entry_state        = rt2800mmio_get_entry_state,
+       .clear_entry            = rt2800mmio_clear_entry,
+       .set_device_state       = rt2800soc_set_device_state,
+       .rfkill_poll            = rt2800_rfkill_poll,
+       .link_stats             = rt2800_link_stats,
+       .reset_tuner            = rt2800_reset_tuner,
+       .link_tuner             = rt2800_link_tuner,
+       .gain_calibration       = rt2800_gain_calibration,
+       .vco_calibration        = rt2800_vco_calibration,
+       .start_queue            = rt2800mmio_start_queue,
+       .kick_queue             = rt2800mmio_kick_queue,
+       .stop_queue             = rt2800mmio_stop_queue,
+       .flush_queue            = rt2x00mmio_flush_queue,
+       .write_tx_desc          = rt2800mmio_write_tx_desc,
+       .write_tx_data          = rt2800_write_tx_data,
+       .write_beacon           = rt2800_write_beacon,
+       .clear_beacon           = rt2800_clear_beacon,
+       .fill_rxdone            = rt2800mmio_fill_rxdone,
+       .config_shared_key      = rt2800_config_shared_key,
+       .config_pairwise_key    = rt2800_config_pairwise_key,
+       .config_filter          = rt2800_config_filter,
+       .config_intf            = rt2800_config_intf,
+       .config_erp             = rt2800_config_erp,
+       .config_ant             = rt2800_config_ant,
+       .config                 = rt2800_config,
+       .sta_add                = rt2800_sta_add,
+       .sta_remove             = rt2800_sta_remove,
+};
+
+static const struct rt2x00_ops rt2800soc_ops = {
+       .name                   = KBUILD_MODNAME,
+       .drv_data_size          = sizeof(struct rt2800_drv_data),
+       .max_ap_intf            = 8,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2800mmio_queue_init,
+       .lib                    = &rt2800soc_rt2x00_ops,
+       .drv                    = &rt2800soc_rt2800_ops,
+       .hw                     = &rt2800soc_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2800_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+static int rt2800soc_probe(struct platform_device *pdev)
+{
+       return rt2x00soc_probe(pdev, &rt2800soc_ops);
+}
+
+static struct platform_driver rt2800soc_driver = {
+       .driver         = {
+               .name           = "rt2800_wmac",
+               .mod_name       = KBUILD_MODNAME,
+       },
+       .probe          = rt2800soc_probe,
+       .remove         = rt2x00soc_remove,
+       .suspend        = rt2x00soc_suspend,
+       .resume         = rt2x00soc_resume,
+};
+
+module_platform_driver(rt2800soc_driver);
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
new file mode 100644 (file)
index 0000000..bf9afbf
--- /dev/null
@@ -0,0 +1,1462 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+       Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800usb
+       Abstract: rt2800usb device specific routines.
+       Supported chipsets: RT2800U.
+ */
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "rt2x00.h"
+#include "rt2x00usb.h"
+#include "rt2800lib.h"
+#include "rt2800.h"
+#include "rt2800usb.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static bool modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
+{
+       return modparam_nohwcrypt;
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt2800usb_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
+               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               break;
+       case QID_BEACON:
+               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
+               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt2800usb_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
+               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+               break;
+       case QID_BEACON:
+               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+                   rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+                       return true;
+       }
+       return false;
+}
+
+static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
+{
+       bool tout;
+
+       if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+               return false;
+
+       tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
+       if (unlikely(tout))
+               rt2x00_dbg(entry->queue->rt2x00dev,
+                          "TX status timeout for entry %d in queue %d\n",
+                          entry->entry_idx, entry->queue->qid);
+       return tout;
+
+}
+
+static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       struct queue_entry *entry;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               if (rt2800usb_entry_txstatus_timeout(entry))
+                       return true;
+       }
+       return false;
+}
+
+#define TXSTATUS_READ_INTERVAL 1000000
+
+static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+                                                int urb_status, u32 tx_status)
+{
+       bool valid;
+
+       if (urb_status) {
+               rt2x00_warn(rt2x00dev, "TX status read failed %d\n",
+                           urb_status);
+
+               goto stop_reading;
+       }
+
+       valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
+       if (valid) {
+               if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
+                       rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
+
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+
+               /* Reschedule urb to read TX status again instantly */
+               return true;
+       }
+
+       /* Check if there is any entry that timedout waiting on TX status */
+       if (rt2800usb_txstatus_timeout(rt2x00dev))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+
+       if (rt2800usb_txstatus_pending(rt2x00dev)) {
+               /* Read register after 1 ms */
+               hrtimer_start(&rt2x00dev->txstatus_timer,
+                             ktime_set(0, TXSTATUS_READ_INTERVAL),
+                             HRTIMER_MODE_REL);
+               return false;
+       }
+
+stop_reading:
+       clear_bit(TX_STATUS_READING, &rt2x00dev->flags);
+       /*
+        * There is small race window above, between txstatus pending check and
+        * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
+        * here again if status reading is needed.
+        */
+       if (rt2800usb_txstatus_pending(rt2x00dev) &&
+           !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+               return true;
+       else
+               return false;
+}
+
+static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
+{
+
+       if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+               return;
+
+       /* Read TX_STA_FIFO register after 2 ms */
+       hrtimer_start(&rt2x00dev->txstatus_timer,
+                     ktime_set(0, 2*TXSTATUS_READ_INTERVAL),
+                     HRTIMER_MODE_REL);
+}
+
+static void rt2800usb_tx_dma_done(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       rt2800usb_async_read_tx_status(rt2x00dev);
+}
+
+static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(timer, struct rt2x00_dev, txstatus_timer);
+
+       rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+                                     rt2800usb_tx_sta_fifo_read_completed);
+
+       return HRTIMER_NORESTART;
+}
+
+/*
+ * Firmware functions
+ */
+static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
+{
+       __le32 *reg;
+       u32 fw_mode;
+       int ret;
+
+       reg = kmalloc(sizeof(*reg), GFP_KERNEL);
+       if (reg == NULL)
+               return -ENOMEM;
+       /* cannot use rt2x00usb_register_read here as it uses different
+        * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
+        * magic value USB_MODE_AUTORUN (0x11) to the device, thus the
+        * returned value would be invalid.
+        */
+       ret = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
+                                      USB_VENDOR_REQUEST_IN, 0,
+                                      USB_MODE_AUTORUN, reg, sizeof(*reg),
+                                      REGISTER_TIMEOUT_FIRMWARE);
+       fw_mode = le32_to_cpu(*reg);
+       kfree(reg);
+       if (ret < 0)
+               return ret;
+
+       if ((fw_mode & 0x00000003) == 2)
+               return 1;
+
+       return 0;
+}
+
+static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+       return FIRMWARE_RT2870;
+}
+
+static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
+                                   const u8 *data, const size_t len)
+{
+       int status;
+       u32 offset;
+       u32 length;
+       int retval;
+
+       /*
+        * Check which section of the firmware we need.
+        */
+       if (rt2x00_rt(rt2x00dev, RT2860) ||
+           rt2x00_rt(rt2x00dev, RT2872) ||
+           rt2x00_rt(rt2x00dev, RT3070)) {
+               offset = 0;
+               length = 4096;
+       } else {
+               offset = 4096;
+               length = 4096;
+       }
+
+       /*
+        * Write firmware to device.
+        */
+       retval = rt2800usb_autorun_detect(rt2x00dev);
+       if (retval < 0)
+               return retval;
+       if (retval) {
+               rt2x00_info(rt2x00dev,
+                           "Firmware loading not required - NIC in AutoRun mode\n");
+               __clear_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       } else {
+               rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+                                             data + offset, length);
+       }
+
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+
+       /*
+        * Send firmware request to device to load firmware,
+        * we need to specify a long timeout time.
+        */
+       status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
+                                            0, USB_MODE_FIRMWARE,
+                                            REGISTER_TIMEOUT_FIRMWARE);
+       if (status < 0) {
+               rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
+               return status;
+       }
+
+       msleep(10);
+       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       /*
+        * Wait until BBP and RF are ready.
+        */
+       if (rt2800_wait_csr_ready(rt2x00dev))
+               return -EBUSY;
+
+       rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+       rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+
+       reg = 0;
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
+       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+
+       rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                   USB_MODE_RESET, REGISTER_TIMEOUT);
+
+       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+       return 0;
+}
+
+static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
+               return -EIO;
+
+       rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+       rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
+       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
+       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
+       /*
+        * Total room for RX frames in kilobytes, PBF might still exceed
+        * this limit so reduce the number to prevent errors.
+        */
+       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
+                          ((rt2x00dev->rx->limit * DATA_FRAME_SIZE)
+                           / 1024) - 3);
+       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
+       rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
+       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
+
+       return rt2800_enable_radio(rt2x00dev);
+}
+
+static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       rt2800_disable_radio(rt2x00dev);
+}
+
+static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       if (state == STATE_AWAKE)
+               rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
+       else
+               rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
+
+       return 0;
+}
+
+static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                     enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               /*
+                * Before the radio can be enabled, the device first has
+                * to be woken up. After that it needs a bit of time
+                * to be fully awake and then the radio can be enabled.
+                */
+               rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
+               msleep(1);
+               retval = rt2800usb_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               /*
+                * After the radio has been disabled, the device should
+                * be put to sleep for powersaving.
+                */
+               rt2800usb_disable_radio(rt2x00dev);
+               rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               /* No support, but no error either */
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt2800usb_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * Watchdog handlers
+ */
+static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
+               rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
+
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+
+               for (i = 0; i < 10; i++) {
+                       udelay(10);
+                       if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q))
+                               break;
+               }
+
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+       }
+
+       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
+               rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
+
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+
+               for (i = 0; i < 10; i++) {
+                       udelay(10);
+                       if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q))
+                               break;
+               }
+
+               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+       }
+
+       rt2x00usb_watchdog(rt2x00dev);
+}
+
+/*
+ * TX descriptor initialization
+ */
+static __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
+{
+       if (entry->queue->qid == QID_BEACON)
+               return (__le32 *) (entry->skb->data);
+       else
+               return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
+}
+
+static void rt2800usb_write_tx_desc(struct queue_entry *entry,
+                                   struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *txi = (__le32 *) entry->skb->data;
+       u32 word;
+
+       /*
+        * Initialize TXINFO descriptor
+        */
+       rt2x00_desc_read(txi, 0, &word);
+
+       /*
+        * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
+        * TXWI + 802.11 header + L2 pad + payload + pad,
+        * so need to decrease size of TXINFO.
+        */
+       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
+                          roundup(entry->skb->len, 4) - TXINFO_DESC_SIZE);
+       rt2x00_set_field32(&word, TXINFO_W0_WIV,
+                          !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
+       rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
+       rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0);
+       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0);
+       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
+                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+       rt2x00_desc_write(txi, 0, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
+       skbdesc->desc = txi;
+       skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
+}
+
+/*
+ * TX data initialization
+ */
+static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
+{
+       /*
+        * pad(1~3 bytes) is needed after each 802.11 payload.
+        * USB end pad(4 bytes) is needed at each USB bulk out packet end.
+        * TX frame format is :
+        * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |
+        *                 |<------------- tx_pkt_len ------------->|
+        */
+
+       return roundup(entry->skb->len, 4) + 4;
+}
+
+/*
+ * TX control handlers
+ */
+static enum txdone_entry_desc_flags
+rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+       __le32 *txwi;
+       u32 word;
+       int wcid, ack, pid;
+       int tx_wcid, tx_ack, tx_pid, is_agg;
+
+       /*
+        * This frames has returned with an IO error,
+        * so the status report is not intended for this
+        * frame.
+        */
+       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+               return TXDONE_FAILURE;
+
+       wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+       ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+       pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+       is_agg  = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
+
+       /*
+        * Validate if this TX status report is intended for
+        * this entry by comparing the WCID/ACK/PID fields.
+        */
+       txwi = rt2800usb_get_txwi(entry);
+
+       rt2x00_desc_read(txwi, 1, &word);
+       tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+       tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
+       tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+       if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
+               rt2x00_dbg(entry->queue->rt2x00dev,
+                          "TX status report missed for queue %d entry %d\n",
+                          entry->queue->qid, entry->entry_idx);
+               return TXDONE_UNKNOWN;
+       }
+
+       return TXDONE_SUCCESS;
+}
+
+static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       struct queue_entry *entry;
+       u32 reg;
+       u8 qid;
+       enum txdone_entry_desc_flags done_status;
+
+       while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
+               /*
+                * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
+                * guaranteed to be one of the TX QIDs .
+                */
+               qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+               queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+
+               if (unlikely(rt2x00queue_empty(queue))) {
+                       rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+                                  qid);
+                       break;
+               }
+
+               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+               if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                            !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
+                       rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
+                                   entry->entry_idx, qid);
+                       break;
+               }
+
+               done_status = rt2800usb_txdone_entry_check(entry, reg);
+               if (likely(done_status == TXDONE_SUCCESS))
+                       rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
+               else
+                       rt2x00lib_txdone_noinfo(entry, done_status);
+       }
+}
+
+static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       struct queue_entry *entry;
+
+       /*
+        * Process any trailing TX status reports for IO failures,
+        * we loop until we find the first non-IO error entry. This
+        * can either be a frame which is free, is being uploaded,
+        * or has completed the upload but didn't have an entry
+        * in the TX_STAT_FIFO register yet.
+        */
+       tx_queue_for_each(rt2x00dev, queue) {
+               while (!rt2x00queue_empty(queue)) {
+                       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+                               break;
+
+                       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+                               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+                       else if (rt2800usb_entry_txstatus_timeout(entry))
+                               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+                       else
+                               break;
+               }
+       }
+}
+
+static void rt2800usb_work_txdone(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, txdone_work);
+
+       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
+              rt2800usb_txstatus_timeout(rt2x00dev)) {
+
+               rt2800usb_txdone(rt2x00dev);
+
+               rt2800usb_txdone_nostatus(rt2x00dev);
+
+               /*
+                * The hw may delay sending the packet after DMA complete
+                * if the medium is busy, thus the TX_STA_FIFO entry is
+                * also delayed -> use a timer to retrieve it.
+                */
+               if (rt2800usb_txstatus_pending(rt2x00dev))
+                       rt2800usb_async_read_tx_status(rt2x00dev);
+       }
+}
+
+/*
+ * RX control handlers
+ */
+static void rt2800usb_fill_rxdone(struct queue_entry *entry,
+                                 struct rxdone_entry_desc *rxdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *rxi = (__le32 *)entry->skb->data;
+       __le32 *rxd;
+       u32 word;
+       int rx_pkt_len;
+
+       /*
+        * Copy descriptor to the skbdesc->desc buffer, making it safe from
+        * moving of frame data in rt2x00usb.
+        */
+       memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
+
+       /*
+        * RX frame format is :
+        * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
+        *          |<------------ rx_pkt_len -------------->|
+        */
+       rt2x00_desc_read(rxi, 0, &word);
+       rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
+
+       /*
+        * Remove the RXINFO structure from the sbk.
+        */
+       skb_pull(entry->skb, RXINFO_DESC_SIZE);
+
+       /*
+        * Check for rx_pkt_len validity. Return if invalid, leaving
+        * rxdesc->size zeroed out by the upper level.
+        */
+       if (unlikely(rx_pkt_len == 0 ||
+                       rx_pkt_len > entry->queue->data_size)) {
+               rt2x00_err(entry->queue->rt2x00dev,
+                          "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+               return;
+       }
+
+       rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
+
+       /*
+        * It is now safe to read the descriptor on all architectures.
+        */
+       rt2x00_desc_read(rxd, 0, &word);
+
+       if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+       rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR);
+
+       if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) {
+               /*
+                * Hardware has stripped IV/EIV data from 802.11 frame during
+                * decryption. Unfortunately the descriptor doesn't contain
+                * any fields with the EIV/IV data either, so they can't
+                * be restored by rt2x00lib.
+                */
+               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+               /*
+                * The hardware has already checked the Michael Mic and has
+                * stripped it from the frame. Signal this to mac80211.
+                */
+               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+                       rxdesc->flags |= RX_FLAG_DECRYPTED;
+               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+       }
+
+       if (rt2x00_get_field32(word, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+       if (rt2x00_get_field32(word, RXD_W0_L2PAD))
+               rxdesc->dev_flags |= RXDONE_L2PAD;
+
+       /*
+        * Remove RXD descriptor from end of buffer.
+        */
+       skb_trim(entry->skb, rx_pkt_len);
+
+       /*
+        * Process the RXWI structure.
+        */
+       rt2800_process_rxwi(entry, rxdesc);
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       retval = rt2800usb_autorun_detect(rt2x00dev);
+       if (retval < 0)
+               return retval;
+       if (retval)
+               return 1;
+       return rt2800_efuse_detect(rt2x00dev);
+}
+
+static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       retval = rt2800usb_efuse_detect(rt2x00dev);
+       if (retval < 0)
+               return retval;
+       if (retval)
+               retval = rt2800_read_eeprom_efuse(rt2x00dev);
+       else
+               retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
+                                              EEPROM_SIZE);
+
+       return retval;
+}
+
+static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       retval = rt2800_probe_hw(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Set txstatus timer function.
+        */
+       rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;
+
+       /*
+        * Overwrite TX done handler
+        */
+       INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
+
+       return 0;
+}
+
+static const struct ieee80211_ops rt2800usb_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_tim                = rt2x00mac_set_tim,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .get_key_seq            = rt2800_get_key_seq,
+       .set_rts_threshold      = rt2800_set_rts_threshold,
+       .sta_add                = rt2x00mac_sta_add,
+       .sta_remove             = rt2x00mac_sta_remove,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt2800_conf_tx,
+       .get_tsf                = rt2800_get_tsf,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .ampdu_action           = rt2800_ampdu_action,
+       .flush                  = rt2x00mac_flush,
+       .get_survey             = rt2800_get_survey,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2800_ops rt2800usb_rt2800_ops = {
+       .register_read          = rt2x00usb_register_read,
+       .register_read_lock     = rt2x00usb_register_read_lock,
+       .register_write         = rt2x00usb_register_write,
+       .register_write_lock    = rt2x00usb_register_write_lock,
+       .register_multiread     = rt2x00usb_register_multiread,
+       .register_multiwrite    = rt2x00usb_register_multiwrite,
+       .regbusy_read           = rt2x00usb_regbusy_read,
+       .read_eeprom            = rt2800usb_read_eeprom,
+       .hwcrypt_disabled       = rt2800usb_hwcrypt_disabled,
+       .drv_write_firmware     = rt2800usb_write_firmware,
+       .drv_init_registers     = rt2800usb_init_registers,
+       .drv_get_txwi           = rt2800usb_get_txwi,
+};
+
+static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
+       .probe_hw               = rt2800usb_probe_hw,
+       .get_firmware_name      = rt2800usb_get_firmware_name,
+       .check_firmware         = rt2800_check_firmware,
+       .load_firmware          = rt2800_load_firmware,
+       .initialize             = rt2x00usb_initialize,
+       .uninitialize           = rt2x00usb_uninitialize,
+       .clear_entry            = rt2x00usb_clear_entry,
+       .set_device_state       = rt2800usb_set_device_state,
+       .rfkill_poll            = rt2800_rfkill_poll,
+       .link_stats             = rt2800_link_stats,
+       .reset_tuner            = rt2800_reset_tuner,
+       .link_tuner             = rt2800_link_tuner,
+       .gain_calibration       = rt2800_gain_calibration,
+       .vco_calibration        = rt2800_vco_calibration,
+       .watchdog               = rt2800usb_watchdog,
+       .start_queue            = rt2800usb_start_queue,
+       .kick_queue             = rt2x00usb_kick_queue,
+       .stop_queue             = rt2800usb_stop_queue,
+       .flush_queue            = rt2x00usb_flush_queue,
+       .tx_dma_done            = rt2800usb_tx_dma_done,
+       .write_tx_desc          = rt2800usb_write_tx_desc,
+       .write_tx_data          = rt2800_write_tx_data,
+       .write_beacon           = rt2800_write_beacon,
+       .clear_beacon           = rt2800_clear_beacon,
+       .get_tx_data_len        = rt2800usb_get_tx_data_len,
+       .fill_rxdone            = rt2800usb_fill_rxdone,
+       .config_shared_key      = rt2800_config_shared_key,
+       .config_pairwise_key    = rt2800_config_pairwise_key,
+       .config_filter          = rt2800_config_filter,
+       .config_intf            = rt2800_config_intf,
+       .config_erp             = rt2800_config_erp,
+       .config_ant             = rt2800_config_ant,
+       .config                 = rt2800_config,
+       .sta_add                = rt2800_sta_add,
+       .sta_remove             = rt2800_sta_remove,
+};
+
+static void rt2800usb_queue_init(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       unsigned short txwi_size, rxwi_size;
+
+       rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
+
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 128;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = RXINFO_DESC_SIZE;
+               queue->winfo_size = rxwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 16;
+               queue->data_size = AGGREGATION_SIZE;
+               queue->desc_size = TXINFO_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 8;
+               queue->data_size = MGMT_FRAME_SIZE;
+               queue->desc_size = TXINFO_DESC_SIZE;
+               queue->winfo_size = txwi_size;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_ATIM:
+               /* fallthrough */
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt2800usb_ops = {
+       .name                   = KBUILD_MODNAME,
+       .drv_data_size          = sizeof(struct rt2800_drv_data),
+       .max_ap_intf            = 8,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt2800usb_queue_init,
+       .lib                    = &rt2800usb_rt2x00_ops,
+       .drv                    = &rt2800usb_rt2800_ops,
+       .hw                     = &rt2800usb_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt2800_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * rt2800usb module information.
+ */
+static struct usb_device_id rt2800usb_device_table[] = {
+       /* Abocom */
+       { USB_DEVICE(0x07b8, 0x2870) },
+       { USB_DEVICE(0x07b8, 0x2770) },
+       { USB_DEVICE(0x07b8, 0x3070) },
+       { USB_DEVICE(0x07b8, 0x3071) },
+       { USB_DEVICE(0x07b8, 0x3072) },
+       { USB_DEVICE(0x1482, 0x3c09) },
+       /* AirTies */
+       { USB_DEVICE(0x1eda, 0x2012) },
+       { USB_DEVICE(0x1eda, 0x2210) },
+       { USB_DEVICE(0x1eda, 0x2310) },
+       /* Allwin */
+       { USB_DEVICE(0x8516, 0x2070) },
+       { USB_DEVICE(0x8516, 0x2770) },
+       { USB_DEVICE(0x8516, 0x2870) },
+       { USB_DEVICE(0x8516, 0x3070) },
+       { USB_DEVICE(0x8516, 0x3071) },
+       { USB_DEVICE(0x8516, 0x3072) },
+       /* Alpha Networks */
+       { USB_DEVICE(0x14b2, 0x3c06) },
+       { USB_DEVICE(0x14b2, 0x3c07) },
+       { USB_DEVICE(0x14b2, 0x3c09) },
+       { USB_DEVICE(0x14b2, 0x3c12) },
+       { USB_DEVICE(0x14b2, 0x3c23) },
+       { USB_DEVICE(0x14b2, 0x3c25) },
+       { USB_DEVICE(0x14b2, 0x3c27) },
+       { USB_DEVICE(0x14b2, 0x3c28) },
+       { USB_DEVICE(0x14b2, 0x3c2c) },
+       /* Amit */
+       { USB_DEVICE(0x15c5, 0x0008) },
+       /* Askey */
+       { USB_DEVICE(0x1690, 0x0740) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x1731) },
+       { USB_DEVICE(0x0b05, 0x1732) },
+       { USB_DEVICE(0x0b05, 0x1742) },
+       { USB_DEVICE(0x0b05, 0x1784) },
+       { USB_DEVICE(0x1761, 0x0b05) },
+       /* AzureWave */
+       { USB_DEVICE(0x13d3, 0x3247) },
+       { USB_DEVICE(0x13d3, 0x3273) },
+       { USB_DEVICE(0x13d3, 0x3305) },
+       { USB_DEVICE(0x13d3, 0x3307) },
+       { USB_DEVICE(0x13d3, 0x3321) },
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x8053) },
+       { USB_DEVICE(0x050d, 0x805c) },
+       { USB_DEVICE(0x050d, 0x815c) },
+       { USB_DEVICE(0x050d, 0x825a) },
+       { USB_DEVICE(0x050d, 0x825b) },
+       { USB_DEVICE(0x050d, 0x935a) },
+       { USB_DEVICE(0x050d, 0x935b) },
+       /* Buffalo */
+       { USB_DEVICE(0x0411, 0x00e8) },
+       { USB_DEVICE(0x0411, 0x0158) },
+       { USB_DEVICE(0x0411, 0x015d) },
+       { USB_DEVICE(0x0411, 0x016f) },
+       { USB_DEVICE(0x0411, 0x01a2) },
+       { USB_DEVICE(0x0411, 0x01ee) },
+       { USB_DEVICE(0x0411, 0x01a8) },
+       /* Corega */
+       { USB_DEVICE(0x07aa, 0x002f) },
+       { USB_DEVICE(0x07aa, 0x003c) },
+       { USB_DEVICE(0x07aa, 0x003f) },
+       { USB_DEVICE(0x18c5, 0x0012) },
+       /* D-Link */
+       { USB_DEVICE(0x07d1, 0x3c09) },
+       { USB_DEVICE(0x07d1, 0x3c0a) },
+       { USB_DEVICE(0x07d1, 0x3c0d) },
+       { USB_DEVICE(0x07d1, 0x3c0e) },
+       { USB_DEVICE(0x07d1, 0x3c0f) },
+       { USB_DEVICE(0x07d1, 0x3c11) },
+       { USB_DEVICE(0x07d1, 0x3c13) },
+       { USB_DEVICE(0x07d1, 0x3c15) },
+       { USB_DEVICE(0x07d1, 0x3c16) },
+       { USB_DEVICE(0x07d1, 0x3c17) },
+       { USB_DEVICE(0x2001, 0x3317) },
+       { USB_DEVICE(0x2001, 0x3c1b) },
+       { USB_DEVICE(0x2001, 0x3c25) },
+       /* Draytek */
+       { USB_DEVICE(0x07fa, 0x7712) },
+       /* DVICO */
+       { USB_DEVICE(0x0fe9, 0xb307) },
+       /* Edimax */
+       { USB_DEVICE(0x7392, 0x4085) },
+       { USB_DEVICE(0x7392, 0x7711) },
+       { USB_DEVICE(0x7392, 0x7717) },
+       { USB_DEVICE(0x7392, 0x7718) },
+       { USB_DEVICE(0x7392, 0x7722) },
+       /* Encore */
+       { USB_DEVICE(0x203d, 0x1480) },
+       { USB_DEVICE(0x203d, 0x14a9) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x9701) },
+       { USB_DEVICE(0x1740, 0x9702) },
+       { USB_DEVICE(0x1740, 0x9703) },
+       { USB_DEVICE(0x1740, 0x9705) },
+       { USB_DEVICE(0x1740, 0x9706) },
+       { USB_DEVICE(0x1740, 0x9707) },
+       { USB_DEVICE(0x1740, 0x9708) },
+       { USB_DEVICE(0x1740, 0x9709) },
+       /* Gemtek */
+       { USB_DEVICE(0x15a9, 0x0012) },
+       /* Gigabyte */
+       { USB_DEVICE(0x1044, 0x800b) },
+       { USB_DEVICE(0x1044, 0x800d) },
+       /* Hawking */
+       { USB_DEVICE(0x0e66, 0x0001) },
+       { USB_DEVICE(0x0e66, 0x0003) },
+       { USB_DEVICE(0x0e66, 0x0009) },
+       { USB_DEVICE(0x0e66, 0x000b) },
+       { USB_DEVICE(0x0e66, 0x0013) },
+       { USB_DEVICE(0x0e66, 0x0017) },
+       { USB_DEVICE(0x0e66, 0x0018) },
+       /* I-O DATA */
+       { USB_DEVICE(0x04bb, 0x0945) },
+       { USB_DEVICE(0x04bb, 0x0947) },
+       { USB_DEVICE(0x04bb, 0x0948) },
+       /* Linksys */
+       { USB_DEVICE(0x13b1, 0x0031) },
+       { USB_DEVICE(0x1737, 0x0070) },
+       { USB_DEVICE(0x1737, 0x0071) },
+       { USB_DEVICE(0x1737, 0x0077) },
+       { USB_DEVICE(0x1737, 0x0078) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x0162) },
+       { USB_DEVICE(0x0789, 0x0163) },
+       { USB_DEVICE(0x0789, 0x0164) },
+       { USB_DEVICE(0x0789, 0x0166) },
+       /* Motorola */
+       { USB_DEVICE(0x100d, 0x9031) },
+       /* MSI */
+       { USB_DEVICE(0x0db0, 0x3820) },
+       { USB_DEVICE(0x0db0, 0x3821) },
+       { USB_DEVICE(0x0db0, 0x3822) },
+       { USB_DEVICE(0x0db0, 0x3870) },
+       { USB_DEVICE(0x0db0, 0x3871) },
+       { USB_DEVICE(0x0db0, 0x6899) },
+       { USB_DEVICE(0x0db0, 0x821a) },
+       { USB_DEVICE(0x0db0, 0x822a) },
+       { USB_DEVICE(0x0db0, 0x822b) },
+       { USB_DEVICE(0x0db0, 0x822c) },
+       { USB_DEVICE(0x0db0, 0x870a) },
+       { USB_DEVICE(0x0db0, 0x871a) },
+       { USB_DEVICE(0x0db0, 0x871b) },
+       { USB_DEVICE(0x0db0, 0x871c) },
+       { USB_DEVICE(0x0db0, 0x899a) },
+       /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x3070) },
+       { USB_DEVICE(0x1b75, 0x3071) },
+       { USB_DEVICE(0x1b75, 0x3072) },
+       { USB_DEVICE(0x1b75, 0xa200) },
+       /* Para */
+       { USB_DEVICE(0x20b8, 0x8888) },
+       /* Pegatron */
+       { USB_DEVICE(0x1d4d, 0x0002) },
+       { USB_DEVICE(0x1d4d, 0x000c) },
+       { USB_DEVICE(0x1d4d, 0x000e) },
+       { USB_DEVICE(0x1d4d, 0x0011) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x200f) },
+       /* Planex */
+       { USB_DEVICE(0x2019, 0x5201) },
+       { USB_DEVICE(0x2019, 0xab25) },
+       { USB_DEVICE(0x2019, 0xed06) },
+       /* Quanta */
+       { USB_DEVICE(0x1a32, 0x0304) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x2070) },
+       { USB_DEVICE(0x148f, 0x2770) },
+       { USB_DEVICE(0x148f, 0x2870) },
+       { USB_DEVICE(0x148f, 0x3070) },
+       { USB_DEVICE(0x148f, 0x3071) },
+       { USB_DEVICE(0x148f, 0x3072) },
+       /* Samsung */
+       { USB_DEVICE(0x04e8, 0x2018) },
+       /* Siemens */
+       { USB_DEVICE(0x129b, 0x1828) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x0017) },
+       { USB_DEVICE(0x0df6, 0x002b) },
+       { USB_DEVICE(0x0df6, 0x002c) },
+       { USB_DEVICE(0x0df6, 0x002d) },
+       { USB_DEVICE(0x0df6, 0x0039) },
+       { USB_DEVICE(0x0df6, 0x003b) },
+       { USB_DEVICE(0x0df6, 0x003d) },
+       { USB_DEVICE(0x0df6, 0x003e) },
+       { USB_DEVICE(0x0df6, 0x003f) },
+       { USB_DEVICE(0x0df6, 0x0040) },
+       { USB_DEVICE(0x0df6, 0x0042) },
+       { USB_DEVICE(0x0df6, 0x0047) },
+       { USB_DEVICE(0x0df6, 0x0048) },
+       { USB_DEVICE(0x0df6, 0x0051) },
+       { USB_DEVICE(0x0df6, 0x005f) },
+       { USB_DEVICE(0x0df6, 0x0060) },
+       /* SMC */
+       { USB_DEVICE(0x083a, 0x6618) },
+       { USB_DEVICE(0x083a, 0x7511) },
+       { USB_DEVICE(0x083a, 0x7512) },
+       { USB_DEVICE(0x083a, 0x7522) },
+       { USB_DEVICE(0x083a, 0x8522) },
+       { USB_DEVICE(0x083a, 0xa618) },
+       { USB_DEVICE(0x083a, 0xa701) },
+       { USB_DEVICE(0x083a, 0xa702) },
+       { USB_DEVICE(0x083a, 0xa703) },
+       { USB_DEVICE(0x083a, 0xb522) },
+       /* Sparklan */
+       { USB_DEVICE(0x15a9, 0x0006) },
+       /* Sweex */
+       { USB_DEVICE(0x177f, 0x0153) },
+       { USB_DEVICE(0x177f, 0x0164) },
+       { USB_DEVICE(0x177f, 0x0302) },
+       { USB_DEVICE(0x177f, 0x0313) },
+       { USB_DEVICE(0x177f, 0x0323) },
+       { USB_DEVICE(0x177f, 0x0324) },
+       /* U-Media */
+       { USB_DEVICE(0x157e, 0x300e) },
+       { USB_DEVICE(0x157e, 0x3013) },
+       /* ZCOM */
+       { USB_DEVICE(0x0cde, 0x0022) },
+       { USB_DEVICE(0x0cde, 0x0025) },
+       /* Zinwell */
+       { USB_DEVICE(0x5a57, 0x0280) },
+       { USB_DEVICE(0x5a57, 0x0282) },
+       { USB_DEVICE(0x5a57, 0x0283) },
+       { USB_DEVICE(0x5a57, 0x5257) },
+       /* Zyxel */
+       { USB_DEVICE(0x0586, 0x3416) },
+       { USB_DEVICE(0x0586, 0x3418) },
+       { USB_DEVICE(0x0586, 0x341a) },
+       { USB_DEVICE(0x0586, 0x341e) },
+       { USB_DEVICE(0x0586, 0x343e) },
+#ifdef CONFIG_RT2800USB_RT33XX
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x945b) },
+       /* D-Link */
+       { USB_DEVICE(0x2001, 0x3c17) },
+       /* Panasonic */
+       { USB_DEVICE(0x083a, 0xb511) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x20dd) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x3370) },
+       { USB_DEVICE(0x148f, 0x8070) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x0050) },
+       /* Sweex */
+       { USB_DEVICE(0x177f, 0x0163) },
+       { USB_DEVICE(0x177f, 0x0165) },
+#endif
+#ifdef CONFIG_RT2800USB_RT35XX
+       /* Allwin */
+       { USB_DEVICE(0x8516, 0x3572) },
+       /* Askey */
+       { USB_DEVICE(0x1690, 0x0744) },
+       { USB_DEVICE(0x1690, 0x0761) },
+       { USB_DEVICE(0x1690, 0x0764) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x179d) },
+       /* Cisco */
+       { USB_DEVICE(0x167b, 0x4001) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x9801) },
+       /* I-O DATA */
+       { USB_DEVICE(0x04bb, 0x0944) },
+       /* Linksys */
+       { USB_DEVICE(0x13b1, 0x002f) },
+       { USB_DEVICE(0x1737, 0x0079) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x0170) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x3572) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x0041) },
+       { USB_DEVICE(0x0df6, 0x0062) },
+       { USB_DEVICE(0x0df6, 0x0065) },
+       { USB_DEVICE(0x0df6, 0x0066) },
+       { USB_DEVICE(0x0df6, 0x0068) },
+       /* Toshiba */
+       { USB_DEVICE(0x0930, 0x0a07) },
+       /* Zinwell */
+       { USB_DEVICE(0x5a57, 0x0284) },
+#endif
+#ifdef CONFIG_RT2800USB_RT3573
+       /* AirLive */
+       { USB_DEVICE(0x1b75, 0x7733) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x17bc) },
+       { USB_DEVICE(0x0b05, 0x17ad) },
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x1103) },
+       /* Cameo */
+       { USB_DEVICE(0x148f, 0xf301) },
+       /* D-Link */
+       { USB_DEVICE(0x2001, 0x3c1f) },
+       /* Edimax */
+       { USB_DEVICE(0x7392, 0x7733) },
+       /* Hawking */
+       { USB_DEVICE(0x0e66, 0x0020) },
+       { USB_DEVICE(0x0e66, 0x0021) },
+       /* I-O DATA */
+       { USB_DEVICE(0x04bb, 0x094e) },
+       /* Linksys */
+       { USB_DEVICE(0x13b1, 0x003b) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x016b) },
+       /* NETGEAR */
+       { USB_DEVICE(0x0846, 0x9012) },
+       { USB_DEVICE(0x0846, 0x9013) },
+       { USB_DEVICE(0x0846, 0x9019) },
+       /* Planex */
+       { USB_DEVICE(0x2019, 0xed19) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x3573) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x0067) },
+       { USB_DEVICE(0x0df6, 0x006a) },
+       { USB_DEVICE(0x0df6, 0x006e) },
+       /* ZyXEL */
+       { USB_DEVICE(0x0586, 0x3421) },
+#endif
+#ifdef CONFIG_RT2800USB_RT53XX
+       /* Arcadyan */
+       { USB_DEVICE(0x043e, 0x7a12) },
+       { USB_DEVICE(0x043e, 0x7a32) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x17e8) },
+       /* Azurewave */
+       { USB_DEVICE(0x13d3, 0x3329) },
+       { USB_DEVICE(0x13d3, 0x3365) },
+       /* D-Link */
+       { USB_DEVICE(0x2001, 0x3c15) },
+       { USB_DEVICE(0x2001, 0x3c19) },
+       { USB_DEVICE(0x2001, 0x3c1c) },
+       { USB_DEVICE(0x2001, 0x3c1d) },
+       { USB_DEVICE(0x2001, 0x3c1e) },
+       { USB_DEVICE(0x2001, 0x3c20) },
+       { USB_DEVICE(0x2001, 0x3c22) },
+       { USB_DEVICE(0x2001, 0x3c23) },
+       /* LG innotek */
+       { USB_DEVICE(0x043e, 0x7a22) },
+       { USB_DEVICE(0x043e, 0x7a42) },
+       /* Panasonic */
+       { USB_DEVICE(0x04da, 0x1801) },
+       { USB_DEVICE(0x04da, 0x1800) },
+       { USB_DEVICE(0x04da, 0x23f6) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x2104) },
+       { USB_DEVICE(0x0471, 0x2126) },
+       { USB_DEVICE(0x0471, 0x2180) },
+       { USB_DEVICE(0x0471, 0x2181) },
+       { USB_DEVICE(0x0471, 0x2182) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x5370) },
+       { USB_DEVICE(0x148f, 0x5372) },
+#endif
+#ifdef CONFIG_RT2800USB_RT55XX
+       /* Arcadyan */
+       { USB_DEVICE(0x043e, 0x7a32) },
+       /* AVM GmbH */
+       { USB_DEVICE(0x057c, 0x8501) },
+       /* Buffalo */
+       { USB_DEVICE(0x0411, 0x0241) },
+       { USB_DEVICE(0x0411, 0x0253) },
+       /* D-Link */
+       { USB_DEVICE(0x2001, 0x3c1a) },
+       { USB_DEVICE(0x2001, 0x3c21) },
+       /* Proware */
+       { USB_DEVICE(0x043e, 0x7a13) },
+       /* Ralink */
+       { USB_DEVICE(0x148f, 0x5572) },
+       /* TRENDnet */
+       { USB_DEVICE(0x20f4, 0x724a) },
+#endif
+#ifdef CONFIG_RT2800USB_UNKNOWN
+       /*
+        * Unclear what kind of devices these are (they aren't supported by the
+        * vendor linux driver).
+        */
+       /* Abocom */
+       { USB_DEVICE(0x07b8, 0x3073) },
+       { USB_DEVICE(0x07b8, 0x3074) },
+       /* Alpha Networks */
+       { USB_DEVICE(0x14b2, 0x3c08) },
+       { USB_DEVICE(0x14b2, 0x3c11) },
+       /* Amigo */
+       { USB_DEVICE(0x0e0b, 0x9031) },
+       { USB_DEVICE(0x0e0b, 0x9041) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x166a) },
+       { USB_DEVICE(0x0b05, 0x1760) },
+       { USB_DEVICE(0x0b05, 0x1761) },
+       { USB_DEVICE(0x0b05, 0x1790) },
+       { USB_DEVICE(0x0b05, 0x17a7) },
+       /* AzureWave */
+       { USB_DEVICE(0x13d3, 0x3262) },
+       { USB_DEVICE(0x13d3, 0x3284) },
+       { USB_DEVICE(0x13d3, 0x3322) },
+       { USB_DEVICE(0x13d3, 0x3340) },
+       { USB_DEVICE(0x13d3, 0x3399) },
+       { USB_DEVICE(0x13d3, 0x3400) },
+       { USB_DEVICE(0x13d3, 0x3401) },
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x1003) },
+       /* Buffalo */
+       { USB_DEVICE(0x0411, 0x012e) },
+       { USB_DEVICE(0x0411, 0x0148) },
+       { USB_DEVICE(0x0411, 0x0150) },
+       /* Corega */
+       { USB_DEVICE(0x07aa, 0x0041) },
+       { USB_DEVICE(0x07aa, 0x0042) },
+       { USB_DEVICE(0x18c5, 0x0008) },
+       /* D-Link */
+       { USB_DEVICE(0x07d1, 0x3c0b) },
+       /* Encore */
+       { USB_DEVICE(0x203d, 0x14a1) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x0600) },
+       { USB_DEVICE(0x1740, 0x0602) },
+       /* Gemtek */
+       { USB_DEVICE(0x15a9, 0x0010) },
+       /* Gigabyte */
+       { USB_DEVICE(0x1044, 0x800c) },
+       /* Hercules */
+       { USB_DEVICE(0x06f8, 0xe036) },
+       /* Huawei */
+       { USB_DEVICE(0x148f, 0xf101) },
+       /* I-O DATA */
+       { USB_DEVICE(0x04bb, 0x094b) },
+       /* LevelOne */
+       { USB_DEVICE(0x1740, 0x0605) },
+       { USB_DEVICE(0x1740, 0x0615) },
+       /* Logitec */
+       { USB_DEVICE(0x0789, 0x0168) },
+       { USB_DEVICE(0x0789, 0x0169) },
+       /* Motorola */
+       { USB_DEVICE(0x100d, 0x9032) },
+       /* Pegatron */
+       { USB_DEVICE(0x05a6, 0x0101) },
+       { USB_DEVICE(0x1d4d, 0x0010) },
+       /* Planex */
+       { USB_DEVICE(0x2019, 0xab24) },
+       { USB_DEVICE(0x2019, 0xab29) },
+       /* Qcom */
+       { USB_DEVICE(0x18e8, 0x6259) },
+       /* RadioShack */
+       { USB_DEVICE(0x08b9, 0x1197) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x003c) },
+       { USB_DEVICE(0x0df6, 0x004a) },
+       { USB_DEVICE(0x0df6, 0x004d) },
+       { USB_DEVICE(0x0df6, 0x0053) },
+       { USB_DEVICE(0x0df6, 0x0069) },
+       { USB_DEVICE(0x0df6, 0x006f) },
+       { USB_DEVICE(0x0df6, 0x0078) },
+       /* SMC */
+       { USB_DEVICE(0x083a, 0xa512) },
+       { USB_DEVICE(0x083a, 0xc522) },
+       { USB_DEVICE(0x083a, 0xd522) },
+       { USB_DEVICE(0x083a, 0xf511) },
+       /* Sweex */
+       { USB_DEVICE(0x177f, 0x0254) },
+       /* TP-LINK */
+       { USB_DEVICE(0xf201, 0x5370) },
+#endif
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards");
+MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
+MODULE_FIRMWARE(FIRMWARE_RT2870);
+MODULE_LICENSE("GPL");
+
+static int rt2800usb_probe(struct usb_interface *usb_intf,
+                          const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
+static struct usb_driver rt2800usb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt2800usb_device_table,
+       .probe          = rt2800usb_probe,
+       .disconnect     = rt2x00usb_disconnect,
+       .suspend        = rt2x00usb_suspend,
+       .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
+       .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(rt2800usb_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.h b/drivers/net/wireless/ralink/rt2x00/rt2800usb.h
new file mode 100644 (file)
index 0000000..ea7cac0
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+       Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+       Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2800usb
+       Abstract: Data structures and registers for the rt2800usb module.
+       Supported chipsets: RT2800U.
+ */
+
+#ifndef RT2800USB_H
+#define RT2800USB_H
+
+/*
+ * 8051 firmware image.
+ */
+#define FIRMWARE_RT2870                        "rt2870.bin"
+#define FIRMWARE_IMAGE_BASE            0x3000
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXINFO_DESC_SIZE               (1 * sizeof(__le32))
+#define RXINFO_DESC_SIZE               (1 * sizeof(__le32))
+
+/*
+ * TX Info structure
+ */
+
+/*
+ * Word0
+ * WIV: Wireless Info Valid. 1: Driver filled WI,  0: DMA needs to copy WI
+ * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
+ *       0:MGMT, 1:HCCA 2:EDCA
+ * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid
+ * DMA_TX_BURST: used ONLY in USB bulk Aggregation.
+ *               Force USB DMA transmit frame from current selected endpoint
+ */
+#define TXINFO_W0_USB_DMA_TX_PKT_LEN   FIELD32(0x0000ffff)
+#define TXINFO_W0_WIV                  FIELD32(0x01000000)
+#define TXINFO_W0_QSEL                 FIELD32(0x06000000)
+#define TXINFO_W0_SW_USE_LAST_ROUND    FIELD32(0x08000000)
+#define TXINFO_W0_USB_DMA_NEXT_VALID   FIELD32(0x40000000)
+#define TXINFO_W0_USB_DMA_TX_BURST     FIELD32(0x80000000)
+
+/*
+ * RX Info structure
+ */
+
+/*
+ * Word 0
+ */
+
+#define RXINFO_W0_USB_DMA_RX_PKT_LEN   FIELD32(0x0000ffff)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ * UNICAST_TO_ME: This RX frame is unicast to me.
+ * MULTICAST: This is a multicast frame.
+ * BROADCAST: This is a broadcast frame.
+ * MY_BSS: this frame belongs to the same BSSID.
+ * CRC_ERROR: CRC error.
+ * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid.
+ * AMSDU: rx with 802.3 header, not 802.11 header.
+ */
+
+#define RXD_W0_BA                      FIELD32(0x00000001)
+#define RXD_W0_DATA                    FIELD32(0x00000002)
+#define RXD_W0_NULLDATA                        FIELD32(0x00000004)
+#define RXD_W0_FRAG                    FIELD32(0x00000008)
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000010)
+#define RXD_W0_MULTICAST               FIELD32(0x00000020)
+#define RXD_W0_BROADCAST               FIELD32(0x00000040)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000080)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000100)
+#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000600)
+#define RXD_W0_AMSDU                   FIELD32(0x00000800)
+#define RXD_W0_HTC                     FIELD32(0x00001000)
+#define RXD_W0_RSSI                    FIELD32(0x00002000)
+#define RXD_W0_L2PAD                   FIELD32(0x00004000)
+#define RXD_W0_AMPDU                   FIELD32(0x00008000)
+#define RXD_W0_DECRYPTED               FIELD32(0x00010000)
+#define RXD_W0_PLCP_RSSI               FIELD32(0x00020000)
+#define RXD_W0_CIPHER_ALG              FIELD32(0x00040000)
+#define RXD_W0_LAST_AMSDU              FIELD32(0x00080000)
+#define RXD_W0_PLCP_SIGNAL             FIELD32(0xfff00000)
+
+#endif /* RT2800USB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
new file mode 100644 (file)
index 0000000..3282ddb
--- /dev/null
@@ -0,0 +1,1478 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00
+       Abstract: rt2x00 global information.
+ */
+
+#ifndef RT2X00_H
+#define RT2X00_H
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include <linux/leds.h>
+#include <linux/mutex.h>
+#include <linux/etherdevice.h>
+#include <linux/input-polldev.h>
+#include <linux/kfifo.h>
+#include <linux/hrtimer.h>
+#include <linux/average.h>
+
+#include <net/mac80211.h>
+
+#include "rt2x00debug.h"
+#include "rt2x00dump.h"
+#include "rt2x00leds.h"
+#include "rt2x00reg.h"
+#include "rt2x00queue.h"
+
+/*
+ * Module information.
+ */
+#define DRV_VERSION    "2.3.0"
+#define DRV_PROJECT    "http://rt2x00.serialmonkey.com"
+
+/* Debug definitions.
+ * Debug output has to be enabled during compile time.
+ */
+#ifdef CONFIG_RT2X00_DEBUG
+#define DEBUG
+#endif /* CONFIG_RT2X00_DEBUG */
+
+/* Utility printing macros
+ * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized
+ */
+#define rt2x00_probe_err(fmt, ...)                                     \
+       printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt,            \
+              __func__, ##__VA_ARGS__)
+#define rt2x00_err(dev, fmt, ...)                                      \
+       wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt,                 \
+                 __func__, ##__VA_ARGS__)
+#define rt2x00_warn(dev, fmt, ...)                                     \
+       wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt,              \
+                  __func__, ##__VA_ARGS__)
+#define rt2x00_info(dev, fmt, ...)                                     \
+       wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt,                 \
+                  __func__, ##__VA_ARGS__)
+
+/* Various debug levels */
+#define rt2x00_dbg(dev, fmt, ...)                                      \
+       wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt,                 \
+                 __func__, ##__VA_ARGS__)
+#define rt2x00_eeprom_dbg(dev, fmt, ...)                               \
+       wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt,       \
+                 __func__, ##__VA_ARGS__)
+
+/*
+ * Duration calculations
+ * The rate variable passed is: 100kbs.
+ * To convert from bytes to bits we multiply size with 8,
+ * then the size is multiplied with 10 to make the
+ * real rate -> rate argument correction.
+ */
+#define GET_DURATION(__size, __rate)   (((__size) * 8 * 10) / (__rate))
+#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
+
+/*
+ * Determine the number of L2 padding bytes required between the header and
+ * the payload.
+ */
+#define L2PAD_SIZE(__hdrlen)   (-(__hdrlen) & 3)
+
+/*
+ * Determine the alignment requirement,
+ * to make sure the 802.11 payload is padded to a 4-byte boundrary
+ * we must determine the address of the payload and calculate the
+ * amount of bytes needed to move the data.
+ */
+#define ALIGN_SIZE(__skb, __header) \
+       (  ((unsigned long)((__skb)->data + (__header))) & 3 )
+
+/*
+ * Constants for extra TX headroom for alignment purposes.
+ */
+#define RT2X00_ALIGN_SIZE      4 /* Only whole frame needs alignment */
+#define RT2X00_L2PAD_SIZE      8 /* Both header & payload need alignment */
+
+/*
+ * Standard timing and size defines.
+ * These values should follow the ieee80211 specifications.
+ */
+#define ACK_SIZE               14
+#define IEEE80211_HEADER       24
+#define PLCP                   48
+#define BEACON                 100
+#define PREAMBLE               144
+#define SHORT_PREAMBLE         72
+#define SLOT_TIME              20
+#define SHORT_SLOT_TIME                9
+#define SIFS                   10
+#define PIFS                   ( SIFS + SLOT_TIME )
+#define SHORT_PIFS             ( SIFS + SHORT_SLOT_TIME )
+#define DIFS                   ( PIFS + SLOT_TIME )
+#define SHORT_DIFS             ( SHORT_PIFS + SHORT_SLOT_TIME )
+#define EIFS                   ( SIFS + DIFS + \
+                                 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
+#define SHORT_EIFS             ( SIFS + SHORT_DIFS + \
+                                 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
+
+enum rt2x00_chip_intf {
+       RT2X00_CHIP_INTF_PCI,
+       RT2X00_CHIP_INTF_PCIE,
+       RT2X00_CHIP_INTF_USB,
+       RT2X00_CHIP_INTF_SOC,
+};
+
+/*
+ * Chipset identification
+ * The chipset on the device is composed of a RT and RF chip.
+ * The chipset combination is important for determining device capabilities.
+ */
+struct rt2x00_chip {
+       u16 rt;
+#define RT2460         0x2460
+#define RT2560         0x2560
+#define RT2570         0x2570
+#define RT2661         0x2661
+#define RT2573         0x2573
+#define RT2860         0x2860  /* 2.4GHz */
+#define RT2872         0x2872  /* WSOC */
+#define RT2883         0x2883  /* WSOC */
+#define RT3070         0x3070
+#define RT3071         0x3071
+#define RT3090         0x3090  /* 2.4GHz PCIe */
+#define RT3290         0x3290
+#define RT3352         0x3352  /* WSOC */
+#define RT3390         0x3390
+#define RT3572         0x3572
+#define RT3593         0x3593
+#define RT3883         0x3883  /* WSOC */
+#define RT5390         0x5390  /* 2.4GHz */
+#define RT5392         0x5392  /* 2.4GHz */
+#define RT5592         0x5592
+
+       u16 rf;
+       u16 rev;
+
+       enum rt2x00_chip_intf intf;
+};
+
+/*
+ * RF register values that belong to a particular channel.
+ */
+struct rf_channel {
+       int channel;
+       u32 rf1;
+       u32 rf2;
+       u32 rf3;
+       u32 rf4;
+};
+
+/*
+ * Channel information structure
+ */
+struct channel_info {
+       unsigned int flags;
+#define GEOGRAPHY_ALLOWED      0x00000001
+
+       short max_power;
+       short default_power1;
+       short default_power2;
+       short default_power3;
+};
+
+/*
+ * Antenna setup values.
+ */
+struct antenna_setup {
+       enum antenna rx;
+       enum antenna tx;
+       u8 rx_chain_num;
+       u8 tx_chain_num;
+};
+
+/*
+ * Quality statistics about the currently active link.
+ */
+struct link_qual {
+       /*
+        * Statistics required for Link tuning by driver
+        * The rssi value is provided by rt2x00lib during the
+        * link_tuner() callback function.
+        * The false_cca field is filled during the link_stats()
+        * callback function and could be used during the
+        * link_tuner() callback function.
+        */
+       int rssi;
+       int false_cca;
+
+       /*
+        * VGC levels
+        * Hardware driver will tune the VGC level during each call
+        * to the link_tuner() callback function. This vgc_level is
+        * is determined based on the link quality statistics like
+        * average RSSI and the false CCA count.
+        *
+        * In some cases the drivers need to differentiate between
+        * the currently "desired" VGC level and the level configured
+        * in the hardware. The latter is important to reduce the
+        * number of BBP register reads to reduce register access
+        * overhead. For this reason we store both values here.
+        */
+       u8 vgc_level;
+       u8 vgc_level_reg;
+
+       /*
+        * Statistics required for Signal quality calculation.
+        * These fields might be changed during the link_stats()
+        * callback function.
+        */
+       int rx_success;
+       int rx_failed;
+       int tx_success;
+       int tx_failed;
+};
+
+DECLARE_EWMA(rssi, 1024, 8)
+
+/*
+ * Antenna settings about the currently active link.
+ */
+struct link_ant {
+       /*
+        * Antenna flags
+        */
+       unsigned int flags;
+#define ANTENNA_RX_DIVERSITY   0x00000001
+#define ANTENNA_TX_DIVERSITY   0x00000002
+#define ANTENNA_MODE_SAMPLE    0x00000004
+
+       /*
+        * Currently active TX/RX antenna setup.
+        * When software diversity is used, this will indicate
+        * which antenna is actually used at this time.
+        */
+       struct antenna_setup active;
+
+       /*
+        * RSSI history information for the antenna.
+        * Used to determine when to switch antenna
+        * when using software diversity.
+        */
+       int rssi_history;
+
+       /*
+        * Current RSSI average of the currently active antenna.
+        * Similar to the avg_rssi in the link_qual structure
+        * this value is updated by using the walking average.
+        */
+       struct ewma_rssi rssi_ant;
+};
+
+/*
+ * To optimize the quality of the link we need to store
+ * the quality of received frames and periodically
+ * optimize the link.
+ */
+struct link {
+       /*
+        * Link tuner counter
+        * The number of times the link has been tuned
+        * since the radio has been switched on.
+        */
+       u32 count;
+
+       /*
+        * Quality measurement values.
+        */
+       struct link_qual qual;
+
+       /*
+        * TX/RX antenna setup.
+        */
+       struct link_ant ant;
+
+       /*
+        * Currently active average RSSI value
+        */
+       struct ewma_rssi avg_rssi;
+
+       /*
+        * Work structure for scheduling periodic link tuning.
+        */
+       struct delayed_work work;
+
+       /*
+        * Work structure for scheduling periodic watchdog monitoring.
+        * This work must be scheduled on the kernel workqueue, while
+        * all other work structures must be queued on the mac80211
+        * workqueue. This guarantees that the watchdog can schedule
+        * other work structures and wait for their completion in order
+        * to bring the device/driver back into the desired state.
+        */
+       struct delayed_work watchdog_work;
+
+       /*
+        * Work structure for scheduling periodic AGC adjustments.
+        */
+       struct delayed_work agc_work;
+
+       /*
+        * Work structure for scheduling periodic VCO calibration.
+        */
+       struct delayed_work vco_work;
+};
+
+enum rt2x00_delayed_flags {
+       DELAYED_UPDATE_BEACON,
+};
+
+/*
+ * Interface structure
+ * Per interface configuration details, this structure
+ * is allocated as the private data for ieee80211_vif.
+ */
+struct rt2x00_intf {
+       /*
+        * beacon->skb must be protected with the mutex.
+        */
+       struct mutex beacon_skb_mutex;
+
+       /*
+        * Entry in the beacon queue which belongs to
+        * this interface. Each interface has its own
+        * dedicated beacon entry.
+        */
+       struct queue_entry *beacon;
+       bool enable_beacon;
+
+       /*
+        * Actions that needed rescheduling.
+        */
+       unsigned long delayed_flags;
+
+       /*
+        * Software sequence counter, this is only required
+        * for hardware which doesn't support hardware
+        * sequence counting.
+        */
+       atomic_t seqno;
+};
+
+static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
+{
+       return (struct rt2x00_intf *)vif->drv_priv;
+}
+
+/**
+ * struct hw_mode_spec: Hardware specifications structure
+ *
+ * Details about the supported modes, rates and channels
+ * of a particular chipset. This is used by rt2x00lib
+ * to build the ieee80211_hw_mode array for mac80211.
+ *
+ * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
+ * @supported_rates: Rate types which are supported (CCK, OFDM).
+ * @num_channels: Number of supported channels. This is used as array size
+ *     for @tx_power_a, @tx_power_bg and @channels.
+ * @channels: Device/chipset specific channel values (See &struct rf_channel).
+ * @channels_info: Additional information for channels (See &struct channel_info).
+ * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
+ */
+struct hw_mode_spec {
+       unsigned int supported_bands;
+#define SUPPORT_BAND_2GHZ      0x00000001
+#define SUPPORT_BAND_5GHZ      0x00000002
+
+       unsigned int supported_rates;
+#define SUPPORT_RATE_CCK       0x00000001
+#define SUPPORT_RATE_OFDM      0x00000002
+
+       unsigned int num_channels;
+       const struct rf_channel *channels;
+       const struct channel_info *channels_info;
+
+       struct ieee80211_sta_ht_cap ht;
+};
+
+/*
+ * Configuration structure wrapper around the
+ * mac80211 configuration structure.
+ * When mac80211 configures the driver, rt2x00lib
+ * can precalculate values which are equal for all
+ * rt2x00 drivers. Those values can be stored in here.
+ */
+struct rt2x00lib_conf {
+       struct ieee80211_conf *conf;
+
+       struct rf_channel rf;
+       struct channel_info channel;
+};
+
+/*
+ * Configuration structure for erp settings.
+ */
+struct rt2x00lib_erp {
+       int short_preamble;
+       int cts_protection;
+
+       u32 basic_rates;
+
+       int slot_time;
+
+       short sifs;
+       short pifs;
+       short difs;
+       short eifs;
+
+       u16 beacon_int;
+       u16 ht_opmode;
+};
+
+/*
+ * Configuration structure for hardware encryption.
+ */
+struct rt2x00lib_crypto {
+       enum cipher cipher;
+
+       enum set_key_cmd cmd;
+       const u8 *address;
+
+       u32 bssidx;
+
+       u8 key[16];
+       u8 tx_mic[8];
+       u8 rx_mic[8];
+
+       int wcid;
+};
+
+/*
+ * Configuration structure wrapper around the
+ * rt2x00 interface configuration handler.
+ */
+struct rt2x00intf_conf {
+       /*
+        * Interface type
+        */
+       enum nl80211_iftype type;
+
+       /*
+        * TSF sync value, this is dependent on the operation type.
+        */
+       enum tsf_sync sync;
+
+       /*
+        * The MAC and BSSID addresses are simple array of bytes,
+        * these arrays are little endian, so when sending the addresses
+        * to the drivers, copy the it into a endian-signed variable.
+        *
+        * Note that all devices (except rt2500usb) have 32 bits
+        * register word sizes. This means that whatever variable we
+        * pass _must_ be a multiple of 32 bits. Otherwise the device
+        * might not accept what we are sending to it.
+        * This will also make it easier for the driver to write
+        * the data to the device.
+        */
+       __le32 mac[2];
+       __le32 bssid[2];
+};
+
+/*
+ * Private structure for storing STA details
+ * wcid: Wireless Client ID
+ */
+struct rt2x00_sta {
+       int wcid;
+};
+
+static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
+{
+       return (struct rt2x00_sta *)sta->drv_priv;
+}
+
+/*
+ * rt2x00lib callback functions.
+ */
+struct rt2x00lib_ops {
+       /*
+        * Interrupt handlers.
+        */
+       irq_handler_t irq_handler;
+
+       /*
+        * TX status tasklet handler.
+        */
+       void (*txstatus_tasklet) (unsigned long data);
+       void (*pretbtt_tasklet) (unsigned long data);
+       void (*tbtt_tasklet) (unsigned long data);
+       void (*rxdone_tasklet) (unsigned long data);
+       void (*autowake_tasklet) (unsigned long data);
+
+       /*
+        * Device init handlers.
+        */
+       int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
+       char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
+       int (*check_firmware) (struct rt2x00_dev *rt2x00dev,
+                              const u8 *data, const size_t len);
+       int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
+                             const u8 *data, const size_t len);
+
+       /*
+        * Device initialization/deinitialization handlers.
+        */
+       int (*initialize) (struct rt2x00_dev *rt2x00dev);
+       void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
+
+       /*
+        * queue initialization handlers
+        */
+       bool (*get_entry_state) (struct queue_entry *entry);
+       void (*clear_entry) (struct queue_entry *entry);
+
+       /*
+        * Radio control handlers.
+        */
+       int (*set_device_state) (struct rt2x00_dev *rt2x00dev,
+                                enum dev_state state);
+       int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev);
+       void (*link_stats) (struct rt2x00_dev *rt2x00dev,
+                           struct link_qual *qual);
+       void (*reset_tuner) (struct rt2x00_dev *rt2x00dev,
+                            struct link_qual *qual);
+       void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
+                           struct link_qual *qual, const u32 count);
+       void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
+       void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
+
+       /*
+        * Data queue handlers.
+        */
+       void (*watchdog) (struct rt2x00_dev *rt2x00dev);
+       void (*start_queue) (struct data_queue *queue);
+       void (*kick_queue) (struct data_queue *queue);
+       void (*stop_queue) (struct data_queue *queue);
+       void (*flush_queue) (struct data_queue *queue, bool drop);
+       void (*tx_dma_done) (struct queue_entry *entry);
+
+       /*
+        * TX control handlers
+        */
+       void (*write_tx_desc) (struct queue_entry *entry,
+                              struct txentry_desc *txdesc);
+       void (*write_tx_data) (struct queue_entry *entry,
+                              struct txentry_desc *txdesc);
+       void (*write_beacon) (struct queue_entry *entry,
+                             struct txentry_desc *txdesc);
+       void (*clear_beacon) (struct queue_entry *entry);
+       int (*get_tx_data_len) (struct queue_entry *entry);
+
+       /*
+        * RX control handlers
+        */
+       void (*fill_rxdone) (struct queue_entry *entry,
+                            struct rxdone_entry_desc *rxdesc);
+
+       /*
+        * Configuration handlers.
+        */
+       int (*config_shared_key) (struct rt2x00_dev *rt2x00dev,
+                                 struct rt2x00lib_crypto *crypto,
+                                 struct ieee80211_key_conf *key);
+       int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev,
+                                   struct rt2x00lib_crypto *crypto,
+                                   struct ieee80211_key_conf *key);
+       void (*config_filter) (struct rt2x00_dev *rt2x00dev,
+                              const unsigned int filter_flags);
+       void (*config_intf) (struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00_intf *intf,
+                            struct rt2x00intf_conf *conf,
+                            const unsigned int flags);
+#define CONFIG_UPDATE_TYPE             ( 1 << 1 )
+#define CONFIG_UPDATE_MAC              ( 1 << 2 )
+#define CONFIG_UPDATE_BSSID            ( 1 << 3 )
+
+       void (*config_erp) (struct rt2x00_dev *rt2x00dev,
+                           struct rt2x00lib_erp *erp,
+                           u32 changed);
+       void (*config_ant) (struct rt2x00_dev *rt2x00dev,
+                           struct antenna_setup *ant);
+       void (*config) (struct rt2x00_dev *rt2x00dev,
+                       struct rt2x00lib_conf *libconf,
+                       const unsigned int changed_flags);
+       int (*sta_add) (struct rt2x00_dev *rt2x00dev,
+                       struct ieee80211_vif *vif,
+                       struct ieee80211_sta *sta);
+       int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
+                          int wcid);
+};
+
+/*
+ * rt2x00 driver callback operation structure.
+ */
+struct rt2x00_ops {
+       const char *name;
+       const unsigned int drv_data_size;
+       const unsigned int max_ap_intf;
+       const unsigned int eeprom_size;
+       const unsigned int rf_size;
+       const unsigned int tx_queues;
+       void (*queue_init)(struct data_queue *queue);
+       const struct rt2x00lib_ops *lib;
+       const void *drv;
+       const struct ieee80211_ops *hw;
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       const struct rt2x00debug *debugfs;
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * rt2x00 state flags
+ */
+enum rt2x00_state_flags {
+       /*
+        * Device flags
+        */
+       DEVICE_STATE_PRESENT,
+       DEVICE_STATE_REGISTERED_HW,
+       DEVICE_STATE_INITIALIZED,
+       DEVICE_STATE_STARTED,
+       DEVICE_STATE_ENABLED_RADIO,
+       DEVICE_STATE_SCANNING,
+
+       /*
+        * Driver configuration
+        */
+       CONFIG_CHANNEL_HT40,
+       CONFIG_POWERSAVING,
+       CONFIG_HT_DISABLED,
+       CONFIG_QOS_DISABLED,
+
+       /*
+        * Mark we currently are sequentially reading TX_STA_FIFO register
+        * FIXME: this is for only rt2800usb, should go to private data
+        */
+       TX_STATUS_READING,
+};
+
+/*
+ * rt2x00 capability flags
+ */
+enum rt2x00_capability_flags {
+       /*
+        * Requirements
+        */
+       REQUIRE_FIRMWARE,
+       REQUIRE_BEACON_GUARD,
+       REQUIRE_ATIM_QUEUE,
+       REQUIRE_DMA,
+       REQUIRE_COPY_IV,
+       REQUIRE_L2PAD,
+       REQUIRE_TXSTATUS_FIFO,
+       REQUIRE_TASKLET_CONTEXT,
+       REQUIRE_SW_SEQNO,
+       REQUIRE_HT_TX_DESC,
+       REQUIRE_PS_AUTOWAKE,
+       REQUIRE_DELAYED_RFKILL,
+
+       /*
+        * Capabilities
+        */
+       CAPABILITY_HW_BUTTON,
+       CAPABILITY_HW_CRYPTO,
+       CAPABILITY_POWER_LIMIT,
+       CAPABILITY_CONTROL_FILTERS,
+       CAPABILITY_CONTROL_FILTER_PSPOLL,
+       CAPABILITY_PRE_TBTT_INTERRUPT,
+       CAPABILITY_LINK_TUNING,
+       CAPABILITY_FRAME_TYPE,
+       CAPABILITY_RF_SEQUENCE,
+       CAPABILITY_EXTERNAL_LNA_A,
+       CAPABILITY_EXTERNAL_LNA_BG,
+       CAPABILITY_DOUBLE_ANTENNA,
+       CAPABILITY_BT_COEXIST,
+       CAPABILITY_VCO_RECALIBRATION,
+};
+
+/*
+ * Interface combinations
+ */
+enum {
+       IF_COMB_AP = 0,
+       NUM_IF_COMB,
+};
+
+/*
+ * rt2x00 device structure.
+ */
+struct rt2x00_dev {
+       /*
+        * Device structure.
+        * The structure stored in here depends on the
+        * system bus (PCI or USB).
+        * When accessing this variable, the rt2x00dev_{pci,usb}
+        * macros should be used for correct typecasting.
+        */
+       struct device *dev;
+
+       /*
+        * Callback functions.
+        */
+       const struct rt2x00_ops *ops;
+
+       /*
+        * Driver data.
+        */
+       void *drv_data;
+
+       /*
+        * IEEE80211 control structure.
+        */
+       struct ieee80211_hw *hw;
+       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+       enum ieee80211_band curr_band;
+       int curr_freq;
+
+       /*
+        * If enabled, the debugfs interface structures
+        * required for deregistration of debugfs.
+        */
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       struct rt2x00debug_intf *debugfs_intf;
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+       /*
+        * LED structure for changing the LED status
+        * by mac8011 or the kernel.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       struct rt2x00_led led_radio;
+       struct rt2x00_led led_assoc;
+       struct rt2x00_led led_qual;
+       u16 led_mcu_reg;
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       /*
+        * Device state flags.
+        * In these flags the current status is stored.
+        * Access to these flags should occur atomically.
+        */
+       unsigned long flags;
+
+       /*
+        * Device capabiltiy flags.
+        * In these flags the device/driver capabilities are stored.
+        * Access to these flags should occur non-atomically.
+        */
+       unsigned long cap_flags;
+
+       /*
+        * Device information, Bus IRQ and name (PCI, SoC)
+        */
+       int irq;
+       const char *name;
+
+       /*
+        * Chipset identification.
+        */
+       struct rt2x00_chip chip;
+
+       /*
+        * hw capability specifications.
+        */
+       struct hw_mode_spec spec;
+
+       /*
+        * This is the default TX/RX antenna setup as indicated
+        * by the device's EEPROM.
+        */
+       struct antenna_setup default_ant;
+
+       /*
+        * Register pointers
+        * csr.base: CSR base register address. (PCI)
+        * csr.cache: CSR cache for usb_control_msg. (USB)
+        */
+       union csr {
+               void __iomem *base;
+               void *cache;
+       } csr;
+
+       /*
+        * Mutex to protect register accesses.
+        * For PCI and USB devices it protects against concurrent indirect
+        * register access (BBP, RF, MCU) since accessing those
+        * registers require multiple calls to the CSR registers.
+        * For USB devices it also protects the csr_cache since that
+        * field is used for normal CSR access and it cannot support
+        * multiple callers simultaneously.
+        */
+       struct mutex csr_mutex;
+
+       /*
+        * Current packet filter configuration for the device.
+        * This contains all currently active FIF_* flags send
+        * to us by mac80211 during configure_filter().
+        */
+       unsigned int packet_filter;
+
+       /*
+        * Interface details:
+        *  - Open ap interface count.
+        *  - Open sta interface count.
+        *  - Association count.
+        *  - Beaconing enabled count.
+        */
+       unsigned int intf_ap_count;
+       unsigned int intf_sta_count;
+       unsigned int intf_associated;
+       unsigned int intf_beaconing;
+
+       /*
+        * Interface combinations
+        */
+       struct ieee80211_iface_limit if_limits_ap;
+       struct ieee80211_iface_combination if_combinations[NUM_IF_COMB];
+
+       /*
+        * Link quality
+        */
+       struct link link;
+
+       /*
+        * EEPROM data.
+        */
+       __le16 *eeprom;
+
+       /*
+        * Active RF register values.
+        * These are stored here so we don't need
+        * to read the rf registers and can directly
+        * use this value instead.
+        * This field should be accessed by using
+        * rt2x00_rf_read() and rt2x00_rf_write().
+        */
+       u32 *rf;
+
+       /*
+        * LNA gain
+        */
+       short lna_gain;
+
+       /*
+        * Current TX power value.
+        */
+       u16 tx_power;
+
+       /*
+        * Current retry values.
+        */
+       u8 short_retry;
+       u8 long_retry;
+
+       /*
+        * Rssi <-> Dbm offset
+        */
+       u8 rssi_offset;
+
+       /*
+        * Frequency offset.
+        */
+       u8 freq_offset;
+
+       /*
+        * Association id.
+        */
+       u16 aid;
+
+       /*
+        * Beacon interval.
+        */
+       u16 beacon_int;
+
+       /**
+        * Timestamp of last received beacon
+        */
+       unsigned long last_beacon;
+
+       /*
+        * Low level statistics which will have
+        * to be kept up to date while device is running.
+        */
+       struct ieee80211_low_level_stats low_level_stats;
+
+       /**
+        * Work queue for all work which should not be placed
+        * on the mac80211 workqueue (because of dependencies
+        * between various work structures).
+        */
+       struct workqueue_struct *workqueue;
+
+       /*
+        * Scheduled work.
+        * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
+        * which means it cannot be placed on the hw->workqueue
+        * due to RTNL locking requirements.
+        */
+       struct work_struct intf_work;
+
+       /**
+        * Scheduled work for TX/RX done handling (USB devices)
+        */
+       struct work_struct rxdone_work;
+       struct work_struct txdone_work;
+
+       /*
+        * Powersaving work
+        */
+       struct delayed_work autowakeup_work;
+       struct work_struct sleep_work;
+
+       /*
+        * Data queue arrays for RX, TX, Beacon and ATIM.
+        */
+       unsigned int data_queues;
+       struct data_queue *rx;
+       struct data_queue *tx;
+       struct data_queue *bcn;
+       struct data_queue *atim;
+
+       /*
+        * Firmware image.
+        */
+       const struct firmware *fw;
+
+       /*
+        * FIFO for storing tx status reports between isr and tasklet.
+        */
+       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+
+       /*
+        * Timer to ensure tx status reports are read (rt2800usb).
+        */
+       struct hrtimer txstatus_timer;
+
+       /*
+        * Tasklet for processing tx status reports (rt2800pci).
+        */
+       struct tasklet_struct txstatus_tasklet;
+       struct tasklet_struct pretbtt_tasklet;
+       struct tasklet_struct tbtt_tasklet;
+       struct tasklet_struct rxdone_tasklet;
+       struct tasklet_struct autowake_tasklet;
+
+       /*
+        * Used for VCO periodic calibration.
+        */
+       int rf_channel;
+
+       /*
+        * Protect the interrupt mask register.
+        */
+       spinlock_t irqmask_lock;
+
+       /*
+        * List of BlockAckReq TX entries that need driver BlockAck processing.
+        */
+       struct list_head bar_list;
+       spinlock_t bar_list_lock;
+
+       /* Extra TX headroom required for alignment purposes. */
+       unsigned int extra_tx_headroom;
+};
+
+struct rt2x00_bar_list_entry {
+       struct list_head list;
+       struct rcu_head head;
+
+       struct queue_entry *entry;
+       int block_acked;
+
+       /* Relevant parts of the IEEE80211 BAR header */
+       __u8 ra[6];
+       __u8 ta[6];
+       __le16 control;
+       __le16 start_seq_num;
+};
+
+/*
+ * Register defines.
+ * Some registers require multiple attempts before success,
+ * in those cases REGISTER_BUSY_COUNT attempts should be
+ * taken with a REGISTER_BUSY_DELAY interval. Due to USB
+ * bus delays, we do not have to loop so many times to wait
+ * for valid register value on that bus.
+ */
+#define REGISTER_BUSY_COUNT    100
+#define REGISTER_USB_BUSY_COUNT 20
+#define REGISTER_BUSY_DELAY    100
+
+/*
+ * Generic RF access.
+ * The RF is being accessed by word index.
+ */
+static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
+                                 const unsigned int word, u32 *data)
+{
+       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+       *data = rt2x00dev->rf[word - 1];
+}
+
+static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int word, u32 data)
+{
+       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+       rt2x00dev->rf[word - 1] = data;
+}
+
+/*
+ * Generic EEPROM access. The EEPROM is being accessed by word or byte index.
+ */
+static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
+                                      const unsigned int word)
+{
+       return (void *)&rt2x00dev->eeprom[word];
+}
+
+static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
+                                     const unsigned int word, u16 *data)
+{
+       *data = le16_to_cpu(rt2x00dev->eeprom[word]);
+}
+
+static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
+                                      const unsigned int word, u16 data)
+{
+       rt2x00dev->eeprom[word] = cpu_to_le16(data);
+}
+
+static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev,
+                                   const unsigned int byte)
+{
+       return *(((u8 *)rt2x00dev->eeprom) + byte);
+}
+
+/*
+ * Chipset handlers
+ */
+static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
+                                  const u16 rt, const u16 rf, const u16 rev)
+{
+       rt2x00dev->chip.rt = rt;
+       rt2x00dev->chip.rf = rf;
+       rt2x00dev->chip.rev = rev;
+
+       rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n",
+                   rt2x00dev->chip.rt, rt2x00dev->chip.rf,
+                   rt2x00dev->chip.rev);
+}
+
+static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
+                                const u16 rt, const u16 rev)
+{
+       rt2x00dev->chip.rt = rt;
+       rt2x00dev->chip.rev = rev;
+
+       rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
+                   rt2x00dev->chip.rt, rt2x00dev->chip.rev);
+}
+
+static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
+{
+       rt2x00dev->chip.rf = rf;
+
+       rt2x00_info(rt2x00dev, "RF chipset %04x detected\n",
+                   rt2x00dev->chip.rf);
+}
+
+static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
+{
+       return (rt2x00dev->chip.rt == rt);
+}
+
+static inline bool rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
+{
+       return (rt2x00dev->chip.rf == rf);
+}
+
+static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00dev->chip.rev;
+}
+
+static inline bool rt2x00_rt_rev(struct rt2x00_dev *rt2x00dev,
+                                const u16 rt, const u16 rev)
+{
+       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) == rev);
+}
+
+static inline bool rt2x00_rt_rev_lt(struct rt2x00_dev *rt2x00dev,
+                                   const u16 rt, const u16 rev)
+{
+       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) < rev);
+}
+
+static inline bool rt2x00_rt_rev_gte(struct rt2x00_dev *rt2x00dev,
+                                    const u16 rt, const u16 rev)
+{
+       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) >= rev);
+}
+
+static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
+                                       enum rt2x00_chip_intf intf)
+{
+       rt2x00dev->chip.intf = intf;
+}
+
+static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev,
+                              enum rt2x00_chip_intf intf)
+{
+       return (rt2x00dev->chip.intf == intf);
+}
+
+static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI) ||
+              rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+}
+
+static inline bool rt2x00_is_pcie(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+}
+
+static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+}
+
+static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+}
+
+/* Helpers for capability flags */
+
+static inline bool
+rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev,
+                   enum rt2x00_capability_flags cap_flag)
+{
+       return test_bit(cap_flag, &rt2x00dev->cap_flags);
+}
+
+static inline bool
+rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO);
+}
+
+static inline bool
+rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT);
+}
+
+static inline bool
+rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS);
+}
+
+static inline bool
+rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL);
+}
+
+static inline bool
+rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT);
+}
+
+static inline bool
+rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING);
+}
+
+static inline bool
+rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE);
+}
+
+static inline bool
+rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE);
+}
+
+static inline bool
+rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A);
+}
+
+static inline bool
+rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG);
+}
+
+static inline bool
+rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA);
+}
+
+static inline bool
+rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST);
+}
+
+static inline bool
+rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev)
+{
+       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION);
+}
+
+/**
+ * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
+ * @entry: Pointer to &struct queue_entry
+ *
+ * Returns -ENOMEM if mapping fail, 0 otherwise.
+ */
+int rt2x00queue_map_txskb(struct queue_entry *entry);
+
+/**
+ * rt2x00queue_unmap_skb - Unmap a skb from DMA.
+ * @entry: Pointer to &struct queue_entry
+ */
+void rt2x00queue_unmap_skb(struct queue_entry *entry);
+
+/**
+ * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @queue: rt2x00 queue index (see &enum data_queue_qid).
+ *
+ * Returns NULL for non tx queues.
+ */
+static inline struct data_queue *
+rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev,
+                        const enum data_queue_qid queue)
+{
+       if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
+               return &rt2x00dev->tx[queue];
+
+       if (queue == QID_ATIM)
+               return rt2x00dev->atim;
+
+       return NULL;
+}
+
+/**
+ * rt2x00queue_get_entry - Get queue entry where the given index points to.
+ * @queue: Pointer to &struct data_queue from where we obtain the entry.
+ * @index: Index identifier for obtaining the correct index.
+ */
+struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
+                                         enum queue_index index);
+
+/**
+ * rt2x00queue_pause_queue - Pause a data queue
+ * @queue: Pointer to &struct data_queue.
+ *
+ * This function will pause the data queue locally, preventing
+ * new frames to be added to the queue (while the hardware is
+ * still allowed to run).
+ */
+void rt2x00queue_pause_queue(struct data_queue *queue);
+
+/**
+ * rt2x00queue_unpause_queue - unpause a data queue
+ * @queue: Pointer to &struct data_queue.
+ *
+ * This function will unpause the data queue locally, allowing
+ * new frames to be added to the queue again.
+ */
+void rt2x00queue_unpause_queue(struct data_queue *queue);
+
+/**
+ * rt2x00queue_start_queue - Start a data queue
+ * @queue: Pointer to &struct data_queue.
+ *
+ * This function will start handling all pending frames in the queue.
+ */
+void rt2x00queue_start_queue(struct data_queue *queue);
+
+/**
+ * rt2x00queue_stop_queue - Halt a data queue
+ * @queue: Pointer to &struct data_queue.
+ *
+ * This function will stop all pending frames in the queue.
+ */
+void rt2x00queue_stop_queue(struct data_queue *queue);
+
+/**
+ * rt2x00queue_flush_queue - Flush a data queue
+ * @queue: Pointer to &struct data_queue.
+ * @drop: True to drop all pending frames.
+ *
+ * This function will flush the queue. After this call
+ * the queue is guaranteed to be empty.
+ */
+void rt2x00queue_flush_queue(struct data_queue *queue, bool drop);
+
+/**
+ * rt2x00queue_start_queues - Start all data queues
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This function will loop through all available queues to start them
+ */
+void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00queue_stop_queues - Halt all data queues
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This function will loop through all available queues to stop
+ * any pending frames.
+ */
+void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00queue_flush_queues - Flush all data queues
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @drop: True to drop all pending frames.
+ *
+ * This function will loop through all available queues to flush
+ * any pending frames.
+ */
+void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop);
+
+/*
+ * Debugfs handlers.
+ */
+/**
+ * rt2x00debug_dump_frame - Dump a frame to userspace through debugfs.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @type: The type of frame that is being dumped.
+ * @skb: The skb containing the frame to be dumped.
+ */
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+                           enum rt2x00_dump_type type, struct sk_buff *skb);
+#else
+static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+                                         enum rt2x00_dump_type type,
+                                         struct sk_buff *skb)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+                        struct ieee80211_vif *vif);
+
+/*
+ * Interrupt context handlers.
+ */
+void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_dmastart(struct queue_entry *entry);
+void rt2x00lib_dmadone(struct queue_entry *entry);
+void rt2x00lib_txdone(struct queue_entry *entry,
+                     struct txdone_entry_desc *txdesc);
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
+void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp);
+
+/*
+ * mac80211 handlers.
+ */
+void rt2x00mac_tx(struct ieee80211_hw *hw,
+                 struct ieee80211_tx_control *control,
+                 struct sk_buff *skb);
+int rt2x00mac_start(struct ieee80211_hw *hw);
+void rt2x00mac_stop(struct ieee80211_hw *hw);
+int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif);
+void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif);
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
+void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
+                               unsigned int changed_flags,
+                               unsigned int *total_flags,
+                               u64 multicast);
+int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+                     bool set);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                     struct ieee80211_key_conf *key);
+#else
+#define rt2x00mac_set_key      NULL
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta);
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta);
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif,
+                            const u8 *mac_addr);
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif);
+int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+                       struct ieee80211_low_level_stats *stats);
+void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_bss_conf *bss_conf,
+                               u32 changes);
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+                     struct ieee80211_vif *vif, u16 queue,
+                     const struct ieee80211_tx_queue_params *params);
+void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
+void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                    u32 queues, bool drop);
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
+
+/*
+ * Driver allocation handlers.
+ */
+int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev);
+#ifdef CONFIG_PM
+int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state);
+int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev);
+#endif /* CONFIG_PM */
+
+#endif /* RT2X00_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
new file mode 100644 (file)
index 0000000..7e8bb11
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 generic configuration routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
+                          struct rt2x00_intf *intf,
+                          enum nl80211_iftype type,
+                          const u8 *mac, const u8 *bssid)
+{
+       struct rt2x00intf_conf conf;
+       unsigned int flags = 0;
+
+       conf.type = type;
+
+       switch (type) {
+       case NL80211_IFTYPE_ADHOC:
+               conf.sync = TSF_SYNC_ADHOC;
+               break;
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_WDS:
+               conf.sync = TSF_SYNC_AP_NONE;
+               break;
+       case NL80211_IFTYPE_STATION:
+               conf.sync = TSF_SYNC_INFRA;
+               break;
+       default:
+               conf.sync = TSF_SYNC_NONE;
+               break;
+       }
+
+       /*
+        * Note that when NULL is passed as address we will send
+        * 00:00:00:00:00 to the device to clear the address.
+        * This will prevent the device being confused when it wants
+        * to ACK frames or considers itself associated.
+        */
+       memset(conf.mac, 0, sizeof(conf.mac));
+       if (mac)
+               memcpy(conf.mac, mac, ETH_ALEN);
+
+       memset(conf.bssid, 0, sizeof(conf.bssid));
+       if (bssid)
+               memcpy(conf.bssid, bssid, ETH_ALEN);
+
+       flags |= CONFIG_UPDATE_TYPE;
+       if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
+               flags |= CONFIG_UPDATE_MAC;
+       if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
+               flags |= CONFIG_UPDATE_BSSID;
+
+       rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
+}
+
+void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
+                         struct rt2x00_intf *intf,
+                         struct ieee80211_bss_conf *bss_conf,
+                         u32 changed)
+{
+       struct rt2x00lib_erp erp;
+
+       memset(&erp, 0, sizeof(erp));
+
+       erp.short_preamble = bss_conf->use_short_preamble;
+       erp.cts_protection = bss_conf->use_cts_prot;
+
+       erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
+       erp.sifs = SIFS;
+       erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
+       erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
+       erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
+
+       erp.basic_rates = bss_conf->basic_rates;
+       erp.beacon_int = bss_conf->beacon_int;
+
+       /* Update the AID, this is needed for dynamic PS support */
+       rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
+       rt2x00dev->last_beacon = bss_conf->sync_tsf;
+
+       /* Update global beacon interval time, this is needed for PS support */
+       rt2x00dev->beacon_int = bss_conf->beacon_int;
+
+       if (changed & BSS_CHANGED_HT)
+               erp.ht_opmode = bss_conf->ht_operation_mode;
+
+       rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
+}
+
+void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+                             struct antenna_setup config)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup *def = &rt2x00dev->default_ant;
+       struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+       /*
+        * When the caller tries to send the SW diversity,
+        * we must update the ANTENNA_RX_DIVERSITY flag to
+        * enable the antenna diversity in the link tuner.
+        *
+        * Secondly, we must guarentee we never send the
+        * software antenna diversity command to the driver.
+        */
+       if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
+               if (config.rx == ANTENNA_SW_DIVERSITY) {
+                       ant->flags |= ANTENNA_RX_DIVERSITY;
+
+                       if (def->rx == ANTENNA_SW_DIVERSITY)
+                               config.rx = ANTENNA_B;
+                       else
+                               config.rx = def->rx;
+               }
+       } else if (config.rx == ANTENNA_SW_DIVERSITY)
+               config.rx = active->rx;
+
+       if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
+               if (config.tx == ANTENNA_SW_DIVERSITY) {
+                       ant->flags |= ANTENNA_TX_DIVERSITY;
+
+                       if (def->tx == ANTENNA_SW_DIVERSITY)
+                               config.tx = ANTENNA_B;
+                       else
+                               config.tx = def->tx;
+               }
+       } else if (config.tx == ANTENNA_SW_DIVERSITY)
+               config.tx = active->tx;
+
+       /*
+        * Antenna setup changes require the RX to be disabled,
+        * else the changes will be ignored by the device.
+        */
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2x00queue_stop_queue(rt2x00dev->rx);
+
+       /*
+        * Write new antenna setup to device and reset the link tuner.
+        * The latter is required since we need to recalibrate the
+        * noise-sensitivity ratio for the new setup.
+        */
+       rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
+
+       rt2x00link_reset_tuner(rt2x00dev, true);
+
+       memcpy(active, &config, sizeof(config));
+
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2x00queue_start_queue(rt2x00dev->rx);
+}
+
+static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
+                                  struct ieee80211_conf *conf)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       int center_channel;
+       u16 i;
+
+       /*
+        * Initialize center channel to current channel.
+        */
+       center_channel = spec->channels[conf->chandef.chan->hw_value].channel;
+
+       /*
+        * Adjust center channel to HT40+ and HT40- operation.
+        */
+       if (conf_is_ht40_plus(conf))
+               center_channel += 2;
+       else if (conf_is_ht40_minus(conf))
+               center_channel -= (center_channel == 14) ? 1 : 2;
+
+       for (i = 0; i < spec->num_channels; i++)
+               if (spec->channels[i].channel == center_channel)
+                       return i;
+
+       WARN_ON(1);
+       return conf->chandef.chan->hw_value;
+}
+
+void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+                     struct ieee80211_conf *conf,
+                     unsigned int ieee80211_flags)
+{
+       struct rt2x00lib_conf libconf;
+       u16 hw_value;
+       u16 autowake_timeout;
+       u16 beacon_int;
+       u16 beacon_diff;
+
+       memset(&libconf, 0, sizeof(libconf));
+
+       libconf.conf = conf;
+
+       if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
+               if (!conf_is_ht(conf))
+                       set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
+               else
+                       clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
+
+               if (conf_is_ht40(conf)) {
+                       set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+                       hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
+               } else {
+                       clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+                       hw_value = conf->chandef.chan->hw_value;
+               }
+
+               memcpy(&libconf.rf,
+                      &rt2x00dev->spec.channels[hw_value],
+                      sizeof(libconf.rf));
+
+               memcpy(&libconf.channel,
+                      &rt2x00dev->spec.channels_info[hw_value],
+                      sizeof(libconf.channel));
+
+               /* Used for VCO periodic calibration */
+               rt2x00dev->rf_channel = libconf.rf.channel;
+       }
+
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
+           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
+               cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+
+       /*
+        * Start configuration.
+        */
+       rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
+
+       /*
+        * Some configuration changes affect the link quality
+        * which means we need to reset the link tuner.
+        */
+       if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt2x00link_reset_tuner(rt2x00dev, false);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
+           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
+           (conf->flags & IEEE80211_CONF_PS)) {
+               beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
+               beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
+
+               if (beacon_diff > beacon_int)
+                       beacon_diff = 0;
+
+               autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff;
+               queue_delayed_work(rt2x00dev->workqueue,
+                                  &rt2x00dev->autowakeup_work,
+                                  autowake_timeout - 15);
+       }
+
+       if (conf->flags & IEEE80211_CONF_PS)
+               set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+       else
+               clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+
+       rt2x00dev->curr_band = conf->chandef.chan->band;
+       rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
+       rt2x00dev->tx_power = conf->power_level;
+       rt2x00dev->short_retry = conf->short_frame_max_tx_count;
+       rt2x00dev->long_retry = conf->long_frame_max_tx_count;
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00crypto.c b/drivers/net/wireless/ralink/rt2x00/rt2x00crypto.c
new file mode 100644 (file)
index 0000000..a2fd05b
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 crypto specific routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
+{
+       switch (key->cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+               return CIPHER_WEP64;
+       case WLAN_CIPHER_SUITE_WEP104:
+               return CIPHER_WEP128;
+       case WLAN_CIPHER_SUITE_TKIP:
+               return CIPHER_TKIP;
+       case WLAN_CIPHER_SUITE_CCMP:
+               return CIPHER_AES;
+       default:
+               return CIPHER_NONE;
+       }
+}
+
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+                                      struct sk_buff *skb,
+                                      struct txentry_desc *txdesc)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+
+       if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key)
+               return;
+
+       __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
+
+       txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
+
+       if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+               __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
+
+       txdesc->key_idx = hw_key->hw_key_idx;
+       txdesc->iv_offset = txdesc->header_length;
+       txdesc->iv_len = hw_key->iv_len;
+
+       if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+               __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
+
+       if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
+               __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
+}
+
+unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_key_conf *key = tx_info->control.hw_key;
+       unsigned int overhead = 0;
+
+       if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key)
+               return overhead;
+
+       /*
+        * Extend frame length to include IV/EIV/ICV/MMIC,
+        * note that these lengths should only be added when
+        * mac80211 does not generate it.
+        */
+       overhead += key->icv_len;
+
+       if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+               overhead += key->iv_len;
+
+       if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
+               if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
+                       overhead += 8;
+       }
+
+       return overhead;
+}
+
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+
+       if (unlikely(!txdesc->iv_len))
+               return;
+
+       /* Copy IV/EIV data */
+       memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
+}
+
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+
+       if (unlikely(!txdesc->iv_len))
+               return;
+
+       /* Copy IV/EIV data */
+       memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
+
+       /* Move ieee80211 header */
+       memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);
+
+       /* Pull buffer to correct size */
+       skb_pull(skb, txdesc->iv_len);
+       txdesc->length -= txdesc->iv_len;
+
+       /* IV/EIV data has officially been stripped */
+       skbdesc->flags |= SKBDESC_IV_STRIPPED;
+}
+
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+       const unsigned int iv_len =
+           ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
+
+       if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
+               return;
+
+       skb_push(skb, iv_len);
+
+       /* Move ieee80211 header */
+       memmove(skb->data, skb->data + iv_len, header_length);
+
+       /* Copy IV/EIV data */
+       memcpy(skb->data + header_length, skbdesc->iv, iv_len);
+
+       /* IV/EIV data has returned into the frame */
+       skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
+}
+
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
+                              unsigned int header_length,
+                              struct rxdone_entry_desc *rxdesc)
+{
+       unsigned int payload_len = rxdesc->size - header_length;
+       unsigned int align = ALIGN_SIZE(skb, header_length);
+       unsigned int iv_len;
+       unsigned int icv_len;
+       unsigned int transfer = 0;
+
+       /*
+        * WEP64/WEP128: Provides IV & ICV
+        * TKIP: Provides IV/EIV & ICV
+        * AES: Provies IV/EIV & ICV
+        */
+       switch (rxdesc->cipher) {
+       case CIPHER_WEP64:
+       case CIPHER_WEP128:
+               iv_len = 4;
+               icv_len = 4;
+               break;
+       case CIPHER_TKIP:
+               iv_len = 8;
+               icv_len = 4;
+               break;
+       case CIPHER_AES:
+               iv_len = 8;
+               icv_len = 8;
+               break;
+       default:
+               /* Unsupport type */
+               return;
+       }
+
+       /*
+        * Make room for new data. There are 2 possibilities
+        * either the alignment is already present between
+        * the 802.11 header and payload. In that case we
+        * we have to move the header less then the iv_len
+        * since we can use the already available l2pad bytes
+        * for the iv data.
+        * When the alignment must be added manually we must
+        * move the header more then iv_len since we must
+        * make room for the payload move as well.
+        */
+       if (rxdesc->dev_flags & RXDONE_L2PAD) {
+               skb_push(skb, iv_len - align);
+               skb_put(skb, icv_len);
+
+               /* Move ieee80211 header */
+               memmove(skb->data + transfer,
+                       skb->data + transfer + (iv_len - align),
+                       header_length);
+               transfer += header_length;
+       } else {
+               skb_push(skb, iv_len + align);
+               if (align < icv_len)
+                       skb_put(skb, icv_len - align);
+               else if (align > icv_len)
+                       skb_trim(skb, rxdesc->size + iv_len + icv_len);
+
+               /* Move ieee80211 header */
+               memmove(skb->data + transfer,
+                       skb->data + transfer + iv_len + align,
+                       header_length);
+               transfer += header_length;
+       }
+
+       /* Copy IV/EIV data */
+       memcpy(skb->data + transfer, rxdesc->iv, iv_len);
+       transfer += iv_len;
+
+       /*
+        * Move payload for alignment purposes. Note that
+        * this is only needed when no l2 padding is present.
+        */
+       if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
+               memmove(skb->data + transfer,
+                       skb->data + transfer + align,
+                       payload_len);
+       }
+
+       /*
+        * NOTE: Always count the payload as transferred,
+        * even when alignment was set to zero. This is required
+        * for determining the correct offset for the ICV data.
+        */
+       transfer += payload_len;
+
+       /*
+        * Copy ICV data
+        * AES appends 8 bytes, we can't fill the upper
+        * 4 bytes, but mac80211 doesn't care about what
+        * we provide here anyway and strips it immediately.
+        */
+       memcpy(skb->data + transfer, &rxdesc->icv, 4);
+       transfer += icv_len;
+
+       /* IV/EIV/ICV has been inserted into frame */
+       rxdesc->size = transfer;
+       rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
new file mode 100644 (file)
index 0000000..90fdb02
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 debugfs specific routines.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+#include "rt2x00dump.h"
+
+#define MAX_LINE_LENGTH 64
+
+struct rt2x00debug_crypto {
+       unsigned long success;
+       unsigned long icv_error;
+       unsigned long mic_error;
+       unsigned long key_error;
+};
+
+struct rt2x00debug_intf {
+       /*
+        * Pointer to driver structure where
+        * this debugfs entry belongs to.
+        */
+       struct rt2x00_dev *rt2x00dev;
+
+       /*
+        * Reference to the rt2x00debug structure
+        * which can be used to communicate with
+        * the registers.
+        */
+       const struct rt2x00debug *debug;
+
+       /*
+        * Debugfs entries for:
+        * - driver folder
+        *   - driver file
+        *   - chipset file
+        *   - device state flags file
+        *   - device capability flags file
+        *   - register folder
+        *     - csr offset/value files
+        *     - eeprom offset/value files
+        *     - bbp offset/value files
+        *     - rf offset/value files
+        *     - rfcsr offset/value files
+        *   - queue folder
+        *     - frame dump file
+        *     - queue stats file
+        *     - crypto stats file
+        */
+       struct dentry *driver_folder;
+       struct dentry *driver_entry;
+       struct dentry *chipset_entry;
+       struct dentry *dev_flags;
+       struct dentry *cap_flags;
+       struct dentry *register_folder;
+       struct dentry *csr_off_entry;
+       struct dentry *csr_val_entry;
+       struct dentry *eeprom_off_entry;
+       struct dentry *eeprom_val_entry;
+       struct dentry *bbp_off_entry;
+       struct dentry *bbp_val_entry;
+       struct dentry *rf_off_entry;
+       struct dentry *rf_val_entry;
+       struct dentry *rfcsr_off_entry;
+       struct dentry *rfcsr_val_entry;
+       struct dentry *queue_folder;
+       struct dentry *queue_frame_dump_entry;
+       struct dentry *queue_stats_entry;
+       struct dentry *crypto_stats_entry;
+
+       /*
+        * The frame dump file only allows a single reader,
+        * so we need to store the current state here.
+        */
+       unsigned long frame_dump_flags;
+#define FRAME_DUMP_FILE_OPEN   1
+
+       /*
+        * We queue each frame before dumping it to the user,
+        * per read command we will pass a single skb structure
+        * so we should be prepared to queue multiple sk buffers
+        * before sending it to userspace.
+        */
+       struct sk_buff_head frame_dump_skbqueue;
+       wait_queue_head_t frame_dump_waitqueue;
+
+       /*
+        * HW crypto statistics.
+        * All statistics are stored separately per cipher type.
+        */
+       struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
+
+       /*
+        * Driver and chipset files will use a data buffer
+        * that has been created in advance. This will simplify
+        * the code since we can use the debugfs functions.
+        */
+       struct debugfs_blob_wrapper driver_blob;
+       struct debugfs_blob_wrapper chipset_blob;
+
+       /*
+        * Requested offset for each register type.
+        */
+       unsigned int offset_csr;
+       unsigned int offset_eeprom;
+       unsigned int offset_bbp;
+       unsigned int offset_rf;
+       unsigned int offset_rfcsr;
+};
+
+void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+                              struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+       enum cipher cipher = rxdesc->cipher;
+       enum rx_crypto status = rxdesc->cipher_status;
+
+       if (cipher == CIPHER_TKIP_NO_MIC)
+               cipher = CIPHER_TKIP;
+       if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX)
+               return;
+
+       /* Remove CIPHER_NONE index */
+       cipher--;
+
+       intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
+       intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
+       intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
+       intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
+}
+
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+                           enum rt2x00_dump_type type, struct sk_buff *skb)
+{
+       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+       struct sk_buff *skbcopy;
+       struct rt2x00dump_hdr *dump_hdr;
+       struct timeval timestamp;
+       u32 data_len;
+
+       if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
+               return;
+
+       do_gettimeofday(&timestamp);
+
+       if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
+               rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
+               return;
+       }
+
+       data_len = skb->len;
+       if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
+               data_len -= skbdesc->desc_len;
+
+       skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
+                           GFP_ATOMIC);
+       if (!skbcopy) {
+               rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
+               return;
+       }
+
+       dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
+       dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
+       dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
+       dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
+       dump_hdr->data_length = cpu_to_le32(data_len);
+       dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
+       dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+       dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
+       dump_hdr->type = cpu_to_le16(type);
+       dump_hdr->queue_index = skbdesc->entry->queue->qid;
+       dump_hdr->entry_index = skbdesc->entry->entry_idx;
+       dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+       dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+
+       if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
+               memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
+                      skbdesc->desc_len);
+       memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
+
+       skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
+       wake_up_interruptible(&intf->frame_dump_waitqueue);
+
+       /*
+        * Verify that the file has not been closed while we were working.
+        */
+       if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+               skb_queue_purge(&intf->frame_dump_skbqueue);
+}
+EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame);
+
+static int rt2x00debug_file_open(struct inode *inode, struct file *file)
+{
+       struct rt2x00debug_intf *intf = inode->i_private;
+
+       file->private_data = inode->i_private;
+
+       if (!try_module_get(intf->debug->owner))
+               return -EBUSY;
+
+       return 0;
+}
+
+static int rt2x00debug_file_release(struct inode *inode, struct file *file)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+
+       module_put(intf->debug->owner);
+
+       return 0;
+}
+
+static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
+{
+       struct rt2x00debug_intf *intf = inode->i_private;
+       int retval;
+
+       retval = rt2x00debug_file_open(inode, file);
+       if (retval)
+               return retval;
+
+       if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
+               rt2x00debug_file_release(inode, file);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
+{
+       struct rt2x00debug_intf *intf = inode->i_private;
+
+       skb_queue_purge(&intf->frame_dump_skbqueue);
+
+       clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
+
+       return rt2x00debug_file_release(inode, file);
+}
+
+static ssize_t rt2x00debug_read_queue_dump(struct file *file,
+                                          char __user *buf,
+                                          size_t length,
+                                          loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       struct sk_buff *skb;
+       size_t status;
+       int retval;
+
+       if (file->f_flags & O_NONBLOCK)
+               return -EAGAIN;
+
+       retval =
+           wait_event_interruptible(intf->frame_dump_waitqueue,
+                                    (skb =
+                                    skb_dequeue(&intf->frame_dump_skbqueue)));
+       if (retval)
+               return retval;
+
+       status = min_t(size_t, skb->len, length);
+       if (copy_to_user(buf, skb->data, status)) {
+               status = -EFAULT;
+               goto exit;
+       }
+
+       *offset += status;
+
+exit:
+       kfree_skb(skb);
+
+       return status;
+}
+
+static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
+                                               poll_table *wait)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+
+       poll_wait(file, &intf->frame_dump_waitqueue, wait);
+
+       if (!skb_queue_empty(&intf->frame_dump_skbqueue))
+               return POLLOUT | POLLWRNORM;
+
+       return 0;
+}
+
+static const struct file_operations rt2x00debug_fop_queue_dump = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_queue_dump,
+       .poll           = rt2x00debug_poll_queue_dump,
+       .open           = rt2x00debug_open_queue_dump,
+       .release        = rt2x00debug_release_queue_dump,
+       .llseek         = default_llseek,
+};
+
+static ssize_t rt2x00debug_read_queue_stats(struct file *file,
+                                           char __user *buf,
+                                           size_t length,
+                                           loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       struct data_queue *queue;
+       unsigned long irqflags;
+       unsigned int lines = 1 + intf->rt2x00dev->data_queues;
+       size_t size;
+       char *data;
+       char *temp;
+
+       if (*offset)
+               return 0;
+
+       data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       temp = data +
+           sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
+
+       queue_for_each(intf->rt2x00dev, queue) {
+               spin_lock_irqsave(&queue->index_lock, irqflags);
+
+               temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
+                               queue->qid, (unsigned int)queue->flags,
+                               queue->count, queue->limit, queue->length,
+                               queue->index[Q_INDEX],
+                               queue->index[Q_INDEX_DMA_DONE],
+                               queue->index[Q_INDEX_DONE]);
+
+               spin_unlock_irqrestore(&queue->index_lock, irqflags);
+       }
+
+       size = strlen(data);
+       size = min(size, length);
+
+       if (copy_to_user(buf, data, size)) {
+               kfree(data);
+               return -EFAULT;
+       }
+
+       kfree(data);
+
+       *offset += size;
+       return size;
+}
+
+static const struct file_operations rt2x00debug_fop_queue_stats = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_queue_stats,
+       .open           = rt2x00debug_file_open,
+       .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
+};
+
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
+                                            char __user *buf,
+                                            size_t length,
+                                            loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
+       char *data;
+       char *temp;
+       size_t size;
+       unsigned int i;
+
+       if (*offset)
+               return 0;
+
+       data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       temp = data;
+       temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
+
+       for (i = 0; i < CIPHER_MAX; i++) {
+               temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
+                               intf->crypto_stats[i].success,
+                               intf->crypto_stats[i].icv_error,
+                               intf->crypto_stats[i].mic_error,
+                               intf->crypto_stats[i].key_error);
+       }
+
+       size = strlen(data);
+       size = min(size, length);
+
+       if (copy_to_user(buf, data, size)) {
+               kfree(data);
+               return -EFAULT;
+       }
+
+       kfree(data);
+
+       *offset += size;
+       return size;
+}
+
+static const struct file_operations rt2x00debug_fop_crypto_stats = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_crypto_stats,
+       .open           = rt2x00debug_file_open,
+       .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
+};
+#endif
+
+#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)       \
+static ssize_t rt2x00debug_read_##__name(struct file *file,    \
+                                        char __user *buf,      \
+                                        size_t length,         \
+                                        loff_t *offset)        \
+{                                                              \
+       struct rt2x00debug_intf *intf = file->private_data;     \
+       const struct rt2x00debug *debug = intf->debug;          \
+       char line[16];                                          \
+       size_t size;                                            \
+       unsigned int index = intf->offset_##__name;             \
+       __type value;                                           \
+                                                               \
+       if (*offset)                                            \
+               return 0;                                       \
+                                                               \
+       if (index >= debug->__name.word_count)                  \
+               return -EINVAL;                                 \
+                                                               \
+       index += (debug->__name.word_base /                     \
+                 debug->__name.word_size);                     \
+                                                               \
+       if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
+               index *= debug->__name.word_size;               \
+                                                               \
+       debug->__name.read(intf->rt2x00dev, index, &value);     \
+                                                               \
+       size = sprintf(line, __format, value);                  \
+                                                               \
+       if (copy_to_user(buf, line, size))                      \
+               return -EFAULT;                                 \
+                                                               \
+       *offset += size;                                        \
+       return size;                                            \
+}
+
+#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                        \
+static ssize_t rt2x00debug_write_##__name(struct file *file,   \
+                                         const char __user *buf,\
+                                         size_t length,        \
+                                         loff_t *offset)       \
+{                                                              \
+       struct rt2x00debug_intf *intf = file->private_data;     \
+       const struct rt2x00debug *debug = intf->debug;          \
+       char line[16];                                          \
+       size_t size;                                            \
+       unsigned int index = intf->offset_##__name;             \
+       __type value;                                           \
+                                                               \
+       if (*offset)                                            \
+               return 0;                                       \
+                                                               \
+       if (index >= debug->__name.word_count)                  \
+               return -EINVAL;                                 \
+                                                               \
+       if (length > sizeof(line))                              \
+               return -EINVAL;                                 \
+                                                               \
+       if (copy_from_user(line, buf, length))                  \
+               return -EFAULT;                                 \
+                                                               \
+       size = strlen(line);                                    \
+       value = simple_strtoul(line, NULL, 0);                  \
+                                                               \
+       index += (debug->__name.word_base /                     \
+                 debug->__name.word_size);                     \
+                                                               \
+       if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
+               index *= debug->__name.word_size;               \
+                                                               \
+       debug->__name.write(intf->rt2x00dev, index, value);     \
+                                                               \
+       *offset += size;                                        \
+       return size;                                            \
+}
+
+#define RT2X00DEBUGFS_OPS(__name, __format, __type)            \
+RT2X00DEBUGFS_OPS_READ(__name, __format, __type);              \
+RT2X00DEBUGFS_OPS_WRITE(__name, __type);                       \
+                                                               \
+static const struct file_operations rt2x00debug_fop_##__name = {\
+       .owner          = THIS_MODULE,                          \
+       .read           = rt2x00debug_read_##__name,            \
+       .write          = rt2x00debug_write_##__name,           \
+       .open           = rt2x00debug_file_open,                \
+       .release        = rt2x00debug_file_release,             \
+       .llseek         = generic_file_llseek,                  \
+};
+
+RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
+RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
+RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
+RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
+RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
+
+static ssize_t rt2x00debug_read_dev_flags(struct file *file,
+                                         char __user *buf,
+                                         size_t length,
+                                         loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       char line[16];
+       size_t size;
+
+       if (*offset)
+               return 0;
+
+       size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
+
+       if (copy_to_user(buf, line, size))
+               return -EFAULT;
+
+       *offset += size;
+       return size;
+}
+
+static const struct file_operations rt2x00debug_fop_dev_flags = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_dev_flags,
+       .open           = rt2x00debug_file_open,
+       .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
+};
+
+static ssize_t rt2x00debug_read_cap_flags(struct file *file,
+                                         char __user *buf,
+                                         size_t length,
+                                         loff_t *offset)
+{
+       struct rt2x00debug_intf *intf = file->private_data;
+       char line[16];
+       size_t size;
+
+       if (*offset)
+               return 0;
+
+       size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
+
+       if (copy_to_user(buf, line, size))
+               return -EFAULT;
+
+       *offset += size;
+       return size;
+}
+
+static const struct file_operations rt2x00debug_fop_cap_flags = {
+       .owner          = THIS_MODULE,
+       .read           = rt2x00debug_read_cap_flags,
+       .open           = rt2x00debug_file_open,
+       .release        = rt2x00debug_file_release,
+       .llseek         = default_llseek,
+};
+
+static struct dentry *rt2x00debug_create_file_driver(const char *name,
+                                                    struct rt2x00debug_intf
+                                                    *intf,
+                                                    struct debugfs_blob_wrapper
+                                                    *blob)
+{
+       char *data;
+
+       data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
+       if (!data)
+               return NULL;
+
+       blob->data = data;
+       data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
+       data += sprintf(data, "version:\t%s\n", DRV_VERSION);
+       blob->size = strlen(blob->data);
+
+       return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
+}
+
+static struct dentry *rt2x00debug_create_file_chipset(const char *name,
+                                                     struct rt2x00debug_intf
+                                                     *intf,
+                                                     struct
+                                                     debugfs_blob_wrapper
+                                                     *blob)
+{
+       const struct rt2x00debug *debug = intf->debug;
+       char *data;
+
+       data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
+       if (!data)
+               return NULL;
+
+       blob->data = data;
+       data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
+       data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
+       data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
+       data += sprintf(data, "\n");
+       data += sprintf(data, "register\tbase\twords\twordsize\n");
+#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name)                 \
+{                                                              \
+       if(debug->__name.read)                                  \
+               data += sprintf(data, __stringify(__name)       \
+                               "\t%d\t%d\t%d\n",               \
+                               debug->__name.word_base,        \
+                               debug->__name.word_count,       \
+                               debug->__name.word_size);       \
+}
+       RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
+       RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
+       RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
+       RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
+       RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
+#undef RT2X00DEBUGFS_SPRINTF_REGISTER
+
+       blob->size = strlen(blob->data);
+
+       return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
+}
+
+void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
+{
+       const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
+       struct rt2x00debug_intf *intf;
+
+       intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
+       if (!intf) {
+               rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
+               return;
+       }
+
+       intf->debug = debug;
+       intf->rt2x00dev = rt2x00dev;
+       rt2x00dev->debugfs_intf = intf;
+
+       intf->driver_folder =
+           debugfs_create_dir(intf->rt2x00dev->ops->name,
+                              rt2x00dev->hw->wiphy->debugfsdir);
+       if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
+               goto exit;
+
+       intf->driver_entry =
+           rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
+       if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
+               goto exit;
+
+       intf->chipset_entry =
+           rt2x00debug_create_file_chipset("chipset",
+                                           intf, &intf->chipset_blob);
+       if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
+               goto exit;
+
+       intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
+                                             intf->driver_folder, intf,
+                                             &rt2x00debug_fop_dev_flags);
+       if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
+               goto exit;
+
+       intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
+                                             intf->driver_folder, intf,
+                                             &rt2x00debug_fop_cap_flags);
+       if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
+               goto exit;
+
+       intf->register_folder =
+           debugfs_create_dir("register", intf->driver_folder);
+       if (IS_ERR(intf->register_folder) || !intf->register_folder)
+               goto exit;
+
+#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)                    \
+({                                                                             \
+       if(debug->__name.read) {                                                \
+               (__intf)->__name##_off_entry =                                  \
+               debugfs_create_u32(__stringify(__name) "_offset",               \
+                                      S_IRUSR | S_IWUSR,                       \
+                                      (__intf)->register_folder,               \
+                                      &(__intf)->offset_##__name);             \
+               if (IS_ERR((__intf)->__name##_off_entry)                        \
+                               || !(__intf)->__name##_off_entry)               \
+                       goto exit;                                              \
+                                                                               \
+               (__intf)->__name##_val_entry =                                  \
+               debugfs_create_file(__stringify(__name) "_value",               \
+                                       S_IRUSR | S_IWUSR,                      \
+                                       (__intf)->register_folder,              \
+                                       (__intf), &rt2x00debug_fop_##__name);   \
+               if (IS_ERR((__intf)->__name##_val_entry)                        \
+                               || !(__intf)->__name##_val_entry)               \
+                       goto exit;                                              \
+       }                                                                       \
+})
+
+       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
+       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
+       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
+       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
+       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
+
+#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
+
+       intf->queue_folder =
+           debugfs_create_dir("queue", intf->driver_folder);
+       if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
+               goto exit;
+
+       intf->queue_frame_dump_entry =
+           debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
+                               intf, &rt2x00debug_fop_queue_dump);
+       if (IS_ERR(intf->queue_frame_dump_entry)
+               || !intf->queue_frame_dump_entry)
+               goto exit;
+
+       skb_queue_head_init(&intf->frame_dump_skbqueue);
+       init_waitqueue_head(&intf->frame_dump_waitqueue);
+
+       intf->queue_stats_entry =
+           debugfs_create_file("queue", S_IRUSR, intf->queue_folder,
+                               intf, &rt2x00debug_fop_queue_stats);
+
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+       if (rt2x00_has_cap_hw_crypto(rt2x00dev))
+               intf->crypto_stats_entry =
+                   debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
+                                       intf, &rt2x00debug_fop_crypto_stats);
+#endif
+
+       return;
+
+exit:
+       rt2x00debug_deregister(rt2x00dev);
+       rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
+}
+
+void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+
+       if (unlikely(!intf))
+               return;
+
+       skb_queue_purge(&intf->frame_dump_skbqueue);
+
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+       debugfs_remove(intf->crypto_stats_entry);
+#endif
+       debugfs_remove(intf->queue_stats_entry);
+       debugfs_remove(intf->queue_frame_dump_entry);
+       debugfs_remove(intf->queue_folder);
+       debugfs_remove(intf->rfcsr_val_entry);
+       debugfs_remove(intf->rfcsr_off_entry);
+       debugfs_remove(intf->rf_val_entry);
+       debugfs_remove(intf->rf_off_entry);
+       debugfs_remove(intf->bbp_val_entry);
+       debugfs_remove(intf->bbp_off_entry);
+       debugfs_remove(intf->eeprom_val_entry);
+       debugfs_remove(intf->eeprom_off_entry);
+       debugfs_remove(intf->csr_val_entry);
+       debugfs_remove(intf->csr_off_entry);
+       debugfs_remove(intf->register_folder);
+       debugfs_remove(intf->dev_flags);
+       debugfs_remove(intf->cap_flags);
+       debugfs_remove(intf->chipset_entry);
+       debugfs_remove(intf->driver_entry);
+       debugfs_remove(intf->driver_folder);
+       kfree(intf->chipset_blob.data);
+       kfree(intf->driver_blob.data);
+       kfree(intf);
+
+       rt2x00dev->debugfs_intf = NULL;
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.h
new file mode 100644 (file)
index 0000000..e65712c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00debug
+       Abstract: Data structures for the rt2x00debug.
+ */
+
+#ifndef RT2X00DEBUG_H
+#define RT2X00DEBUG_H
+
+struct rt2x00_dev;
+
+/**
+ * enum rt2x00debugfs_entry_flags: Flags for debugfs registry entry
+ *
+ * @RT2X00DEBUGFS_OFFSET: rt2x00lib should pass the register offset
+ *     as argument when using the callback function read()/write()
+ */
+enum rt2x00debugfs_entry_flags {
+       RT2X00DEBUGFS_OFFSET    = (1 << 0),
+};
+
+#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type)           \
+struct reg##__name {                                           \
+       void (*read)(struct rt2x00_dev *rt2x00dev,              \
+                    const unsigned int word, __type *data);    \
+       void (*write)(struct rt2x00_dev *rt2x00dev,             \
+                     const unsigned int word, __type data);    \
+                                                               \
+       unsigned int flags;                                     \
+                                                               \
+       unsigned int word_base;                                 \
+       unsigned int word_size;                                 \
+       unsigned int word_count;                                \
+} __name
+
+struct rt2x00debug {
+       /*
+        * Reference to the modules structure.
+        */
+       struct module *owner;
+
+       /*
+        * Register access entries.
+        */
+       RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32);
+       RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
+       RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
+       RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
+       RT2X00DEBUGFS_REGISTER_ENTRY(rfcsr, u8);
+};
+
+#endif /* RT2X00DEBUG_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
new file mode 100644 (file)
index 0000000..5639ed8
--- /dev/null
@@ -0,0 +1,1549 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 generic device routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/log2.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+/*
+ * Utility functions.
+ */
+u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
+                        struct ieee80211_vif *vif)
+{
+       /*
+        * When in STA mode, bssidx is always 0 otherwise local_address[5]
+        * contains the bss number, see BSS_ID_MASK comments for details.
+        */
+       if (rt2x00dev->intf_sta_count)
+               return 0;
+       return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
+
+/*
+ * Radio control handlers.
+ */
+int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       int status;
+
+       /*
+        * Don't enable the radio twice.
+        * And check if the hardware button has been disabled.
+        */
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * Initialize all data queues.
+        */
+       rt2x00queue_init_queues(rt2x00dev);
+
+       /*
+        * Enable radio.
+        */
+       status =
+           rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
+       if (status)
+               return status;
+
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON);
+
+       rt2x00leds_led_radio(rt2x00dev, true);
+       rt2x00led_led_activity(rt2x00dev, true);
+
+       set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
+
+       /*
+        * Enable queues.
+        */
+       rt2x00queue_start_queues(rt2x00dev);
+       rt2x00link_start_tuner(rt2x00dev);
+       rt2x00link_start_agc(rt2x00dev);
+       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
+               rt2x00link_start_vcocal(rt2x00dev);
+
+       /*
+        * Start watchdog monitoring.
+        */
+       rt2x00link_start_watchdog(rt2x00dev);
+
+       return 0;
+}
+
+void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Stop watchdog monitoring.
+        */
+       rt2x00link_stop_watchdog(rt2x00dev);
+
+       /*
+        * Stop all queues
+        */
+       rt2x00link_stop_agc(rt2x00dev);
+       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
+               rt2x00link_stop_vcocal(rt2x00dev);
+       rt2x00link_stop_tuner(rt2x00dev);
+       rt2x00queue_stop_queues(rt2x00dev);
+       rt2x00queue_flush_queues(rt2x00dev, true);
+
+       /*
+        * Disable radio.
+        */
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
+       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF);
+       rt2x00led_led_activity(rt2x00dev, false);
+       rt2x00leds_led_radio(rt2x00dev, false);
+}
+
+static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
+                                         struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = data;
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+
+       /*
+        * It is possible the radio was disabled while the work had been
+        * scheduled. If that happens we should return here immediately,
+        * note that in the spinlock protected area above the delayed_flags
+        * have been cleared correctly.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
+               mutex_lock(&intf->beacon_skb_mutex);
+               rt2x00queue_update_beacon(rt2x00dev, vif);
+               mutex_unlock(&intf->beacon_skb_mutex);
+       }
+}
+
+static void rt2x00lib_intf_scheduled(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, intf_work);
+
+       /*
+        * Iterate over each interface and perform the
+        * requested configurations.
+        */
+       ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+                                           IEEE80211_IFACE_ITER_RESUME_ALL,
+                                           rt2x00lib_intf_scheduled_iter,
+                                           rt2x00dev);
+}
+
+static void rt2x00lib_autowakeup(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, autowakeup_work.work);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               rt2x00_err(rt2x00dev, "Device failed to wakeup\n");
+       clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
+}
+
+/*
+ * Interrupt context handlers.
+ */
+static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
+                                    struct ieee80211_vif *vif)
+{
+       struct ieee80211_tx_control control = {};
+       struct rt2x00_dev *rt2x00dev = data;
+       struct sk_buff *skb;
+
+       /*
+        * Only AP mode interfaces do broad- and multicast buffering
+        */
+       if (vif->type != NL80211_IFTYPE_AP)
+               return;
+
+       /*
+        * Send out buffered broad- and multicast frames
+        */
+       skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+       while (skb) {
+               rt2x00mac_tx(rt2x00dev->hw, &control, skb);
+               skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+       }
+}
+
+static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
+                                       struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = data;
+
+       if (vif->type != NL80211_IFTYPE_AP &&
+           vif->type != NL80211_IFTYPE_ADHOC &&
+           vif->type != NL80211_IFTYPE_MESH_POINT &&
+           vif->type != NL80211_IFTYPE_WDS)
+               return;
+
+       /*
+        * Update the beacon without locking. This is safe on PCI devices
+        * as they only update the beacon periodically here. This should
+        * never be called for USB devices.
+        */
+       WARN_ON(rt2x00_is_usb(rt2x00dev));
+       rt2x00queue_update_beacon(rt2x00dev, vif);
+}
+
+void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
+{
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /* send buffered bc/mc frames out for every bssid */
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_bc_buffer_iter, rt2x00dev);
+       /*
+        * Devices with pre tbtt interrupt don't need to update the beacon
+        * here as they will fetch the next beacon directly prior to
+        * transmission.
+        */
+       if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev))
+               return;
+
+       /* fetch next beacon */
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_beaconupdate_iter, rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
+
+void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
+{
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /* fetch next beacon */
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00lib_beaconupdate_iter, rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
+
+void rt2x00lib_dmastart(struct queue_entry *entry)
+{
+       set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+       rt2x00queue_index_inc(entry, Q_INDEX);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
+
+void rt2x00lib_dmadone(struct queue_entry *entry)
+{
+       set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
+       clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+       rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
+
+static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct ieee80211_bar *bar = (void *) entry->skb->data;
+       struct rt2x00_bar_list_entry *bar_entry;
+       int ret;
+
+       if (likely(!ieee80211_is_back_req(bar->frame_control)))
+               return 0;
+
+       /*
+        * Unlike all other frames, the status report for BARs does
+        * not directly come from the hardware as it is incapable of
+        * matching a BA to a previously send BAR. The hardware will
+        * report all BARs as if they weren't acked at all.
+        *
+        * Instead the RX-path will scan for incoming BAs and set the
+        * block_acked flag if it sees one that was likely caused by
+        * a BAR from us.
+        *
+        * Remove remaining BARs here and return their status for
+        * TX done processing.
+        */
+       ret = 0;
+       rcu_read_lock();
+       list_for_each_entry_rcu(bar_entry, &rt2x00dev->bar_list, list) {
+               if (bar_entry->entry != entry)
+                       continue;
+
+               spin_lock_bh(&rt2x00dev->bar_list_lock);
+               /* Return whether this BAR was blockacked or not */
+               ret = bar_entry->block_acked;
+               /* Remove the BAR from our checklist */
+               list_del_rcu(&bar_entry->list);
+               spin_unlock_bh(&rt2x00dev->bar_list_lock);
+               kfree_rcu(bar_entry, head);
+
+               break;
+       }
+       rcu_read_unlock();
+
+       return ret;
+}
+
+void rt2x00lib_txdone(struct queue_entry *entry,
+                     struct txdone_entry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int header_length, i;
+       u8 rate_idx, rate_flags, retry_rates;
+       u8 skbdesc_flags = skbdesc->flags;
+       bool success;
+
+       /*
+        * Unmap the skb.
+        */
+       rt2x00queue_unmap_skb(entry);
+
+       /*
+        * Remove the extra tx headroom from the skb.
+        */
+       skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
+
+       /*
+        * Signal that the TX descriptor is no longer in the skb.
+        */
+       skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
+       /*
+        * Determine the length of 802.11 header.
+        */
+       header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+       /*
+        * Remove L2 padding which was added during
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
+               rt2x00queue_remove_l2pad(entry->skb, header_length);
+
+       /*
+        * If the IV/EIV data was stripped from the frame before it was
+        * passed to the hardware, we should now reinsert it again because
+        * mac80211 will expect the same data to be present it the
+        * frame as it was passed to us.
+        */
+       if (rt2x00_has_cap_hw_crypto(rt2x00dev))
+               rt2x00crypto_tx_insert_iv(entry->skb, header_length);
+
+       /*
+        * Send frame to debugfs immediately, after this call is completed
+        * we are going to overwrite the skb->cb array.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
+
+       /*
+        * Determine if the frame has been successfully transmitted and
+        * remove BARs from our check list while checking for their
+        * TX status.
+        */
+       success =
+           rt2x00lib_txdone_bar_status(entry) ||
+           test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+           test_bit(TXDONE_UNKNOWN, &txdesc->flags);
+
+       /*
+        * Update TX statistics.
+        */
+       rt2x00dev->link.qual.tx_success += success;
+       rt2x00dev->link.qual.tx_failed += !success;
+
+       rate_idx = skbdesc->tx_rate_idx;
+       rate_flags = skbdesc->tx_rate_flags;
+       retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ?
+           (txdesc->retry + 1) : 1;
+
+       /*
+        * Initialize TX status
+        */
+       memset(&tx_info->status, 0, sizeof(tx_info->status));
+       tx_info->status.ack_signal = 0;
+
+       /*
+        * Frame was send with retries, hardware tried
+        * different rates to send out the frame, at each
+        * retry it lowered the rate 1 step except when the
+        * lowest rate was used.
+        */
+       for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) {
+               tx_info->status.rates[i].idx = rate_idx - i;
+               tx_info->status.rates[i].flags = rate_flags;
+
+               if (rate_idx - i == 0) {
+                       /*
+                        * The lowest rate (index 0) was used until the
+                        * number of max retries was reached.
+                        */
+                       tx_info->status.rates[i].count = retry_rates - i;
+                       i++;
+                       break;
+               }
+               tx_info->status.rates[i].count = 1;
+       }
+       if (i < (IEEE80211_TX_MAX_RATES - 1))
+               tx_info->status.rates[i].idx = -1; /* terminate */
+
+       if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+               if (success)
+                       tx_info->flags |= IEEE80211_TX_STAT_ACK;
+               else
+                       rt2x00dev->low_level_stats.dot11ACKFailureCount++;
+       }
+
+       /*
+        * Every single frame has it's own tx status, hence report
+        * every frame as ampdu of size 1.
+        *
+        * TODO: if we can find out how many frames were aggregated
+        * by the hw we could provide the real ampdu_len to mac80211
+        * which would allow the rc algorithm to better decide on
+        * which rates are suitable.
+        */
+       if (test_bit(TXDONE_AMPDU, &txdesc->flags) ||
+           tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+               tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+               tx_info->status.ampdu_len = 1;
+               tx_info->status.ampdu_ack_len = success ? 1 : 0;
+
+               if (!success)
+                       tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+       }
+
+       if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+               if (success)
+                       rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
+               else
+                       rt2x00dev->low_level_stats.dot11RTSFailureCount++;
+       }
+
+       /*
+        * Only send the status report to mac80211 when it's a frame
+        * that originated in mac80211. If this was a extra frame coming
+        * through a mac80211 library call (RTS/CTS) then we should not
+        * send the status report back.
+        */
+       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
+               if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TASKLET_CONTEXT))
+                       ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+               else
+                       ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
+       } else
+               dev_kfree_skb_any(entry->skb);
+
+       /*
+        * Make this entry available for reuse.
+        */
+       entry->skb = NULL;
+       entry->flags = 0;
+
+       rt2x00dev->ops->lib->clear_entry(entry);
+
+       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
+
+       /*
+        * If the data queue was below the threshold before the txdone
+        * handler we must make sure the packet queue in the mac80211 stack
+        * is reenabled when the txdone handler has finished. This has to be
+        * serialized with rt2x00mac_tx(), otherwise we can wake up queue
+        * before it was stopped.
+        */
+       spin_lock_bh(&entry->queue->tx_lock);
+       if (!rt2x00queue_threshold(entry->queue))
+               rt2x00queue_unpause_queue(entry->queue);
+       spin_unlock_bh(&entry->queue->tx_lock);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+
+void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
+{
+       struct txdone_entry_desc txdesc;
+
+       txdesc.flags = 0;
+       __set_bit(status, &txdesc.flags);
+       txdesc.retry = 0;
+
+       rt2x00lib_txdone(entry, &txdesc);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
+
+static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
+{
+       struct ieee80211_mgmt *mgmt = (void *)data;
+       u8 *pos, *end;
+
+       pos = (u8 *)mgmt->u.beacon.variable;
+       end = data + len;
+       while (pos < end) {
+               if (pos + 2 + pos[1] > end)
+                       return NULL;
+
+               if (pos[0] == ie)
+                       return pos;
+
+               pos += 2 + pos[1];
+       }
+
+       return NULL;
+}
+
+static void rt2x00lib_sleep(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, sleep_work);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Check again is powersaving is enabled, to prevent races from delayed
+        * work execution.
+        */
+       if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
+                                IEEE80211_CONF_CHANGE_PS);
+}
+
+static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb,
+                                     struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00_bar_list_entry *entry;
+       struct ieee80211_bar *ba = (void *)skb->data;
+
+       if (likely(!ieee80211_is_back(ba->frame_control)))
+               return;
+
+       if (rxdesc->size < sizeof(*ba) + FCS_LEN)
+               return;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(entry, &rt2x00dev->bar_list, list) {
+
+               if (ba->start_seq_num != entry->start_seq_num)
+                       continue;
+
+#define TID_CHECK(a, b) (                                              \
+       ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) ==        \
+       ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)))          \
+
+               if (!TID_CHECK(ba->control, entry->control))
+                       continue;
+
+#undef TID_CHECK
+
+               if (!ether_addr_equal_64bits(ba->ra, entry->ta))
+                       continue;
+
+               if (!ether_addr_equal_64bits(ba->ta, entry->ra))
+                       continue;
+
+               /* Mark BAR since we received the according BA */
+               spin_lock_bh(&rt2x00dev->bar_list_lock);
+               entry->block_acked = 1;
+               spin_unlock_bh(&rt2x00dev->bar_list_lock);
+               break;
+       }
+       rcu_read_unlock();
+
+}
+
+static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb,
+                                     struct rxdone_entry_desc *rxdesc)
+{
+       struct ieee80211_hdr *hdr = (void *) skb->data;
+       struct ieee80211_tim_ie *tim_ie;
+       u8 *tim;
+       u8 tim_len;
+       bool cam;
+
+       /* If this is not a beacon, or if mac80211 has no powersaving
+        * configured, or if the device is already in powersaving mode
+        * we can exit now. */
+       if (likely(!ieee80211_is_beacon(hdr->frame_control) ||
+                  !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS)))
+               return;
+
+       /* min. beacon length + FCS_LEN */
+       if (skb->len <= 40 + FCS_LEN)
+               return;
+
+       /* and only beacons from the associated BSSID, please */
+       if (!(rxdesc->dev_flags & RXDONE_MY_BSS) ||
+           !rt2x00dev->aid)
+               return;
+
+       rt2x00dev->last_beacon = jiffies;
+
+       tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM);
+       if (!tim)
+               return;
+
+       if (tim[1] < sizeof(*tim_ie))
+               return;
+
+       tim_len = tim[1];
+       tim_ie = (struct ieee80211_tim_ie *) &tim[2];
+
+       /* Check whenever the PHY can be turned off again. */
+
+       /* 1. What about buffered unicast traffic for our AID? */
+       cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid);
+
+       /* 2. Maybe the AP wants to send multicast/broadcast data? */
+       cam |= (tim_ie->bitmap_ctrl & 0x01);
+
+       if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
+}
+
+static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
+                                       struct rxdone_entry_desc *rxdesc)
+{
+       struct ieee80211_supported_band *sband;
+       const struct rt2x00_rate *rate;
+       unsigned int i;
+       int signal = rxdesc->signal;
+       int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
+
+       switch (rxdesc->rate_mode) {
+       case RATE_MODE_CCK:
+       case RATE_MODE_OFDM:
+               /*
+                * For non-HT rates the MCS value needs to contain the
+                * actually used rate modulation (CCK or OFDM).
+                */
+               if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
+                       signal = RATE_MCS(rxdesc->rate_mode, signal);
+
+               sband = &rt2x00dev->bands[rt2x00dev->curr_band];
+               for (i = 0; i < sband->n_bitrates; i++) {
+                       rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
+                       if (((type == RXDONE_SIGNAL_PLCP) &&
+                            (rate->plcp == signal)) ||
+                           ((type == RXDONE_SIGNAL_BITRATE) &&
+                             (rate->bitrate == signal)) ||
+                           ((type == RXDONE_SIGNAL_MCS) &&
+                             (rate->mcs == signal))) {
+                               return i;
+                       }
+               }
+               break;
+       case RATE_MODE_HT_MIX:
+       case RATE_MODE_HT_GREENFIELD:
+               if (signal >= 0 && signal <= 76)
+                       return signal;
+               break;
+       default:
+               break;
+       }
+
+       rt2x00_warn(rt2x00dev, "Frame received with unrecognized signal, mode=0x%.4x, signal=0x%.4x, type=%d\n",
+                   rxdesc->rate_mode, signal, type);
+       return 0;
+}
+
+void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct rxdone_entry_desc rxdesc;
+       struct sk_buff *skb;
+       struct ieee80211_rx_status *rx_status;
+       unsigned int header_length;
+       int rate_idx;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+           !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               goto submit_entry;
+
+       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+               goto submit_entry;
+
+       /*
+        * Allocate a new sk_buffer. If no new buffer available, drop the
+        * received frame and reuse the existing buffer.
+        */
+       skb = rt2x00queue_alloc_rxskb(entry, gfp);
+       if (!skb)
+               goto submit_entry;
+
+       /*
+        * Unmap the skb.
+        */
+       rt2x00queue_unmap_skb(entry);
+
+       /*
+        * Extract the RXD details.
+        */
+       memset(&rxdesc, 0, sizeof(rxdesc));
+       rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
+
+       /*
+        * Check for valid size in case we get corrupted descriptor from
+        * hardware.
+        */
+       if (unlikely(rxdesc.size == 0 ||
+                    rxdesc.size > entry->queue->data_size)) {
+               rt2x00_err(rt2x00dev, "Wrong frame size %d max %d\n",
+                          rxdesc.size, entry->queue->data_size);
+               dev_kfree_skb(entry->skb);
+               goto renew_skb;
+       }
+
+       /*
+        * The data behind the ieee80211 header must be
+        * aligned on a 4 byte boundary.
+        */
+       header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+       /*
+        * Hardware might have stripped the IV/EIV/ICV data,
+        * in that case it is possible that the data was
+        * provided separately (through hardware descriptor)
+        * in which case we should reinsert the data into the frame.
+        */
+       if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
+           (rxdesc.flags & RX_FLAG_IV_STRIPPED))
+               rt2x00crypto_rx_insert_iv(entry->skb, header_length,
+                                         &rxdesc);
+       else if (header_length &&
+                (rxdesc.size > header_length) &&
+                (rxdesc.dev_flags & RXDONE_L2PAD))
+               rt2x00queue_remove_l2pad(entry->skb, header_length);
+
+       /* Trim buffer to correct size */
+       skb_trim(entry->skb, rxdesc.size);
+
+       /*
+        * Translate the signal to the correct bitrate index.
+        */
+       rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
+       if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
+           rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
+               rxdesc.flags |= RX_FLAG_HT;
+
+       /*
+        * Check if this is a beacon, and more frames have been
+        * buffered while we were in powersaving mode.
+        */
+       rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc);
+
+       /*
+        * Check for incoming BlockAcks to match to the BlockAckReqs
+        * we've send out.
+        */
+       rt2x00lib_rxdone_check_ba(rt2x00dev, entry->skb, &rxdesc);
+
+       /*
+        * Update extra components
+        */
+       rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
+       rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
+
+       /*
+        * Initialize RX status information, and send frame
+        * to mac80211.
+        */
+       rx_status = IEEE80211_SKB_RXCB(entry->skb);
+
+       /* Ensure that all fields of rx_status are initialized
+        * properly. The skb->cb array was used for driver
+        * specific informations, so rx_status might contain
+        * garbage.
+        */
+       memset(rx_status, 0, sizeof(*rx_status));
+
+       rx_status->mactime = rxdesc.timestamp;
+       rx_status->band = rt2x00dev->curr_band;
+       rx_status->freq = rt2x00dev->curr_freq;
+       rx_status->rate_idx = rate_idx;
+       rx_status->signal = rxdesc.rssi;
+       rx_status->flag = rxdesc.flags;
+       rx_status->antenna = rt2x00dev->link.ant.active.rx;
+
+       ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
+
+renew_skb:
+       /*
+        * Replace the skb with the freshly allocated one.
+        */
+       entry->skb = skb;
+
+submit_entry:
+       entry->flags = 0;
+       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt2x00dev->ops->lib->clear_entry(entry);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
+
+/*
+ * Driver initialization handlers.
+ */
+const struct rt2x00_rate rt2x00_supported_rates[12] = {
+       {
+               .flags = DEV_RATE_CCK,
+               .bitrate = 10,
+               .ratemask = BIT(0),
+               .plcp = 0x00,
+               .mcs = RATE_MCS(RATE_MODE_CCK, 0),
+       },
+       {
+               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
+               .bitrate = 20,
+               .ratemask = BIT(1),
+               .plcp = 0x01,
+               .mcs = RATE_MCS(RATE_MODE_CCK, 1),
+       },
+       {
+               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
+               .bitrate = 55,
+               .ratemask = BIT(2),
+               .plcp = 0x02,
+               .mcs = RATE_MCS(RATE_MODE_CCK, 2),
+       },
+       {
+               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
+               .bitrate = 110,
+               .ratemask = BIT(3),
+               .plcp = 0x03,
+               .mcs = RATE_MCS(RATE_MODE_CCK, 3),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 60,
+               .ratemask = BIT(4),
+               .plcp = 0x0b,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 0),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 90,
+               .ratemask = BIT(5),
+               .plcp = 0x0f,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 1),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 120,
+               .ratemask = BIT(6),
+               .plcp = 0x0a,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 2),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 180,
+               .ratemask = BIT(7),
+               .plcp = 0x0e,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 3),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 240,
+               .ratemask = BIT(8),
+               .plcp = 0x09,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 4),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 360,
+               .ratemask = BIT(9),
+               .plcp = 0x0d,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 5),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 480,
+               .ratemask = BIT(10),
+               .plcp = 0x08,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 6),
+       },
+       {
+               .flags = DEV_RATE_OFDM,
+               .bitrate = 540,
+               .ratemask = BIT(11),
+               .plcp = 0x0c,
+               .mcs = RATE_MCS(RATE_MODE_OFDM, 7),
+       },
+};
+
+static void rt2x00lib_channel(struct ieee80211_channel *entry,
+                             const int channel, const int tx_power,
+                             const int value)
+{
+       /* XXX: this assumption about the band is wrong for 802.11j */
+       entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+       entry->center_freq = ieee80211_channel_to_frequency(channel,
+                                                           entry->band);
+       entry->hw_value = value;
+       entry->max_power = tx_power;
+       entry->max_antenna_gain = 0xff;
+}
+
+static void rt2x00lib_rate(struct ieee80211_rate *entry,
+                          const u16 index, const struct rt2x00_rate *rate)
+{
+       entry->flags = 0;
+       entry->bitrate = rate->bitrate;
+       entry->hw_value = index;
+       entry->hw_value_short = index;
+
+       if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
+               entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
+}
+
+static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
+                                   struct hw_mode_spec *spec)
+{
+       struct ieee80211_hw *hw = rt2x00dev->hw;
+       struct ieee80211_channel *channels;
+       struct ieee80211_rate *rates;
+       unsigned int num_rates;
+       unsigned int i;
+
+       num_rates = 0;
+       if (spec->supported_rates & SUPPORT_RATE_CCK)
+               num_rates += 4;
+       if (spec->supported_rates & SUPPORT_RATE_OFDM)
+               num_rates += 8;
+
+       channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL);
+       if (!channels)
+               return -ENOMEM;
+
+       rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL);
+       if (!rates)
+               goto exit_free_channels;
+
+       /*
+        * Initialize Rate list.
+        */
+       for (i = 0; i < num_rates; i++)
+               rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
+
+       /*
+        * Initialize Channel list.
+        */
+       for (i = 0; i < spec->num_channels; i++) {
+               rt2x00lib_channel(&channels[i],
+                                 spec->channels[i].channel,
+                                 spec->channels_info[i].max_power, i);
+       }
+
+       /*
+        * Intitialize 802.11b, 802.11g
+        * Rates: CCK, OFDM.
+        * Channels: 2.4 GHz
+        */
+       if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
+               rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
+               rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
+               rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
+               rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
+               hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                   &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
+               memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap,
+                      &spec->ht, sizeof(spec->ht));
+       }
+
+       /*
+        * Intitialize 802.11a
+        * Rates: OFDM.
+        * Channels: OFDM, UNII, HiperLAN2.
+        */
+       if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
+               rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
+                   spec->num_channels - 14;
+               rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
+                   num_rates - 4;
+               rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
+               rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
+               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                   &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
+               memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap,
+                      &spec->ht, sizeof(spec->ht));
+       }
+
+       return 0;
+
+ exit_free_channels:
+       kfree(channels);
+       rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");
+       return -ENOMEM;
+}
+
+static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
+{
+       if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
+               ieee80211_unregister_hw(rt2x00dev->hw);
+
+       if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
+               kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
+               kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
+               rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+               rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+       }
+
+       kfree(rt2x00dev->spec.channels_info);
+}
+
+static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       int status;
+
+       if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * Initialize HW modes.
+        */
+       status = rt2x00lib_probe_hw_modes(rt2x00dev, spec);
+       if (status)
+               return status;
+
+       /*
+        * Initialize HW fields.
+        */
+       rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues;
+
+       /*
+        * Initialize extra TX headroom required.
+        */
+       rt2x00dev->hw->extra_tx_headroom =
+               max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM,
+                     rt2x00dev->extra_tx_headroom);
+
+       /*
+        * Take TX headroom required for alignment into account.
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
+               rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
+       else if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA))
+               rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
+
+       /*
+        * Tell mac80211 about the size of our private STA structure.
+        */
+       rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
+
+       /*
+        * Allocate tx status FIFO for driver use.
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TXSTATUS_FIFO)) {
+               /*
+                * Allocate the txstatus fifo. In the worst case the tx
+                * status fifo has to hold the tx status of all entries
+                * in all tx queues. Hence, calculate the kfifo size as
+                * tx_queues * entry_num and round up to the nearest
+                * power of 2.
+                */
+               int kfifo_size =
+                       roundup_pow_of_two(rt2x00dev->ops->tx_queues *
+                                          rt2x00dev->tx->limit *
+                                          sizeof(u32));
+
+               status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size,
+                                    GFP_KERNEL);
+               if (status)
+                       return status;
+       }
+
+       /*
+        * Initialize tasklets if used by the driver. Tasklets are
+        * disabled until the interrupts are turned on. The driver
+        * has to handle that.
+        */
+#define RT2X00_TASKLET_INIT(taskletname) \
+       if (rt2x00dev->ops->lib->taskletname) { \
+               tasklet_init(&rt2x00dev->taskletname, \
+                            rt2x00dev->ops->lib->taskletname, \
+                            (unsigned long)rt2x00dev); \
+       }
+
+       RT2X00_TASKLET_INIT(txstatus_tasklet);
+       RT2X00_TASKLET_INIT(pretbtt_tasklet);
+       RT2X00_TASKLET_INIT(tbtt_tasklet);
+       RT2X00_TASKLET_INIT(rxdone_tasklet);
+       RT2X00_TASKLET_INIT(autowake_tasklet);
+
+#undef RT2X00_TASKLET_INIT
+
+       /*
+        * Register HW.
+        */
+       status = ieee80211_register_hw(rt2x00dev->hw);
+       if (status)
+               return status;
+
+       set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);
+
+       return 0;
+}
+
+/*
+ * Initialization/uninitialization handlers.
+ */
+static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+       if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Stop rfkill polling.
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
+               rt2x00rfkill_unregister(rt2x00dev);
+
+       /*
+        * Allow the HW to uninitialize.
+        */
+       rt2x00dev->ops->lib->uninitialize(rt2x00dev);
+
+       /*
+        * Free allocated queue entries.
+        */
+       rt2x00queue_uninitialize(rt2x00dev);
+}
+
+static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+{
+       int status;
+
+       if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * Allocate all queue entries.
+        */
+       status = rt2x00queue_initialize(rt2x00dev);
+       if (status)
+               return status;
+
+       /*
+        * Initialize the device.
+        */
+       status = rt2x00dev->ops->lib->initialize(rt2x00dev);
+       if (status) {
+               rt2x00queue_uninitialize(rt2x00dev);
+               return status;
+       }
+
+       set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
+
+       /*
+        * Start rfkill polling.
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
+               rt2x00rfkill_register(rt2x00dev);
+
+       return 0;
+}
+
+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * If this is the first interface which is added,
+        * we should load the firmware now.
+        */
+       retval = rt2x00lib_load_firmware(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Initialize the device.
+        */
+       retval = rt2x00lib_initialize(rt2x00dev);
+       if (retval)
+               return retval;
+
+       rt2x00dev->intf_ap_count = 0;
+       rt2x00dev->intf_sta_count = 0;
+       rt2x00dev->intf_associated = 0;
+
+       /* Enable the radio */
+       retval = rt2x00lib_enable_radio(rt2x00dev);
+       if (retval)
+               return retval;
+
+       set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
+
+       return 0;
+}
+
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
+{
+       if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Perhaps we can add something smarter here,
+        * but for now just disabling the radio should do.
+        */
+       rt2x00lib_disable_radio(rt2x00dev);
+
+       rt2x00dev->intf_ap_count = 0;
+       rt2x00dev->intf_sta_count = 0;
+       rt2x00dev->intf_associated = 0;
+}
+
+static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
+{
+       struct ieee80211_iface_limit *if_limit;
+       struct ieee80211_iface_combination *if_combination;
+
+       if (rt2x00dev->ops->max_ap_intf < 2)
+               return;
+
+       /*
+        * Build up AP interface limits structure.
+        */
+       if_limit = &rt2x00dev->if_limits_ap;
+       if_limit->max = rt2x00dev->ops->max_ap_intf;
+       if_limit->types = BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_MAC80211_MESH
+       if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+#endif
+
+       /*
+        * Build up AP interface combinations structure.
+        */
+       if_combination = &rt2x00dev->if_combinations[IF_COMB_AP];
+       if_combination->limits = if_limit;
+       if_combination->n_limits = 1;
+       if_combination->max_interfaces = if_limit->max;
+       if_combination->num_different_channels = 1;
+
+       /*
+        * Finally, specify the possible combinations to mac80211.
+        */
+       rt2x00dev->hw->wiphy->iface_combinations = rt2x00dev->if_combinations;
+       rt2x00dev->hw->wiphy->n_iface_combinations = 1;
+}
+
+static unsigned int rt2x00dev_extra_tx_headroom(struct rt2x00_dev *rt2x00dev)
+{
+       if (WARN_ON(!rt2x00dev->tx))
+               return 0;
+
+       if (rt2x00_is_usb(rt2x00dev))
+               return rt2x00dev->tx[0].winfo_size + rt2x00dev->tx[0].desc_size;
+
+       return rt2x00dev->tx[0].winfo_size;
+}
+
+/*
+ * driver allocation handlers.
+ */
+int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
+{
+       int retval = -ENOMEM;
+
+       /*
+        * Set possible interface combinations.
+        */
+       rt2x00lib_set_if_combinations(rt2x00dev);
+
+       /*
+        * Allocate the driver data memory, if necessary.
+        */
+       if (rt2x00dev->ops->drv_data_size > 0) {
+               rt2x00dev->drv_data = kzalloc(rt2x00dev->ops->drv_data_size,
+                                             GFP_KERNEL);
+               if (!rt2x00dev->drv_data) {
+                       retval = -ENOMEM;
+                       goto exit;
+               }
+       }
+
+       spin_lock_init(&rt2x00dev->irqmask_lock);
+       mutex_init(&rt2x00dev->csr_mutex);
+       INIT_LIST_HEAD(&rt2x00dev->bar_list);
+       spin_lock_init(&rt2x00dev->bar_list_lock);
+
+       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+
+       /*
+        * Make room for rt2x00_intf inside the per-interface
+        * structure ieee80211_vif.
+        */
+       rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
+
+       /*
+        * rt2x00 devices can only use the last n bits of the MAC address
+        * for virtual interfaces.
+        */
+       rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] =
+               (rt2x00dev->ops->max_ap_intf - 1);
+
+       /*
+        * Initialize work.
+        */
+       rt2x00dev->workqueue =
+           alloc_ordered_workqueue("%s", 0, wiphy_name(rt2x00dev->hw->wiphy));
+       if (!rt2x00dev->workqueue) {
+               retval = -ENOMEM;
+               goto exit;
+       }
+
+       INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
+       INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
+
+       /*
+        * Let the driver probe the device to detect the capabilities.
+        */
+       retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
+       if (retval) {
+               rt2x00_err(rt2x00dev, "Failed to allocate device\n");
+               goto exit;
+       }
+
+       /*
+        * Allocate queue array.
+        */
+       retval = rt2x00queue_allocate(rt2x00dev);
+       if (retval)
+               goto exit;
+
+       /* Cache TX headroom value */
+       rt2x00dev->extra_tx_headroom = rt2x00dev_extra_tx_headroom(rt2x00dev);
+
+       /*
+        * Determine which operating modes are supported, all modes
+        * which require beaconing, depend on the availability of
+        * beacon entries.
+        */
+       rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+       if (rt2x00dev->bcn->limit > 0)
+               rt2x00dev->hw->wiphy->interface_modes |=
+                   BIT(NL80211_IFTYPE_ADHOC) |
+                   BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+                   BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
+                   BIT(NL80211_IFTYPE_WDS);
+
+       rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
+       /*
+        * Initialize ieee80211 structure.
+        */
+       retval = rt2x00lib_probe_hw(rt2x00dev);
+       if (retval) {
+               rt2x00_err(rt2x00dev, "Failed to initialize hw\n");
+               goto exit;
+       }
+
+       /*
+        * Register extra components.
+        */
+       rt2x00link_register(rt2x00dev);
+       rt2x00leds_register(rt2x00dev);
+       rt2x00debug_register(rt2x00dev);
+
+       /*
+        * Start rfkill polling.
+        */
+       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
+               rt2x00rfkill_register(rt2x00dev);
+
+       return 0;
+
+exit:
+       rt2x00lib_remove_dev(rt2x00dev);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);
+
+void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
+{
+       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+
+       /*
+        * Stop rfkill polling.
+        */
+       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
+               rt2x00rfkill_unregister(rt2x00dev);
+
+       /*
+        * Disable radio.
+        */
+       rt2x00lib_disable_radio(rt2x00dev);
+
+       /*
+        * Stop all work.
+        */
+       cancel_work_sync(&rt2x00dev->intf_work);
+       cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+       cancel_work_sync(&rt2x00dev->sleep_work);
+       if (rt2x00_is_usb(rt2x00dev)) {
+               hrtimer_cancel(&rt2x00dev->txstatus_timer);
+               cancel_work_sync(&rt2x00dev->rxdone_work);
+               cancel_work_sync(&rt2x00dev->txdone_work);
+       }
+       if (rt2x00dev->workqueue)
+               destroy_workqueue(rt2x00dev->workqueue);
+
+       /*
+        * Free the tx status fifo.
+        */
+       kfifo_free(&rt2x00dev->txstatus_fifo);
+
+       /*
+        * Kill the tx status tasklet.
+        */
+       tasklet_kill(&rt2x00dev->txstatus_tasklet);
+       tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+       tasklet_kill(&rt2x00dev->tbtt_tasklet);
+       tasklet_kill(&rt2x00dev->rxdone_tasklet);
+       tasklet_kill(&rt2x00dev->autowake_tasklet);
+
+       /*
+        * Uninitialize device.
+        */
+       rt2x00lib_uninitialize(rt2x00dev);
+
+       /*
+        * Free extra components
+        */
+       rt2x00debug_deregister(rt2x00dev);
+       rt2x00leds_unregister(rt2x00dev);
+
+       /*
+        * Free ieee80211_hw memory.
+        */
+       rt2x00lib_remove_hw(rt2x00dev);
+
+       /*
+        * Free firmware image.
+        */
+       rt2x00lib_free_firmware(rt2x00dev);
+
+       /*
+        * Free queue structures.
+        */
+       rt2x00queue_free(rt2x00dev);
+
+       /*
+        * Free the driver data.
+        */
+       kfree(rt2x00dev->drv_data);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+
+/*
+ * Device state handlers
+ */
+#ifdef CONFIG_PM
+int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
+{
+       rt2x00_dbg(rt2x00dev, "Going to sleep\n");
+
+       /*
+        * Prevent mac80211 from accessing driver while suspended.
+        */
+       if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * Cleanup as much as possible.
+        */
+       rt2x00lib_uninitialize(rt2x00dev);
+
+       /*
+        * Suspend/disable extra components.
+        */
+       rt2x00leds_suspend(rt2x00dev);
+       rt2x00debug_deregister(rt2x00dev);
+
+       /*
+        * Set device mode to sleep for power management,
+        * on some hardware this call seems to consistently fail.
+        * From the specifications it is hard to tell why it fails,
+        * and if this is a "bad thing".
+        * Overall it is safe to just ignore the failure and
+        * continue suspending. The only downside is that the
+        * device will not be in optimal power save mode, but with
+        * the radio and the other components already disabled the
+        * device is as good as disabled.
+        */
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP))
+               rt2x00_warn(rt2x00dev, "Device failed to enter sleep state, continue suspending\n");
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
+
+int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
+{
+       rt2x00_dbg(rt2x00dev, "Waking up\n");
+
+       /*
+        * Restore/enable extra components.
+        */
+       rt2x00debug_register(rt2x00dev);
+       rt2x00leds_resume(rt2x00dev);
+
+       /*
+        * We are ready again to receive requests from mac80211.
+        */
+       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_resume);
+#endif /* CONFIG_PM */
+
+/*
+ * rt2x00lib module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dump.h b/drivers/net/wireless/ralink/rt2x00/rt2x00dump.h
new file mode 100644 (file)
index 0000000..4c0e01b
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00dump
+       Abstract:
+               Data structures for the rt2x00debug & userspace.
+
+               The declarations in this file can be used by both rt2x00
+               and userspace and therefore should be kept together in
+               this file.
+ */
+
+#ifndef RT2X00DUMP_H
+#define RT2X00DUMP_H
+
+/**
+ * DOC: Introduction
+ *
+ * This header is intended to be exported to userspace,
+ * to make the structures and enumerations available to userspace
+ * applications. This means that all data types should be exportable.
+ *
+ * When rt2x00 is compiled with debugfs support enabled,
+ * it is possible to capture all data coming in and out of the device
+ * by reading the frame dump file. This file can have only a single reader.
+ * The following frames will be reported:
+ *   - All incoming frames (rx)
+ *   - All outgoing frames (tx, including beacon and atim)
+ *   - All completed frames (txdone including atim)
+ *
+ * The data is send to the file using the following format:
+ *
+ *   [rt2x00dump header][hardware descriptor][ieee802.11 frame]
+ *
+ * rt2x00dump header: The description of the dumped frame, as well as
+ *     additional information useful for debugging. See &rt2x00dump_hdr.
+ * hardware descriptor: Descriptor that was used to receive or transmit
+ *     the frame.
+ * ieee802.11 frame: The actual frame that was received or transmitted.
+ */
+
+/**
+ * enum rt2x00_dump_type - Frame type
+ *
+ * These values are used for the @type member of &rt2x00dump_hdr.
+ * @DUMP_FRAME_RXDONE: This frame has been received by the hardware.
+ * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware.
+ * @DUMP_FRAME_TXDONE: This frame indicates the device has handled
+ *     the tx event which has either succeeded or failed. A frame
+ *     with this type should also have been reported with as a
+ *     %DUMP_FRAME_TX frame.
+ * @DUMP_FRAME_BEACON: This beacon frame is queued for transmission to the
+ *     hardware.
+ */
+enum rt2x00_dump_type {
+       DUMP_FRAME_RXDONE = 1,
+       DUMP_FRAME_TX = 2,
+       DUMP_FRAME_TXDONE = 3,
+       DUMP_FRAME_BEACON = 4,
+};
+
+/**
+ * struct rt2x00dump_hdr - Dump frame header
+ *
+ * Each frame dumped to the debugfs file starts with this header
+ * attached. This header contains the description of the actual
+ * frame which was dumped.
+ *
+ * New fields inside the structure must be appended to the end of
+ * the structure. This way userspace tools compiled for earlier
+ * header versions can still correctly handle the frame dump
+ * (although they will not handle all data passed to them in the dump).
+ *
+ * @version: Header version should always be set to %DUMP_HEADER_VERSION.
+ *     This field must be checked by userspace to determine if it can
+ *     handle this frame.
+ * @header_length: The length of the &rt2x00dump_hdr structure. This is
+ *     used for compatibility reasons so userspace can easily determine
+ *     the location of the next field in the dump.
+ * @desc_length: The length of the device descriptor.
+ * @data_length: The length of the frame data (including the ieee802.11 header.
+ * @chip_rt: RT chipset
+ * @chip_rf: RF chipset
+ * @chip_rev: Chipset revision
+ * @type: The frame type (&rt2x00_dump_type)
+ * @queue_index: The index number of the data queue.
+ * @entry_index: The index number of the entry inside the data queue.
+ * @timestamp_sec: Timestamp - seconds
+ * @timestamp_usec: Timestamp - microseconds
+ */
+struct rt2x00dump_hdr {
+       __le32 version;
+#define DUMP_HEADER_VERSION    2
+
+       __le32 header_length;
+       __le32 desc_length;
+       __le32 data_length;
+
+       __le16 chip_rt;
+       __le16 chip_rf;
+       __le16 chip_rev;
+
+       __le16 type;
+       __u8 queue_index;
+       __u8 entry_index;
+
+       __le32 timestamp_sec;
+       __le32 timestamp_usec;
+};
+
+#endif /* RT2X00DUMP_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c b/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
new file mode 100644 (file)
index 0000000..5813300
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 firmware loading routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
+{
+       struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
+       const struct firmware *fw;
+       char *fw_name;
+       int retval;
+
+       /*
+        * Read correct firmware from harddisk.
+        */
+       fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
+       if (!fw_name) {
+               rt2x00_err(rt2x00dev,
+                          "Invalid firmware filename\n"
+                          "Please file bug report to %s\n", DRV_PROJECT);
+               return -EINVAL;
+       }
+
+       rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
+
+       retval = request_firmware(&fw, fw_name, device);
+       if (retval) {
+               rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
+               return retval;
+       }
+
+       if (!fw || !fw->size || !fw->data) {
+               rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
+               release_firmware(fw);
+               return -ENOENT;
+       }
+
+       rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
+                   fw->data[fw->size - 4], fw->data[fw->size - 3]);
+       snprintf(rt2x00dev->hw->wiphy->fw_version,
+                       sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
+                       fw->data[fw->size - 4], fw->data[fw->size - 3]);
+
+       retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
+       switch (retval) {
+       case FW_OK:
+               break;
+       case FW_BAD_CRC:
+               rt2x00_err(rt2x00dev, "Firmware checksum error\n");
+               goto exit;
+       case FW_BAD_LENGTH:
+               rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
+                          fw->size);
+               goto exit;
+       case FW_BAD_VERSION:
+               rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
+               goto exit;
+       }
+
+       rt2x00dev->fw = fw;
+
+       return 0;
+
+exit:
+       release_firmware(fw);
+
+       return -ENOENT;
+}
+
+int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+
+       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_FIRMWARE))
+               return 0;
+
+       if (!rt2x00dev->fw) {
+               retval = rt2x00lib_request_firmware(rt2x00dev);
+               if (retval)
+                       return retval;
+       }
+
+       /*
+        * Send firmware to the device.
+        */
+       retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
+                                                   rt2x00dev->fw->data,
+                                                   rt2x00dev->fw->size);
+
+       /*
+        * When the firmware is uploaded to the hardware the LED
+        * association status might have been triggered, for correct
+        * LED handling it should now be reset.
+        */
+       rt2x00leds_led_assoc(rt2x00dev, false);
+
+       return retval;
+}
+
+void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
+{
+       release_firmware(rt2x00dev->fw);
+       rt2x00dev->fw = NULL;
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
new file mode 100644 (file)
index 0000000..c681d04
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 led specific routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
+{
+       struct rt2x00_led *led = &rt2x00dev->led_qual;
+       unsigned int brightness;
+
+       if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED))
+               return;
+
+       /*
+        * Led handling requires a positive value for the rssi,
+        * to do that correctly we need to add the correction.
+        */
+       rssi += rt2x00dev->rssi_offset;
+
+       /*
+        * Get the rssi level, this is used to convert the rssi
+        * to a LED value inside the range LED_OFF - LED_FULL.
+        */
+       if (rssi <= 30)
+               rssi = 0;
+       else if (rssi <= 39)
+               rssi = 1;
+       else if (rssi <= 49)
+               rssi = 2;
+       else if (rssi <= 53)
+               rssi = 3;
+       else if (rssi <= 63)
+               rssi = 4;
+       else
+               rssi = 5;
+
+       /*
+        * Note that we must _not_ send LED_OFF since the driver
+        * is going to calculate the value and might use it in a
+        * division.
+        */
+       brightness = ((LED_FULL / 6) * rssi) + 1;
+       if (brightness != led->led_dev.brightness) {
+               led->led_dev.brightness_set(&led->led_dev, brightness);
+               led->led_dev.brightness = brightness;
+       }
+}
+
+static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled)
+{
+       unsigned int brightness = enabled ? LED_FULL : LED_OFF;
+
+       if (!(led->flags & LED_REGISTERED))
+               return;
+
+       led->led_dev.brightness_set(&led->led_dev, brightness);
+       led->led_dev.brightness = brightness;
+}
+
+void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
+{
+       if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY)
+               rt2x00led_led_simple(&rt2x00dev->led_qual, enabled);
+}
+
+void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
+{
+       if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC)
+               rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled);
+}
+
+void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
+{
+       if (rt2x00dev->led_radio.type == LED_TYPE_RADIO)
+               rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
+}
+
+static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
+                                  struct rt2x00_led *led,
+                                  const char *name)
+{
+       struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
+       int retval;
+
+       led->led_dev.name = name;
+       led->led_dev.brightness = LED_OFF;
+
+       retval = led_classdev_register(device, &led->led_dev);
+       if (retval) {
+               rt2x00_err(rt2x00dev, "Failed to register led handler\n");
+               return retval;
+       }
+
+       led->flags |= LED_REGISTERED;
+
+       return 0;
+}
+
+void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
+{
+       char name[36];
+       int retval;
+       unsigned long on_period;
+       unsigned long off_period;
+       const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy);
+
+       if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
+               snprintf(name, sizeof(name), "%s-%s::radio",
+                        rt2x00dev->ops->name, phy_name);
+
+               retval = rt2x00leds_register_led(rt2x00dev,
+                                                &rt2x00dev->led_radio,
+                                                name);
+               if (retval)
+                       goto exit_fail;
+       }
+
+       if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
+               snprintf(name, sizeof(name), "%s-%s::assoc",
+                        rt2x00dev->ops->name, phy_name);
+
+               retval = rt2x00leds_register_led(rt2x00dev,
+                                                &rt2x00dev->led_assoc,
+                                                name);
+               if (retval)
+                       goto exit_fail;
+       }
+
+       if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
+               snprintf(name, sizeof(name), "%s-%s::quality",
+                        rt2x00dev->ops->name, phy_name);
+
+               retval = rt2x00leds_register_led(rt2x00dev,
+                                                &rt2x00dev->led_qual,
+                                                name);
+               if (retval)
+                       goto exit_fail;
+       }
+
+       /*
+        * Initialize blink time to default value:
+        * On period: 70ms
+        * Off period: 30ms
+        */
+       if (rt2x00dev->led_radio.led_dev.blink_set) {
+               on_period = 70;
+               off_period = 30;
+               rt2x00dev->led_radio.led_dev.blink_set(
+                   &rt2x00dev->led_radio.led_dev, &on_period, &off_period);
+       }
+
+       return;
+
+exit_fail:
+       rt2x00leds_unregister(rt2x00dev);
+}
+
+static void rt2x00leds_unregister_led(struct rt2x00_led *led)
+{
+       led_classdev_unregister(&led->led_dev);
+
+       /*
+        * This might look weird, but when we are unregistering while
+        * suspended the led is already off, and since we haven't
+        * fully resumed yet, access to the device might not be
+        * possible yet.
+        */
+       if (!(led->led_dev.flags & LED_SUSPENDED))
+               led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+
+       led->flags &= ~LED_REGISTERED;
+}
+
+void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
+{
+       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
+               rt2x00leds_unregister_led(&rt2x00dev->led_qual);
+       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
+               rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
+       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
+               rt2x00leds_unregister_led(&rt2x00dev->led_radio);
+}
+
+static inline void rt2x00leds_suspend_led(struct rt2x00_led *led)
+{
+       led_classdev_suspend(&led->led_dev);
+
+       /* This shouldn't be needed, but just to be safe */
+       led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+       led->led_dev.brightness = LED_OFF;
+}
+
+void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
+{
+       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
+               rt2x00leds_suspend_led(&rt2x00dev->led_qual);
+       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
+               rt2x00leds_suspend_led(&rt2x00dev->led_assoc);
+       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
+               rt2x00leds_suspend_led(&rt2x00dev->led_radio);
+}
+
+static inline void rt2x00leds_resume_led(struct rt2x00_led *led)
+{
+       led_classdev_resume(&led->led_dev);
+
+       /* Device might have enabled the LEDS during resume */
+       led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+       led->led_dev.brightness = LED_OFF;
+}
+
+void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
+{
+       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
+               rt2x00leds_resume_led(&rt2x00dev->led_radio);
+       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
+               rt2x00leds_resume_led(&rt2x00dev->led_assoc);
+       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
+               rt2x00leds_resume_led(&rt2x00dev->led_qual);
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.h b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.h
new file mode 100644 (file)
index 0000000..b2c5269
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 led datastructures and routines
+ */
+
+#ifndef RT2X00LEDS_H
+#define RT2X00LEDS_H
+
+enum led_type {
+       LED_TYPE_RADIO,
+       LED_TYPE_ASSOC,
+       LED_TYPE_ACTIVITY,
+       LED_TYPE_QUALITY,
+};
+
+struct rt2x00_led {
+       struct rt2x00_dev *rt2x00dev;
+       struct led_classdev led_dev;
+
+       enum led_type type;
+       unsigned int flags;
+#define LED_INITIALIZED                ( 1 << 0 )
+#define LED_REGISTERED         ( 1 << 1 )
+};
+
+#endif /* RT2X00LEDS_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h b/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
new file mode 100644 (file)
index 0000000..fb7c349
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: Data structures and definitions for the rt2x00lib module.
+ */
+
+#ifndef RT2X00LIB_H
+#define RT2X00LIB_H
+
+/*
+ * Interval defines
+ */
+#define WATCHDOG_INTERVAL      round_jiffies_relative(HZ)
+#define LINK_TUNE_INTERVAL     round_jiffies_relative(HZ)
+#define AGC_INTERVAL           round_jiffies_relative(4 * HZ)
+#define VCO_INTERVAL           round_jiffies_relative(10 * HZ) /* 10 sec */
+
+/*
+ * rt2x00_rate: Per rate device information
+ */
+struct rt2x00_rate {
+       unsigned short flags;
+#define DEV_RATE_CCK                   0x0001
+#define DEV_RATE_OFDM                  0x0002
+#define DEV_RATE_SHORT_PREAMBLE                0x0004
+
+       unsigned short bitrate; /* In 100kbit/s */
+       unsigned short ratemask;
+
+       unsigned short plcp;
+       unsigned short mcs;
+};
+
+extern const struct rt2x00_rate rt2x00_supported_rates[12];
+
+static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
+{
+       return &rt2x00_supported_rates[hw_value & 0xff];
+}
+
+#define RATE_MCS(__mode, __mcs) \
+       ((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
+
+static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
+{
+       return (mcs_value & 0x00ff);
+}
+
+/*
+ * Radio control handlers.
+ */
+int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
+
+/*
+ * Initialization handlers.
+ */
+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
+
+/*
+ * Configuration handlers.
+ */
+void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
+                          struct rt2x00_intf *intf,
+                          enum nl80211_iftype type,
+                          const u8 *mac, const u8 *bssid);
+void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
+                         struct rt2x00_intf *intf,
+                         struct ieee80211_bss_conf *conf,
+                         u32 changed);
+void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+                             struct antenna_setup ant);
+void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+                     struct ieee80211_conf *conf,
+                     const unsigned int changed_flags);
+
+/**
+ * DOC: Queue handlers
+ */
+
+/**
+ * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
+ * @entry: The entry for which the skb will be applicable.
+ */
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp);
+
+/**
+ * rt2x00queue_free_skb - free a skb
+ * @entry: The entry for which the skb will be applicable.
+ */
+void rt2x00queue_free_skb(struct queue_entry *entry);
+
+/**
+ * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
+ * @skb: The skb to align
+ *
+ * Align the start of the 802.11 frame to a 4-byte boundary, this could
+ * mean the payload is not aligned properly though.
+ */
+void rt2x00queue_align_frame(struct sk_buff *skb);
+
+/**
+ * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary
+ * @skb: The skb to align
+ * @header_length: Length of 802.11 header
+ *
+ * Apply L2 padding to align both header and payload to 4-byte boundary
+ */
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length);
+
+/**
+ * rt2x00queue_insert_l2pad - Remove L2 padding from 802.11 frame
+ * @skb: The skb to align
+ * @header_length: Length of 802.11 header
+ *
+ * Remove L2 padding used to align both header and payload to 4-byte boundary,
+ * by removing the L2 padding the header will no longer be 4-byte aligned.
+ */
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length);
+
+/**
+ * rt2x00queue_write_tx_frame - Write TX frame to hardware
+ * @queue: Queue over which the frame should be send
+ * @skb: The skb to send
+ * @local: frame is not from mac80211
+ */
+int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
+                              struct ieee80211_sta *sta, bool local);
+
+/**
+ * rt2x00queue_update_beacon - Send new beacon from mac80211
+ *     to hardware. Handles locking by itself (mutex).
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+                             struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_update_beacon_locked - Send new beacon from mac80211
+ *     to hardware. Caller needs to ensure locking.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+                                    struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_clear_beacon - Clear beacon in hardware
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+                            struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_index_inc - Index incrementation function
+ * @entry: Queue entry (&struct queue_entry) to perform the action on.
+ * @index: Index type (&enum queue_index) to perform the action on.
+ *
+ * This function will increase the requested index on the entry's queue,
+ * it will grab the appropriate locks and handle queue overflow events by
+ * resetting the index to the start of the queue.
+ */
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);
+
+/**
+ * rt2x00queue_init_queues - Initialize all data queues
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This function will loop through all available queues to clear all
+ * index numbers and set the queue entry to the correct initialization
+ * state.
+ */
+void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev);
+
+int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
+void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_update_stats - Update link statistics from RX frame
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @skb: Received frame
+ * @rxdesc: Received frame descriptor
+ *
+ * Update link statistics based on the information from the
+ * received frame descriptor.
+ */
+void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
+                            struct sk_buff *skb,
+                            struct rxdone_entry_desc *rxdesc);
+
+/**
+ * rt2x00link_start_tuner - Start periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This start the link tuner periodic work, this work will
+ * be executed periodically until &rt2x00link_stop_tuner has
+ * been called.
+ */
+void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_tuner - Stop periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * After this function completed the link tuner will not
+ * be running until &rt2x00link_start_tuner is called.
+ */
+void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_reset_tuner - Reset periodic link tuner work
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @antenna: Should the antenna tuning also be reset
+ *
+ * The VGC limit configured in the hardware will be reset to 0
+ * which forces the driver to rediscover the correct value for
+ * the current association. This is needed when configuration
+ * options have changed which could drastically change the
+ * SNR level or link quality (i.e. changing the antenna setting).
+ *
+ * Resetting the link tuner will also cause the periodic work counter
+ * to be reset. Any driver which has a fixed limit on the number
+ * of rounds the link tuner is supposed to work will accept the
+ * tuner actions again if this limit was previously reached.
+ *
+ * If @antenna is set to true a the software antenna diversity
+ * tuning will also be reset.
+ */
+void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
+
+/**
+ * rt2x00link_start_watchdog - Start periodic watchdog monitoring
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This start the watchdog periodic work, this work will
+ *be executed periodically until &rt2x00link_stop_watchdog has
+ * been called.
+ */
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * After this function completed the watchdog monitoring will not
+ * be running until &rt2x00link_start_watchdog is called.
+ */
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_start_agc - Start periodic gain calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_start_vcocal - Start periodic VCO calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_agc - Stop periodic gain calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_vcocal - Stop periodic VCO calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_register - Initialize link tuning & watchdog functionality
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * Initialize work structure and all link tuning and watchdog related
+ * parameters. This will not start the periodic work itself.
+ */
+void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
+
+/*
+ * Firmware handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_FIRMWARE
+int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev);
+#else
+static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
+{
+       return 0;
+}
+static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_FIRMWARE */
+
+/*
+ * Debugfs handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+                              struct rxdone_entry_desc *rxdesc);
+#else
+static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
+                                            struct rxdone_entry_desc *rxdesc)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+/*
+ * Crypto handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
+void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+                                      struct sk_buff *skb,
+                                      struct txentry_desc *txdesc);
+unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                     struct sk_buff *skb);
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
+                            struct txentry_desc *txdesc);
+void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
+                              struct txentry_desc *txdesc);
+void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
+void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
+                              unsigned int header_length,
+                              struct rxdone_entry_desc *rxdesc);
+#else
+static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
+{
+       return CIPHER_NONE;
+}
+
+static inline void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+                                                    struct sk_buff *skb,
+                                                    struct txentry_desc *txdesc)
+{
+}
+
+static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
+                                                   struct sk_buff *skb)
+{
+       return 0;
+}
+
+static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
+                                          struct txentry_desc *txdesc)
+{
+}
+
+static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
+                                            struct txentry_desc *txdesc)
+{
+}
+
+static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
+                                            unsigned int header_length)
+{
+}
+
+static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
+                                            unsigned int header_length,
+                                            struct rxdone_entry_desc *rxdesc)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+
+/*
+ * RFkill handlers.
+ */
+static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
+{
+       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
+               wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
+}
+
+static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
+{
+       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
+               wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
+}
+
+/*
+ * LED handlers
+ */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
+void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled);
+void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
+void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
+void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
+void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
+#else
+static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
+                                         int rssi)
+{
+}
+
+static inline void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev,
+                                         bool enabled)
+{
+}
+
+static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
+                                       bool enabled)
+{
+}
+
+static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev,
+                                       bool enabled)
+{
+}
+
+static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+#endif /* RT2X00LIB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
new file mode 100644 (file)
index 0000000..017188e
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 generic link tuning routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+/*
+ * When we lack RSSI information return something less then -80 to
+ * tell the driver to tune the device to maximum sensitivity.
+ */
+#define DEFAULT_RSSI           -128
+
+static inline int rt2x00link_get_avg_rssi(struct ewma_rssi *ewma)
+{
+       unsigned long avg;
+
+       avg = ewma_rssi_read(ewma);
+       if (avg)
+               return -avg;
+
+       return DEFAULT_RSSI;
+}
+
+static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       if (rt2x00dev->link.qual.rx_success)
+               return rt2x00link_get_avg_rssi(&ant->rssi_ant);
+
+       return DEFAULT_RSSI;
+}
+
+static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       if (ant->rssi_history)
+               return ant->rssi_history;
+       return DEFAULT_RSSI;
+}
+
+static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
+                                                  int rssi)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       ant->rssi_history = rssi;
+}
+
+static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
+{
+       ewma_rssi_init(&rt2x00dev->link.ant.rssi_ant);
+}
+
+static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup new_ant;
+       int other_antenna;
+
+       int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
+       int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
+
+       memcpy(&new_ant, &ant->active, sizeof(new_ant));
+
+       /*
+        * We are done sampling. Now we should evaluate the results.
+        */
+       ant->flags &= ~ANTENNA_MODE_SAMPLE;
+
+       /*
+        * During the last period we have sampled the RSSI
+        * from both antennas. It now is time to determine
+        * which antenna demonstrated the best performance.
+        * When we are already on the antenna with the best
+        * performance, just create a good starting point
+        * for the history and we are done.
+        */
+       if (sample_current >= sample_other) {
+               rt2x00link_antenna_update_rssi_history(rt2x00dev,
+                       sample_current);
+               return;
+       }
+
+       other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               new_ant.rx = other_antenna;
+
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               new_ant.tx = other_antenna;
+
+       rt2x00lib_config_antenna(rt2x00dev, new_ant);
+}
+
+static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup new_ant;
+       int rssi_curr;
+       int rssi_old;
+
+       memcpy(&new_ant, &ant->active, sizeof(new_ant));
+
+       /*
+        * Get current RSSI value along with the historical value,
+        * after that update the history with the current value.
+        */
+       rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
+       rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
+       rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
+
+       /*
+        * Legacy driver indicates that we should swap antenna's
+        * when the difference in RSSI is greater that 5. This
+        * also should be done when the RSSI was actually better
+        * then the previous sample.
+        * When the difference exceeds the threshold we should
+        * sample the rssi from the other antenna to make a valid
+        * comparison between the 2 antennas.
+        */
+       if (abs(rssi_curr - rssi_old) < 5)
+               return;
+
+       ant->flags |= ANTENNA_MODE_SAMPLE;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+       rt2x00lib_config_antenna(rt2x00dev, new_ant);
+}
+
+static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_ant *ant = &rt2x00dev->link.ant;
+
+       /*
+        * Determine if software diversity is enabled for
+        * either the TX or RX antenna (or both).
+        */
+       if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
+           !(ant->flags & ANTENNA_TX_DIVERSITY)) {
+               ant->flags = 0;
+               return true;
+       }
+
+       /*
+        * If we have only sampled the data over the last period
+        * we should now harvest the data. Otherwise just evaluate
+        * the data. The latter should only be performed once
+        * every 2 seconds.
+        */
+       if (ant->flags & ANTENNA_MODE_SAMPLE) {
+               rt2x00lib_antenna_diversity_sample(rt2x00dev);
+               return true;
+       } else if (rt2x00dev->link.count & 1) {
+               rt2x00lib_antenna_diversity_eval(rt2x00dev);
+               return true;
+       }
+
+       return false;
+}
+
+void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
+                            struct sk_buff *skb,
+                            struct rxdone_entry_desc *rxdesc)
+{
+       struct link *link = &rt2x00dev->link;
+       struct link_qual *qual = &rt2x00dev->link.qual;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+       /*
+        * No need to update the stats for !=STA interfaces
+        */
+       if (!rt2x00dev->intf_sta_count)
+               return;
+
+       /*
+        * Frame was received successfully since non-succesfull
+        * frames would have been dropped by the hardware.
+        */
+       qual->rx_success++;
+
+       /*
+        * We are only interested in quality statistics from
+        * beacons which came from the BSS which we are
+        * associated with.
+        */
+       if (!ieee80211_is_beacon(hdr->frame_control) ||
+           !(rxdesc->dev_flags & RXDONE_MY_BSS))
+               return;
+
+       /*
+        * Update global RSSI
+        */
+       ewma_rssi_add(&link->avg_rssi, -rxdesc->rssi);
+
+       /*
+        * Update antenna RSSI
+        */
+       ewma_rssi_add(&ant->rssi_ant, -rxdesc->rssi);
+}
+
+void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * Link tuning should only be performed when
+        * an active sta interface exists. AP interfaces
+        * don't need link tuning and monitor mode interfaces
+        * should never have to work with link tuners.
+        */
+       if (!rt2x00dev->intf_sta_count)
+               return;
+
+       /**
+        * While scanning, link tuning is disabled. By default
+        * the most sensitive settings will be used to make sure
+        * that all beacons and probe responses will be received
+        * during the scan.
+        */
+       if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
+               return;
+
+       rt2x00link_reset_tuner(rt2x00dev, false);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->work, LINK_TUNE_INTERVAL);
+}
+
+void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.work);
+}
+
+void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
+{
+       struct link_qual *qual = &rt2x00dev->link.qual;
+       u8 vgc_level = qual->vgc_level_reg;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Reset link information.
+        * Both the currently active vgc level as well as
+        * the link tuner counter should be reset. Resetting
+        * the counter is important for devices where the
+        * device should only perform link tuning during the
+        * first minute after being enabled.
+        */
+       rt2x00dev->link.count = 0;
+       memset(qual, 0, sizeof(*qual));
+       ewma_rssi_init(&rt2x00dev->link.avg_rssi);
+
+       /*
+        * Restore the VGC level as stored in the registers,
+        * the driver can use this to determine if the register
+        * must be updated during reset or not.
+        */
+       qual->vgc_level_reg = vgc_level;
+
+       /*
+        * Reset the link tuner.
+        */
+       rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
+
+       if (antenna)
+               rt2x00link_antenna_reset(rt2x00dev);
+}
+
+static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
+{
+       struct link_qual *qual = &rt2x00dev->link.qual;
+
+       qual->rx_success = 0;
+       qual->rx_failed = 0;
+       qual->tx_success = 0;
+       qual->tx_failed = 0;
+}
+
+static void rt2x00link_tuner(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.work.work);
+       struct link *link = &rt2x00dev->link;
+       struct link_qual *qual = &rt2x00dev->link.qual;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease all link tuning.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
+           test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Update statistics.
+        */
+       rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
+       rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
+
+       /*
+        * Update quality RSSI for link tuning,
+        * when we have received some frames and we managed to
+        * collect the RSSI data we could use this. Otherwise we
+        * must fallback to the default RSSI value.
+        */
+       if (!qual->rx_success)
+               qual->rssi = DEFAULT_RSSI;
+       else
+               qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi);
+
+       /*
+        * Check if link tuning is supported by the hardware, some hardware
+        * do not support link tuning at all, while other devices can disable
+        * the feature from the EEPROM.
+        */
+       if (rt2x00_has_cap_link_tuning(rt2x00dev))
+               rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
+
+       /*
+        * Send a signal to the led to update the led signal strength.
+        */
+       rt2x00leds_led_quality(rt2x00dev, qual->rssi);
+
+       /*
+        * Evaluate antenna setup, make this the last step when
+        * rt2x00lib_antenna_diversity made changes the quality
+        * statistics will be reset.
+        */
+       if (rt2x00lib_antenna_diversity(rt2x00dev))
+               rt2x00link_reset_qual(rt2x00dev);
+
+       /*
+        * Increase tuner counter, and reschedule the next link tuner run.
+        */
+       link->count++;
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->work, LINK_TUNE_INTERVAL);
+}
+
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           rt2x00dev->ops->lib->watchdog)
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->watchdog_work,
+                                            WATCHDOG_INTERVAL);
+}
+
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
+}
+
+static void rt2x00link_watchdog(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.watchdog_work.work);
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease the watchdog monitoring.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       rt2x00dev->ops->lib->watchdog(rt2x00dev);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->watchdog_work,
+                                            WATCHDOG_INTERVAL);
+}
+
+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           rt2x00dev->ops->lib->gain_calibration)
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->agc_work,
+                                            AGC_INTERVAL);
+}
+
+void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+           rt2x00dev->ops->lib->vco_calibration)
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->vco_work,
+                                            VCO_INTERVAL);
+}
+
+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
+}
+
+void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
+}
+
+static void rt2x00link_agc(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.agc_work.work);
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease the watchdog monitoring.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->agc_work,
+                                            AGC_INTERVAL);
+}
+
+static void rt2x00link_vcocal(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.vco_work.work);
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease the VCO calibration.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->vco_work,
+                                            VCO_INTERVAL);
+}
+
+void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
+{
+       INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
+       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
+               INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
+       INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
+       INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
new file mode 100644 (file)
index 0000000..3c26ee6
--- /dev/null
@@ -0,0 +1,846 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00mac
+       Abstract: rt2x00 generic mac80211 routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+                               struct data_queue *queue,
+                               struct sk_buff *frag_skb)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
+       struct ieee80211_tx_info *rts_info;
+       struct sk_buff *skb;
+       unsigned int data_length;
+       int retval = 0;
+
+       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+               data_length = sizeof(struct ieee80211_cts);
+       else
+               data_length = sizeof(struct ieee80211_rts);
+
+       skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
+       if (unlikely(!skb)) {
+               rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n");
+               return -ENOMEM;
+       }
+
+       skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
+       skb_put(skb, data_length);
+
+       /*
+        * Copy TX information over from original frame to
+        * RTS/CTS frame. Note that we set the no encryption flag
+        * since we don't want this frame to be encrypted.
+        * RTS frames should be acked, while CTS-to-self frames
+        * should not. The ready for TX flag is cleared to prevent
+        * it being automatically send when the descriptor is
+        * written to the hardware.
+        */
+       memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
+       rts_info = IEEE80211_SKB_CB(skb);
+       rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
+       rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
+
+       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+               rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       else
+               rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
+
+       /* Disable hardware encryption */
+       rts_info->control.hw_key = NULL;
+
+       /*
+        * RTS/CTS frame should use the length of the frame plus any
+        * encryption overhead that will be added by the hardware.
+        */
+       data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
+
+       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+               ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
+                                       frag_skb->data, data_length, tx_info,
+                                       (struct ieee80211_cts *)(skb->data));
+       else
+               ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
+                                 frag_skb->data, data_length, tx_info,
+                                 (struct ieee80211_rts *)(skb->data));
+
+       retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true);
+       if (retval) {
+               dev_kfree_skb_any(skb);
+               rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n");
+       }
+
+       return retval;
+}
+
+void rt2x00mac_tx(struct ieee80211_hw *hw,
+                 struct ieee80211_tx_control *control,
+                 struct sk_buff *skb)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       enum data_queue_qid qid = skb_get_queue_mapping(skb);
+       struct data_queue *queue = NULL;
+
+       /*
+        * Mac80211 might be calling this function while we are trying
+        * to remove the device or perhaps suspending it.
+        * Note that we can only stop the TX queues inside the TX path
+        * due to possible race conditions in mac80211.
+        */
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               goto exit_free_skb;
+
+       /*
+        * Use the ATIM queue if appropriate and present.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
+           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE))
+               qid = QID_ATIM;
+
+       queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+       if (unlikely(!queue)) {
+               rt2x00_err(rt2x00dev,
+                          "Attempt to send packet over invalid queue %d\n"
+                          "Please file bug report to %s\n", qid, DRV_PROJECT);
+               goto exit_free_skb;
+       }
+
+       /*
+        * If CTS/RTS is required. create and queue that frame first.
+        * Make sure we have at least enough entries available to send
+        * this CTS/RTS frame as well as the data frame.
+        * Note that when the driver has set the set_rts_threshold()
+        * callback function it doesn't need software generation of
+        * either RTS or CTS-to-self frame and handles everything
+        * inside the hardware.
+        */
+       if (!rt2x00dev->ops->hw->set_rts_threshold &&
+           (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+                                               IEEE80211_TX_RC_USE_CTS_PROTECT))) {
+               if (rt2x00queue_available(queue) <= 1)
+                       goto exit_fail;
+
+               if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
+                       goto exit_fail;
+       }
+
+       if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false)))
+               goto exit_fail;
+
+       /*
+        * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
+        * we should not use spin_lock_bh variant as bottom halve was already
+        * disabled before ieee80211_xmit() call.
+        */
+       spin_lock(&queue->tx_lock);
+       if (rt2x00queue_threshold(queue))
+               rt2x00queue_pause_queue(queue);
+       spin_unlock(&queue->tx_lock);
+
+       return;
+
+ exit_fail:
+       spin_lock(&queue->tx_lock);
+       rt2x00queue_pause_queue(queue);
+       spin_unlock(&queue->tx_lock);
+ exit_free_skb:
+       ieee80211_free_txskb(hw, skb);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_tx);
+
+int rt2x00mac_start(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       return rt2x00lib_start(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_start);
+
+void rt2x00mac_stop(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       rt2x00lib_stop(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_stop);
+
+int rt2x00mac_add_interface(struct ieee80211_hw *hw,
+                           struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+       struct data_queue *queue = rt2x00dev->bcn;
+       struct queue_entry *entry = NULL;
+       unsigned int i;
+
+       /*
+        * Don't allow interfaces to be added
+        * the device has disappeared.
+        */
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+           !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
+               return -ENODEV;
+
+       /*
+        * Loop through all beacon queues to find a free
+        * entry. Since there are as much beacon entries
+        * as the maximum interfaces, this search shouldn't
+        * fail.
+        */
+       for (i = 0; i < queue->limit; i++) {
+               entry = &queue->entries[i];
+               if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
+                       break;
+       }
+
+       if (unlikely(i == queue->limit))
+               return -ENOBUFS;
+
+       /*
+        * We are now absolutely sure the interface can be created,
+        * increase interface count and start initialization.
+        */
+
+       if (vif->type == NL80211_IFTYPE_AP)
+               rt2x00dev->intf_ap_count++;
+       else
+               rt2x00dev->intf_sta_count++;
+
+       mutex_init(&intf->beacon_skb_mutex);
+       intf->beacon = entry;
+
+       /*
+        * The MAC address must be configured after the device
+        * has been initialized. Otherwise the device can reset
+        * the MAC registers.
+        * The BSSID address must only be configured in AP mode,
+        * however we should not send an empty BSSID address for
+        * STA interfaces at this time, since this can cause
+        * invalid behavior in the device.
+        */
+       rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
+                             vif->addr, NULL);
+
+       /*
+        * Some filters depend on the current working mode. We can force
+        * an update during the next configure_filter() run by mac80211 by
+        * resetting the current packet_filter state.
+        */
+       rt2x00dev->packet_filter = 0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
+
+void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+
+       /*
+        * Don't allow interfaces to be remove while
+        * either the device has disappeared or when
+        * no interface is present.
+        */
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+           (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
+           (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
+               return;
+
+       if (vif->type == NL80211_IFTYPE_AP)
+               rt2x00dev->intf_ap_count--;
+       else
+               rt2x00dev->intf_sta_count--;
+
+       /*
+        * Release beacon entry so it is available for
+        * new interfaces again.
+        */
+       clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
+
+       /*
+        * Make sure the bssid and mac address registers
+        * are cleared to prevent false ACKing of frames.
+        */
+       rt2x00lib_config_intf(rt2x00dev, intf,
+                             NL80211_IFTYPE_UNSPECIFIED, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
+
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct ieee80211_conf *conf = &hw->conf;
+
+       /*
+        * mac80211 might be calling this function while we are trying
+        * to remove the device or perhaps suspending it.
+        */
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       /*
+        * Some configuration parameters (e.g. channel and antenna values) can
+        * only be set when the radio is enabled, but do require the RX to
+        * be off. During this period we should keep link tuning enabled,
+        * if for any reason the link tuner must be reset, this will be
+        * handled by rt2x00lib_config().
+        */
+       rt2x00queue_stop_queue(rt2x00dev->rx);
+
+       /*
+        * When we've just turned on the radio, we want to reprogram
+        * everything to ensure a consistent state
+        */
+       rt2x00lib_config(rt2x00dev, conf, changed);
+
+       /*
+        * After the radio has been enabled we need to configure
+        * the antenna to the default settings. rt2x00lib_config_antenna()
+        * should determine if any action should be taken based on
+        * checking if diversity has been enabled or no antenna changes
+        * have been made since the last configuration change.
+        */
+       rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);
+
+       /* Turn RX back on */
+       rt2x00queue_start_queue(rt2x00dev->rx);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_config);
+
+void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
+                               unsigned int changed_flags,
+                               unsigned int *total_flags,
+                               u64 multicast)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * Mask off any flags we are going to ignore
+        * from the total_flags field.
+        */
+       *total_flags &=
+           FIF_ALLMULTI |
+           FIF_FCSFAIL |
+           FIF_PLCPFAIL |
+           FIF_CONTROL |
+           FIF_PSPOLL |
+           FIF_OTHER_BSS;
+
+       /*
+        * Apply some rules to the filters:
+        * - Some filters imply different filters to be set.
+        * - Some things we can't filter out at all.
+        * - Multicast filter seems to kill broadcast traffic so never use it.
+        */
+       *total_flags |= FIF_ALLMULTI;
+
+       /*
+        * If the device has a single filter for all control frames,
+        * FIF_CONTROL and FIF_PSPOLL flags imply each other.
+        * And if the device has more than one filter for control frames
+        * of different types, but has no a separate filter for PS Poll frames,
+        * FIF_CONTROL flag implies FIF_PSPOLL.
+        */
+       if (!rt2x00_has_cap_control_filters(rt2x00dev)) {
+               if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
+                       *total_flags |= FIF_CONTROL | FIF_PSPOLL;
+       }
+       if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) {
+               if (*total_flags & FIF_CONTROL)
+                       *total_flags |= FIF_PSPOLL;
+       }
+
+       /*
+        * Check if there is any work left for us.
+        */
+       if (rt2x00dev->packet_filter == *total_flags)
+               return;
+       rt2x00dev->packet_filter = *total_flags;
+
+       rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
+
+static void rt2x00mac_set_tim_iter(void *data, u8 *mac,
+                                  struct ieee80211_vif *vif)
+{
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+
+       if (vif->type != NL80211_IFTYPE_AP &&
+           vif->type != NL80211_IFTYPE_ADHOC &&
+           vif->type != NL80211_IFTYPE_MESH_POINT &&
+           vif->type != NL80211_IFTYPE_WDS)
+               return;
+
+       set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags);
+}
+
+int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+                     bool set)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return 0;
+
+       ieee80211_iterate_active_interfaces_atomic(
+               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
+               rt2x00mac_set_tim_iter, rt2x00dev);
+
+       /* queue work to upodate the beacon template */
+       ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
+
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
+{
+       if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
+               memcpy(crypto->key,
+                      &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
+                      sizeof(crypto->key));
+
+       if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+               memcpy(crypto->tx_mic,
+                      &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
+                      sizeof(crypto->tx_mic));
+
+       if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
+               memcpy(crypto->rx_mic,
+                      &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
+                      sizeof(crypto->rx_mic));
+}
+
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+                     struct ieee80211_key_conf *key)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       int (*set_key) (struct rt2x00_dev *rt2x00dev,
+                       struct rt2x00lib_crypto *crypto,
+                       struct ieee80211_key_conf *key);
+       struct rt2x00lib_crypto crypto;
+       static const u8 bcast_addr[ETH_ALEN] =
+               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
+       struct rt2x00_sta *sta_priv = NULL;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       if (!rt2x00_has_cap_hw_crypto(rt2x00dev))
+               return -EOPNOTSUPP;
+
+       /*
+        * To support IBSS RSN, don't program group keys in IBSS, the
+        * hardware will then not attempt to decrypt the frames.
+        */
+       if (vif->type == NL80211_IFTYPE_ADHOC &&
+           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+               return -EOPNOTSUPP;
+
+       if (key->keylen > 32)
+               return -ENOSPC;
+
+       memset(&crypto, 0, sizeof(crypto));
+
+       crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
+       crypto.cipher = rt2x00crypto_key_to_cipher(key);
+       if (crypto.cipher == CIPHER_NONE)
+               return -EOPNOTSUPP;
+       if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev))
+               return -EOPNOTSUPP;
+
+       crypto.cmd = cmd;
+
+       if (sta) {
+               crypto.address = sta->addr;
+               sta_priv = sta_to_rt2x00_sta(sta);
+               crypto.wcid = sta_priv->wcid;
+       } else
+               crypto.address = bcast_addr;
+
+       if (crypto.cipher == CIPHER_TKIP)
+               memcpy_tkip(&crypto, &key->key[0], key->keylen);
+       else
+               memcpy(crypto.key, &key->key[0], key->keylen);
+       /*
+        * Each BSS has a maximum of 4 shared keys.
+        * Shared key index values:
+        *      0) BSS0 key0
+        *      1) BSS0 key1
+        *      ...
+        *      4) BSS1 key0
+        *      ...
+        *      8) BSS2 key0
+        *      ...
+        * Both pairwise as shared key indeces are determined by
+        * driver. This is required because the hardware requires
+        * keys to be assigned in correct order (When key 1 is
+        * provided but key 0 is not, then the key is not found
+        * by the hardware during RX).
+        */
+       if (cmd == SET_KEY)
+               key->hw_key_idx = 0;
+
+       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+               set_key = rt2x00dev->ops->lib->config_pairwise_key;
+       else
+               set_key = rt2x00dev->ops->lib->config_shared_key;
+
+       if (!set_key)
+               return -EOPNOTSUPP;
+
+       return set_key(rt2x00dev, &crypto, key);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
+
+int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                     struct ieee80211_sta *sta)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
+
+int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+
+       return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
+
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif,
+                            const u8 *mac_addr)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+       rt2x00link_stop_tuner(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
+
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+       rt2x00link_start_tuner(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
+
+int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+                       struct ieee80211_low_level_stats *stats)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * The dot11ACKFailureCount, dot11RTSFailureCount and
+        * dot11RTSSuccessCount are updated in interrupt time.
+        * dot11FCSErrorCount is updated in the link tuner.
+        */
+       memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
+
+void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               struct ieee80211_bss_conf *bss_conf,
+                               u32 changes)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+
+       /*
+        * mac80211 might be calling this function while we are trying
+        * to remove the device or perhaps suspending it.
+        */
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Update the BSSID.
+        */
+       if (changes & BSS_CHANGED_BSSID)
+               rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
+                                     bss_conf->bssid);
+
+       /*
+        * Start/stop beaconing.
+        */
+       if (changes & BSS_CHANGED_BEACON_ENABLED) {
+               mutex_lock(&intf->beacon_skb_mutex);
+               if (!bss_conf->enable_beacon && intf->enable_beacon) {
+                       rt2x00dev->intf_beaconing--;
+                       intf->enable_beacon = false;
+
+                       if (rt2x00dev->intf_beaconing == 0) {
+                               /*
+                                * Last beaconing interface disabled
+                                * -> stop beacon queue.
+                                */
+                               rt2x00queue_stop_queue(rt2x00dev->bcn);
+                       }
+                       /*
+                        * Clear beacon in the H/W for this vif. This is needed
+                        * to disable beaconing on this particular interface
+                        * and keep it running on other interfaces.
+                        */
+                       rt2x00queue_clear_beacon(rt2x00dev, vif);
+               } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
+                       rt2x00dev->intf_beaconing++;
+                       intf->enable_beacon = true;
+                       /*
+                        * Upload beacon to the H/W. This is only required on
+                        * USB devices. PCI devices fetch beacons periodically.
+                        */
+                       if (rt2x00_is_usb(rt2x00dev))
+                               rt2x00queue_update_beacon(rt2x00dev, vif);
+
+                       if (rt2x00dev->intf_beaconing == 1) {
+                               /*
+                                * First beaconing interface enabled
+                                * -> start beacon queue.
+                                */
+                               rt2x00queue_start_queue(rt2x00dev->bcn);
+                       }
+               }
+               mutex_unlock(&intf->beacon_skb_mutex);
+       }
+
+       /*
+        * When the association status has changed we must reset the link
+        * tuner counter. This is because some drivers determine if they
+        * should perform link tuning based on the number of seconds
+        * while associated or not associated.
+        */
+       if (changes & BSS_CHANGED_ASSOC) {
+               rt2x00dev->link.count = 0;
+
+               if (bss_conf->assoc)
+                       rt2x00dev->intf_associated++;
+               else
+                       rt2x00dev->intf_associated--;
+
+               rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
+
+               clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
+       }
+
+       /*
+        * Check for access point which do not support 802.11e . We have to
+        * generate data frames sequence number in S/W for such AP, because
+        * of H/W bug.
+        */
+       if (changes & BSS_CHANGED_QOS && !bss_conf->qos)
+               set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
+
+       /*
+        * When the erp information has changed, we should perform
+        * additional configuration steps. For all other changes we are done.
+        */
+       if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE |
+                      BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES |
+                      BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT))
+               rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
+
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
+                     struct ieee80211_vif *vif, u16 queue_idx,
+                     const struct ieee80211_tx_queue_params *params)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+
+       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+       if (unlikely(!queue))
+               return -EINVAL;
+
+       /*
+        * The passed variables are stored as real value ((2^n)-1).
+        * Ralink registers require to know the bit number 'n'.
+        */
+       if (params->cw_min > 0)
+               queue->cw_min = fls(params->cw_min);
+       else
+               queue->cw_min = 5; /* cw_min: 2^5 = 32. */
+
+       if (params->cw_max > 0)
+               queue->cw_max = fls(params->cw_max);
+       else
+               queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
+
+       queue->aifs = params->aifs;
+       queue->txop = params->txop;
+
+       rt2x00_dbg(rt2x00dev,
+                  "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d\n",
+                  queue_idx, queue->cw_min, queue->cw_max, queue->aifs,
+                  queue->txop);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);
+
+void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
+
+       wiphy_rfkill_set_hw_state(hw->wiphy, !active);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
+
+void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                    u32 queues, bool drop)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_flush_queue(queue, drop);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_flush);
+
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup *def = &rt2x00dev->default_ant;
+       struct antenna_setup setup;
+
+       // The antenna value is not supposed to be 0,
+       // or exceed the maximum number of antenna's.
+       if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
+               return -EINVAL;
+
+       // When the client tried to configure the antenna to or from
+       // diversity mode, we must reset the default antenna as well
+       // as that controls the diversity switch.
+       if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
+               ant->flags &= ~ANTENNA_TX_DIVERSITY;
+       if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
+               ant->flags &= ~ANTENNA_RX_DIVERSITY;
+
+       // If diversity is being enabled, check if we need hardware
+       // or software diversity. In the latter case, reset the value,
+       // and make sure we update the antenna flags to have the
+       // link tuner pick up the diversity tuning.
+       if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
+               tx_ant = ANTENNA_SW_DIVERSITY;
+               ant->flags |= ANTENNA_TX_DIVERSITY;
+       }
+
+       if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
+               rx_ant = ANTENNA_SW_DIVERSITY;
+               ant->flags |= ANTENNA_RX_DIVERSITY;
+       }
+
+       setup.tx = tx_ant;
+       setup.rx = rx_ant;
+       setup.rx_chain_num = 0;
+       setup.tx_chain_num = 0;
+
+       rt2x00lib_config_antenna(rt2x00dev, setup);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
+
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct link_ant *ant = &rt2x00dev->link.ant;
+       struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+       // When software diversity is active, we must report this to the
+       // client and not the current active antenna state.
+       if (ant->flags & ANTENNA_TX_DIVERSITY)
+               *tx_ant = ANTENNA_HW_DIVERSITY;
+       else
+               *tx_ant = active->tx;
+
+       if (ant->flags & ANTENNA_RX_DIVERSITY)
+               *rx_ant = ANTENNA_HW_DIVERSITY;
+       else
+               *rx_ant = active->rx;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
+
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               *tx += queue->length;
+               *tx_max += queue->limit;
+       }
+
+       *rx = rt2x00dev->rx->length;
+       *rx_max = rt2x00dev->rx->limit;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
+
+bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               if (!rt2x00queue_empty(queue))
+                       return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.c
new file mode 100644 (file)
index 0000000..f0178fd
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00mmio
+       Abstract: rt2x00 generic mmio device routines.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+
+/*
+ * Register access.
+ */
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int offset,
+                           const struct rt2x00_field32 field,
+                           u32 *reg)
+{
+       unsigned int i;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return 0;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00mmio_register_read(rt2x00dev, offset, reg);
+               if (!rt2x00_get_field32(*reg, field))
+                       return 1;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       printk_once(KERN_ERR "%s() Indirect register access failed: "
+             "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
+       *reg = ~0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read);
+
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue = rt2x00dev->rx;
+       struct queue_entry *entry;
+       struct queue_entry_priv_mmio *entry_priv;
+       struct skb_frame_desc *skbdesc;
+       int max_rx = 16;
+
+       while (--max_rx) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+               entry_priv = entry->priv_data;
+
+               if (rt2x00dev->ops->lib->get_entry_state(entry))
+                       break;
+
+               /*
+                * Fill in desc fields of the skb descriptor
+                */
+               skbdesc = get_skb_frame_desc(entry->skb);
+               skbdesc->desc = entry_priv->desc;
+               skbdesc->desc_len = entry->queue->desc_size;
+
+               /*
+                * DMA is already done, notify rt2x00lib that
+                * it finished successfully.
+                */
+               rt2x00lib_dmastart(entry);
+               rt2x00lib_dmadone(entry);
+
+               /*
+                * Send the frame to rt2x00lib for further processing.
+                */
+               rt2x00lib_rxdone(entry, GFP_ATOMIC);
+       }
+
+       return !max_rx;
+}
+EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone);
+
+void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop)
+{
+       unsigned int i;
+
+       for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+               msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue);
+
+/*
+ * Device initialization handlers.
+ */
+static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+                                     struct data_queue *queue)
+{
+       struct queue_entry_priv_mmio *entry_priv;
+       void *addr;
+       dma_addr_t dma;
+       unsigned int i;
+
+       /*
+        * Allocate DMA memory for descriptor and buffer.
+        */
+       addr = dma_zalloc_coherent(rt2x00dev->dev,
+                                  queue->limit * queue->desc_size, &dma,
+                                  GFP_KERNEL);
+       if (!addr)
+               return -ENOMEM;
+
+       /*
+        * Initialize all queue entries to contain valid addresses.
+        */
+       for (i = 0; i < queue->limit; i++) {
+               entry_priv = queue->entries[i].priv_data;
+               entry_priv->desc = addr + i * queue->desc_size;
+               entry_priv->desc_dma = dma + i * queue->desc_size;
+       }
+
+       return 0;
+}
+
+static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+                                     struct data_queue *queue)
+{
+       struct queue_entry_priv_mmio *entry_priv =
+           queue->entries[0].priv_data;
+
+       if (entry_priv->desc)
+               dma_free_coherent(rt2x00dev->dev,
+                                 queue->limit * queue->desc_size,
+                                 entry_priv->desc, entry_priv->desc_dma);
+       entry_priv->desc = NULL;
+}
+
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       int status;
+
+       /*
+        * Allocate DMA
+        */
+       queue_for_each(rt2x00dev, queue) {
+               status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue);
+               if (status)
+                       goto exit;
+       }
+
+       /*
+        * Register interrupt handler.
+        */
+       status = request_irq(rt2x00dev->irq,
+                            rt2x00dev->ops->lib->irq_handler,
+                            IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+       if (status) {
+               rt2x00_err(rt2x00dev, "IRQ %d allocation failed (error %d)\n",
+                          rt2x00dev->irq, status);
+               goto exit;
+       }
+
+       return 0;
+
+exit:
+       queue_for_each(rt2x00dev, queue)
+               rt2x00mmio_free_queue_dma(rt2x00dev, queue);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00mmio_initialize);
+
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       /*
+        * Free irq line.
+        */
+       free_irq(rt2x00dev->irq, rt2x00dev);
+
+       /*
+        * Free DMA
+        */
+       queue_for_each(rt2x00dev, queue)
+               rt2x00mmio_free_queue_dma(rt2x00dev, queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize);
+
+/*
+ * rt2x00mmio module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 mmio library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
new file mode 100644 (file)
index 0000000..701c312
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00mmio
+       Abstract: Data structures for the rt2x00mmio module.
+ */
+
+#ifndef RT2X00MMIO_H
+#define RT2X00MMIO_H
+
+#include <linux/io.h>
+
+/*
+ * Register access.
+ */
+static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
+                                           const unsigned int offset,
+                                           u32 *value)
+{
+       *value = readl(rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                void *value, const u32 length)
+{
+       memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+}
+
+static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev,
+                                            const unsigned int offset,
+                                            u32 value)
+{
+       writel(value, rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+                                                 const unsigned int offset,
+                                                 const void *value,
+                                                 const u32 length)
+{
+       __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
+}
+
+/**
+ * rt2x00mmio_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                           const unsigned int offset,
+                           const struct rt2x00_field32 field,
+                           u32 *reg);
+
+/**
+ * struct queue_entry_priv_mmio: Per entry PCI specific information
+ *
+ * @desc: Pointer to device descriptor
+ * @desc_dma: DMA pointer to &desc.
+ * @data: Pointer to device's entry memory.
+ * @data_dma: DMA pointer to &data.
+ */
+struct queue_entry_priv_mmio {
+       __le32 *desc;
+       dma_addr_t desc_dma;
+};
+
+/**
+ * rt2x00mmio_rxdone - Handle RX done events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ *
+ * Returns true if there are still rx frames pending and false if all
+ * pending rx frames were processed.
+ */
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00mmio_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop);
+
+/*
+ * Device initialization handlers.
+ */
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
new file mode 100644 (file)
index 0000000..d93db4b
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00pci
+       Abstract: rt2x00 generic pci device routines.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00pci.h"
+
+/*
+ * PCI driver handlers.
+ */
+static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
+{
+       kfree(rt2x00dev->rf);
+       rt2x00dev->rf = NULL;
+
+       kfree(rt2x00dev->eeprom);
+       rt2x00dev->eeprom = NULL;
+
+       if (rt2x00dev->csr.base) {
+               iounmap(rt2x00dev->csr.base);
+               rt2x00dev->csr.base = NULL;
+       }
+}
+
+static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
+{
+       struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev);
+
+       rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0);
+       if (!rt2x00dev->csr.base)
+               goto exit;
+
+       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+       if (!rt2x00dev->eeprom)
+               goto exit;
+
+       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
+       if (!rt2x00dev->rf)
+               goto exit;
+
+       return 0;
+
+exit:
+       rt2x00_probe_err("Failed to allocate registers\n");
+
+       rt2x00pci_free_reg(rt2x00dev);
+
+       return -ENOMEM;
+}
+
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
+{
+       struct ieee80211_hw *hw;
+       struct rt2x00_dev *rt2x00dev;
+       int retval;
+       u16 chip;
+
+       retval = pci_enable_device(pci_dev);
+       if (retval) {
+               rt2x00_probe_err("Enable device failed\n");
+               return retval;
+       }
+
+       retval = pci_request_regions(pci_dev, pci_name(pci_dev));
+       if (retval) {
+               rt2x00_probe_err("PCI request regions failed\n");
+               goto exit_disable_device;
+       }
+
+       pci_set_master(pci_dev);
+
+       if (pci_set_mwi(pci_dev))
+               rt2x00_probe_err("MWI not available\n");
+
+       if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
+               rt2x00_probe_err("PCI DMA not supported\n");
+               retval = -EIO;
+               goto exit_release_regions;
+       }
+
+       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
+       if (!hw) {
+               rt2x00_probe_err("Failed to allocate hardware\n");
+               retval = -ENOMEM;
+               goto exit_release_regions;
+       }
+
+       pci_set_drvdata(pci_dev, hw);
+
+       rt2x00dev = hw->priv;
+       rt2x00dev->dev = &pci_dev->dev;
+       rt2x00dev->ops = ops;
+       rt2x00dev->hw = hw;
+       rt2x00dev->irq = pci_dev->irq;
+       rt2x00dev->name = ops->name;
+
+       if (pci_is_pcie(pci_dev))
+               rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+       else
+               rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+
+       retval = rt2x00pci_alloc_reg(rt2x00dev);
+       if (retval)
+               goto exit_free_device;
+
+       /*
+        * Because rt3290 chip use different efuse offset to read efuse data.
+        * So before read efuse it need to indicate it is the
+        * rt3290 or not.
+        */
+       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
+       rt2x00dev->chip.rt = chip;
+
+       retval = rt2x00lib_probe_dev(rt2x00dev);
+       if (retval)
+               goto exit_free_reg;
+
+       return 0;
+
+exit_free_reg:
+       rt2x00pci_free_reg(rt2x00dev);
+
+exit_free_device:
+       ieee80211_free_hw(hw);
+
+exit_release_regions:
+       pci_release_regions(pci_dev);
+
+exit_disable_device:
+       pci_disable_device(pci_dev);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_probe);
+
+void rt2x00pci_remove(struct pci_dev *pci_dev)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * Free all allocated data.
+        */
+       rt2x00lib_remove_dev(rt2x00dev);
+       rt2x00pci_free_reg(rt2x00dev);
+       ieee80211_free_hw(hw);
+
+       /*
+        * Free the PCI device data.
+        */
+       pci_disable_device(pci_dev);
+       pci_release_regions(pci_dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_remove);
+
+#ifdef CONFIG_PM
+int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       int retval;
+
+       retval = rt2x00lib_suspend(rt2x00dev, state);
+       if (retval)
+               return retval;
+
+       pci_save_state(pci_dev);
+       pci_disable_device(pci_dev);
+       return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_suspend);
+
+int rt2x00pci_resume(struct pci_dev *pci_dev)
+{
+       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       if (pci_set_power_state(pci_dev, PCI_D0) ||
+           pci_enable_device(pci_dev)) {
+               rt2x00_err(rt2x00dev, "Failed to resume device\n");
+               return -EIO;
+       }
+
+       pci_restore_state(pci_dev);
+       return rt2x00lib_resume(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_resume);
+#endif /* CONFIG_PM */
+
+/*
+ * rt2x00pci module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 pci library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.h b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.h
new file mode 100644 (file)
index 0000000..bc0ca5f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00pci
+       Abstract: Data structures for the rt2x00pci module.
+ */
+
+#ifndef RT2X00PCI_H
+#define RT2X00PCI_H
+
+#include <linux/io.h>
+#include <linux/pci.h>
+
+/*
+ * This variable should be used with the
+ * pci_driver structure initialization.
+ */
+#define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops)
+
+/*
+ * PCI driver handlers.
+ */
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
+void rt2x00pci_remove(struct pci_dev *pci_dev);
+#ifdef CONFIG_PM
+int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
+int rt2x00pci_resume(struct pci_dev *pci_dev);
+#else
+#define rt2x00pci_suspend      NULL
+#define rt2x00pci_resume       NULL
+#endif /* CONFIG_PM */
+
+#endif /* RT2X00PCI_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
new file mode 100644 (file)
index 0000000..68b620b
--- /dev/null
@@ -0,0 +1,1290 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00lib
+       Abstract: rt2x00 queue specific routines.
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
+{
+       struct data_queue *queue = entry->queue;
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       struct sk_buff *skb;
+       struct skb_frame_desc *skbdesc;
+       unsigned int frame_size;
+       unsigned int head_size = 0;
+       unsigned int tail_size = 0;
+
+       /*
+        * The frame size includes descriptor size, because the
+        * hardware directly receive the frame into the skbuffer.
+        */
+       frame_size = queue->data_size + queue->desc_size + queue->winfo_size;
+
+       /*
+        * The payload should be aligned to a 4-byte boundary,
+        * this means we need at least 3 bytes for moving the frame
+        * into the correct offset.
+        */
+       head_size = 4;
+
+       /*
+        * For IV/EIV/ICV assembly we must make sure there is
+        * at least 8 bytes bytes available in headroom for IV/EIV
+        * and 8 bytes for ICV data as tailroon.
+        */
+       if (rt2x00_has_cap_hw_crypto(rt2x00dev)) {
+               head_size += 8;
+               tail_size += 8;
+       }
+
+       /*
+        * Allocate skbuffer.
+        */
+       skb = __dev_alloc_skb(frame_size + head_size + tail_size, gfp);
+       if (!skb)
+               return NULL;
+
+       /*
+        * Make sure we not have a frame with the requested bytes
+        * available in the head and tail.
+        */
+       skb_reserve(skb, head_size);
+       skb_put(skb, frame_size);
+
+       /*
+        * Populate skbdesc.
+        */
+       skbdesc = get_skb_frame_desc(skb);
+       memset(skbdesc, 0, sizeof(*skbdesc));
+       skbdesc->entry = entry;
+
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA)) {
+               dma_addr_t skb_dma;
+
+               skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
+                                        DMA_FROM_DEVICE);
+               if (unlikely(dma_mapping_error(rt2x00dev->dev, skb_dma))) {
+                       dev_kfree_skb_any(skb);
+                       return NULL;
+               }
+
+               skbdesc->skb_dma = skb_dma;
+               skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;
+       }
+
+       return skb;
+}
+
+int rt2x00queue_map_txskb(struct queue_entry *entry)
+{
+       struct device *dev = entry->queue->rt2x00dev->dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+
+       skbdesc->skb_dma =
+           dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
+
+       if (unlikely(dma_mapping_error(dev, skbdesc->skb_dma)))
+               return -ENOMEM;
+
+       skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
+
+void rt2x00queue_unmap_skb(struct queue_entry *entry)
+{
+       struct device *dev = entry->queue->rt2x00dev->dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+
+       if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) {
+               dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
+                                DMA_FROM_DEVICE);
+               skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX;
+       } else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
+               dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
+                                DMA_TO_DEVICE);
+               skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb);
+
+void rt2x00queue_free_skb(struct queue_entry *entry)
+{
+       if (!entry->skb)
+               return;
+
+       rt2x00queue_unmap_skb(entry);
+       dev_kfree_skb_any(entry->skb);
+       entry->skb = NULL;
+}
+
+void rt2x00queue_align_frame(struct sk_buff *skb)
+{
+       unsigned int frame_length = skb->len;
+       unsigned int align = ALIGN_SIZE(skb, 0);
+
+       if (!align)
+               return;
+
+       skb_push(skb, align);
+       memmove(skb->data, skb->data + align, frame_length);
+       skb_trim(skb, frame_length);
+}
+
+/*
+ * H/W needs L2 padding between the header and the paylod if header size
+ * is not 4 bytes aligned.
+ */
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+{
+       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+
+       if (!l2pad)
+               return;
+
+       skb_push(skb, l2pad);
+       memmove(skb->data, skb->data + l2pad, hdr_len);
+}
+
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+{
+       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+
+       if (!l2pad)
+               return;
+
+       memmove(skb->data + l2pad, skb->data, hdr_len);
+       skb_pull(skb, l2pad);
+}
+
+static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
+                                                struct sk_buff *skb,
+                                                struct txentry_desc *txdesc)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
+       u16 seqno;
+
+       if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+               return;
+
+       __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+
+       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_SW_SEQNO)) {
+               /*
+                * rt2800 has a H/W (or F/W) bug, device incorrectly increase
+                * seqno on retransmited data (non-QOS) frames. To workaround
+                * the problem let's generate seqno in software if QOS is
+                * disabled.
+                */
+               if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags))
+                       __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+               else
+                       /* H/W will generate sequence number */
+                       return;
+       }
+
+       /*
+        * The hardware is not able to insert a sequence number. Assign a
+        * software generated one here.
+        *
+        * This is wrong because beacons are not getting sequence
+        * numbers assigned properly.
+        *
+        * A secondary problem exists for drivers that cannot toggle
+        * sequence counting per-frame, since those will override the
+        * sequence counter given by mac80211.
+        */
+       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+               seqno = atomic_add_return(0x10, &intf->seqno);
+       else
+               seqno = atomic_read(&intf->seqno);
+
+       hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+       hdr->seq_ctrl |= cpu_to_le16(seqno);
+}
+
+static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
+                                                 struct sk_buff *skb,
+                                                 struct txentry_desc *txdesc,
+                                                 const struct rt2x00_rate *hwrate)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+       unsigned int data_length;
+       unsigned int duration;
+       unsigned int residual;
+
+       /*
+        * Determine with what IFS priority this frame should be send.
+        * Set ifs to IFS_SIFS when the this is not the first fragment,
+        * or this fragment came after RTS/CTS.
+        */
+       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+               txdesc->u.plcp.ifs = IFS_BACKOFF;
+       else
+               txdesc->u.plcp.ifs = IFS_SIFS;
+
+       /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
+       data_length = skb->len + 4;
+       data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
+
+       /*
+        * PLCP setup
+        * Length calculation depends on OFDM/CCK rate.
+        */
+       txdesc->u.plcp.signal = hwrate->plcp;
+       txdesc->u.plcp.service = 0x04;
+
+       if (hwrate->flags & DEV_RATE_OFDM) {
+               txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f;
+               txdesc->u.plcp.length_low = data_length & 0x3f;
+       } else {
+               /*
+                * Convert length to microseconds.
+                */
+               residual = GET_DURATION_RES(data_length, hwrate->bitrate);
+               duration = GET_DURATION(data_length, hwrate->bitrate);
+
+               if (residual != 0) {
+                       duration++;
+
+                       /*
+                        * Check if we need to set the Length Extension
+                        */
+                       if (hwrate->bitrate == 110 && residual <= 30)
+                               txdesc->u.plcp.service |= 0x80;
+               }
+
+               txdesc->u.plcp.length_high = (duration >> 8) & 0xff;
+               txdesc->u.plcp.length_low = duration & 0xff;
+
+               /*
+                * When preamble is enabled we should set the
+                * preamble bit for the signal.
+                */
+               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       txdesc->u.plcp.signal |= 0x08;
+       }
+}
+
+static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
+                                               struct sk_buff *skb,
+                                               struct txentry_desc *txdesc,
+                                               struct ieee80211_sta *sta,
+                                               const struct rt2x00_rate *hwrate)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct rt2x00_sta *sta_priv = NULL;
+
+       if (sta) {
+               txdesc->u.ht.mpdu_density =
+                   sta->ht_cap.ampdu_density;
+
+               sta_priv = sta_to_rt2x00_sta(sta);
+               txdesc->u.ht.wcid = sta_priv->wcid;
+       }
+
+       /*
+        * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
+        * mcs rate to be used
+        */
+       if (txrate->flags & IEEE80211_TX_RC_MCS) {
+               txdesc->u.ht.mcs = txrate->idx;
+
+               /*
+                * MIMO PS should be set to 1 for STA's using dynamic SM PS
+                * when using more then one tx stream (>MCS7).
+                */
+               if (sta && txdesc->u.ht.mcs > 7 &&
+                   sta->smps_mode == IEEE80211_SMPS_DYNAMIC)
+                       __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
+       } else {
+               txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       txdesc->u.ht.mcs |= 0x08;
+       }
+
+       if (test_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags)) {
+               if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+                       txdesc->u.ht.txop = TXOP_SIFS;
+               else
+                       txdesc->u.ht.txop = TXOP_BACKOFF;
+
+               /* Left zero on all other settings. */
+               return;
+       }
+
+       txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
+
+       /*
+        * Only one STBC stream is supported for now.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+               txdesc->u.ht.stbc = 1;
+
+       /*
+        * This frame is eligible for an AMPDU, however, don't aggregate
+        * frames that are intended to probe a specific tx rate.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+           !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+               __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+       /*
+        * Set 40Mhz mode if necessary (for legacy rates this will
+        * duplicate the frame to both channels).
+        */
+       if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+           txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+               __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+       if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+               __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+
+       /*
+        * Determine IFS values
+        * - Use TXOP_BACKOFF for management frames except beacons
+        * - Use TXOP_SIFS for fragment bursts
+        * - Use TXOP_HTTXOP for everything else
+        *
+        * Note: rt2800 devices won't use CTS protection (if used)
+        * for frames not transmitted with TXOP_HTTXOP
+        */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+           !ieee80211_is_beacon(hdr->frame_control))
+               txdesc->u.ht.txop = TXOP_BACKOFF;
+       else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+               txdesc->u.ht.txop = TXOP_SIFS;
+       else
+               txdesc->u.ht.txop = TXOP_HTTXOP;
+}
+
+static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
+                                            struct sk_buff *skb,
+                                            struct txentry_desc *txdesc,
+                                            struct ieee80211_sta *sta)
+{
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+       struct ieee80211_rate *rate;
+       const struct rt2x00_rate *hwrate = NULL;
+
+       memset(txdesc, 0, sizeof(*txdesc));
+
+       /*
+        * Header and frame information.
+        */
+       txdesc->length = skb->len;
+       txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
+
+       /*
+        * Check whether this frame is to be acked.
+        */
+       if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
+               __set_bit(ENTRY_TXD_ACK, &txdesc->flags);
+
+       /*
+        * Check if this is a RTS/CTS frame
+        */
+       if (ieee80211_is_rts(hdr->frame_control) ||
+           ieee80211_is_cts(hdr->frame_control)) {
+               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
+               if (ieee80211_is_rts(hdr->frame_control))
+                       __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags);
+               else
+                       __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags);
+               if (tx_info->control.rts_cts_rate_idx >= 0)
+                       rate =
+                           ieee80211_get_rts_cts_rate(rt2x00dev->hw, tx_info);
+       }
+
+       /*
+        * Determine retry information.
+        */
+       txdesc->retry_limit = tx_info->control.rates[0].count - 1;
+       if (txdesc->retry_limit >= rt2x00dev->long_retry)
+               __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
+
+       /*
+        * Check if more fragments are pending
+        */
+       if (ieee80211_has_morefrags(hdr->frame_control)) {
+               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
+               __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags);
+       }
+
+       /*
+        * Check if more frames (!= fragments) are pending
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)
+               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
+
+       /*
+        * Beacons and probe responses require the tsf timestamp
+        * to be inserted into the frame.
+        */
+       if (ieee80211_is_beacon(hdr->frame_control) ||
+           ieee80211_is_probe_resp(hdr->frame_control))
+               __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
+
+       if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) &&
+           !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags))
+               __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
+
+       /*
+        * Determine rate modulation.
+        */
+       if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+               txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
+       else if (txrate->flags & IEEE80211_TX_RC_MCS)
+               txdesc->rate_mode = RATE_MODE_HT_MIX;
+       else {
+               rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
+               hwrate = rt2x00_get_rate(rate->hw_value);
+               if (hwrate->flags & DEV_RATE_OFDM)
+                       txdesc->rate_mode = RATE_MODE_OFDM;
+               else
+                       txdesc->rate_mode = RATE_MODE_CCK;
+       }
+
+       /*
+        * Apply TX descriptor handling by components
+        */
+       rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
+       rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
+
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_HT_TX_DESC))
+               rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
+                                                  sta, hwrate);
+       else
+               rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
+                                                     hwrate);
+}
+
+static int rt2x00queue_write_tx_data(struct queue_entry *entry,
+                                    struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       /*
+        * This should not happen, we already checked the entry
+        * was ours. When the hardware disagrees there has been
+        * a queue corruption!
+        */
+       if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
+                    rt2x00dev->ops->lib->get_entry_state(entry))) {
+               rt2x00_err(rt2x00dev,
+                          "Corrupt queue %d, accessing entry which is not ours\n"
+                          "Please file bug report to %s\n",
+                          entry->queue->qid, DRV_PROJECT);
+               return -EINVAL;
+       }
+
+       /*
+        * Add the requested extra tx headroom in front of the skb.
+        */
+       skb_push(entry->skb, rt2x00dev->extra_tx_headroom);
+       memset(entry->skb->data, 0, rt2x00dev->extra_tx_headroom);
+
+       /*
+        * Call the driver's write_tx_data function, if it exists.
+        */
+       if (rt2x00dev->ops->lib->write_tx_data)
+               rt2x00dev->ops->lib->write_tx_data(entry, txdesc);
+
+       /*
+        * Map the skb to DMA.
+        */
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA) &&
+           rt2x00queue_map_txskb(entry))
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
+                                           struct txentry_desc *txdesc)
+{
+       struct data_queue *queue = entry->queue;
+
+       queue->rt2x00dev->ops->lib->write_tx_desc(entry, txdesc);
+
+       /*
+        * All processing on the frame has been completed, this means
+        * it is now ready to be dumped to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb);
+}
+
+static void rt2x00queue_kick_tx_queue(struct data_queue *queue,
+                                     struct txentry_desc *txdesc)
+{
+       /*
+        * Check if we need to kick the queue, there are however a few rules
+        *      1) Don't kick unless this is the last in frame in a burst.
+        *         When the burst flag is set, this frame is always followed
+        *         by another frame which in some way are related to eachother.
+        *         This is true for fragments, RTS or CTS-to-self frames.
+        *      2) Rule 1 can be broken when the available entries
+        *         in the queue are less then a certain threshold.
+        */
+       if (rt2x00queue_threshold(queue) ||
+           !test_bit(ENTRY_TXD_BURST, &txdesc->flags))
+               queue->rt2x00dev->ops->lib->kick_queue(queue);
+}
+
+static void rt2x00queue_bar_check(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct ieee80211_bar *bar = (void *) (entry->skb->data +
+                                   rt2x00dev->extra_tx_headroom);
+       struct rt2x00_bar_list_entry *bar_entry;
+
+       if (likely(!ieee80211_is_back_req(bar->frame_control)))
+               return;
+
+       bar_entry = kmalloc(sizeof(*bar_entry), GFP_ATOMIC);
+
+       /*
+        * If the alloc fails we still send the BAR out but just don't track
+        * it in our bar list. And as a result we will report it to mac80211
+        * back as failed.
+        */
+       if (!bar_entry)
+               return;
+
+       bar_entry->entry = entry;
+       bar_entry->block_acked = 0;
+
+       /*
+        * Copy the relevant parts of the 802.11 BAR into out check list
+        * such that we can use RCU for less-overhead in the RX path since
+        * sending BARs and processing the according BlockAck should be
+        * the exception.
+        */
+       memcpy(bar_entry->ra, bar->ra, sizeof(bar->ra));
+       memcpy(bar_entry->ta, bar->ta, sizeof(bar->ta));
+       bar_entry->control = bar->control;
+       bar_entry->start_seq_num = bar->start_seq_num;
+
+       /*
+        * Insert BAR into our BAR check list.
+        */
+       spin_lock_bh(&rt2x00dev->bar_list_lock);
+       list_add_tail_rcu(&bar_entry->list, &rt2x00dev->bar_list);
+       spin_unlock_bh(&rt2x00dev->bar_list_lock);
+}
+
+int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
+                              struct ieee80211_sta *sta, bool local)
+{
+       struct ieee80211_tx_info *tx_info;
+       struct queue_entry *entry;
+       struct txentry_desc txdesc;
+       struct skb_frame_desc *skbdesc;
+       u8 rate_idx, rate_flags;
+       int ret = 0;
+
+       /*
+        * Copy all TX descriptor information into txdesc,
+        * after that we are free to use the skb->cb array
+        * for our information.
+        */
+       rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, sta);
+
+       /*
+        * All information is retrieved from the skb->cb array,
+        * now we should claim ownership of the driver part of that
+        * array, preserving the bitrate index and flags.
+        */
+       tx_info = IEEE80211_SKB_CB(skb);
+       rate_idx = tx_info->control.rates[0].idx;
+       rate_flags = tx_info->control.rates[0].flags;
+       skbdesc = get_skb_frame_desc(skb);
+       memset(skbdesc, 0, sizeof(*skbdesc));
+       skbdesc->tx_rate_idx = rate_idx;
+       skbdesc->tx_rate_flags = rate_flags;
+
+       if (local)
+               skbdesc->flags |= SKBDESC_NOT_MAC80211;
+
+       /*
+        * When hardware encryption is supported, and this frame
+        * is to be encrypted, we should strip the IV/EIV data from
+        * the frame so we can provide it to the driver separately.
+        */
+       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
+           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
+               if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_COPY_IV))
+                       rt2x00crypto_tx_copy_iv(skb, &txdesc);
+               else
+                       rt2x00crypto_tx_remove_iv(skb, &txdesc);
+       }
+
+       /*
+        * When DMA allocation is required we should guarantee to the
+        * driver that the DMA is aligned to a 4-byte boundary.
+        * However some drivers require L2 padding to pad the payload
+        * rather then the header. This could be a requirement for
+        * PCI and USB devices, while header alignment only is valid
+        * for PCI devices.
+        */
+       if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_L2PAD))
+               rt2x00queue_insert_l2pad(skb, txdesc.header_length);
+       else if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_DMA))
+               rt2x00queue_align_frame(skb);
+
+       /*
+        * That function must be called with bh disabled.
+        */
+       spin_lock(&queue->tx_lock);
+
+       if (unlikely(rt2x00queue_full(queue))) {
+               rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
+                          queue->qid);
+               ret = -ENOBUFS;
+               goto out;
+       }
+
+       entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+       if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+                                     &entry->flags))) {
+               rt2x00_err(queue->rt2x00dev,
+                          "Arrived at non-free entry in the non-full queue %d\n"
+                          "Please file bug report to %s\n",
+                          queue->qid, DRV_PROJECT);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       skbdesc->entry = entry;
+       entry->skb = skb;
+
+       /*
+        * It could be possible that the queue was corrupted and this
+        * call failed. Since we always return NETDEV_TX_OK to mac80211,
+        * this frame will simply be dropped.
+        */
+       if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
+               clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+               entry->skb = NULL;
+               ret = -EIO;
+               goto out;
+       }
+
+       /*
+        * Put BlockAckReqs into our check list for driver BA processing.
+        */
+       rt2x00queue_bar_check(entry);
+
+       set_bit(ENTRY_DATA_PENDING, &entry->flags);
+
+       rt2x00queue_index_inc(entry, Q_INDEX);
+       rt2x00queue_write_tx_descriptor(entry, &txdesc);
+       rt2x00queue_kick_tx_queue(queue, &txdesc);
+
+out:
+       spin_unlock(&queue->tx_lock);
+       return ret;
+}
+
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+                            struct ieee80211_vif *vif)
+{
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+
+       if (unlikely(!intf->beacon))
+               return -ENOBUFS;
+
+       /*
+        * Clean up the beacon skb.
+        */
+       rt2x00queue_free_skb(intf->beacon);
+
+       /*
+        * Clear beacon (single bssid devices don't need to clear the beacon
+        * since the beacon queue will get stopped anyway).
+        */
+       if (rt2x00dev->ops->lib->clear_beacon)
+               rt2x00dev->ops->lib->clear_beacon(intf->beacon);
+
+       return 0;
+}
+
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+                             struct ieee80211_vif *vif)
+{
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+       struct skb_frame_desc *skbdesc;
+       struct txentry_desc txdesc;
+
+       if (unlikely(!intf->beacon))
+               return -ENOBUFS;
+
+       /*
+        * Clean up the beacon skb.
+        */
+       rt2x00queue_free_skb(intf->beacon);
+
+       intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
+       if (!intf->beacon->skb)
+               return -ENOMEM;
+
+       /*
+        * Copy all TX descriptor information into txdesc,
+        * after that we are free to use the skb->cb array
+        * for our information.
+        */
+       rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc, NULL);
+
+       /*
+        * Fill in skb descriptor
+        */
+       skbdesc = get_skb_frame_desc(intf->beacon->skb);
+       memset(skbdesc, 0, sizeof(*skbdesc));
+       skbdesc->entry = intf->beacon;
+
+       /*
+        * Send beacon to hardware.
+        */
+       rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);
+
+       return 0;
+
+}
+
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
+                               enum queue_index start,
+                               enum queue_index end,
+                               void *data,
+                               bool (*fn)(struct queue_entry *entry,
+                                          void *data))
+{
+       unsigned long irqflags;
+       unsigned int index_start;
+       unsigned int index_end;
+       unsigned int i;
+
+       if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
+               rt2x00_err(queue->rt2x00dev,
+                          "Entry requested from invalid index range (%d - %d)\n",
+                          start, end);
+               return true;
+       }
+
+       /*
+        * Only protect the range we are going to loop over,
+        * if during our loop a extra entry is set to pending
+        * it should not be kicked during this run, since it
+        * is part of another TX operation.
+        */
+       spin_lock_irqsave(&queue->index_lock, irqflags);
+       index_start = queue->index[start];
+       index_end = queue->index[end];
+       spin_unlock_irqrestore(&queue->index_lock, irqflags);
+
+       /*
+        * Start from the TX done pointer, this guarantees that we will
+        * send out all frames in the correct order.
+        */
+       if (index_start < index_end) {
+               for (i = index_start; i < index_end; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
+       } else {
+               for (i = index_start; i < queue->limit; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
+
+               for (i = 0; i < index_end; i++) {
+                       if (fn(&queue->entries[i], data))
+                               return true;
+               }
+       }
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
+
+struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
+                                         enum queue_index index)
+{
+       struct queue_entry *entry;
+       unsigned long irqflags;
+
+       if (unlikely(index >= Q_INDEX_MAX)) {
+               rt2x00_err(queue->rt2x00dev, "Entry requested from invalid index type (%d)\n",
+                          index);
+               return NULL;
+       }
+
+       spin_lock_irqsave(&queue->index_lock, irqflags);
+
+       entry = &queue->entries[queue->index[index]];
+
+       spin_unlock_irqrestore(&queue->index_lock, irqflags);
+
+       return entry;
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
+
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
+{
+       struct data_queue *queue = entry->queue;
+       unsigned long irqflags;
+
+       if (unlikely(index >= Q_INDEX_MAX)) {
+               rt2x00_err(queue->rt2x00dev,
+                          "Index change on invalid index type (%d)\n", index);
+               return;
+       }
+
+       spin_lock_irqsave(&queue->index_lock, irqflags);
+
+       queue->index[index]++;
+       if (queue->index[index] >= queue->limit)
+               queue->index[index] = 0;
+
+       entry->last_action = jiffies;
+
+       if (index == Q_INDEX) {
+               queue->length++;
+       } else if (index == Q_INDEX_DONE) {
+               queue->length--;
+               queue->count++;
+       }
+
+       spin_unlock_irqrestore(&queue->index_lock, irqflags);
+}
+
+static void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               /*
+                * For TX queues, we have to disable the queue
+                * inside mac80211.
+                */
+               ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+               break;
+       default:
+               break;
+       }
+}
+void rt2x00queue_pause_queue(struct data_queue *queue)
+{
+       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
+           !test_bit(QUEUE_STARTED, &queue->flags) ||
+           test_and_set_bit(QUEUE_PAUSED, &queue->flags))
+               return;
+
+       rt2x00queue_pause_queue_nocheck(queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
+
+void rt2x00queue_unpause_queue(struct data_queue *queue)
+{
+       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
+           !test_bit(QUEUE_STARTED, &queue->flags) ||
+           !test_and_clear_bit(QUEUE_PAUSED, &queue->flags))
+               return;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               /*
+                * For TX queues, we have to enable the queue
+                * inside mac80211.
+                */
+               ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+               break;
+       case QID_RX:
+               /*
+                * For RX we need to kick the queue now in order to
+                * receive frames.
+                */
+               queue->rt2x00dev->ops->lib->kick_queue(queue);
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue);
+
+void rt2x00queue_start_queue(struct data_queue *queue)
+{
+       mutex_lock(&queue->status_lock);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
+           test_and_set_bit(QUEUE_STARTED, &queue->flags)) {
+               mutex_unlock(&queue->status_lock);
+               return;
+       }
+
+       set_bit(QUEUE_PAUSED, &queue->flags);
+
+       queue->rt2x00dev->ops->lib->start_queue(queue);
+
+       rt2x00queue_unpause_queue(queue);
+
+       mutex_unlock(&queue->status_lock);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_start_queue);
+
+void rt2x00queue_stop_queue(struct data_queue *queue)
+{
+       mutex_lock(&queue->status_lock);
+
+       if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) {
+               mutex_unlock(&queue->status_lock);
+               return;
+       }
+
+       rt2x00queue_pause_queue_nocheck(queue);
+
+       queue->rt2x00dev->ops->lib->stop_queue(queue);
+
+       mutex_unlock(&queue->status_lock);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
+
+void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
+{
+       bool tx_queue =
+               (queue->qid == QID_AC_VO) ||
+               (queue->qid == QID_AC_VI) ||
+               (queue->qid == QID_AC_BE) ||
+               (queue->qid == QID_AC_BK);
+
+
+       /*
+        * If we are not supposed to drop any pending
+        * frames, this means we must force a start (=kick)
+        * to the queue to make sure the hardware will
+        * start transmitting.
+        */
+       if (!drop && tx_queue)
+               queue->rt2x00dev->ops->lib->kick_queue(queue);
+
+       /*
+        * Check if driver supports flushing, if that is the case we can
+        * defer the flushing to the driver. Otherwise we must use the
+        * alternative which just waits for the queue to become empty.
+        */
+       if (likely(queue->rt2x00dev->ops->lib->flush_queue))
+               queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
+
+       /*
+        * The queue flush has failed...
+        */
+       if (unlikely(!rt2x00queue_empty(queue)))
+               rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n",
+                           queue->qid);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue);
+
+void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       /*
+        * rt2x00queue_start_queue will call ieee80211_wake_queue
+        * for each queue after is has been properly initialized.
+        */
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_start_queue(queue);
+
+       rt2x00queue_start_queue(rt2x00dev->rx);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_start_queues);
+
+void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       /*
+        * rt2x00queue_stop_queue will call ieee80211_stop_queue
+        * as well, but we are completely shutting doing everything
+        * now, so it is much safer to stop all TX queues at once,
+        * and use rt2x00queue_stop_queue for cleaning up.
+        */
+       ieee80211_stop_queues(rt2x00dev->hw);
+
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_stop_queue(queue);
+
+       rt2x00queue_stop_queue(rt2x00dev->rx);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues);
+
+void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop)
+{
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_flush_queue(queue, drop);
+
+       rt2x00queue_flush_queue(rt2x00dev->rx, drop);
+}
+EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues);
+
+static void rt2x00queue_reset(struct data_queue *queue)
+{
+       unsigned long irqflags;
+       unsigned int i;
+
+       spin_lock_irqsave(&queue->index_lock, irqflags);
+
+       queue->count = 0;
+       queue->length = 0;
+
+       for (i = 0; i < Q_INDEX_MAX; i++)
+               queue->index[i] = 0;
+
+       spin_unlock_irqrestore(&queue->index_lock, irqflags);
+}
+
+void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       unsigned int i;
+
+       queue_for_each(rt2x00dev, queue) {
+               rt2x00queue_reset(queue);
+
+               for (i = 0; i < queue->limit; i++)
+                       rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
+       }
+}
+
+static int rt2x00queue_alloc_entries(struct data_queue *queue)
+{
+       struct queue_entry *entries;
+       unsigned int entry_size;
+       unsigned int i;
+
+       rt2x00queue_reset(queue);
+
+       /*
+        * Allocate all queue entries.
+        */
+       entry_size = sizeof(*entries) + queue->priv_size;
+       entries = kcalloc(queue->limit, entry_size, GFP_KERNEL);
+       if (!entries)
+               return -ENOMEM;
+
+#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
+       (((char *)(__base)) + ((__limit) * (__esize)) + \
+           ((__index) * (__psize)))
+
+       for (i = 0; i < queue->limit; i++) {
+               entries[i].flags = 0;
+               entries[i].queue = queue;
+               entries[i].skb = NULL;
+               entries[i].entry_idx = i;
+               entries[i].priv_data =
+                   QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
+                                           sizeof(*entries), queue->priv_size);
+       }
+
+#undef QUEUE_ENTRY_PRIV_OFFSET
+
+       queue->entries = entries;
+
+       return 0;
+}
+
+static void rt2x00queue_free_skbs(struct data_queue *queue)
+{
+       unsigned int i;
+
+       if (!queue->entries)
+               return;
+
+       for (i = 0; i < queue->limit; i++) {
+               rt2x00queue_free_skb(&queue->entries[i]);
+       }
+}
+
+static int rt2x00queue_alloc_rxskbs(struct data_queue *queue)
+{
+       unsigned int i;
+       struct sk_buff *skb;
+
+       for (i = 0; i < queue->limit; i++) {
+               skb = rt2x00queue_alloc_rxskb(&queue->entries[i], GFP_KERNEL);
+               if (!skb)
+                       return -ENOMEM;
+               queue->entries[i].skb = skb;
+       }
+
+       return 0;
+}
+
+int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       int status;
+
+       status = rt2x00queue_alloc_entries(rt2x00dev->rx);
+       if (status)
+               goto exit;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               status = rt2x00queue_alloc_entries(queue);
+               if (status)
+                       goto exit;
+       }
+
+       status = rt2x00queue_alloc_entries(rt2x00dev->bcn);
+       if (status)
+               goto exit;
+
+       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE)) {
+               status = rt2x00queue_alloc_entries(rt2x00dev->atim);
+               if (status)
+                       goto exit;
+       }
+
+       status = rt2x00queue_alloc_rxskbs(rt2x00dev->rx);
+       if (status)
+               goto exit;
+
+       return 0;
+
+exit:
+       rt2x00_err(rt2x00dev, "Queue entries allocation failed\n");
+
+       rt2x00queue_uninitialize(rt2x00dev);
+
+       return status;
+}
+
+void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       rt2x00queue_free_skbs(rt2x00dev->rx);
+
+       queue_for_each(rt2x00dev, queue) {
+               kfree(queue->entries);
+               queue->entries = NULL;
+       }
+}
+
+static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
+                            struct data_queue *queue, enum data_queue_qid qid)
+{
+       mutex_init(&queue->status_lock);
+       spin_lock_init(&queue->tx_lock);
+       spin_lock_init(&queue->index_lock);
+
+       queue->rt2x00dev = rt2x00dev;
+       queue->qid = qid;
+       queue->txop = 0;
+       queue->aifs = 2;
+       queue->cw_min = 5;
+       queue->cw_max = 10;
+
+       rt2x00dev->ops->queue_init(queue);
+
+       queue->threshold = DIV_ROUND_UP(queue->limit, 10);
+}
+
+int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       enum data_queue_qid qid;
+       unsigned int req_atim =
+           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE);
+
+       /*
+        * We need the following queues:
+        * RX: 1
+        * TX: ops->tx_queues
+        * Beacon: 1
+        * Atim: 1 (if required)
+        */
+       rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim;
+
+       queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
+       if (!queue) {
+               rt2x00_err(rt2x00dev, "Queue allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /*
+        * Initialize pointers
+        */
+       rt2x00dev->rx = queue;
+       rt2x00dev->tx = &queue[1];
+       rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues];
+       rt2x00dev->atim = req_atim ? &queue[2 + rt2x00dev->ops->tx_queues] : NULL;
+
+       /*
+        * Initialize queue parameters.
+        * RX: qid = QID_RX
+        * TX: qid = QID_AC_VO + index
+        * TX: cw_min: 2^5 = 32.
+        * TX: cw_max: 2^10 = 1024.
+        * BCN: qid = QID_BEACON
+        * ATIM: qid = QID_ATIM
+        */
+       rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
+
+       qid = QID_AC_VO;
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_init(rt2x00dev, queue, qid++);
+
+       rt2x00queue_init(rt2x00dev, rt2x00dev->bcn, QID_BEACON);
+       if (req_atim)
+               rt2x00queue_init(rt2x00dev, rt2x00dev->atim, QID_ATIM);
+
+       return 0;
+}
+
+void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
+{
+       kfree(rt2x00dev->rx);
+       rt2x00dev->rx = NULL;
+       rt2x00dev->tx = NULL;
+       rt2x00dev->bcn = NULL;
+}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
new file mode 100644 (file)
index 0000000..2233b91
--- /dev/null
@@ -0,0 +1,686 @@
+/*
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00
+       Abstract: rt2x00 queue datastructures and routines
+ */
+
+#ifndef RT2X00QUEUE_H
+#define RT2X00QUEUE_H
+
+#include <linux/prefetch.h>
+
+/**
+ * DOC: Entry frame size
+ *
+ * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
+ * for USB devices this restriction does not apply, but the value of
+ * 2432 makes sense since it is big enough to contain the maximum fragment
+ * size according to the ieee802.11 specs.
+ * The aggregation size depends on support from the driver, but should
+ * be something around 3840 bytes.
+ */
+#define DATA_FRAME_SIZE                2432
+#define MGMT_FRAME_SIZE                256
+#define AGGREGATION_SIZE       3840
+
+/**
+ * enum data_queue_qid: Queue identification
+ *
+ * @QID_AC_VO: AC VO queue
+ * @QID_AC_VI: AC VI queue
+ * @QID_AC_BE: AC BE queue
+ * @QID_AC_BK: AC BK queue
+ * @QID_HCCA: HCCA queue
+ * @QID_MGMT: MGMT queue (prio queue)
+ * @QID_RX: RX queue
+ * @QID_OTHER: None of the above (don't use, only present for completeness)
+ * @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
+ * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
+ */
+enum data_queue_qid {
+       QID_AC_VO = 0,
+       QID_AC_VI = 1,
+       QID_AC_BE = 2,
+       QID_AC_BK = 3,
+       QID_HCCA = 4,
+       QID_MGMT = 13,
+       QID_RX = 14,
+       QID_OTHER = 15,
+       QID_BEACON,
+       QID_ATIM,
+};
+
+/**
+ * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
+ *
+ * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX
+ * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
+ * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by
+ *     mac80211 but was stripped for processing by the driver.
+ * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211,
+ *     don't try to pass it back.
+ * @SKBDESC_DESC_IN_SKB: The descriptor is at the start of the
+ *     skb, instead of in the desc field.
+ */
+enum skb_frame_desc_flags {
+       SKBDESC_DMA_MAPPED_RX = 1 << 0,
+       SKBDESC_DMA_MAPPED_TX = 1 << 1,
+       SKBDESC_IV_STRIPPED = 1 << 2,
+       SKBDESC_NOT_MAC80211 = 1 << 3,
+       SKBDESC_DESC_IN_SKB = 1 << 4,
+};
+
+/**
+ * struct skb_frame_desc: Descriptor information for the skb buffer
+ *
+ * This structure is placed over the driver_data array, this means that
+ * this structure should not exceed the size of that array (40 bytes).
+ *
+ * @flags: Frame flags, see &enum skb_frame_desc_flags.
+ * @desc_len: Length of the frame descriptor.
+ * @tx_rate_idx: the index of the TX rate, used for TX status reporting
+ * @tx_rate_flags: the TX rate flags, used for TX status reporting
+ * @desc: Pointer to descriptor part of the frame.
+ *     Note that this pointer could point to something outside
+ *     of the scope of the skb->data pointer.
+ * @iv: IV/EIV data used during encryption/decryption.
+ * @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
+ * @entry: The entry to which this sk buffer belongs.
+ */
+struct skb_frame_desc {
+       u8 flags;
+
+       u8 desc_len;
+       u8 tx_rate_idx;
+       u8 tx_rate_flags;
+
+       void *desc;
+
+       __le32 iv[2];
+
+       dma_addr_t skb_dma;
+
+       struct queue_entry *entry;
+};
+
+/**
+ * get_skb_frame_desc - Obtain the rt2x00 frame descriptor from a sk_buff.
+ * @skb: &struct sk_buff from where we obtain the &struct skb_frame_desc
+ */
+static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
+{
+       BUILD_BUG_ON(sizeof(struct skb_frame_desc) >
+                    IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
+       return (struct skb_frame_desc *)&IEEE80211_SKB_CB(skb)->driver_data;
+}
+
+/**
+ * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
+ *
+ * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
+ * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
+ * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
+ * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
+ * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
+ * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
+ * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
+ */
+enum rxdone_entry_desc_flags {
+       RXDONE_SIGNAL_PLCP = BIT(0),
+       RXDONE_SIGNAL_BITRATE = BIT(1),
+       RXDONE_SIGNAL_MCS = BIT(2),
+       RXDONE_MY_BSS = BIT(3),
+       RXDONE_CRYPTO_IV = BIT(4),
+       RXDONE_CRYPTO_ICV = BIT(5),
+       RXDONE_L2PAD = BIT(6),
+};
+
+/**
+ * RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags
+ * except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags
+ * from &rxdone_entry_desc to a signal value type.
+ */
+#define RXDONE_SIGNAL_MASK \
+       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
+
+/**
+ * struct rxdone_entry_desc: RX Entry descriptor
+ *
+ * Summary of information that has been read from the RX frame descriptor.
+ *
+ * @timestamp: RX Timestamp
+ * @signal: Signal of the received frame.
+ * @rssi: RSSI of the received frame.
+ * @size: Data size of the received frame.
+ * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
+ * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
+ * @rate_mode: Rate mode (See @enum rate_modulation).
+ * @cipher: Cipher type used during decryption.
+ * @cipher_status: Decryption status.
+ * @iv: IV/EIV data used during decryption.
+ * @icv: ICV data used during decryption.
+ */
+struct rxdone_entry_desc {
+       u64 timestamp;
+       int signal;
+       int rssi;
+       int size;
+       int flags;
+       int dev_flags;
+       u16 rate_mode;
+       u8 cipher;
+       u8 cipher_status;
+
+       __le32 iv[2];
+       __le32 icv;
+};
+
+/**
+ * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc
+ *
+ * Every txdone report has to contain the basic result of the
+ * transmission, either &TXDONE_UNKNOWN, &TXDONE_SUCCESS or
+ * &TXDONE_FAILURE. The flag &TXDONE_FALLBACK can be used in
+ * conjunction with all of these flags but should only be set
+ * if retires > 0. The flag &TXDONE_EXCESSIVE_RETRY can only be used
+ * in conjunction with &TXDONE_FAILURE.
+ *
+ * @TXDONE_UNKNOWN: Hardware could not determine success of transmission.
+ * @TXDONE_SUCCESS: Frame was successfully send
+ * @TXDONE_FALLBACK: Hardware used fallback rates for retries
+ * @TXDONE_FAILURE: Frame was not successfully send
+ * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
+ *     frame transmission failed due to excessive retries.
+ */
+enum txdone_entry_desc_flags {
+       TXDONE_UNKNOWN,
+       TXDONE_SUCCESS,
+       TXDONE_FALLBACK,
+       TXDONE_FAILURE,
+       TXDONE_EXCESSIVE_RETRY,
+       TXDONE_AMPDU,
+};
+
+/**
+ * struct txdone_entry_desc: TX done entry descriptor
+ *
+ * Summary of information that has been read from the TX frame descriptor
+ * after the device is done with transmission.
+ *
+ * @flags: TX done flags (See &enum txdone_entry_desc_flags).
+ * @retry: Retry count.
+ */
+struct txdone_entry_desc {
+       unsigned long flags;
+       int retry;
+};
+
+/**
+ * enum txentry_desc_flags: Status flags for TX entry descriptor
+ *
+ * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
+ * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame.
+ * @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter.
+ * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame.
+ * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
+ * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
+ * @ENTRY_TXD_BURST: This frame belongs to the same burst event.
+ * @ENTRY_TXD_ACK: An ACK is required for this frame.
+ * @ENTRY_TXD_RETRY_MODE: When set, the long retry count is used.
+ * @ENTRY_TXD_ENCRYPT: This frame should be encrypted.
+ * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
+ * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
+ * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
+ * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
+ * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
+ * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
+ * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode.
+ */
+enum txentry_desc_flags {
+       ENTRY_TXD_RTS_FRAME,
+       ENTRY_TXD_CTS_FRAME,
+       ENTRY_TXD_GENERATE_SEQ,
+       ENTRY_TXD_FIRST_FRAGMENT,
+       ENTRY_TXD_MORE_FRAG,
+       ENTRY_TXD_REQ_TIMESTAMP,
+       ENTRY_TXD_BURST,
+       ENTRY_TXD_ACK,
+       ENTRY_TXD_RETRY_MODE,
+       ENTRY_TXD_ENCRYPT,
+       ENTRY_TXD_ENCRYPT_PAIRWISE,
+       ENTRY_TXD_ENCRYPT_IV,
+       ENTRY_TXD_ENCRYPT_MMIC,
+       ENTRY_TXD_HT_AMPDU,
+       ENTRY_TXD_HT_BW_40,
+       ENTRY_TXD_HT_SHORT_GI,
+       ENTRY_TXD_HT_MIMO_PS,
+};
+
+/**
+ * struct txentry_desc: TX Entry descriptor
+ *
+ * Summary of information for the frame descriptor before sending a TX frame.
+ *
+ * @flags: Descriptor flags (See &enum queue_entry_flags).
+ * @length: Length of the entire frame.
+ * @header_length: Length of 802.11 header.
+ * @length_high: PLCP length high word.
+ * @length_low: PLCP length low word.
+ * @signal: PLCP signal.
+ * @service: PLCP service.
+ * @msc: MCS.
+ * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
+ * @ba_size: Size of the recepients RX reorder buffer - 1.
+ * @rate_mode: Rate mode (See @enum rate_modulation).
+ * @mpdu_density: MDPU density.
+ * @retry_limit: Max number of retries.
+ * @ifs: IFS value.
+ * @txop: IFS value for 11n capable chips.
+ * @cipher: Cipher type used for encryption.
+ * @key_idx: Key index used for encryption.
+ * @iv_offset: Position where IV should be inserted by hardware.
+ * @iv_len: Length of IV data.
+ */
+struct txentry_desc {
+       unsigned long flags;
+
+       u16 length;
+       u16 header_length;
+
+       union {
+               struct {
+                       u16 length_high;
+                       u16 length_low;
+                       u16 signal;
+                       u16 service;
+                       enum ifs ifs;
+               } plcp;
+
+               struct {
+                       u16 mcs;
+                       u8 stbc;
+                       u8 ba_size;
+                       u8 mpdu_density;
+                       enum txop txop;
+                       int wcid;
+               } ht;
+       } u;
+
+       enum rate_modulation rate_mode;
+
+       short retry_limit;
+
+       enum cipher cipher;
+       u16 key_idx;
+       u16 iv_offset;
+       u16 iv_len;
+};
+
+/**
+ * enum queue_entry_flags: Status flags for queue entry
+ *
+ * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
+ *     As long as this bit is set, this entry may only be touched
+ *     through the interface structure.
+ * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
+ *     transfer (either TX or RX depending on the queue). The entry should
+ *     only be touched after the device has signaled it is done with it.
+ * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting
+ *     for the signal to start sending.
+ * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occurred
+ *     while transferring the data to the hardware. No TX status report will
+ *     be expected from the hardware.
+ * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
+ *     returned. It is now waiting for the status reporting before the
+ *     entry can be reused again.
+ */
+enum queue_entry_flags {
+       ENTRY_BCN_ASSIGNED,
+       ENTRY_BCN_ENABLED,
+       ENTRY_OWNER_DEVICE_DATA,
+       ENTRY_DATA_PENDING,
+       ENTRY_DATA_IO_FAILED,
+       ENTRY_DATA_STATUS_PENDING,
+       ENTRY_DATA_STATUS_SET,
+};
+
+/**
+ * struct queue_entry: Entry inside the &struct data_queue
+ *
+ * @flags: Entry flags, see &enum queue_entry_flags.
+ * @last_action: Timestamp of last change.
+ * @queue: The data queue (&struct data_queue) to which this entry belongs.
+ * @skb: The buffer which is currently being transmitted (for TX queue),
+ *     or used to directly receive data in (for RX queue).
+ * @entry_idx: The entry index number.
+ * @priv_data: Private data belonging to this queue entry. The pointer
+ *     points to data specific to a particular driver and queue type.
+ * @status: Device specific status
+ */
+struct queue_entry {
+       unsigned long flags;
+       unsigned long last_action;
+
+       struct data_queue *queue;
+
+       struct sk_buff *skb;
+
+       unsigned int entry_idx;
+
+       u32 status;
+
+       void *priv_data;
+};
+
+/**
+ * enum queue_index: Queue index type
+ *
+ * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
+ *     owned by the hardware then the queue is considered to be full.
+ * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
+ *     transferred to the hardware.
+ * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
+ *     the hardware and for which we need to run the txdone handler. If this
+ *     entry is not owned by the hardware the queue is considered to be empty.
+ * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
+ *     of the index array.
+ */
+enum queue_index {
+       Q_INDEX,
+       Q_INDEX_DMA_DONE,
+       Q_INDEX_DONE,
+       Q_INDEX_MAX,
+};
+
+/**
+ * enum data_queue_flags: Status flags for data queues
+ *
+ * @QUEUE_STARTED: The queue has been started. Fox RX queues this means the
+ *     device might be DMA'ing skbuffers. TX queues will accept skbuffers to
+ *     be transmitted and beacon queues will start beaconing the configured
+ *     beacons.
+ * @QUEUE_PAUSED: The queue has been started but is currently paused.
+ *     When this bit is set, the queue has been stopped in mac80211,
+ *     preventing new frames to be enqueued. However, a few frames
+ *     might still appear shortly after the pausing...
+ */
+enum data_queue_flags {
+       QUEUE_STARTED,
+       QUEUE_PAUSED,
+};
+
+/**
+ * struct data_queue: Data queue
+ *
+ * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
+ * @entries: Base address of the &struct queue_entry which are
+ *     part of this queue.
+ * @qid: The queue identification, see &enum data_queue_qid.
+ * @flags: Entry flags, see &enum queue_entry_flags.
+ * @status_lock: The mutex for protecting the start/stop/flush
+ *     handling on this queue.
+ * @tx_lock: Spinlock to serialize tx operations on this queue.
+ * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
+ *     @index_crypt needs to be changed this lock should be grabbed to prevent
+ *     index corruption due to concurrency.
+ * @count: Number of frames handled in the queue.
+ * @limit: Maximum number of entries in the queue.
+ * @threshold: Minimum number of free entries before queue is kicked by force.
+ * @length: Number of frames in queue.
+ * @index: Index pointers to entry positions in the queue,
+ *     use &enum queue_index to get a specific index field.
+ * @txop: maximum burst time.
+ * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
+ * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
+ * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
+ * @data_size: Maximum data size for the frames in this queue.
+ * @desc_size: Hardware descriptor size for the data in this queue.
+ * @priv_size: Size of per-queue_entry private data.
+ * @usb_endpoint: Device endpoint used for communication (USB only)
+ * @usb_maxpacket: Max packet size for given endpoint (USB only)
+ */
+struct data_queue {
+       struct rt2x00_dev *rt2x00dev;
+       struct queue_entry *entries;
+
+       enum data_queue_qid qid;
+       unsigned long flags;
+
+       struct mutex status_lock;
+       spinlock_t tx_lock;
+       spinlock_t index_lock;
+
+       unsigned int count;
+       unsigned short limit;
+       unsigned short threshold;
+       unsigned short length;
+       unsigned short index[Q_INDEX_MAX];
+
+       unsigned short txop;
+       unsigned short aifs;
+       unsigned short cw_min;
+       unsigned short cw_max;
+
+       unsigned short data_size;
+       unsigned char  desc_size;
+       unsigned char  winfo_size;
+       unsigned short priv_size;
+
+       unsigned short usb_endpoint;
+       unsigned short usb_maxpacket;
+};
+
+/**
+ * queue_end - Return pointer to the last queue (HELPER MACRO).
+ * @__dev: Pointer to &struct rt2x00_dev
+ *
+ * Using the base rx pointer and the maximum number of available queues,
+ * this macro will return the address of 1 position beyond  the end of the
+ * queues array.
+ */
+#define queue_end(__dev) \
+       &(__dev)->rx[(__dev)->data_queues]
+
+/**
+ * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
+ * @__dev: Pointer to &struct rt2x00_dev
+ *
+ * Using the base tx pointer and the maximum number of available TX
+ * queues, this macro will return the address of 1 position beyond
+ * the end of the TX queue array.
+ */
+#define tx_queue_end(__dev) \
+       &(__dev)->tx[(__dev)->ops->tx_queues]
+
+/**
+ * queue_next - Return pointer to next queue in list (HELPER MACRO).
+ * @__queue: Current queue for which we need the next queue
+ *
+ * Using the current queue address we take the address directly
+ * after the queue to take the next queue. Note that this macro
+ * should be used carefully since it does not protect against
+ * moving past the end of the list. (See macros &queue_end and
+ * &tx_queue_end for determining the end of the queue).
+ */
+#define queue_next(__queue) \
+       &(__queue)[1]
+
+/**
+ * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
+ * @__entry: Pointer where the current queue entry will be stored in.
+ * @__start: Start queue pointer.
+ * @__end: End queue pointer.
+ *
+ * This macro will loop through all queues between &__start and &__end.
+ */
+#define queue_loop(__entry, __start, __end)                    \
+       for ((__entry) = (__start);                             \
+            prefetch(queue_next(__entry)), (__entry) != (__end);\
+            (__entry) = queue_next(__entry))
+
+/**
+ * queue_for_each - Loop through all queues
+ * @__dev: Pointer to &struct rt2x00_dev
+ * @__entry: Pointer where the current queue entry will be stored in.
+ *
+ * This macro will loop through all available queues.
+ */
+#define queue_for_each(__dev, __entry) \
+       queue_loop(__entry, (__dev)->rx, queue_end(__dev))
+
+/**
+ * tx_queue_for_each - Loop through the TX queues
+ * @__dev: Pointer to &struct rt2x00_dev
+ * @__entry: Pointer where the current queue entry will be stored in.
+ *
+ * This macro will loop through all TX related queues excluding
+ * the Beacon and Atim queues.
+ */
+#define tx_queue_for_each(__dev, __entry) \
+       queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
+
+/**
+ * txall_queue_for_each - Loop through all TX related queues
+ * @__dev: Pointer to &struct rt2x00_dev
+ * @__entry: Pointer where the current queue entry will be stored in.
+ *
+ * This macro will loop through all TX related queues including
+ * the Beacon and Atim queues.
+ */
+#define txall_queue_for_each(__dev, __entry) \
+       queue_loop(__entry, (__dev)->tx, queue_end(__dev))
+
+/**
+ * rt2x00queue_for_each_entry - Loop through all entries in the queue
+ * @queue: Pointer to @data_queue
+ * @start: &enum queue_index Pointer to start index
+ * @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
+ * @fn: The function to call for each &struct queue_entry
+ *
+ * This will walk through all entries in the queue, in chronological
+ * order. This means it will start at the current @start pointer
+ * and will walk through the queue until it reaches the @end pointer.
+ *
+ * If fn returns true for an entry rt2x00queue_for_each_entry will stop
+ * processing and return true as well.
+ */
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
+                               enum queue_index start,
+                               enum queue_index end,
+                               void *data,
+                               bool (*fn)(struct queue_entry *entry,
+                                          void *data));
+
+/**
+ * rt2x00queue_empty - Check if the queue is empty.
+ * @queue: Queue to check if empty.
+ */
+static inline int rt2x00queue_empty(struct data_queue *queue)
+{
+       return queue->length == 0;
+}
+
+/**
+ * rt2x00queue_full - Check if the queue is full.
+ * @queue: Queue to check if full.
+ */
+static inline int rt2x00queue_full(struct data_queue *queue)
+{
+       return queue->length == queue->limit;
+}
+
+/**
+ * rt2x00queue_free - Check the number of available entries in queue.
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_available(struct data_queue *queue)
+{
+       return queue->limit - queue->length;
+}
+
+/**
+ * rt2x00queue_threshold - Check if the queue is below threshold
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_threshold(struct data_queue *queue)
+{
+       return rt2x00queue_available(queue) < queue->threshold;
+}
+/**
+ * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers
+ * @entry: Queue entry to check.
+ */
+static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
+{
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return false;
+       return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
+}
+
+/**
+ * _rt2x00_desc_read - Read a word from the hardware descriptor.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be read.
+ * @value: Address where the descriptor value should be written into.
+ */
+static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
+{
+       *value = desc[word];
+}
+
+/**
+ * rt2x00_desc_read - Read a word from the hardware descriptor, this
+ * function will take care of the byte ordering.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be read.
+ * @value: Address where the descriptor value should be written into.
+ */
+static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
+{
+       __le32 tmp;
+       _rt2x00_desc_read(desc, word, &tmp);
+       *value = le32_to_cpu(tmp);
+}
+
+/**
+ * rt2x00_desc_write - write a word to the hardware descriptor, this
+ * function will take care of the byte ordering.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be written.
+ * @value: Value that should be written into the descriptor.
+ */
+static inline void _rt2x00_desc_write(__le32 *desc, const u8 word, __le32 value)
+{
+       desc[word] = value;
+}
+
+/**
+ * rt2x00_desc_write - write a word to the hardware descriptor.
+ * @desc: Base descriptor address
+ * @word: Word index from where the descriptor should be written.
+ * @value: Value that should be written into the descriptor.
+ */
+static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
+{
+       _rt2x00_desc_write(desc, word, cpu_to_le32(value));
+}
+
+#endif /* RT2X00QUEUE_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00reg.h b/drivers/net/wireless/ralink/rt2x00/rt2x00reg.h
new file mode 100644 (file)
index 0000000..3cc541d
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00
+       Abstract: rt2x00 generic register information.
+ */
+
+#ifndef RT2X00REG_H
+#define RT2X00REG_H
+
+/*
+ * RX crypto status
+ */
+enum rx_crypto {
+       RX_CRYPTO_SUCCESS = 0,
+       RX_CRYPTO_FAIL_ICV = 1,
+       RX_CRYPTO_FAIL_MIC = 2,
+       RX_CRYPTO_FAIL_KEY = 3,
+};
+
+/*
+ * Antenna values
+ */
+enum antenna {
+       ANTENNA_SW_DIVERSITY = 0,
+       ANTENNA_A = 1,
+       ANTENNA_B = 2,
+       ANTENNA_HW_DIVERSITY = 3,
+};
+
+/*
+ * Led mode values.
+ */
+enum led_mode {
+       LED_MODE_DEFAULT = 0,
+       LED_MODE_TXRX_ACTIVITY = 1,
+       LED_MODE_SIGNAL_STRENGTH = 2,
+       LED_MODE_ASUS = 3,
+       LED_MODE_ALPHA = 4,
+};
+
+/*
+ * TSF sync values
+ */
+enum tsf_sync {
+       TSF_SYNC_NONE = 0,
+       TSF_SYNC_INFRA = 1,
+       TSF_SYNC_ADHOC = 2,
+       TSF_SYNC_AP_NONE = 3,
+};
+
+/*
+ * Device states
+ */
+enum dev_state {
+       STATE_DEEP_SLEEP = 0,
+       STATE_SLEEP = 1,
+       STATE_STANDBY = 2,
+       STATE_AWAKE = 3,
+
+/*
+ * Additional device states, these values are
+ * not strict since they are not directly passed
+ * into the device.
+ */
+       STATE_RADIO_ON,
+       STATE_RADIO_OFF,
+       STATE_RADIO_IRQ_ON,
+       STATE_RADIO_IRQ_OFF,
+};
+
+/*
+ * IFS backoff values
+ */
+enum ifs {
+       IFS_BACKOFF = 0,
+       IFS_SIFS = 1,
+       IFS_NEW_BACKOFF = 2,
+       IFS_NONE = 3,
+};
+
+/*
+ * IFS backoff values for HT devices
+ */
+enum txop {
+       TXOP_HTTXOP = 0,
+       TXOP_PIFS = 1,
+       TXOP_SIFS = 2,
+       TXOP_BACKOFF = 3,
+};
+
+/*
+ * Cipher types for hardware encryption
+ */
+enum cipher {
+       CIPHER_NONE = 0,
+       CIPHER_WEP64 = 1,
+       CIPHER_WEP128 = 2,
+       CIPHER_TKIP = 3,
+       CIPHER_AES = 4,
+/*
+ * The following fields were added by rt61pci and rt73usb.
+ */
+       CIPHER_CKIP64 = 5,
+       CIPHER_CKIP128 = 6,
+       CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
+
+/*
+ * Max cipher type.
+ * Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
+ * are excluded due to limitations in mac80211.
+ */
+       CIPHER_MAX = 4,
+};
+
+/*
+ * Rate modulations
+ */
+enum rate_modulation {
+       RATE_MODE_CCK = 0,
+       RATE_MODE_OFDM = 1,
+       RATE_MODE_HT_MIX = 2,
+       RATE_MODE_HT_GREENFIELD = 3,
+};
+
+/*
+ * Firmware validation error codes
+ */
+enum firmware_errors {
+       FW_OK,
+       FW_BAD_CRC,
+       FW_BAD_LENGTH,
+       FW_BAD_VERSION,
+};
+
+/*
+ * Register handlers.
+ * We store the position of a register field inside a field structure,
+ * This will simplify the process of setting and reading a certain field
+ * inside the register while making sure the process remains byte order safe.
+ */
+struct rt2x00_field8 {
+       u8 bit_offset;
+       u8 bit_mask;
+};
+
+struct rt2x00_field16 {
+       u16 bit_offset;
+       u16 bit_mask;
+};
+
+struct rt2x00_field32 {
+       u32 bit_offset;
+       u32 bit_mask;
+};
+
+/*
+ * Power of two check, this will check
+ * if the mask that has been given contains and contiguous set of bits.
+ * Note that we cannot use the is_power_of_2() function since this
+ * check must be done at compile-time.
+ */
+#define is_power_of_two(x)     ( !((x) & ((x)-1)) )
+#define low_bit_mask(x)                ( ((x)-1) & ~(x) )
+#define is_valid_mask(x)       is_power_of_two(1LU + (x) + low_bit_mask(x))
+
+/*
+ * Macros to find first set bit in a variable.
+ * These macros behave the same as the __ffs() functions but
+ * the most important difference that this is done during
+ * compile-time rather then run-time.
+ */
+#define compile_ffs2(__x) \
+       __builtin_choose_expr(((__x) & 0x1), 0, 1)
+
+#define compile_ffs4(__x) \
+       __builtin_choose_expr(((__x) & 0x3), \
+                             (compile_ffs2((__x))), \
+                             (compile_ffs2((__x) >> 2) + 2))
+
+#define compile_ffs8(__x) \
+       __builtin_choose_expr(((__x) & 0xf), \
+                             (compile_ffs4((__x))), \
+                             (compile_ffs4((__x) >> 4) + 4))
+
+#define compile_ffs16(__x) \
+       __builtin_choose_expr(((__x) & 0xff), \
+                             (compile_ffs8((__x))), \
+                             (compile_ffs8((__x) >> 8) + 8))
+
+#define compile_ffs32(__x) \
+       __builtin_choose_expr(((__x) & 0xffff), \
+                             (compile_ffs16((__x))), \
+                             (compile_ffs16((__x) >> 16) + 16))
+
+/*
+ * This macro will check the requirements for the FIELD{8,16,32} macros
+ * The mask should be a constant non-zero contiguous set of bits which
+ * does not exceed the given typelimit.
+ */
+#define FIELD_CHECK(__mask, __type)                    \
+       BUILD_BUG_ON(!(__mask) ||                       \
+                    !is_valid_mask(__mask) ||          \
+                    (__mask) != (__type)(__mask))      \
+
+#define FIELD8(__mask)                         \
+({                                             \
+       FIELD_CHECK(__mask, u8);                \
+       (struct rt2x00_field8) {                \
+               compile_ffs8(__mask), (__mask)  \
+       };                                      \
+})
+
+#define FIELD16(__mask)                                \
+({                                             \
+       FIELD_CHECK(__mask, u16);               \
+       (struct rt2x00_field16) {               \
+               compile_ffs16(__mask), (__mask) \
+       };                                      \
+})
+
+#define FIELD32(__mask)                                \
+({                                             \
+       FIELD_CHECK(__mask, u32);               \
+       (struct rt2x00_field32) {               \
+               compile_ffs32(__mask), (__mask) \
+       };                                      \
+})
+
+#define SET_FIELD(__reg, __type, __field, __value)\
+({                                             \
+       typecheck(__type, __field);             \
+       *(__reg) &= ~((__field).bit_mask);      \
+       *(__reg) |= ((__value) <<               \
+           ((__field).bit_offset)) &           \
+           ((__field).bit_mask);               \
+})
+
+#define GET_FIELD(__reg, __type, __field)      \
+({                                             \
+       typecheck(__type, __field);             \
+       ((__reg) & ((__field).bit_mask)) >>     \
+           ((__field).bit_offset);             \
+})
+
+#define rt2x00_set_field32(__reg, __field, __value) \
+       SET_FIELD(__reg, struct rt2x00_field32, __field, __value)
+#define rt2x00_get_field32(__reg, __field) \
+       GET_FIELD(__reg, struct rt2x00_field32, __field)
+
+#define rt2x00_set_field16(__reg, __field, __value) \
+       SET_FIELD(__reg, struct rt2x00_field16, __field, __value)
+#define rt2x00_get_field16(__reg, __field) \
+       GET_FIELD(__reg, struct rt2x00_field16, __field)
+
+#define rt2x00_set_field8(__reg, __field, __value) \
+       SET_FIELD(__reg, struct rt2x00_field8, __field, __value)
+#define rt2x00_get_field8(__reg, __field) \
+       GET_FIELD(__reg, struct rt2x00_field8, __field)
+
+#endif /* RT2X00REG_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
new file mode 100644 (file)
index 0000000..69a0cda
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       Copyright (C) 2004 - 2009 Felix Fietkau <nbd@openwrt.org>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00soc
+       Abstract: rt2x00 generic soc device routines.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00soc.h"
+
+static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev)
+{
+       kfree(rt2x00dev->rf);
+       rt2x00dev->rf = NULL;
+
+       kfree(rt2x00dev->eeprom);
+       rt2x00dev->eeprom = NULL;
+
+       iounmap(rt2x00dev->csr.base);
+}
+
+static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
+{
+       struct platform_device *pdev = to_platform_device(rt2x00dev->dev);
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       rt2x00dev->csr.base = ioremap(res->start, resource_size(res));
+       if (!rt2x00dev->csr.base)
+               return -ENOMEM;
+
+       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+       if (!rt2x00dev->eeprom)
+               goto exit;
+
+       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
+       if (!rt2x00dev->rf)
+               goto exit;
+
+       return 0;
+
+exit:
+       rt2x00_probe_err("Failed to allocate registers\n");
+       rt2x00soc_free_reg(rt2x00dev);
+
+       return -ENOMEM;
+}
+
+int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
+{
+       struct ieee80211_hw *hw;
+       struct rt2x00_dev *rt2x00dev;
+       int retval;
+
+       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
+       if (!hw) {
+               rt2x00_probe_err("Failed to allocate hardware\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, hw);
+
+       rt2x00dev = hw->priv;
+       rt2x00dev->dev = &pdev->dev;
+       rt2x00dev->ops = ops;
+       rt2x00dev->hw = hw;
+       rt2x00dev->irq = platform_get_irq(pdev, 0);
+       rt2x00dev->name = pdev->dev.driver->name;
+
+       rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
+       retval = rt2x00soc_alloc_reg(rt2x00dev);
+       if (retval)
+               goto exit_free_device;
+
+       retval = rt2x00lib_probe_dev(rt2x00dev);
+       if (retval)
+               goto exit_free_reg;
+
+       return 0;
+
+exit_free_reg:
+       rt2x00soc_free_reg(rt2x00dev);
+
+exit_free_device:
+       ieee80211_free_hw(hw);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(rt2x00soc_probe);
+
+int rt2x00soc_remove(struct platform_device *pdev)
+{
+       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * Free all allocated data.
+        */
+       rt2x00lib_remove_dev(rt2x00dev);
+       rt2x00soc_free_reg(rt2x00dev);
+       ieee80211_free_hw(hw);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00soc_remove);
+
+#ifdef CONFIG_PM
+int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       return rt2x00lib_suspend(rt2x00dev, state);
+}
+EXPORT_SYMBOL_GPL(rt2x00soc_suspend);
+
+int rt2x00soc_resume(struct platform_device *pdev)
+{
+       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       return rt2x00lib_resume(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00soc_resume);
+#endif /* CONFIG_PM */
+
+/*
+ * rt2x00soc module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 soc library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
new file mode 100644 (file)
index 0000000..9948d35
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00soc
+       Abstract: Data structures for the rt2x00soc module.
+ */
+
+#ifndef RT2X00SOC_H
+#define RT2X00SOC_H
+
+/*
+ * SoC driver handlers.
+ */
+int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops);
+int rt2x00soc_remove(struct platform_device *pdev);
+#ifdef CONFIG_PM
+int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state);
+int rt2x00soc_resume(struct platform_device *pdev);
+#else
+#define rt2x00soc_suspend      NULL
+#define rt2x00soc_resume       NULL
+#endif /* CONFIG_PM */
+
+#endif /* RT2X00SOC_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
new file mode 100644 (file)
index 0000000..7627af6
--- /dev/null
@@ -0,0 +1,884 @@
+/*
+       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
+       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00usb
+       Abstract: rt2x00 generic usb device routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/bug.h>
+
+#include "rt2x00.h"
+#include "rt2x00usb.h"
+
+/*
+ * Interfacing with the HW.
+ */
+int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+                            const u8 request, const u8 requesttype,
+                            const u16 offset, const u16 value,
+                            void *buffer, const u16 buffer_length,
+                            const int timeout)
+{
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       int status;
+       unsigned int pipe =
+           (requesttype == USB_VENDOR_REQUEST_IN) ?
+           usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
+       unsigned long expire = jiffies + msecs_to_jiffies(timeout);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return -ENODEV;
+
+       do {
+               status = usb_control_msg(usb_dev, pipe, request, requesttype,
+                                        value, offset, buffer, buffer_length,
+                                        timeout / 2);
+               if (status >= 0)
+                       return 0;
+
+               if (status == -ENODEV) {
+                       /* Device has disappeared. */
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+                       break;
+               }
+       } while (time_before(jiffies, expire));
+
+       rt2x00_err(rt2x00dev,
+                  "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
+                  request, offset, status);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
+
+int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+                                  const u8 request, const u8 requesttype,
+                                  const u16 offset, void *buffer,
+                                  const u16 buffer_length, const int timeout)
+{
+       int status;
+
+       BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex));
+
+       /*
+        * Check for Cache availability.
+        */
+       if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
+               rt2x00_err(rt2x00dev, "CSR cache not available\n");
+               return -ENOMEM;
+       }
+
+       if (requesttype == USB_VENDOR_REQUEST_OUT)
+               memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
+
+       status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
+                                         offset, 0, rt2x00dev->csr.cache,
+                                         buffer_length, timeout);
+
+       if (!status && requesttype == USB_VENDOR_REQUEST_IN)
+               memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
+
+int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
+                                 const u8 request, const u8 requesttype,
+                                 const u16 offset, void *buffer,
+                                 const u16 buffer_length)
+{
+       int status = 0;
+       unsigned char *tb;
+       u16 off, len, bsize;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       tb  = (char *)buffer;
+       off = offset;
+       len = buffer_length;
+       while (len && !status) {
+               bsize = min_t(u16, CSR_CACHE_SIZE, len);
+               status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
+                                                       requesttype, off, tb,
+                                                       bsize, REGISTER_TIMEOUT);
+
+               tb  += bsize;
+               len -= bsize;
+               off += bsize;
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
+
+int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int offset,
+                          const struct rt2x00_field32 field,
+                          u32 *reg)
+{
+       unsigned int i;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return -ENODEV;
+
+       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+               rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
+               if (!rt2x00_get_field32(*reg, field))
+                       return 1;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+                  offset, *reg);
+       *reg = ~0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
+
+
+struct rt2x00_async_read_data {
+       __le32 reg;
+       struct usb_ctrlrequest cr;
+       struct rt2x00_dev *rt2x00dev;
+       bool (*callback)(struct rt2x00_dev *, int, u32);
+};
+
+static void rt2x00usb_register_read_async_cb(struct urb *urb)
+{
+       struct rt2x00_async_read_data *rd = urb->context;
+       if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) {
+               if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+                       kfree(rd);
+       } else
+               kfree(rd);
+}
+
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset,
+                                  bool (*callback)(struct rt2x00_dev*, int, u32))
+{
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct urb *urb;
+       struct rt2x00_async_read_data *rd;
+
+       rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+       if (!rd)
+               return;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               kfree(rd);
+               return;
+       }
+
+       rd->rt2x00dev = rt2x00dev;
+       rd->callback = callback;
+       rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
+       rd->cr.bRequest = USB_MULTI_READ;
+       rd->cr.wValue = 0;
+       rd->cr.wIndex = cpu_to_le16(offset);
+       rd->cr.wLength = cpu_to_le16(sizeof(u32));
+
+       usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+                            (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
+                            rt2x00usb_register_read_async_cb, rd);
+       if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+               kfree(rd);
+       usb_free_urb(urb);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
+
+/*
+ * TX data handlers.
+ */
+static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)
+{
+       /*
+        * If the transfer to hardware succeeded, it does not mean the
+        * frame was send out correctly. It only means the frame
+        * was successfully pushed to the hardware, we have no
+        * way to determine the transmission status right now.
+        * (Only indirectly by looking at the failed TX counters
+        * in the register).
+        */
+       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+       else
+               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+}
+
+static void rt2x00usb_work_txdone(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, txdone_work);
+       struct data_queue *queue;
+       struct queue_entry *entry;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               while (!rt2x00queue_empty(queue)) {
+                       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+                               break;
+
+                       rt2x00usb_work_txdone_entry(entry);
+               }
+       }
+}
+
+static void rt2x00usb_interrupt_txdone(struct urb *urb)
+{
+       struct queue_entry *entry = (struct queue_entry *)urb->context;
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return;
+       /*
+        * Check if the frame was correctly uploaded
+        */
+       if (urb->status)
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
+
+       if (rt2x00dev->ops->lib->tx_dma_done)
+               rt2x00dev->ops->lib->tx_dma_done(entry);
+       /*
+        * Schedule the delayed work for reading the TX status
+        * from the device.
+        */
+       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TXSTATUS_FIFO) ||
+           !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+}
+
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       u32 length;
+       int status;
+
+       if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
+           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+               return false;
+
+       /*
+        * USB devices require certain padding at the end of each frame
+        * and urb. Those paddings are not included in skbs. Pass entry
+        * to the driver to determine what the overall length should be.
+        */
+       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
+
+       status = skb_padto(entry->skb, length);
+       if (unlikely(status)) {
+               /* TODO: report something more appropriate than IO_FAILED. */
+               rt2x00_warn(rt2x00dev, "TX SKB padding error, out of memory\n");
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+
+               return false;
+       }
+
+       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+                         usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
+                         entry->skb->data, length,
+                         rt2x00usb_interrupt_txdone, entry);
+
+       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (status) {
+               if (status == -ENODEV)
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+       }
+
+       return false;
+}
+
+/*
+ * RX data handlers.
+ */
+static void rt2x00usb_work_rxdone(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, rxdone_work);
+       struct queue_entry *entry;
+       struct skb_frame_desc *skbdesc;
+       u8 rxd[32];
+
+       while (!rt2x00queue_empty(rt2x00dev->rx)) {
+               entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
+
+               if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                   !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+                       break;
+
+               /*
+                * Fill in desc fields of the skb descriptor
+                */
+               skbdesc = get_skb_frame_desc(entry->skb);
+               skbdesc->desc = rxd;
+               skbdesc->desc_len = entry->queue->desc_size;
+
+               /*
+                * Send the frame to rt2x00lib for further processing.
+                */
+               rt2x00lib_rxdone(entry, GFP_KERNEL);
+       }
+}
+
+static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+{
+       struct queue_entry *entry = (struct queue_entry *)urb->context;
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return;
+
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
+
+       /*
+        * Check if the received data is simply too small
+        * to be actually valid, or if the urb is signaling
+        * a problem.
+        */
+       if (urb->actual_length < entry->queue->desc_size || urb->status)
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+
+       /*
+        * Schedule the delayed work for reading the RX status
+        * from the device.
+        */
+       queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
+}
+
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       int status;
+
+       if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+               return false;
+
+       rt2x00lib_dmastart(entry);
+
+       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+                         usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint),
+                         entry->skb->data, entry->skb->len,
+                         rt2x00usb_interrupt_rxdone, entry);
+
+       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (status) {
+               if (status == -ENODEV)
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+       }
+
+       return false;
+}
+
+void rt2x00usb_kick_queue(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               if (!rt2x00queue_empty(queue))
+                       rt2x00queue_for_each_entry(queue,
+                                                  Q_INDEX_DONE,
+                                                  Q_INDEX,
+                                                  NULL,
+                                                  rt2x00usb_kick_tx_entry);
+               break;
+       case QID_RX:
+               if (!rt2x00queue_full(queue))
+                       rt2x00queue_for_each_entry(queue,
+                                                  Q_INDEX,
+                                                  Q_INDEX_DONE,
+                                                  NULL,
+                                                  rt2x00usb_kick_rx_entry);
+               break;
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
+
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+
+       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               return false;
+
+       usb_kill_urb(entry_priv->urb);
+
+       /*
+        * Kill guardian urb (if required by driver).
+        */
+       if ((entry->queue->qid == QID_BEACON) &&
+           (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD)))
+               usb_kill_urb(bcn_priv->guardian_urb);
+
+       return false;
+}
+
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
+{
+       struct work_struct *completion;
+       unsigned int i;
+
+       if (drop)
+               rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+                                          rt2x00usb_flush_entry);
+
+       /*
+        * Obtain the queue completion handler
+        */
+       switch (queue->qid) {
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               completion = &queue->rt2x00dev->txdone_work;
+               break;
+       case QID_RX:
+               completion = &queue->rt2x00dev->rxdone_work;
+               break;
+       default:
+               return;
+       }
+
+       for (i = 0; i < 10; i++) {
+               /*
+                * Check if the driver is already done, otherwise we
+                * have to sleep a little while to give the driver/hw
+                * the oppurtunity to complete interrupt process itself.
+                */
+               if (rt2x00queue_empty(queue))
+                       break;
+
+               /*
+                * Schedule the completion handler manually, when this
+                * worker function runs, it should cleanup the queue.
+                */
+               queue_work(queue->rt2x00dev->workqueue, completion);
+
+               /*
+                * Wait for a little while to give the driver
+                * the oppurtunity to recover itself.
+                */
+               msleep(10);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue);
+
+static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
+{
+       rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
+                   queue->qid);
+
+       rt2x00queue_stop_queue(queue);
+       rt2x00queue_flush_queue(queue, true);
+       rt2x00queue_start_queue(queue);
+}
+
+static int rt2x00usb_dma_timeout(struct data_queue *queue)
+{
+       struct queue_entry *entry;
+
+       entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+       return rt2x00queue_dma_timeout(entry);
+}
+
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               if (!rt2x00queue_empty(queue)) {
+                       if (rt2x00usb_dma_timeout(queue))
+                               rt2x00usb_watchdog_tx_dma(queue);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
+
+/*
+ * Radio handlers
+ */
+void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0,
+                                   REGISTER_TIMEOUT);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+
+/*
+ * Device initialization handlers.
+ */
+void rt2x00usb_clear_entry(struct queue_entry *entry)
+{
+       entry->flags = 0;
+
+       if (entry->queue->qid == QID_RX)
+               rt2x00usb_kick_rx_entry(entry, NULL);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
+
+static void rt2x00usb_assign_endpoint(struct data_queue *queue,
+                                     struct usb_endpoint_descriptor *ep_desc)
+{
+       struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev);
+       int pipe;
+
+       queue->usb_endpoint = usb_endpoint_num(ep_desc);
+
+       if (queue->qid == QID_RX) {
+               pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
+               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
+       } else {
+               pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
+               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
+       }
+
+       if (!queue->usb_maxpacket)
+               queue->usb_maxpacket = 1;
+}
+
+static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
+{
+       struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
+       struct usb_host_interface *intf_desc = intf->cur_altsetting;
+       struct usb_endpoint_descriptor *ep_desc;
+       struct data_queue *queue = rt2x00dev->tx;
+       struct usb_endpoint_descriptor *tx_ep_desc = NULL;
+       unsigned int i;
+
+       /*
+        * Walk through all available endpoints to search for "bulk in"
+        * and "bulk out" endpoints. When we find such endpoints collect
+        * the information we need from the descriptor and assign it
+        * to the queue.
+        */
+       for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+               ep_desc = &intf_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_bulk_in(ep_desc)) {
+                       rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
+               } else if (usb_endpoint_is_bulk_out(ep_desc) &&
+                          (queue != queue_end(rt2x00dev))) {
+                       rt2x00usb_assign_endpoint(queue, ep_desc);
+                       queue = queue_next(queue);
+
+                       tx_ep_desc = ep_desc;
+               }
+       }
+
+       /*
+        * At least 1 endpoint for RX and 1 endpoint for TX must be available.
+        */
+       if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
+               rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
+               return -EPIPE;
+       }
+
+       /*
+        * It might be possible not all queues have a dedicated endpoint.
+        * Loop through all TX queues and copy the endpoint information
+        * which we have gathered from already assigned endpoints.
+        */
+       txall_queue_for_each(rt2x00dev, queue) {
+               if (!queue->usb_endpoint)
+                       rt2x00usb_assign_endpoint(queue, tx_ep_desc);
+       }
+
+       return 0;
+}
+
+static int rt2x00usb_alloc_entries(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       struct queue_entry_priv_usb *entry_priv;
+       struct queue_entry_priv_usb_bcn *bcn_priv;
+       unsigned int i;
+
+       for (i = 0; i < queue->limit; i++) {
+               entry_priv = queue->entries[i].priv_data;
+               entry_priv->urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!entry_priv->urb)
+                       return -ENOMEM;
+       }
+
+       /*
+        * If this is not the beacon queue or
+        * no guardian byte was required for the beacon,
+        * then we are done.
+        */
+       if (queue->qid != QID_BEACON ||
+           !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD))
+               return 0;
+
+       for (i = 0; i < queue->limit; i++) {
+               bcn_priv = queue->entries[i].priv_data;
+               bcn_priv->guardian_urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!bcn_priv->guardian_urb)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void rt2x00usb_free_entries(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       struct queue_entry_priv_usb *entry_priv;
+       struct queue_entry_priv_usb_bcn *bcn_priv;
+       unsigned int i;
+
+       if (!queue->entries)
+               return;
+
+       for (i = 0; i < queue->limit; i++) {
+               entry_priv = queue->entries[i].priv_data;
+               usb_kill_urb(entry_priv->urb);
+               usb_free_urb(entry_priv->urb);
+       }
+
+       /*
+        * If this is not the beacon queue or
+        * no guardian byte was required for the beacon,
+        * then we are done.
+        */
+       if (queue->qid != QID_BEACON ||
+           !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD))
+               return;
+
+       for (i = 0; i < queue->limit; i++) {
+               bcn_priv = queue->entries[i].priv_data;
+               usb_kill_urb(bcn_priv->guardian_urb);
+               usb_free_urb(bcn_priv->guardian_urb);
+       }
+}
+
+int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       int status;
+
+       /*
+        * Find endpoints for each queue
+        */
+       status = rt2x00usb_find_endpoints(rt2x00dev);
+       if (status)
+               goto exit;
+
+       /*
+        * Allocate DMA
+        */
+       queue_for_each(rt2x00dev, queue) {
+               status = rt2x00usb_alloc_entries(queue);
+               if (status)
+                       goto exit;
+       }
+
+       return 0;
+
+exit:
+       rt2x00usb_uninitialize(rt2x00dev);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
+
+void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       queue_for_each(rt2x00dev, queue)
+               rt2x00usb_free_entries(queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
+
+/*
+ * USB driver handlers.
+ */
+static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
+{
+       kfree(rt2x00dev->rf);
+       rt2x00dev->rf = NULL;
+
+       kfree(rt2x00dev->eeprom);
+       rt2x00dev->eeprom = NULL;
+
+       kfree(rt2x00dev->csr.cache);
+       rt2x00dev->csr.cache = NULL;
+}
+
+static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
+{
+       rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
+       if (!rt2x00dev->csr.cache)
+               goto exit;
+
+       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+       if (!rt2x00dev->eeprom)
+               goto exit;
+
+       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
+       if (!rt2x00dev->rf)
+               goto exit;
+
+       return 0;
+
+exit:
+       rt2x00_probe_err("Failed to allocate registers\n");
+
+       rt2x00usb_free_reg(rt2x00dev);
+
+       return -ENOMEM;
+}
+
+int rt2x00usb_probe(struct usb_interface *usb_intf,
+                   const struct rt2x00_ops *ops)
+{
+       struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
+       struct ieee80211_hw *hw;
+       struct rt2x00_dev *rt2x00dev;
+       int retval;
+
+       usb_dev = usb_get_dev(usb_dev);
+       usb_reset_device(usb_dev);
+
+       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
+       if (!hw) {
+               rt2x00_probe_err("Failed to allocate hardware\n");
+               retval = -ENOMEM;
+               goto exit_put_device;
+       }
+
+       usb_set_intfdata(usb_intf, hw);
+
+       rt2x00dev = hw->priv;
+       rt2x00dev->dev = &usb_intf->dev;
+       rt2x00dev->ops = ops;
+       rt2x00dev->hw = hw;
+
+       rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+
+       INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
+       INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+       hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
+                    HRTIMER_MODE_REL);
+
+       retval = rt2x00usb_alloc_reg(rt2x00dev);
+       if (retval)
+               goto exit_free_device;
+
+       retval = rt2x00lib_probe_dev(rt2x00dev);
+       if (retval)
+               goto exit_free_reg;
+
+       return 0;
+
+exit_free_reg:
+       rt2x00usb_free_reg(rt2x00dev);
+
+exit_free_device:
+       ieee80211_free_hw(hw);
+
+exit_put_device:
+       usb_put_dev(usb_dev);
+
+       usb_set_intfdata(usb_intf, NULL);
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_probe);
+
+void rt2x00usb_disconnect(struct usb_interface *usb_intf)
+{
+       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       /*
+        * Free all allocated data.
+        */
+       rt2x00lib_remove_dev(rt2x00dev);
+       rt2x00usb_free_reg(rt2x00dev);
+       ieee80211_free_hw(hw);
+
+       /*
+        * Free the USB device data.
+        */
+       usb_set_intfdata(usb_intf, NULL);
+       usb_put_dev(interface_to_usbdev(usb_intf));
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_disconnect);
+
+#ifdef CONFIG_PM
+int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
+{
+       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       return rt2x00lib_suspend(rt2x00dev, state);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_suspend);
+
+int rt2x00usb_resume(struct usb_interface *usb_intf)
+{
+       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+
+       return rt2x00lib_resume(rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_resume);
+#endif /* CONFIG_PM */
+
+/*
+ * rt2x00usb module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 usb library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.h
new file mode 100644 (file)
index 0000000..569363d
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt2x00usb
+       Abstract: Data structures for the rt2x00usb module.
+ */
+
+#ifndef RT2X00USB_H
+#define RT2X00USB_H
+
+#include <linux/usb.h>
+
+#define to_usb_device_intf(d) \
+({ \
+       struct usb_interface *intf = to_usb_interface(d); \
+       interface_to_usbdev(intf); \
+})
+
+/*
+ * For USB vendor requests we need to pass a timeout time in ms, for this we
+ * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM
+ * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE
+ * and EEPROM_TIMEOUT.
+ */
+#define REGISTER_TIMEOUT               100
+#define REGISTER_TIMEOUT_FIRMWARE      1000
+#define EEPROM_TIMEOUT                 2000
+
+/*
+ * Cache size
+ */
+#define CSR_CACHE_SIZE                 64
+
+/*
+ * USB request types.
+ */
+#define USB_VENDOR_REQUEST     ( USB_TYPE_VENDOR | USB_RECIP_DEVICE )
+#define USB_VENDOR_REQUEST_IN  ( USB_DIR_IN | USB_VENDOR_REQUEST )
+#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
+
+/**
+ * enum rt2x00usb_vendor_request: USB vendor commands.
+ */
+enum rt2x00usb_vendor_request {
+       USB_DEVICE_MODE = 1,
+       USB_SINGLE_WRITE = 2,
+       USB_SINGLE_READ = 3,
+       USB_MULTI_WRITE = 6,
+       USB_MULTI_READ = 7,
+       USB_EEPROM_WRITE = 8,
+       USB_EEPROM_READ = 9,
+       USB_LED_CONTROL = 10, /* RT73USB */
+       USB_RX_CONTROL = 12,
+};
+
+/**
+ * enum rt2x00usb_mode_offset: Device modes offset.
+ */
+enum rt2x00usb_mode_offset {
+       USB_MODE_RESET = 1,
+       USB_MODE_UNPLUG = 2,
+       USB_MODE_FUNCTION = 3,
+       USB_MODE_TEST = 4,
+       USB_MODE_SLEEP = 7,     /* RT73USB */
+       USB_MODE_FIRMWARE = 8,  /* RT73USB */
+       USB_MODE_WAKEUP = 9,    /* RT73USB */
+       USB_MODE_AUTORUN = 17, /* RT2800USB */
+};
+
+/**
+ * rt2x00usb_vendor_request - Send register command to device
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
+ * @offset: Register offset to perform action on
+ * @value: Value to write to device
+ * @buffer: Buffer where information will be read/written to by device
+ * @buffer_length: Size of &buffer
+ * @timeout: Operation timeout
+ *
+ * This is the main function to communicate with the device,
+ * the &buffer argument _must_ either be NULL or point to
+ * a buffer allocated by kmalloc. Failure to do so can lead
+ * to unexpected behavior depending on the architecture.
+ */
+int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
+                            const u8 request, const u8 requesttype,
+                            const u16 offset, const u16 value,
+                            void *buffer, const u16 buffer_length,
+                            const int timeout);
+
+/**
+ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
+ * @offset: Register offset to perform action on
+ * @buffer: Buffer where information will be read/written to by device
+ * @buffer_length: Size of &buffer
+ *
+ * This function will use a previously with kmalloc allocated cache
+ * to communicate with the device. The contents of the buffer pointer
+ * will be copied to this cache when writing, or read from the cache
+ * when reading.
+ * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
+ * kmalloc. Hence the reason for using a previously allocated cache
+ * which has been allocated properly.
+ */
+int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
+                                 const u8 request, const u8 requesttype,
+                                 const u16 offset, void *buffer,
+                                 const u16 buffer_length);
+
+/**
+ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
+ * @offset: Register offset to perform action on
+ * @buffer: Buffer where information will be read/written to by device
+ * @buffer_length: Size of &buffer
+ * @timeout: Operation timeout
+ *
+ * A version of &rt2x00usb_vendor_request_buff which must be called
+ * if the usb_cache_mutex is already held.
+ */
+int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+                                  const u8 request, const u8 requesttype,
+                                  const u16 offset, void *buffer,
+                                  const u16 buffer_length, const int timeout);
+
+/**
+ * rt2x00usb_vendor_request_sw - Send single register command to device
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
+ * @offset: Register offset to perform action on
+ * @value: Value to write to device
+ * @timeout: Operation timeout
+ *
+ * Simple wrapper around rt2x00usb_vendor_request to write a single
+ * command to the device. Since we don't use the buffer argument we
+ * don't have to worry about kmalloc here.
+ */
+static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
+                                             const u8 request,
+                                             const u16 offset,
+                                             const u16 value,
+                                             const int timeout)
+{
+       return rt2x00usb_vendor_request(rt2x00dev, request,
+                                       USB_VENDOR_REQUEST_OUT, offset,
+                                       value, NULL, 0, timeout);
+}
+
+/**
+ * rt2x00usb_eeprom_read - Read eeprom from device
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ * @eeprom: Pointer to eeprom array to store the information in
+ * @length: Number of bytes to read from the eeprom
+ *
+ * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
+ * from the device. Note that the eeprom argument _must_ be allocated using
+ * kmalloc for correct handling inside the kernel USB layer.
+ */
+static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
+                                       __le16 *eeprom, const u16 length)
+{
+       return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
+                                       USB_VENDOR_REQUEST_IN, 0, 0,
+                                       eeprom, length, EEPROM_TIMEOUT);
+}
+
+/**
+ * rt2x00usb_register_read - Read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
+                                          const unsigned int offset,
+                                          u32 *value)
+{
+       __le32 reg = 0;
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+                                     USB_VENDOR_REQUEST_IN, offset,
+                                     &reg, sizeof(reg));
+       *value = le32_to_cpu(reg);
+}
+
+/**
+ * rt2x00usb_register_read_lock - Read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_req_buff_lock().
+ */
+static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               u32 *value)
+{
+       __le32 reg = 0;
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+                                      USB_VENDOR_REQUEST_IN, offset,
+                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
+       *value = le32_to_cpu(reg);
+}
+
+/**
+ * rt2x00usb_register_multiread - Read 32bit register words
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ * @length: Length of the data
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
+                                               const unsigned int offset,
+                                               void *value, const u32 length)
+{
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+                                     USB_VENDOR_REQUEST_IN, offset,
+                                     value, length);
+}
+
+/**
+ * rt2x00usb_register_write - Write 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
+                                           const unsigned int offset,
+                                           u32 value)
+{
+       __le32 reg = cpu_to_le32(value);
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+                                     USB_VENDOR_REQUEST_OUT, offset,
+                                     &reg, sizeof(reg));
+}
+
+/**
+ * rt2x00usb_register_write_lock - Write 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_req_buff_lock().
+ */
+static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                u32 value)
+{
+       __le32 reg = cpu_to_le32(value);
+       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+                                      USB_VENDOR_REQUEST_OUT, offset,
+                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
+}
+
+/**
+ * rt2x00usb_register_multiwrite - Write 32bit register words
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ * @length: Length of the data
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+                                                const unsigned int offset,
+                                                const void *value,
+                                                const u32 length)
+{
+       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+                                     USB_VENDOR_REQUEST_OUT, offset,
+                                     (void *)value, length);
+}
+
+/**
+ * rt2x00usb_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+                          const unsigned int offset,
+                          const struct rt2x00_field32 field,
+                          u32 *reg);
+
+/**
+ * rt2x00usb_register_read_async - Asynchronously read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @callback: Functon to call when read completes.
+ *
+ * Submit a control URB to read a 32bit register. This safe to
+ * be called from atomic context.  The callback will be called
+ * when the URB completes. Otherwise the function is similar
+ * to rt2x00usb_register_read().
+ * When the callback function returns false, the memory will be cleaned up,
+ * when it returns true, the urb will be fired again.
+ */
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+                                  const unsigned int offset,
+                                  bool (*callback)(struct rt2x00_dev*, int, u32));
+
+/*
+ * Radio handlers
+ */
+void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * struct queue_entry_priv_usb: Per entry USB specific information
+ *
+ * @urb: Urb structure used for device communication.
+ */
+struct queue_entry_priv_usb {
+       struct urb *urb;
+};
+
+/**
+ * struct queue_entry_priv_usb_bcn: Per TX entry USB specific information
+ *
+ * The first section should match &struct queue_entry_priv_usb exactly.
+ * rt2500usb can use this structure to send a guardian byte when working
+ * with beacons.
+ *
+ * @urb: Urb structure used for device communication.
+ * @guardian_data: Set to 0, used for sending the guardian data.
+ * @guardian_urb: Urb structure used to send the guardian data.
+ */
+struct queue_entry_priv_usb_bcn {
+       struct urb *urb;
+
+       unsigned int guardian_data;
+       struct urb *guardian_urb;
+};
+
+/**
+ * rt2x00usb_kick_queue - Kick data queue
+ * @queue: Data queue to kick
+ *
+ * This will walk through all entries of the queue and push all pending
+ * frames to the hardware as a single burst.
+ */
+void rt2x00usb_kick_queue(struct data_queue *queue);
+
+/**
+ * rt2x00usb_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will walk through all entries of the queue and will optionally
+ * kill all URB's which were send to the device, or at least wait until
+ * they have been returned from the device..
+ */
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
+
+/**
+ * rt2x00usb_watchdog - Watchdog for USB communication
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ *
+ * Check the health of the USB communication and determine
+ * if timeouts have occurred. If this is the case, this function
+ * will reset all communication to restore functionality again.
+ */
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/*
+ * Device initialization handlers.
+ */
+void rt2x00usb_clear_entry(struct queue_entry *entry);
+int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+/*
+ * USB driver handlers.
+ */
+int rt2x00usb_probe(struct usb_interface *usb_intf,
+                   const struct rt2x00_ops *ops);
+void rt2x00usb_disconnect(struct usb_interface *usb_intf);
+#ifdef CONFIG_PM
+int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
+int rt2x00usb_resume(struct usb_interface *usb_intf);
+#else
+#define rt2x00usb_suspend      NULL
+#define rt2x00usb_resume       NULL
+#endif /* CONFIG_PM */
+
+#endif /* RT2X00USB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
new file mode 100644 (file)
index 0000000..c0e730e
--- /dev/null
@@ -0,0 +1,3111 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt61pci
+       Abstract: rt61pci device specific routines.
+       Supported chipsets: RT2561, RT2561s, RT2661.
+ */
+
+#include <linux/crc-itu-t.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/eeprom_93cx6.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+#include "rt2x00pci.h"
+#include "rt61pci.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static bool modparam_nohwcrypt = false;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
+ * Register access.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attempt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+       rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+                               H2M_MAILBOX_CSR_OWNER, (__reg))
+
+static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
+               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
+
+               rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
+
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word, const u32 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+               rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS, 21);
+               rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
+               rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
+
+               rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
+                               const u8 command, const u8 token,
+                               const u8 arg0, const u8 arg1)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the MCU becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+               rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+               rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
+               rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+
+}
+
+static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+
+       eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
+       eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
+       eeprom->reg_data_clock =
+           !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK);
+       eeprom->reg_chip_select =
+           !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT);
+}
+
+static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
+{
+       struct rt2x00_dev *rt2x00dev = eeprom->data;
+       u32 reg = 0;
+
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in);
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out);
+       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK,
+                          !!eeprom->reg_data_clock);
+       rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
+                          !!eeprom->reg_chip_select);
+
+       rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static const struct rt2x00debug rt61pci_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = rt2x00mmio_register_read,
+               .write          = rt2x00mmio_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = CSR_REG_SIZE / sizeof(u32),
+       },
+       .eeprom = {
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt61pci_bbp_read,
+               .write          = rt61pci_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt61pci_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+       return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt61pci_brightness_set(struct led_classdev *led_cdev,
+                                  enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       unsigned int a_mode =
+           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+       unsigned int bg_mode =
+           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+
+       if (led->type == LED_TYPE_RADIO) {
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_RADIO_STATUS, enabled);
+
+               rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
+                                   (led->rt2x00dev->led_mcu_reg & 0xff),
+                                   ((led->rt2x00dev->led_mcu_reg >> 8)));
+       } else if (led->type == LED_TYPE_ASSOC) {
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_LINK_BG_STATUS, bg_mode);
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_LINK_A_STATUS, a_mode);
+
+               rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
+                                   (led->rt2x00dev->led_mcu_reg & 0xff),
+                                   ((led->rt2x00dev->led_mcu_reg >> 8)));
+       } else if (led->type == LED_TYPE_QUALITY) {
+               /*
+                * The brightness is divided into 6 levels (0 - 5),
+                * this means we need to convert the brightness
+                * argument into the matching level within that range.
+                */
+               rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+                                   brightness / (LED_FULL / 6), 0);
+       }
+}
+
+static int rt61pci_blink_set(struct led_classdev *led_cdev,
+                            unsigned long *delay_on,
+                            unsigned long *delay_off)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       u32 reg;
+
+       rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
+       rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
+       rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
+
+       return 0;
+}
+
+static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00_led *led,
+                            enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt61pci_brightness_set;
+       led->led_dev.blink_set = rt61pci_blink_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
+                                    struct rt2x00lib_crypto *crypto,
+                                    struct ieee80211_key_conf *key)
+{
+       struct hw_key_entry key_entry;
+       struct rt2x00_field32 field;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for shared keys. We have 1 register
+                * with key valid bits. The goal is simple, read
+                * the register, if that is full we have no slots
+                * left.
+                * Note that each BSS is allowed to have up to 4
+                * shared keys, so put a mask over the allowed
+                * entries.
+                */
+               mask = (0xf << crypto->bssidx);
+
+               rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+               reg &= mask;
+
+               if (reg && reg == mask)
+                       return -ENOSPC;
+
+               key->hw_key_idx += reg ? ffz(reg) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               reg = SHARED_KEY_ENTRY(key->hw_key_idx);
+               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+                                              &key_entry, sizeof(key_entry));
+
+               /*
+                * The cipher types are stored over 2 registers.
+                * bssidx 0 and 1 keys are stored in SEC_CSR1 and
+                * bssidx 1 and 2 keys are stored in SEC_CSR5.
+                * Using the correct defines correctly will cause overhead,
+                * so just calculate the correct offset.
+                */
+               if (key->hw_key_idx < 8) {
+                       field.bit_offset = (3 * key->hw_key_idx);
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
+               } else {
+                       field.bit_offset = (3 * (key->hw_key_idx - 8));
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
+               }
+
+               /*
+                * The driver does not support the IV/EIV generation
+                * in hardware. However it doesn't support the IV/EIV
+                * inside the ieee80211 frame either, but requires it
+                * to be provided separately for the descriptor.
+                * rt2x00lib will cut the IV/EIV data out of all frames
+                * given to us by mac80211, but we must tell mac80211
+                * to generate the IV/EIV data.
+                */
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       }
+
+       /*
+        * SEC_CSR0 contains only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead, we use
+        * a calculation to determine the correct bit directly.
+        */
+       mask = 1 << key->hw_key_idx;
+
+       rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
+       if (crypto->cmd == SET_KEY)
+               reg |= mask;
+       else if (crypto->cmd == DISABLE_KEY)
+               reg &= ~mask;
+       rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
+
+       return 0;
+}
+
+static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+                                      struct rt2x00lib_crypto *crypto,
+                                      struct ieee80211_key_conf *key)
+{
+       struct hw_pairwise_ta_entry addr_entry;
+       struct hw_key_entry key_entry;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for pairwise keys. We have 2 registers
+                * with key valid bits. The goal is simple: read
+                * the first register. If that is full, move to
+                * the next register.
+                * When both registers are full, we drop the key.
+                * Otherwise, we use the first invalid entry.
+                */
+               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (reg && reg == ~0) {
+                       key->hw_key_idx = 32;
+                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       if (reg && reg == ~0)
+                               return -ENOSPC;
+               }
+
+               key->hw_key_idx += reg ? ffz(reg) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               memset(&addr_entry, 0, sizeof(addr_entry));
+               memcpy(&addr_entry, crypto->address, ETH_ALEN);
+               addr_entry.cipher = crypto->cipher;
+
+               reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+                                              &key_entry, sizeof(key_entry));
+
+               reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
+               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+                                              &addr_entry, sizeof(addr_entry));
+
+               /*
+                * Enable pairwise lookup table for given BSS idx.
+                * Without this, received frames will not be decrypted
+                * by the hardware.
+                */
+               rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
+               reg |= (1 << crypto->bssidx);
+               rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
+
+               /*
+                * The driver does not support the IV/EIV generation
+                * in hardware. However it doesn't support the IV/EIV
+                * inside the ieee80211 frame either, but requires it
+                * to be provided separately for the descriptor.
+                * rt2x00lib will cut the IV/EIV data out of all frames
+                * given to us by mac80211, but we must tell mac80211
+                * to generate the IV/EIV data.
+                */
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       }
+
+       /*
+        * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead, we use
+        * a calculation to determine the correct bit directly.
+        */
+       if (key->hw_key_idx < 32) {
+               mask = 1 << key->hw_key_idx;
+
+               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg);
+       } else {
+               mask = 1 << (key->hw_key_idx - 32);
+
+               rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg);
+       }
+
+       return 0;
+}
+
+static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
+                                 const unsigned int filter_flags)
+{
+       u32 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
+                          !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+                          !rt2x00dev->intf_ap_count);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
+                          !(filter_flags & FIF_ALLMULTI));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
+}
+
+static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00_intf *intf,
+                               struct rt2x00intf_conf *conf,
+                               const unsigned int flags)
+{
+       u32 reg;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable synchronisation.
+                */
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+       }
+
+       if (flags & CONFIG_UPDATE_MAC) {
+               reg = le32_to_cpu(conf->mac[1]);
+               rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+               conf->mac[1] = cpu_to_le32(reg);
+
+               rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2,
+                                              conf->mac, sizeof(conf->mac));
+       }
+
+       if (flags & CONFIG_UPDATE_BSSID) {
+               reg = le32_to_cpu(conf->bssid[1]);
+               rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
+               conf->bssid[1] = cpu_to_le32(reg);
+
+               rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4,
+                                              conf->bssid,
+                                              sizeof(conf->bssid));
+       }
+}
+
+static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00lib_erp *erp,
+                              u32 changed)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+                                  !!erp->short_preamble);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5,
+                                         erp->basic_rates);
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+       }
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+               rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg);
+       }
+}
+
+static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+                                     struct antenna_setup *ant)
+{
+       u8 r3;
+       u8 r4;
+       u8 r77;
+
+       rt61pci_bbp_read(rt2x00dev, 3, &r3);
+       rt61pci_bbp_read(rt2x00dev, 4, &r4);
+       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+                                 (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               else
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               else
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               break;
+       }
+
+       rt61pci_bbp_write(rt2x00dev, 77, r77);
+       rt61pci_bbp_write(rt2x00dev, 3, r3);
+       rt61pci_bbp_write(rt2x00dev, 4, r4);
+}
+
+static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+                                     struct antenna_setup *ant)
+{
+       u8 r3;
+       u8 r4;
+       u8 r77;
+
+       rt61pci_bbp_read(rt2x00dev, 3, &r3);
+       rt61pci_bbp_read(rt2x00dev, 4, &r4);
+       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
+       rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+                         !rt2x00_has_cap_frame_type(rt2x00dev));
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               break;
+       }
+
+       rt61pci_bbp_write(rt2x00dev, 77, r77);
+       rt61pci_bbp_write(rt2x00dev, 3, r3);
+       rt61pci_bbp_write(rt2x00dev, 4, r4);
+}
+
+static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
+                                          const int p1, const int p2)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+
+       rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
+       rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
+
+       rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
+       rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
+
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
+}
+
+static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
+                                       struct antenna_setup *ant)
+{
+       u8 r3;
+       u8 r4;
+       u8 r77;
+
+       rt61pci_bbp_read(rt2x00dev, 3, &r3);
+       rt61pci_bbp_read(rt2x00dev, 4, &r4);
+       rt61pci_bbp_read(rt2x00dev, 77, &r77);
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_A:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
+               break;
+       case ANTENNA_HW_DIVERSITY:
+               /*
+                * FIXME: Antenna selection for the rf 2529 is very confusing
+                * in the legacy driver. Just default to antenna B until the
+                * legacy code can be properly translated into rt2x00 code.
+                */
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
+               break;
+       }
+
+       rt61pci_bbp_write(rt2x00dev, 77, r77);
+       rt61pci_bbp_write(rt2x00dev, 3, r3);
+       rt61pci_bbp_write(rt2x00dev, 4, r4);
+}
+
+struct antenna_sel {
+       u8 word;
+       /*
+        * value[0] -> non-LNA
+        * value[1] -> LNA
+        */
+       u8 value[2];
+};
+
+static const struct antenna_sel antenna_sel_a[] = {
+       { 96,  { 0x58, 0x78 } },
+       { 104, { 0x38, 0x48 } },
+       { 75,  { 0xfe, 0x80 } },
+       { 86,  { 0xfe, 0x80 } },
+       { 88,  { 0xfe, 0x80 } },
+       { 35,  { 0x60, 0x60 } },
+       { 97,  { 0x58, 0x58 } },
+       { 98,  { 0x58, 0x58 } },
+};
+
+static const struct antenna_sel antenna_sel_bg[] = {
+       { 96,  { 0x48, 0x68 } },
+       { 104, { 0x2c, 0x3c } },
+       { 75,  { 0xfe, 0x80 } },
+       { 86,  { 0xfe, 0x80 } },
+       { 88,  { 0xfe, 0x80 } },
+       { 35,  { 0x50, 0x50 } },
+       { 97,  { 0x48, 0x48 } },
+       { 98,  { 0x48, 0x48 } },
+};
+
+static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
+                              struct antenna_setup *ant)
+{
+       const struct antenna_sel *sel;
+       unsigned int lna;
+       unsigned int i;
+       u32 reg;
+
+       /*
+        * We should never come here because rt2x00lib is supposed
+        * to catch this and send us the correct antenna explicitely.
+        */
+       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+              ant->tx == ANTENNA_SW_DIVERSITY);
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               sel = antenna_sel_a;
+               lna = rt2x00_has_cap_external_lna_a(rt2x00dev);
+       } else {
+               sel = antenna_sel_bg;
+               lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
+               rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
+
+       rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
+
+       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+                          rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+                          rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+
+       rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg);
+
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
+               rt61pci_config_antenna_5x(rt2x00dev, ant);
+       else if (rt2x00_rf(rt2x00dev, RF2527))
+               rt61pci_config_antenna_2x(rt2x00dev, ant);
+       else if (rt2x00_rf(rt2x00dev, RF2529)) {
+               if (rt2x00_has_cap_double_antenna(rt2x00dev))
+                       rt61pci_config_antenna_2x(rt2x00dev, ant);
+               else
+                       rt61pci_config_antenna_2529(rt2x00dev, ant);
+       }
+}
+
+static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+                                   struct rt2x00lib_conf *libconf)
+{
+       u16 eeprom;
+       short lna_gain = 0;
+
+       if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
+               if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
+                       lna_gain += 14;
+
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+       } else {
+               if (rt2x00_has_cap_external_lna_a(rt2x00dev))
+                       lna_gain += 14;
+
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+       }
+
+       rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
+                                  struct rf_channel *rf, const int txpower)
+{
+       u8 r3;
+       u8 r94;
+       u8 smart;
+
+       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+       smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
+
+       rt61pci_bbp_read(rt2x00dev, 3, &r3);
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+       rt61pci_bbp_write(rt2x00dev, 3, r3);
+
+       r94 = 6;
+       if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+               r94 += txpower - MAX_TXPOWER;
+       else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+               r94 += txpower;
+       rt61pci_bbp_write(rt2x00dev, 94, r94);
+
+       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+       udelay(200);
+
+       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+       udelay(200);
+
+       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+       msleep(1);
+}
+
+static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
+                                  const int txpower)
+{
+       struct rf_channel rf;
+
+       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+       rt61pci_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+                                   struct rt2x00lib_conf *libconf)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+                          libconf->conf->long_frame_max_tx_count);
+       rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+                          libconf->conf->short_frame_max_tx_count);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
+
+static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
+                                  rt2x00dev->beacon_int - 10);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+                                         0x00000005);
+               rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
+               rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
+
+               rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
+       } else {
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+                                         0x00000007);
+               rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
+               rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
+
+               rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+       }
+}
+
+static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
+                          struct rt2x00lib_conf *libconf,
+                          const unsigned int flags)
+{
+       /* Always recalculate LNA gain before changing configuration */
+       rt61pci_config_lna_gain(rt2x00dev, libconf);
+
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt61pci_config_channel(rt2x00dev, &libconf->rf,
+                                      libconf->conf->power_level);
+       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
+               rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt61pci_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt61pci_config_ps(rt2x00dev, libconf);
+}
+
+/*
+ * Link tuning
+ */
+static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual)
+{
+       u32 reg;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+       qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+
+       /*
+        * Update False CCA count from register.
+        */
+       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+       qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
+}
+
+static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                  struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level != vgc_level) {
+               rt61pci_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                               struct link_qual *qual)
+{
+       rt61pci_set_vgc(rt2x00dev, qual, 0x20);
+}
+
+static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
+{
+       u8 up_bound;
+       u8 low_bound;
+
+       /*
+        * Determine r17 bounds.
+        */
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               low_bound = 0x28;
+               up_bound = 0x48;
+               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
+                       low_bound += 0x10;
+                       up_bound += 0x10;
+               }
+       } else {
+               low_bound = 0x20;
+               up_bound = 0x40;
+               if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+                       low_bound += 0x10;
+                       up_bound += 0x10;
+               }
+       }
+
+       /*
+        * If we are not associated, we should go straight to the
+        * dynamic CCA tuning.
+        */
+       if (!rt2x00dev->intf_associated)
+               goto dynamic_cca_tune;
+
+       /*
+        * Special big-R17 for very short distance
+        */
+       if (qual->rssi >= -35) {
+               rt61pci_set_vgc(rt2x00dev, qual, 0x60);
+               return;
+       }
+
+       /*
+        * Special big-R17 for short distance
+        */
+       if (qual->rssi >= -58) {
+               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
+               return;
+       }
+
+       /*
+        * Special big-R17 for middle-short distance
+        */
+       if (qual->rssi >= -66) {
+               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10);
+               return;
+       }
+
+       /*
+        * Special mid-R17 for middle distance
+        */
+       if (qual->rssi >= -74) {
+               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08);
+               return;
+       }
+
+       /*
+        * Special case: Change up_bound based on the rssi.
+        * Lower up_bound when rssi is weaker then -74 dBm.
+        */
+       up_bound -= 2 * (-74 - qual->rssi);
+       if (low_bound > up_bound)
+               up_bound = low_bound;
+
+       if (qual->vgc_level > up_bound) {
+               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
+               return;
+       }
+
+dynamic_cca_tune:
+
+       /*
+        * r17 does not yet exceed upper limit, continue and base
+        * the r17 tuning on the false CCA count.
+        */
+       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+               rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+               rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt61pci_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt61pci_kick_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_VI:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_BE:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_BK:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt61pci_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_AC_VO:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_VI:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_BE:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_AC_BK:
+               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
+               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+               break;
+       case QID_RX:
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+               /*
+                * Wait for possibly running tbtt tasklets.
+                */
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Firmware functions
+ */
+static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+       u16 chip;
+       char *fw_name;
+
+       pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip);
+       switch (chip) {
+       case RT2561_PCI_ID:
+               fw_name = FIRMWARE_RT2561;
+               break;
+       case RT2561s_PCI_ID:
+               fw_name = FIRMWARE_RT2561s;
+               break;
+       case RT2661_PCI_ID:
+               fw_name = FIRMWARE_RT2661;
+               break;
+       default:
+               fw_name = NULL;
+               break;
+       }
+
+       return fw_name;
+}
+
+static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev,
+                                 const u8 *data, const size_t len)
+{
+       u16 fw_crc;
+       u16 crc;
+
+       /*
+        * Only support 8kb firmware files.
+        */
+       if (len != 8192)
+               return FW_BAD_LENGTH;
+
+       /*
+        * The last 2 bytes in the firmware array are the crc checksum itself.
+        * This means that we should never pass those 2 bytes to the crc
+        * algorithm.
+        */
+       fw_crc = (data[len - 2] << 8 | data[len - 1]);
+
+       /*
+        * Use the crc itu-t algorithm.
+        */
+       crc = crc_itu_t(0, data, len - 2);
+       crc = crc_itu_t_byte(crc, 0);
+       crc = crc_itu_t_byte(crc, 0);
+
+       return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
+}
+
+static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
+                                const u8 *data, const size_t len)
+{
+       int i;
+       u32 reg;
+
+       /*
+        * Wait for stable hardware.
+        */
+       for (i = 0; i < 100; i++) {
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+               if (reg)
+                       break;
+               msleep(1);
+       }
+
+       if (!reg) {
+               rt2x00_err(rt2x00dev, "Unstable hardware\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Prepare MCU and mailbox for firmware loading.
+        */
+       reg = 0;
+       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
+       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+       rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+       rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0);
+
+       /*
+        * Write firmware to device.
+        */
+       reg = 0;
+       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
+       rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 1);
+       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+
+       rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+                                      data, len);
+
+       rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 0);
+       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+
+       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 0);
+       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+
+       for (i = 0; i < 100; i++) {
+               rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
+               if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
+                       break;
+               msleep(1);
+       }
+
+       if (i == 100) {
+               rt2x00_err(rt2x00dev, "MCU Control register not ready\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Hardware needs another millisecond before it is ready.
+        */
+       msleep(1);
+
+       /*
+        * Reset MAC and BBP registers.
+        */
+       reg = 0;
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       return 0;
+}
+
+/*
+ * Initialization functions.
+ */
+static bool rt61pci_get_entry_state(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                       rt2x00_get_field32(word, TXD_W0_VALID));
+       }
+}
+
+static void rt61pci_clear_entry(struct queue_entry *entry)
+{
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       u32 word;
+
+       if (entry->queue->qid == QID_RX) {
+               rt2x00_desc_read(entry_priv->desc, 5, &word);
+               rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+                                  skbdesc->skb_dma);
+               rt2x00_desc_write(entry_priv->desc, 5, word);
+
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       } else {
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+               rt2x00_desc_write(entry_priv->desc, 0, word);
+       }
+}
+
+static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
+{
+       struct queue_entry_priv_mmio *entry_priv;
+       u32 reg;
+
+       /*
+        * Initialize registers.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+       rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
+                          rt2x00dev->tx[0].limit);
+       rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
+                          rt2x00dev->tx[1].limit);
+       rt2x00_set_field32(&reg, TX_RING_CSR0_AC2_RING_SIZE,
+                          rt2x00dev->tx[2].limit);
+       rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
+                          rt2x00dev->tx[3].limit);
+       rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+       rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
+                          rt2x00dev->tx[0].desc_size / 4);
+       rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
+
+       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+       rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+
+       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+       rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+
+       entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+       rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+
+       entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+       rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
+       rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
+       rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
+                          rt2x00dev->rx->desc_size / 4);
+       rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
+       rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
+
+       entry_priv = rt2x00dev->rx->entries[0].priv_data;
+       rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+       rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
+                          entry_priv->desc_dma);
+       rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC0, 2);
+       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
+       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
+       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
+       rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1);
+       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
+       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
+       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
+       rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+       rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
+       rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+
+       return 0;
+}
+
+static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg);
+
+       /*
+        * CCK TXD BBP registers
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2, 11);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg);
+
+       /*
+        * OFDM TXD BBP registers
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
+
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               return -EBUSY;
+
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
+
+       /*
+        * Invalidate all Shared Keys (SEC_CSR0),
+        * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
+        */
+       rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
+       rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
+       rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+
+       rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
+       rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
+       rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+       rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
+
+       rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
+
+       rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
+
+       rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+
+       /*
+        * Clear all beacons
+        * For the Beacon base registers we only need to clear
+        * the first byte since that byte contains the VALID and OWNER
+        * bits which (when set to 0) will invalidate the entire beacon.
+        */
+       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+
+       /*
+        * We must clear the error counters.
+        * These registers are cleared on read,
+        * so we may pass a useless variable to store the value.
+        */
+       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+       rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
+
+       /*
+        * Reset MAC and BBP registers.
+        */
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       return 0;
+}
+
+static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt61pci_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
+
+       rt61pci_bbp_write(rt2x00dev, 3, 0x00);
+       rt61pci_bbp_write(rt2x00dev, 15, 0x30);
+       rt61pci_bbp_write(rt2x00dev, 21, 0xc8);
+       rt61pci_bbp_write(rt2x00dev, 22, 0x38);
+       rt61pci_bbp_write(rt2x00dev, 23, 0x06);
+       rt61pci_bbp_write(rt2x00dev, 24, 0xfe);
+       rt61pci_bbp_write(rt2x00dev, 25, 0x0a);
+       rt61pci_bbp_write(rt2x00dev, 26, 0x0d);
+       rt61pci_bbp_write(rt2x00dev, 34, 0x12);
+       rt61pci_bbp_write(rt2x00dev, 37, 0x07);
+       rt61pci_bbp_write(rt2x00dev, 39, 0xf8);
+       rt61pci_bbp_write(rt2x00dev, 41, 0x60);
+       rt61pci_bbp_write(rt2x00dev, 53, 0x10);
+       rt61pci_bbp_write(rt2x00dev, 54, 0x18);
+       rt61pci_bbp_write(rt2x00dev, 60, 0x10);
+       rt61pci_bbp_write(rt2x00dev, 61, 0x04);
+       rt61pci_bbp_write(rt2x00dev, 62, 0x04);
+       rt61pci_bbp_write(rt2x00dev, 75, 0xfe);
+       rt61pci_bbp_write(rt2x00dev, 86, 0xfe);
+       rt61pci_bbp_write(rt2x00dev, 88, 0xfe);
+       rt61pci_bbp_write(rt2x00dev, 90, 0x0f);
+       rt61pci_bbp_write(rt2x00dev, 99, 0x00);
+       rt61pci_bbp_write(rt2x00dev, 102, 0x16);
+       rt61pci_bbp_write(rt2x00dev, 107, 0x04);
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt61pci_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
+                              enum dev_state state)
+{
+       int mask = (state == STATE_RADIO_IRQ_OFF);
+       u32 reg;
+       unsigned long flags;
+
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (state == STATE_RADIO_IRQ_ON) {
+               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+               rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+               rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
+       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_3, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_4, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
+       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+       if (state == STATE_RADIO_IRQ_OFF) {
+               /*
+                * Ensure that all tasklets are finished.
+                */
+               tasklet_kill(&rt2x00dev->txstatus_tasklet);
+               tasklet_kill(&rt2x00dev->rxdone_tasklet);
+               tasklet_kill(&rt2x00dev->autowake_tasklet);
+               tasklet_kill(&rt2x00dev->tbtt_tasklet);
+       }
+}
+
+static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       /*
+        * Initialize all registers.
+        */
+       if (unlikely(rt61pci_init_queues(rt2x00dev) ||
+                    rt61pci_init_registers(rt2x00dev) ||
+                    rt61pci_init_bbp(rt2x00dev)))
+               return -EIO;
+
+       /*
+        * Enable RX.
+        */
+       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+       rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
+       rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+
+       return 0;
+}
+
+static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Disable power
+        */
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+}
+
+static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+{
+       u32 reg, reg2;
+       unsigned int i;
+       char put_to_sleep;
+
+       put_to_sleep = (state != STATE_AWAKE);
+
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
+       rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
+
+       /*
+        * Device is not guaranteed to be in the requested state yet.
+        * We must wait until the register indicates that the
+        * device has entered the correct state.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
+               state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
+               if (state == !put_to_sleep)
+                       return 0;
+               rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
+               msleep(10);
+       }
+
+       return -EBUSY;
+}
+
+static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                   enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt61pci_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               rt61pci_disable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               rt61pci_toggle_irq(rt2x00dev, state);
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt61pci_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt61pci_write_tx_desc(struct queue_entry *entry,
+                                 struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       __le32 *txd = entry_priv->desc;
+       u32 word;
+
+       /*
+        * Start writing the descriptor words.
+        */
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
+       rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
+       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
+       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
+       rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
+                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+       rt2x00_desc_write(txd, 1, word);
+
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
+       rt2x00_desc_write(txd, 2, word);
+
+       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
+       }
+
+       rt2x00_desc_read(txd, 5, &word);
+       rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
+       rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
+                          skbdesc->entry->entry_idx);
+       rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+                          TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
+       rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+       rt2x00_desc_write(txd, 5, word);
+
+       if (entry->queue->qid != QID_BEACON) {
+               rt2x00_desc_read(txd, 6, &word);
+               rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+                                  skbdesc->skb_dma);
+               rt2x00_desc_write(txd, 6, word);
+
+               rt2x00_desc_read(txd, 11, &word);
+               rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
+                                  txdesc->length);
+               rt2x00_desc_write(txd, 11, word);
+       }
+
+       /*
+        * Writing TXD word 0 must the last to prevent a race condition with
+        * the device, whereby the device may take hold of the TXD before we
+        * finished updating it.
+        */
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_OFDM,
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
+       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
+       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
+                          test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
+                          test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
+       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
+       rt2x00_set_field32(&word, TXD_W0_BURST,
+                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
+       rt2x00_desc_write(txd, 0, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->desc = txd;
+       skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE :
+                           TXD_DESC_SIZE;
+}
+
+/*
+ * TX data initialization
+ */
+static void rt61pci_write_beacon(struct queue_entry *entry,
+                                struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       unsigned int beacon_base;
+       unsigned int padding_len;
+       u32 orig_reg, reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       orig_reg = reg;
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt61pci_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
+       /*
+        * Write entire beacon with descriptor and padding to register.
+        */
+       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
+       if (padding_len && skb_pad(entry->skb, padding_len)) {
+               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
+               /* skb freed by skb_pad() on failure */
+               entry->skb = NULL;
+               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+               return;
+       }
+
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base,
+                                      entry_priv->desc, TXINFO_SIZE);
+       rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
+                                      entry->skb->data,
+                                      entry->skb->len + padding_len);
+
+       /*
+        * Enable beaconing again.
+        *
+        * For Wi-Fi faily generated beacons between participating
+        * stations. Set TBTT phase adaptive adjustment step to 8us.
+        */
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Clean up beacon skb.
+        */
+       dev_kfree_skb_any(entry->skb);
+       entry->skb = NULL;
+}
+
+static void rt61pci_clear_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       u32 orig_reg, reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+       reg = orig_reg;
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Clear beacon.
+        */
+       rt2x00mmio_register_write(rt2x00dev,
+                                 HW_BEACON_OFFSET(entry->entry_idx), 0);
+
+       /*
+        * Restore global beaconing state.
+        */
+       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+}
+
+/*
+ * RX control handlers
+ */
+static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+{
+       u8 offset = rt2x00dev->lna_gain;
+       u8 lna;
+
+       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
+       switch (lna) {
+       case 3:
+               offset += 90;
+               break;
+       case 2:
+               offset += 74;
+               break;
+       case 1:
+               offset += 64;
+               break;
+       default:
+               return 0;
+       }
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               if (lna == 3 || lna == 2)
+                       offset += 10;
+       }
+
+       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+}
+
+static void rt61pci_fill_rxdone(struct queue_entry *entry,
+                               struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
+       u32 word0;
+       u32 word1;
+
+       rt2x00_desc_read(entry_priv->desc, 0, &word0);
+       rt2x00_desc_read(entry_priv->desc, 1, &word1);
+
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+       rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
+
+       if (rxdesc->cipher != CIPHER_NONE) {
+               _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
+               _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
+               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
+               _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
+               rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
+
+               /*
+                * Hardware has stripped IV/EIV data from 802.11 frame during
+                * decryption. It has provided the data separately but rt2x00lib
+                * should decide if it should be reinserted.
+                */
+               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+               /*
+                * The hardware has already checked the Michael Mic and has
+                * stripped it from the frame. Signal this to mac80211.
+                */
+               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+                       rxdesc->flags |= RX_FLAG_DECRYPTED;
+               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+       }
+
+       /*
+        * Obtain the status about this packet.
+        * When frame was received with an OFDM bitrate,
+        * the signal is the PLCP value. If it was received with
+        * a CCK bitrate the signal is the rate in 100kbit/s.
+        */
+       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       rxdesc->rssi = rt61pci_agc_to_rssi(rt2x00dev, word1);
+       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+
+       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
+               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+       else
+               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
+       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+}
+
+/*
+ * Interrupt functions.
+ */
+static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+       struct queue_entry *entry;
+       struct queue_entry *entry_done;
+       struct queue_entry_priv_mmio *entry_priv;
+       struct txdone_entry_desc txdesc;
+       u32 word;
+       u32 reg;
+       int type;
+       int index;
+       int i;
+
+       /*
+        * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
+        * at most X times and also stop processing once the TX_STA_FIFO_VALID
+        * flag is not set anymore.
+        *
+        * The legacy drivers use X=TX_RING_SIZE but state in a comment
+        * that the TX_STA_FIFO stack has a size of 16. We stick to our
+        * tx ring size for now.
+        */
+       for (i = 0; i < rt2x00dev->tx->limit; i++) {
+               rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
+               if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
+                       break;
+
+               /*
+                * Skip this entry when it contains an invalid
+                * queue identication number.
+                */
+               type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
+               queue = rt2x00queue_get_tx_queue(rt2x00dev, type);
+               if (unlikely(!queue))
+                       continue;
+
+               /*
+                * Skip this entry when it contains an invalid
+                * index number.
+                */
+               index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
+               if (unlikely(index >= queue->limit))
+                       continue;
+
+               entry = &queue->entries[index];
+               entry_priv = entry->priv_data;
+               rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+                   !rt2x00_get_field32(word, TXD_W0_VALID))
+                       return;
+
+               entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               while (entry != entry_done) {
+                       /* Catch up.
+                        * Just report any entries we missed as failed.
+                        */
+                       rt2x00_warn(rt2x00dev, "TX status report missed for entry %d\n",
+                                   entry_done->entry_idx);
+
+                       rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
+                       entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               }
+
+               /*
+                * Obtain the status about this packet.
+                */
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
+               case 0: /* Success, maybe with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 6: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
+               txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
+
+               /*
+                * the frame was retried at least once
+                * -> hw used fallback rates
+                */
+               if (txdesc.retry)
+                       __set_bit(TXDONE_FALLBACK, &txdesc.flags);
+
+               rt2x00lib_txdone(entry, &txdesc);
+       }
+}
+
+static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
+{
+       struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };
+
+       rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
+}
+
+static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+                                           struct rt2x00_field32 irq_field)
+{
+       u32 reg;
+
+       /*
+        * Enable a single interrupt. The interrupt mask register
+        * access needs locking.
+        */
+       spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, irq_field, 0);
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+       spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
+                                        struct rt2x00_field32 irq_field)
+{
+       u32 reg;
+
+       /*
+        * Enable a single MCU interrupt. The interrupt mask register
+        * access needs locking.
+        */
+       spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, irq_field, 0);
+       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+       spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt61pci_txstatus_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt61pci_txdone(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
+}
+
+static void rt61pci_tbtt_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt2x00lib_beacondone(rt2x00dev);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
+}
+
+static void rt61pci_rxdone_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       if (rt2x00mmio_rxdone(rt2x00dev))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
+}
+
+static void rt61pci_autowake_tasklet(unsigned long data)
+{
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+       rt61pci_wakeup(rt2x00dev);
+       rt2x00mmio_register_write(rt2x00dev,
+                                 M2H_CMD_DONE_CSR, 0xffffffff);
+       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
+}
+
+static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
+{
+       struct rt2x00_dev *rt2x00dev = dev_instance;
+       u32 reg_mcu, mask_mcu;
+       u32 reg, mask;
+
+       /*
+        * Get the interrupt sources & saved to local variable.
+        * Write register value back to clear pending interrupts.
+        */
+       rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+       rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
+
+       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+       rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+       if (!reg && !reg_mcu)
+               return IRQ_NONE;
+
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return IRQ_HANDLED;
+
+       /*
+        * Schedule tasklets for interrupt handling.
+        */
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
+               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
+               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
+               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+       if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
+               tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+       /*
+        * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+        * for interrupts and interrupt masks we can just use the value of
+        * INT_SOURCE_CSR to create the interrupt mask.
+        */
+       mask = reg;
+       mask_mcu = reg_mcu;
+
+       /*
+        * Disable all interrupts for which a tasklet was scheduled right now,
+        * the tasklet will reenable the appropriate interrupts.
+        */
+       spin_lock(&rt2x00dev->irqmask_lock);
+
+       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       reg |= mask;
+       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       reg |= mask_mcu;
+       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+       spin_unlock(&rt2x00dev->irqmask_lock);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       struct eeprom_93cx6 eeprom;
+       u32 reg;
+       u16 word;
+       u8 *mac;
+       s8 value;
+
+       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
+
+       eeprom.data = rt2x00dev;
+       eeprom.register_read = rt61pci_eepromregister_read;
+       eeprom.register_write = rt61pci_eepromregister_write;
+       eeprom.width = rt2x00_get_field32(reg, E2PROM_CSR_TYPE_93C46) ?
+           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
+       eeprom.reg_data_in = 0;
+       eeprom.reg_data_out = 0;
+       eeprom.reg_data_clock = 0;
+       eeprom.reg_chip_select = 0;
+
+       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
+                              EEPROM_SIZE / sizeof(u16));
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+                                  ANTENNA_B);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+                                  ANTENNA_B);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_RX_FIXED, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_TX_FIXED, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
+               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
+                                  LED_MODE_DEFAULT);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+               rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+       }
+
+       return 0;
+}
+
+static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 value;
+       u16 eeprom;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+       /*
+        * Identify RF chipset.
+        */
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
+       rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
+                       value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
+
+       if (!rt2x00_rf(rt2x00dev, RF5225) &&
+           !rt2x00_rf(rt2x00dev, RF5325) &&
+           !rt2x00_rf(rt2x00dev, RF2527) &&
+           !rt2x00_rf(rt2x00dev, RF2529)) {
+               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Determine number of antennas.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
+               __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
+       rt2x00dev->default_ant.rx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
+
+       /*
+        * Read the Frame type.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
+               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
+
+       /*
+        * Detect if this device has a hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+
+       /*
+        * Read frequency offset and RF programming sequence.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
+               __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
+
+       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
+
+       /*
+        * Read external LNA informations.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
+
+       /*
+        * When working with a RF2529 chip without double antenna,
+        * the antenna settings should be gathered from the NIC
+        * eeprom word.
+        */
+       if (rt2x00_rf(rt2x00dev, RF2529) &&
+           !rt2x00_has_cap_double_antenna(rt2x00dev)) {
+               rt2x00dev->default_ant.rx =
+                   ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
+               rt2x00dev->default_ant.tx =
+                   ANTENNA_B - rt2x00_get_field16(eeprom, EEPROM_NIC_TX_FIXED);
+
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
+                       rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
+               if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY))
+                       rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY;
+       }
+
+       /*
+        * Store led settings, for correct led behaviour.
+        * If the eeprom value is invalid,
+        * switch to default led mode.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+       value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
+
+       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+       if (value == LED_MODE_SIGNAL_STRENGTH)
+               rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                LED_TYPE_QUALITY);
+
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_0));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_1));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_2));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_3));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_4));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+                          rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_RDY_G));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_RDY_A));
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       return 0;
+}
+
+/*
+ * RF value list for RF5225 & RF5325
+ * Supports: 2.4 GHz & 5.2 GHz, rf_sequence disabled
+ */
+static const struct rf_channel rf_vals_noseq[] = {
+       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
+       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
+       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
+       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
+       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
+       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
+       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
+       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
+       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
+       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
+       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
+       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
+       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
+       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 },
+       { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 },
+       { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b },
+       { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 },
+       { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b },
+       { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 },
+       { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 },
+       { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 },
+       { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b },
+       { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 },
+       { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b },
+       { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 },
+       { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 },
+       { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b },
+       { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 },
+       { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b },
+       { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 },
+
+       /* 802.11 UNII */
+       { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 },
+       { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f },
+       { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 },
+       { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 },
+       { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f },
+       { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 },
+
+       /* MMAC(Japan)J52 ch 34,38,42,46 */
+       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b },
+       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 },
+       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b },
+       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 },
+};
+
+/*
+ * RF value list for RF5225 & RF5325
+ * Supports: 2.4 GHz & 5.2 GHz, rf_sequence enabled
+ */
+static const struct rf_channel rf_vals_seq[] = {
+       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
+       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
+       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
+       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
+       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
+       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
+       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
+       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
+       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
+       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
+       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
+       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
+       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
+       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00002cd4, 0x0004481a, 0x00098455, 0x000c0a03 },
+       { 40, 0x00002cd0, 0x00044682, 0x00098455, 0x000c0a03 },
+       { 44, 0x00002cd0, 0x00044686, 0x00098455, 0x000c0a1b },
+       { 48, 0x00002cd0, 0x0004468e, 0x00098655, 0x000c0a0b },
+       { 52, 0x00002cd0, 0x00044692, 0x00098855, 0x000c0a23 },
+       { 56, 0x00002cd0, 0x0004469a, 0x00098c55, 0x000c0a13 },
+       { 60, 0x00002cd0, 0x000446a2, 0x00098e55, 0x000c0a03 },
+       { 64, 0x00002cd0, 0x000446a6, 0x00099255, 0x000c0a1b },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00002cd4, 0x0004489a, 0x000b9855, 0x000c0a03 },
+       { 104, 0x00002cd4, 0x000448a2, 0x000b9855, 0x000c0a03 },
+       { 108, 0x00002cd4, 0x000448aa, 0x000b9855, 0x000c0a03 },
+       { 112, 0x00002cd4, 0x000448b2, 0x000b9a55, 0x000c0a03 },
+       { 116, 0x00002cd4, 0x000448ba, 0x000b9a55, 0x000c0a03 },
+       { 120, 0x00002cd0, 0x00044702, 0x000b9a55, 0x000c0a03 },
+       { 124, 0x00002cd0, 0x00044706, 0x000b9a55, 0x000c0a1b },
+       { 128, 0x00002cd0, 0x0004470e, 0x000b9c55, 0x000c0a0b },
+       { 132, 0x00002cd0, 0x00044712, 0x000b9c55, 0x000c0a23 },
+       { 136, 0x00002cd0, 0x0004471a, 0x000b9e55, 0x000c0a13 },
+
+       /* 802.11 UNII */
+       { 140, 0x00002cd0, 0x00044722, 0x000b9e55, 0x000c0a03 },
+       { 149, 0x00002cd0, 0x0004472e, 0x000ba255, 0x000c0a1b },
+       { 153, 0x00002cd0, 0x00044736, 0x000ba255, 0x000c0a0b },
+       { 157, 0x00002cd4, 0x0004490a, 0x000ba255, 0x000c0a17 },
+       { 161, 0x00002cd4, 0x00044912, 0x000ba255, 0x000c0a17 },
+       { 165, 0x00002cd4, 0x0004491a, 0x000ba255, 0x000c0a17 },
+
+       /* MMAC(Japan)J52 ch 34,38,42,46 */
+       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000c0a0b },
+       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000c0a13 },
+       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000c0a1b },
+       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000c0a23 },
+};
+
+static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *tx_power;
+       unsigned int i;
+
+       /*
+        * Disable powersaving as default.
+        */
+       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+       /*
+        * Initialize all hw fields.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2x00_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * As rt61 has a global fallback table we cannot specify
+        * more then one tx rate per frame but since the hw will
+        * try several rates (based on the fallback table) we should
+        * initialize max_report_rates to the maximum number of rates
+        * we are going to try. Otherwise mac80211 will truncate our
+        * reported tx rates and the rc algortihm will end up with
+        * incorrect data.
+        */
+       rt2x00dev->hw->max_rates = 1;
+       rt2x00dev->hw->max_report_rates = 7;
+       rt2x00dev->hw->max_rate_tries = 1;
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+       if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) {
+               spec->num_channels = 14;
+               spec->channels = rf_vals_noseq;
+       } else {
+               spec->num_channels = 14;
+               spec->channels = rf_vals_seq;
+       }
+
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_seq);
+       }
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = MAX_TXPOWER;
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
+
+       if (spec->num_channels > 14) {
+               tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].max_power = MAX_TXPOWER;
+                       info[i].default_power1 =
+                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
+               }
+       }
+
+       return 0;
+}
+
+static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u32 reg;
+
+       /*
+        * Disable power saving.
+        */
+       rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt61pci_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt61pci_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
+       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt61pci_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * This device has multiple filters for control frames,
+        * but has no a separate filter for PS Poll frames.
+        */
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+
+       /*
+        * This device requires firmware and DMA mapped skbs.
+        */
+       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+       if (!modparam_nohwcrypt)
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static int rt61pci_conf_tx(struct ieee80211_hw *hw,
+                          struct ieee80211_vif *vif, u16 queue_idx,
+                          const struct ieee80211_tx_queue_params *params)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+       struct rt2x00_field32 field;
+       int retval;
+       u32 reg;
+       u32 offset;
+
+       /*
+        * First pass the configuration through rt2x00lib, that will
+        * update the queue settings and validate the input. After that
+        * we are free to update the registers based on the value
+        * in the queue parameter.
+        */
+       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
+       if (retval)
+               return retval;
+
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues.
+        */
+       if (queue_idx >= 4)
+               return 0;
+
+       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+
+       /* Update WMM TXOP register */
+       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
+       field.bit_offset = (queue_idx & 1) * 16;
+       field.bit_mask = 0xffff << field.bit_offset;
+
+       rt2x00mmio_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field, queue->txop);
+       rt2x00mmio_register_write(rt2x00dev, offset, reg);
+
+       /* Update WMM registers */
+       field.bit_offset = queue_idx * 4;
+       field.bit_mask = 0xf << field.bit_offset;
+
+       rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->aifs);
+       rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_min);
+       rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
+
+       rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_max);
+       rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
+
+       return 0;
+}
+
+static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u64 tsf;
+       u32 reg;
+
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
+       tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
+       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
+       tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
+
+       return tsf;
+}
+
+static const struct ieee80211_ops rt61pci_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt61pci_conf_tx,
+       .get_tsf                = rt61pci_get_tsf,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
+       .irq_handler            = rt61pci_interrupt,
+       .txstatus_tasklet       = rt61pci_txstatus_tasklet,
+       .tbtt_tasklet           = rt61pci_tbtt_tasklet,
+       .rxdone_tasklet         = rt61pci_rxdone_tasklet,
+       .autowake_tasklet       = rt61pci_autowake_tasklet,
+       .probe_hw               = rt61pci_probe_hw,
+       .get_firmware_name      = rt61pci_get_firmware_name,
+       .check_firmware         = rt61pci_check_firmware,
+       .load_firmware          = rt61pci_load_firmware,
+       .initialize             = rt2x00mmio_initialize,
+       .uninitialize           = rt2x00mmio_uninitialize,
+       .get_entry_state        = rt61pci_get_entry_state,
+       .clear_entry            = rt61pci_clear_entry,
+       .set_device_state       = rt61pci_set_device_state,
+       .rfkill_poll            = rt61pci_rfkill_poll,
+       .link_stats             = rt61pci_link_stats,
+       .reset_tuner            = rt61pci_reset_tuner,
+       .link_tuner             = rt61pci_link_tuner,
+       .start_queue            = rt61pci_start_queue,
+       .kick_queue             = rt61pci_kick_queue,
+       .stop_queue             = rt61pci_stop_queue,
+       .flush_queue            = rt2x00mmio_flush_queue,
+       .write_tx_desc          = rt61pci_write_tx_desc,
+       .write_beacon           = rt61pci_write_beacon,
+       .clear_beacon           = rt61pci_clear_beacon,
+       .fill_rxdone            = rt61pci_fill_rxdone,
+       .config_shared_key      = rt61pci_config_shared_key,
+       .config_pairwise_key    = rt61pci_config_pairwise_key,
+       .config_filter          = rt61pci_config_filter,
+       .config_intf            = rt61pci_config_intf,
+       .config_erp             = rt61pci_config_erp,
+       .config_ant             = rt61pci_config_ant,
+       .config                 = rt61pci_config,
+};
+
+static void rt61pci_queue_init(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 4;
+               queue->data_size = 0; /* No DMA required for beacons */
+               queue->desc_size = TXINFO_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
+               break;
+
+       case QID_ATIM:
+               /* fallthrough */
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt61pci_ops = {
+       .name                   = KBUILD_MODNAME,
+       .max_ap_intf            = 4,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt61pci_queue_init,
+       .lib                    = &rt61pci_rt2x00_ops,
+       .hw                     = &rt61pci_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt61pci_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * RT61pci module information.
+ */
+static const struct pci_device_id rt61pci_device_table[] = {
+       /* RT2561s */
+       { PCI_DEVICE(0x1814, 0x0301) },
+       /* RT2561 v2 */
+       { PCI_DEVICE(0x1814, 0x0302) },
+       /* RT2661 */
+       { PCI_DEVICE(0x1814, 0x0401) },
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT61 PCI & PCMCIA Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2561, RT2561s & RT2661 "
+                       "PCI & PCMCIA chipset based cards");
+MODULE_DEVICE_TABLE(pci, rt61pci_device_table);
+MODULE_FIRMWARE(FIRMWARE_RT2561);
+MODULE_FIRMWARE(FIRMWARE_RT2561s);
+MODULE_FIRMWARE(FIRMWARE_RT2661);
+MODULE_LICENSE("GPL");
+
+static int rt61pci_probe(struct pci_dev *pci_dev,
+                        const struct pci_device_id *id)
+{
+       return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
+static struct pci_driver rt61pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt61pci_device_table,
+       .probe          = rt61pci_probe,
+       .remove         = rt2x00pci_remove,
+       .suspend        = rt2x00pci_suspend,
+       .resume         = rt2x00pci_resume,
+};
+
+module_pci_driver(rt61pci_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.h b/drivers/net/wireless/ralink/rt2x00/rt61pci.h
new file mode 100644 (file)
index 0000000..1442075
--- /dev/null
@@ -0,0 +1,1500 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt61pci
+       Abstract: Data structures and registers for the rt61pci module.
+       Supported chipsets: RT2561, RT2561s, RT2661.
+ */
+
+#ifndef RT61PCI_H
+#define RT61PCI_H
+
+/*
+ * RT chip PCI IDs.
+ */
+#define RT2561s_PCI_ID                 0x0301
+#define RT2561_PCI_ID                  0x0302
+#define RT2661_PCI_ID                  0x0401
+
+/*
+ * RF chip defines.
+ */
+#define RF5225                         0x0001
+#define RF5325                         0x0002
+#define RF2527                         0x0003
+#define RF2529                         0x0004
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET            120
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x3000
+#define CSR_REG_SIZE                   0x04b0
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x0100
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x0080
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  4
+
+/*
+ * PCI registers.
+ */
+
+/*
+ * HOST_CMD_CSR: For HOST to interrupt embedded processor
+ */
+#define HOST_CMD_CSR                   0x0008
+#define HOST_CMD_CSR_HOST_COMMAND      FIELD32(0x0000007f)
+#define HOST_CMD_CSR_INTERRUPT_MCU     FIELD32(0x00000080)
+
+/*
+ * MCU_CNTL_CSR
+ * SELECT_BANK: Select 8051 program bank.
+ * RESET: Enable 8051 reset state.
+ * READY: Ready state for 8051.
+ */
+#define MCU_CNTL_CSR                   0x000c
+#define MCU_CNTL_CSR_SELECT_BANK       FIELD32(0x00000001)
+#define MCU_CNTL_CSR_RESET             FIELD32(0x00000002)
+#define MCU_CNTL_CSR_READY             FIELD32(0x00000004)
+
+/*
+ * SOFT_RESET_CSR
+ * FORCE_CLOCK_ON: Host force MAC clock ON
+ */
+#define SOFT_RESET_CSR                 0x0010
+#define SOFT_RESET_CSR_FORCE_CLOCK_ON  FIELD32(0x00000002)
+
+/*
+ * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register.
+ */
+#define MCU_INT_SOURCE_CSR             0x0014
+#define MCU_INT_SOURCE_CSR_0           FIELD32(0x00000001)
+#define MCU_INT_SOURCE_CSR_1           FIELD32(0x00000002)
+#define MCU_INT_SOURCE_CSR_2           FIELD32(0x00000004)
+#define MCU_INT_SOURCE_CSR_3           FIELD32(0x00000008)
+#define MCU_INT_SOURCE_CSR_4           FIELD32(0x00000010)
+#define MCU_INT_SOURCE_CSR_5           FIELD32(0x00000020)
+#define MCU_INT_SOURCE_CSR_6           FIELD32(0x00000040)
+#define MCU_INT_SOURCE_CSR_7           FIELD32(0x00000080)
+#define MCU_INT_SOURCE_CSR_TWAKEUP     FIELD32(0x00000100)
+#define MCU_INT_SOURCE_CSR_TBTT_EXPIRE FIELD32(0x00000200)
+
+/*
+ * MCU_INT_MASK_CSR: MCU interrupt source/mask register.
+ */
+#define MCU_INT_MASK_CSR               0x0018
+#define MCU_INT_MASK_CSR_0             FIELD32(0x00000001)
+#define MCU_INT_MASK_CSR_1             FIELD32(0x00000002)
+#define MCU_INT_MASK_CSR_2             FIELD32(0x00000004)
+#define MCU_INT_MASK_CSR_3             FIELD32(0x00000008)
+#define MCU_INT_MASK_CSR_4             FIELD32(0x00000010)
+#define MCU_INT_MASK_CSR_5             FIELD32(0x00000020)
+#define MCU_INT_MASK_CSR_6             FIELD32(0x00000040)
+#define MCU_INT_MASK_CSR_7             FIELD32(0x00000080)
+#define MCU_INT_MASK_CSR_TWAKEUP       FIELD32(0x00000100)
+#define MCU_INT_MASK_CSR_TBTT_EXPIRE   FIELD32(0x00000200)
+
+/*
+ * PCI_USEC_CSR
+ */
+#define PCI_USEC_CSR                   0x001c
+
+/*
+ * Security key table memory.
+ * 16 entries 32-byte for shared key table
+ * 64 entries 32-byte for pairwise key table
+ * 64 entries 8-byte for pairwise ta key table
+ */
+#define SHARED_KEY_TABLE_BASE          0x1000
+#define PAIRWISE_KEY_TABLE_BASE                0x1200
+#define PAIRWISE_TA_TABLE_BASE         0x1a00
+
+#define SHARED_KEY_ENTRY(__idx) \
+       ( SHARED_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+       ( PAIRWISE_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+       ( PAIRWISE_TA_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
+struct hw_key_entry {
+       u8 key[16];
+       u8 tx_mic[8];
+       u8 rx_mic[8];
+} __packed;
+
+struct hw_pairwise_ta_entry {
+       u8 address[6];
+       u8 cipher;
+       u8 reserved;
+} __packed;
+
+/*
+ * Other on-chip shared memory space.
+ */
+#define HW_CIS_BASE                    0x2000
+#define HW_NULL_BASE                   0x2b00
+
+/*
+ * Since NULL frame won't be that long (256 byte),
+ * We steal 16 tail bytes to save debugging settings.
+ */
+#define HW_DEBUG_SETTING_BASE          0x2bf0
+
+/*
+ * On-chip BEACON frame space.
+ */
+#define HW_BEACON_BASE0                        0x2c00
+#define HW_BEACON_BASE1                        0x2d00
+#define HW_BEACON_BASE2                        0x2e00
+#define HW_BEACON_BASE3                        0x2f00
+
+#define HW_BEACON_OFFSET(__index) \
+       ( HW_BEACON_BASE0 + (__index * 0x0100) )
+
+/*
+ * HOST-MCU shared memory.
+ */
+
+/*
+ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
+ */
+#define H2M_MAILBOX_CSR                        0x2100
+#define H2M_MAILBOX_CSR_ARG0           FIELD32(0x000000ff)
+#define H2M_MAILBOX_CSR_ARG1           FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CSR_CMD_TOKEN      FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CSR_OWNER          FIELD32(0xff000000)
+
+/*
+ * MCU_LEDCS: LED control for MCU Mailbox.
+ */
+#define MCU_LEDCS_LED_MODE             FIELD16(0x001f)
+#define MCU_LEDCS_RADIO_STATUS         FIELD16(0x0020)
+#define MCU_LEDCS_LINK_BG_STATUS       FIELD16(0x0040)
+#define MCU_LEDCS_LINK_A_STATUS                FIELD16(0x0080)
+#define MCU_LEDCS_POLARITY_GPIO_0      FIELD16(0x0100)
+#define MCU_LEDCS_POLARITY_GPIO_1      FIELD16(0x0200)
+#define MCU_LEDCS_POLARITY_GPIO_2      FIELD16(0x0400)
+#define MCU_LEDCS_POLARITY_GPIO_3      FIELD16(0x0800)
+#define MCU_LEDCS_POLARITY_GPIO_4      FIELD16(0x1000)
+#define MCU_LEDCS_POLARITY_ACT         FIELD16(0x2000)
+#define MCU_LEDCS_POLARITY_READY_BG    FIELD16(0x4000)
+#define MCU_LEDCS_POLARITY_READY_A     FIELD16(0x8000)
+
+/*
+ * M2H_CMD_DONE_CSR.
+ */
+#define M2H_CMD_DONE_CSR               0x2104
+
+/*
+ * MCU_TXOP_ARRAY_BASE.
+ */
+#define MCU_TXOP_ARRAY_BASE            0x2110
+
+/*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ */
+#define MAC_CSR0                       0x3000
+#define MAC_CSR0_REVISION              FIELD32(0x0000000f)
+#define MAC_CSR0_CHIPSET               FIELD32(0x000ffff0)
+
+/*
+ * MAC_CSR1: System control register.
+ * SOFT_RESET: Software reset bit, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset BBP.
+ * HOST_READY: Host is ready after initialization, 1: ready.
+ */
+#define MAC_CSR1                       0x3004
+#define MAC_CSR1_SOFT_RESET            FIELD32(0x00000001)
+#define MAC_CSR1_BBP_RESET             FIELD32(0x00000002)
+#define MAC_CSR1_HOST_READY            FIELD32(0x00000004)
+
+/*
+ * MAC_CSR2: STA MAC register 0.
+ */
+#define MAC_CSR2                       0x3008
+#define MAC_CSR2_BYTE0                 FIELD32(0x000000ff)
+#define MAC_CSR2_BYTE1                 FIELD32(0x0000ff00)
+#define MAC_CSR2_BYTE2                 FIELD32(0x00ff0000)
+#define MAC_CSR2_BYTE3                 FIELD32(0xff000000)
+
+/*
+ * MAC_CSR3: STA MAC register 1.
+ * UNICAST_TO_ME_MASK:
+ *     Used to mask off bits from byte 5 of the MAC address
+ *     to determine the UNICAST_TO_ME bit for RX frames.
+ *     The full mask is complemented by BSS_ID_MASK:
+ *             MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+#define MAC_CSR3                       0x300c
+#define MAC_CSR3_BYTE4                 FIELD32(0x000000ff)
+#define MAC_CSR3_BYTE5                 FIELD32(0x0000ff00)
+#define MAC_CSR3_UNICAST_TO_ME_MASK    FIELD32(0x00ff0000)
+
+/*
+ * MAC_CSR4: BSSID register 0.
+ */
+#define MAC_CSR4                       0x3010
+#define MAC_CSR4_BYTE0                 FIELD32(0x000000ff)
+#define MAC_CSR4_BYTE1                 FIELD32(0x0000ff00)
+#define MAC_CSR4_BYTE2                 FIELD32(0x00ff0000)
+#define MAC_CSR4_BYTE3                 FIELD32(0xff000000)
+
+/*
+ * MAC_CSR5: BSSID register 1.
+ * BSS_ID_MASK:
+ *     This mask is used to mask off bits 0 and 1 of byte 5 of the
+ *     BSSID. This will make sure that those bits will be ignored
+ *     when determining the MY_BSS of RX frames.
+ *             0: 1-BSSID mode (BSS index = 0)
+ *             1: 2-BSSID mode (BSS index: Byte5, bit 0)
+ *             2: 2-BSSID mode (BSS index: byte5, bit 1)
+ *             3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ */
+#define MAC_CSR5                       0x3014
+#define MAC_CSR5_BYTE4                 FIELD32(0x000000ff)
+#define MAC_CSR5_BYTE5                 FIELD32(0x0000ff00)
+#define MAC_CSR5_BSS_ID_MASK           FIELD32(0x00ff0000)
+
+/*
+ * MAC_CSR6: Maximum frame length register.
+ */
+#define MAC_CSR6                       0x3018
+#define MAC_CSR6_MAX_FRAME_UNIT                FIELD32(0x00000fff)
+
+/*
+ * MAC_CSR7: Reserved
+ */
+#define MAC_CSR7                       0x301c
+
+/*
+ * MAC_CSR8: SIFS/EIFS register.
+ * All units are in US.
+ */
+#define MAC_CSR8                       0x3020
+#define MAC_CSR8_SIFS                  FIELD32(0x000000ff)
+#define MAC_CSR8_SIFS_AFTER_RX_OFDM    FIELD32(0x0000ff00)
+#define MAC_CSR8_EIFS                  FIELD32(0xffff0000)
+
+/*
+ * MAC_CSR9: Back-Off control register.
+ * SLOT_TIME: Slot time, default is 20us for 802.11BG.
+ * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1).
+ * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1).
+ * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD.
+ */
+#define MAC_CSR9                       0x3024
+#define MAC_CSR9_SLOT_TIME             FIELD32(0x000000ff)
+#define MAC_CSR9_CWMIN                 FIELD32(0x00000f00)
+#define MAC_CSR9_CWMAX                 FIELD32(0x0000f000)
+#define MAC_CSR9_CW_SELECT             FIELD32(0x00010000)
+
+/*
+ * MAC_CSR10: Power state configuration.
+ */
+#define MAC_CSR10                      0x3028
+
+/*
+ * MAC_CSR11: Power saving transition time register.
+ * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU.
+ * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
+ * WAKEUP_LATENCY: In unit of TU.
+ */
+#define MAC_CSR11                      0x302c
+#define MAC_CSR11_DELAY_AFTER_TBCN     FIELD32(0x000000ff)
+#define MAC_CSR11_TBCN_BEFORE_WAKEUP   FIELD32(0x00007f00)
+#define MAC_CSR11_AUTOWAKE             FIELD32(0x00008000)
+#define MAC_CSR11_WAKEUP_LATENCY       FIELD32(0x000f0000)
+
+/*
+ * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1).
+ * CURRENT_STATE: 0:sleep, 1:awake.
+ * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP.
+ * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake.
+ */
+#define MAC_CSR12                      0x3030
+#define MAC_CSR12_CURRENT_STATE                FIELD32(0x00000001)
+#define MAC_CSR12_PUT_TO_SLEEP         FIELD32(0x00000002)
+#define MAC_CSR12_FORCE_WAKEUP         FIELD32(0x00000004)
+#define MAC_CSR12_BBP_CURRENT_STATE    FIELD32(0x00000008)
+
+/*
+ * MAC_CSR13: GPIO.
+ *     MAC_CSR13_VALx: GPIO value
+ *     MAC_CSR13_DIRx: GPIO direction: 0 = output; 1 = input
+ */
+#define MAC_CSR13                      0x3034
+#define MAC_CSR13_VAL0                 FIELD32(0x00000001)
+#define MAC_CSR13_VAL1                 FIELD32(0x00000002)
+#define MAC_CSR13_VAL2                 FIELD32(0x00000004)
+#define MAC_CSR13_VAL3                 FIELD32(0x00000008)
+#define MAC_CSR13_VAL4                 FIELD32(0x00000010)
+#define MAC_CSR13_VAL5                 FIELD32(0x00000020)
+#define MAC_CSR13_DIR0                 FIELD32(0x00000100)
+#define MAC_CSR13_DIR1                 FIELD32(0x00000200)
+#define MAC_CSR13_DIR2                 FIELD32(0x00000400)
+#define MAC_CSR13_DIR3                 FIELD32(0x00000800)
+#define MAC_CSR13_DIR4                 FIELD32(0x00001000)
+#define MAC_CSR13_DIR5                 FIELD32(0x00002000)
+
+/*
+ * MAC_CSR14: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON.
+ * SW_LED: s/w LED, 1: ON, 0: OFF.
+ * HW_LED_POLARITY: 0: active low, 1: active high.
+ */
+#define MAC_CSR14                      0x3038
+#define MAC_CSR14_ON_PERIOD            FIELD32(0x000000ff)
+#define MAC_CSR14_OFF_PERIOD           FIELD32(0x0000ff00)
+#define MAC_CSR14_HW_LED               FIELD32(0x00010000)
+#define MAC_CSR14_SW_LED               FIELD32(0x00020000)
+#define MAC_CSR14_HW_LED_POLARITY      FIELD32(0x00040000)
+#define MAC_CSR14_SW_LED2              FIELD32(0x00080000)
+
+/*
+ * MAC_CSR15: NAV control.
+ */
+#define MAC_CSR15                      0x303c
+
+/*
+ * TXRX control registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * TXRX_CSR0: TX/RX configuration register.
+ * TSF_OFFSET: Default is 24.
+ * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame.
+ * DISABLE_RX: Disable Rx engine.
+ * DROP_CRC: Drop CRC error.
+ * DROP_PHYSICAL: Drop physical error.
+ * DROP_CONTROL: Drop control frame.
+ * DROP_NOT_TO_ME: Drop not to me unicast frame.
+ * DROP_TO_DS: Drop fram ToDs bit is true.
+ * DROP_VERSION_ERROR: Drop version error frame.
+ * DROP_MULTICAST: Drop multicast frames.
+ * DROP_BORADCAST: Drop broadcast frames.
+ * DROP_ACK_CTS: Drop received ACK and CTS.
+ */
+#define TXRX_CSR0                      0x3040
+#define TXRX_CSR0_RX_ACK_TIMEOUT       FIELD32(0x000001ff)
+#define TXRX_CSR0_TSF_OFFSET           FIELD32(0x00007e00)
+#define TXRX_CSR0_AUTO_TX_SEQ          FIELD32(0x00008000)
+#define TXRX_CSR0_DISABLE_RX           FIELD32(0x00010000)
+#define TXRX_CSR0_DROP_CRC             FIELD32(0x00020000)
+#define TXRX_CSR0_DROP_PHYSICAL                FIELD32(0x00040000)
+#define TXRX_CSR0_DROP_CONTROL         FIELD32(0x00080000)
+#define TXRX_CSR0_DROP_NOT_TO_ME       FIELD32(0x00100000)
+#define TXRX_CSR0_DROP_TO_DS           FIELD32(0x00200000)
+#define TXRX_CSR0_DROP_VERSION_ERROR   FIELD32(0x00400000)
+#define TXRX_CSR0_DROP_MULTICAST       FIELD32(0x00800000)
+#define TXRX_CSR0_DROP_BROADCAST       FIELD32(0x01000000)
+#define TXRX_CSR0_DROP_ACK_CTS         FIELD32(0x02000000)
+#define TXRX_CSR0_TX_WITHOUT_WAITING   FIELD32(0x04000000)
+
+/*
+ * TXRX_CSR1
+ */
+#define TXRX_CSR1                      0x3044
+#define TXRX_CSR1_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR1_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR1_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR1_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR1_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR1_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR1_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR1_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR2
+ */
+#define TXRX_CSR2                      0x3048
+#define TXRX_CSR2_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR2_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR2_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR2_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR2_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR2_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR2_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR2_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR3
+ */
+#define TXRX_CSR3                      0x304c
+#define TXRX_CSR3_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR3_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR3_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR3_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR3_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR3_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR3_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR3_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR4: Auto-Responder/Tx-retry register.
+ * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble.
+ * OFDM_TX_RATE_DOWN: 1:enable.
+ * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step.
+ * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M.
+ */
+#define TXRX_CSR4                      0x3050
+#define TXRX_CSR4_TX_ACK_TIMEOUT       FIELD32(0x000000ff)
+#define TXRX_CSR4_CNTL_ACK_POLICY      FIELD32(0x00000700)
+#define TXRX_CSR4_ACK_CTS_PSM          FIELD32(0x00010000)
+#define TXRX_CSR4_AUTORESPOND_ENABLE   FIELD32(0x00020000)
+#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000)
+#define TXRX_CSR4_OFDM_TX_RATE_DOWN    FIELD32(0x00080000)
+#define TXRX_CSR4_OFDM_TX_RATE_STEP    FIELD32(0x00300000)
+#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000)
+#define TXRX_CSR4_LONG_RETRY_LIMIT     FIELD32(0x0f000000)
+#define TXRX_CSR4_SHORT_RETRY_LIMIT    FIELD32(0xf0000000)
+
+/*
+ * TXRX_CSR5
+ */
+#define TXRX_CSR5                      0x3054
+
+/*
+ * TXRX_CSR6: ACK/CTS payload consumed time
+ */
+#define TXRX_CSR6                      0x3058
+
+/*
+ * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
+#define TXRX_CSR7                      0x305c
+#define TXRX_CSR7_ACK_CTS_6MBS         FIELD32(0x000000ff)
+#define TXRX_CSR7_ACK_CTS_9MBS         FIELD32(0x0000ff00)
+#define TXRX_CSR7_ACK_CTS_12MBS                FIELD32(0x00ff0000)
+#define TXRX_CSR7_ACK_CTS_18MBS                FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
+#define TXRX_CSR8                      0x3060
+#define TXRX_CSR8_ACK_CTS_24MBS                FIELD32(0x000000ff)
+#define TXRX_CSR8_ACK_CTS_36MBS                FIELD32(0x0000ff00)
+#define TXRX_CSR8_ACK_CTS_48MBS                FIELD32(0x00ff0000)
+#define TXRX_CSR8_ACK_CTS_54MBS                FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR9: Synchronization control register.
+ * BEACON_INTERVAL: In unit of 1/16 TU.
+ * TSF_TICKING: Enable TSF auto counting.
+ * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
+ * BEACON_GEN: Enable beacon generator.
+ */
+#define TXRX_CSR9                      0x3064
+#define TXRX_CSR9_BEACON_INTERVAL      FIELD32(0x0000ffff)
+#define TXRX_CSR9_TSF_TICKING          FIELD32(0x00010000)
+#define TXRX_CSR9_TSF_SYNC             FIELD32(0x00060000)
+#define TXRX_CSR9_TBTT_ENABLE          FIELD32(0x00080000)
+#define TXRX_CSR9_BEACON_GEN           FIELD32(0x00100000)
+#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR10: BEACON alignment.
+ */
+#define TXRX_CSR10                     0x3068
+
+/*
+ * TXRX_CSR11: AES mask.
+ */
+#define TXRX_CSR11                     0x306c
+
+/*
+ * TXRX_CSR12: TSF low 32.
+ */
+#define TXRX_CSR12                     0x3070
+#define TXRX_CSR12_LOW_TSFTIMER                FIELD32(0xffffffff)
+
+/*
+ * TXRX_CSR13: TSF high 32.
+ */
+#define TXRX_CSR13                     0x3074
+#define TXRX_CSR13_HIGH_TSFTIMER       FIELD32(0xffffffff)
+
+/*
+ * TXRX_CSR14: TBTT timer.
+ */
+#define TXRX_CSR14                     0x3078
+
+/*
+ * TXRX_CSR15: TKIP MIC priority byte "AND" mask.
+ */
+#define TXRX_CSR15                     0x307c
+
+/*
+ * PHY control registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * PHY_CSR0: RF/PS control.
+ */
+#define PHY_CSR0                       0x3080
+#define PHY_CSR0_PA_PE_BG              FIELD32(0x00010000)
+#define PHY_CSR0_PA_PE_A               FIELD32(0x00020000)
+
+/*
+ * PHY_CSR1
+ */
+#define PHY_CSR1                       0x3084
+
+/*
+ * PHY_CSR2: Pre-TX BBP control.
+ */
+#define PHY_CSR2                       0x3088
+
+/*
+ * PHY_CSR3: BBP serial control register.
+ * VALUE: Register value to program into BBP.
+ * REG_NUM: Selected BBP register.
+ * READ_CONTROL: 0: Write BBP, 1: Read BBP.
+ * BUSY: 1: ASIC is busy execute BBP programming.
+ */
+#define PHY_CSR3                       0x308c
+#define PHY_CSR3_VALUE                 FIELD32(0x000000ff)
+#define PHY_CSR3_REGNUM                        FIELD32(0x00007f00)
+#define PHY_CSR3_READ_CONTROL          FIELD32(0x00008000)
+#define PHY_CSR3_BUSY                  FIELD32(0x00010000)
+
+/*
+ * PHY_CSR4: RF serial control register
+ * VALUE: Register value (include register id) serial out to RF/IF chip.
+ * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22).
+ * IF_SELECT: 1: select IF to program, 0: select RF to program.
+ * PLL_LD: RF PLL_LD status.
+ * BUSY: 1: ASIC is busy execute RF programming.
+ */
+#define PHY_CSR4                       0x3090
+#define PHY_CSR4_VALUE                 FIELD32(0x00ffffff)
+#define PHY_CSR4_NUMBER_OF_BITS                FIELD32(0x1f000000)
+#define PHY_CSR4_IF_SELECT             FIELD32(0x20000000)
+#define PHY_CSR4_PLL_LD                        FIELD32(0x40000000)
+#define PHY_CSR4_BUSY                  FIELD32(0x80000000)
+
+/*
+ * PHY_CSR5: RX to TX signal switch timing control.
+ */
+#define PHY_CSR5                       0x3094
+#define PHY_CSR5_IQ_FLIP               FIELD32(0x00000004)
+
+/*
+ * PHY_CSR6: TX to RX signal timing control.
+ */
+#define PHY_CSR6                       0x3098
+#define PHY_CSR6_IQ_FLIP               FIELD32(0x00000004)
+
+/*
+ * PHY_CSR7: TX DAC switching timing control.
+ */
+#define PHY_CSR7                       0x309c
+
+/*
+ * Security control register.
+ */
+
+/*
+ * SEC_CSR0: Shared key table control.
+ */
+#define SEC_CSR0                       0x30a0
+#define SEC_CSR0_BSS0_KEY0_VALID       FIELD32(0x00000001)
+#define SEC_CSR0_BSS0_KEY1_VALID       FIELD32(0x00000002)
+#define SEC_CSR0_BSS0_KEY2_VALID       FIELD32(0x00000004)
+#define SEC_CSR0_BSS0_KEY3_VALID       FIELD32(0x00000008)
+#define SEC_CSR0_BSS1_KEY0_VALID       FIELD32(0x00000010)
+#define SEC_CSR0_BSS1_KEY1_VALID       FIELD32(0x00000020)
+#define SEC_CSR0_BSS1_KEY2_VALID       FIELD32(0x00000040)
+#define SEC_CSR0_BSS1_KEY3_VALID       FIELD32(0x00000080)
+#define SEC_CSR0_BSS2_KEY0_VALID       FIELD32(0x00000100)
+#define SEC_CSR0_BSS2_KEY1_VALID       FIELD32(0x00000200)
+#define SEC_CSR0_BSS2_KEY2_VALID       FIELD32(0x00000400)
+#define SEC_CSR0_BSS2_KEY3_VALID       FIELD32(0x00000800)
+#define SEC_CSR0_BSS3_KEY0_VALID       FIELD32(0x00001000)
+#define SEC_CSR0_BSS3_KEY1_VALID       FIELD32(0x00002000)
+#define SEC_CSR0_BSS3_KEY2_VALID       FIELD32(0x00004000)
+#define SEC_CSR0_BSS3_KEY3_VALID       FIELD32(0x00008000)
+
+/*
+ * SEC_CSR1: Shared key table security mode register.
+ */
+#define SEC_CSR1                       0x30a4
+#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG  FIELD32(0x00000007)
+#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG  FIELD32(0x00000070)
+#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG  FIELD32(0x00000700)
+#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG  FIELD32(0x00007000)
+#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG  FIELD32(0x00070000)
+#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG  FIELD32(0x00700000)
+#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG  FIELD32(0x07000000)
+#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG  FIELD32(0x70000000)
+
+/*
+ * Pairwise key table valid bitmap registers.
+ * SEC_CSR2: pairwise key table valid bitmap 0.
+ * SEC_CSR3: pairwise key table valid bitmap 1.
+ */
+#define SEC_CSR2                       0x30a8
+#define SEC_CSR3                       0x30ac
+
+/*
+ * SEC_CSR4: Pairwise key table lookup control.
+ */
+#define SEC_CSR4                       0x30b0
+#define SEC_CSR4_ENABLE_BSS0           FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1           FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2           FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3           FIELD32(0x00000008)
+
+/*
+ * SEC_CSR5: shared key table security mode register.
+ */
+#define SEC_CSR5                       0x30b4
+#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG  FIELD32(0x00000007)
+#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG  FIELD32(0x00000070)
+#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG  FIELD32(0x00000700)
+#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG  FIELD32(0x00007000)
+#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG  FIELD32(0x00070000)
+#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG  FIELD32(0x00700000)
+#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG  FIELD32(0x07000000)
+#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG  FIELD32(0x70000000)
+
+/*
+ * STA control registers.
+ */
+
+/*
+ * STA_CSR0: RX PLCP error count & RX FCS error count.
+ */
+#define STA_CSR0                       0x30c0
+#define STA_CSR0_FCS_ERROR             FIELD32(0x0000ffff)
+#define STA_CSR0_PLCP_ERROR            FIELD32(0xffff0000)
+
+/*
+ * STA_CSR1: RX False CCA count & RX LONG frame count.
+ */
+#define STA_CSR1                       0x30c4
+#define STA_CSR1_PHYSICAL_ERROR                FIELD32(0x0000ffff)
+#define STA_CSR1_FALSE_CCA_ERROR       FIELD32(0xffff0000)
+
+/*
+ * STA_CSR2: TX Beacon count and RX FIFO overflow count.
+ */
+#define STA_CSR2                       0x30c8
+#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT        FIELD32(0x0000ffff)
+#define STA_CSR2_RX_OVERFLOW_COUNT     FIELD32(0xffff0000)
+
+/*
+ * STA_CSR3: TX Beacon count.
+ */
+#define STA_CSR3                       0x30cc
+#define STA_CSR3_TX_BEACON_COUNT       FIELD32(0x0000ffff)
+
+/*
+ * STA_CSR4: TX Result status register.
+ * VALID: 1:This register contains a valid TX result.
+ */
+#define STA_CSR4                       0x30d0
+#define STA_CSR4_VALID                 FIELD32(0x00000001)
+#define STA_CSR4_TX_RESULT             FIELD32(0x0000000e)
+#define STA_CSR4_RETRY_COUNT           FIELD32(0x000000f0)
+#define STA_CSR4_PID_SUBTYPE           FIELD32(0x00001f00)
+#define STA_CSR4_PID_TYPE              FIELD32(0x0000e000)
+#define STA_CSR4_TXRATE                        FIELD32(0x000f0000)
+
+/*
+ * QOS control registers.
+ */
+
+/*
+ * QOS_CSR0: TXOP holder MAC address register.
+ */
+#define QOS_CSR0                       0x30e0
+#define QOS_CSR0_BYTE0                 FIELD32(0x000000ff)
+#define QOS_CSR0_BYTE1                 FIELD32(0x0000ff00)
+#define QOS_CSR0_BYTE2                 FIELD32(0x00ff0000)
+#define QOS_CSR0_BYTE3                 FIELD32(0xff000000)
+
+/*
+ * QOS_CSR1: TXOP holder MAC address register.
+ */
+#define QOS_CSR1                       0x30e4
+#define QOS_CSR1_BYTE4                 FIELD32(0x000000ff)
+#define QOS_CSR1_BYTE5                 FIELD32(0x0000ff00)
+
+/*
+ * QOS_CSR2: TXOP holder timeout register.
+ */
+#define QOS_CSR2                       0x30e8
+
+/*
+ * RX QOS-CFPOLL MAC address register.
+ * QOS_CSR3: RX QOS-CFPOLL MAC address 0.
+ * QOS_CSR4: RX QOS-CFPOLL MAC address 1.
+ */
+#define QOS_CSR3                       0x30ec
+#define QOS_CSR4                       0x30f0
+
+/*
+ * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL.
+ */
+#define QOS_CSR5                       0x30f4
+
+/*
+ * Host DMA registers.
+ */
+
+/*
+ * AC0_BASE_CSR: AC_VO base address.
+ */
+#define AC0_BASE_CSR                   0x3400
+#define AC0_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
+
+/*
+ * AC1_BASE_CSR: AC_VI base address.
+ */
+#define AC1_BASE_CSR                   0x3404
+#define AC1_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
+
+/*
+ * AC2_BASE_CSR: AC_BE base address.
+ */
+#define AC2_BASE_CSR                   0x3408
+#define AC2_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
+
+/*
+ * AC3_BASE_CSR: AC_BK base address.
+ */
+#define AC3_BASE_CSR                   0x340c
+#define AC3_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
+
+/*
+ * MGMT_BASE_CSR: MGMT ring base address.
+ */
+#define MGMT_BASE_CSR                  0x3410
+#define MGMT_BASE_CSR_RING_REGISTER    FIELD32(0xffffffff)
+
+/*
+ * TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK.
+ */
+#define TX_RING_CSR0                   0x3418
+#define TX_RING_CSR0_AC0_RING_SIZE     FIELD32(0x000000ff)
+#define TX_RING_CSR0_AC1_RING_SIZE     FIELD32(0x0000ff00)
+#define TX_RING_CSR0_AC2_RING_SIZE     FIELD32(0x00ff0000)
+#define TX_RING_CSR0_AC3_RING_SIZE     FIELD32(0xff000000)
+
+/*
+ * TX_RING_CSR1: TX Ring size for MGMT Ring, HCCA Ring
+ * TXD_SIZE: In unit of 32-bit.
+ */
+#define TX_RING_CSR1                   0x341c
+#define TX_RING_CSR1_MGMT_RING_SIZE    FIELD32(0x000000ff)
+#define TX_RING_CSR1_HCCA_RING_SIZE    FIELD32(0x0000ff00)
+#define TX_RING_CSR1_TXD_SIZE          FIELD32(0x003f0000)
+
+/*
+ * AIFSN_CSR: AIFSN for each EDCA AC.
+ * AIFSN0: For AC_VO.
+ * AIFSN1: For AC_VI.
+ * AIFSN2: For AC_BE.
+ * AIFSN3: For AC_BK.
+ */
+#define AIFSN_CSR                      0x3420
+#define AIFSN_CSR_AIFSN0               FIELD32(0x0000000f)
+#define AIFSN_CSR_AIFSN1               FIELD32(0x000000f0)
+#define AIFSN_CSR_AIFSN2               FIELD32(0x00000f00)
+#define AIFSN_CSR_AIFSN3               FIELD32(0x0000f000)
+
+/*
+ * CWMIN_CSR: CWmin for each EDCA AC.
+ * CWMIN0: For AC_VO.
+ * CWMIN1: For AC_VI.
+ * CWMIN2: For AC_BE.
+ * CWMIN3: For AC_BK.
+ */
+#define CWMIN_CSR                      0x3424
+#define CWMIN_CSR_CWMIN0               FIELD32(0x0000000f)
+#define CWMIN_CSR_CWMIN1               FIELD32(0x000000f0)
+#define CWMIN_CSR_CWMIN2               FIELD32(0x00000f00)
+#define CWMIN_CSR_CWMIN3               FIELD32(0x0000f000)
+
+/*
+ * CWMAX_CSR: CWmax for each EDCA AC.
+ * CWMAX0: For AC_VO.
+ * CWMAX1: For AC_VI.
+ * CWMAX2: For AC_BE.
+ * CWMAX3: For AC_BK.
+ */
+#define CWMAX_CSR                      0x3428
+#define CWMAX_CSR_CWMAX0               FIELD32(0x0000000f)
+#define CWMAX_CSR_CWMAX1               FIELD32(0x000000f0)
+#define CWMAX_CSR_CWMAX2               FIELD32(0x00000f00)
+#define CWMAX_CSR_CWMAX3               FIELD32(0x0000f000)
+
+/*
+ * TX_DMA_DST_CSR: TX DMA destination
+ * 0: TX ring0, 1: TX ring1, 2: TX ring2 3: invalid
+ */
+#define TX_DMA_DST_CSR                 0x342c
+#define TX_DMA_DST_CSR_DEST_AC0                FIELD32(0x00000003)
+#define TX_DMA_DST_CSR_DEST_AC1                FIELD32(0x0000000c)
+#define TX_DMA_DST_CSR_DEST_AC2                FIELD32(0x00000030)
+#define TX_DMA_DST_CSR_DEST_AC3                FIELD32(0x000000c0)
+#define TX_DMA_DST_CSR_DEST_MGMT       FIELD32(0x00000300)
+
+/*
+ * TX_CNTL_CSR: KICK/Abort TX.
+ * KICK_TX_AC0: For AC_VO.
+ * KICK_TX_AC1: For AC_VI.
+ * KICK_TX_AC2: For AC_BE.
+ * KICK_TX_AC3: For AC_BK.
+ * ABORT_TX_AC0: For AC_VO.
+ * ABORT_TX_AC1: For AC_VI.
+ * ABORT_TX_AC2: For AC_BE.
+ * ABORT_TX_AC3: For AC_BK.
+ */
+#define TX_CNTL_CSR                    0x3430
+#define TX_CNTL_CSR_KICK_TX_AC0                FIELD32(0x00000001)
+#define TX_CNTL_CSR_KICK_TX_AC1                FIELD32(0x00000002)
+#define TX_CNTL_CSR_KICK_TX_AC2                FIELD32(0x00000004)
+#define TX_CNTL_CSR_KICK_TX_AC3                FIELD32(0x00000008)
+#define TX_CNTL_CSR_KICK_TX_MGMT       FIELD32(0x00000010)
+#define TX_CNTL_CSR_ABORT_TX_AC0       FIELD32(0x00010000)
+#define TX_CNTL_CSR_ABORT_TX_AC1       FIELD32(0x00020000)
+#define TX_CNTL_CSR_ABORT_TX_AC2       FIELD32(0x00040000)
+#define TX_CNTL_CSR_ABORT_TX_AC3       FIELD32(0x00080000)
+#define TX_CNTL_CSR_ABORT_TX_MGMT      FIELD32(0x00100000)
+
+/*
+ * LOAD_TX_RING_CSR: Load RX desriptor
+ */
+#define LOAD_TX_RING_CSR               0x3434
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC0  FIELD32(0x00000001)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC1  FIELD32(0x00000002)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC2  FIELD32(0x00000004)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC3  FIELD32(0x00000008)
+#define LOAD_TX_RING_CSR_LOAD_TXD_MGMT FIELD32(0x00000010)
+
+/*
+ * Several read-only registers, for debugging.
+ */
+#define AC0_TXPTR_CSR                  0x3438
+#define AC1_TXPTR_CSR                  0x343c
+#define AC2_TXPTR_CSR                  0x3440
+#define AC3_TXPTR_CSR                  0x3444
+#define MGMT_TXPTR_CSR                 0x3448
+
+/*
+ * RX_BASE_CSR
+ */
+#define RX_BASE_CSR                    0x3450
+#define RX_BASE_CSR_RING_REGISTER      FIELD32(0xffffffff)
+
+/*
+ * RX_RING_CSR.
+ * RXD_SIZE: In unit of 32-bit.
+ */
+#define RX_RING_CSR                    0x3454
+#define RX_RING_CSR_RING_SIZE          FIELD32(0x000000ff)
+#define RX_RING_CSR_RXD_SIZE           FIELD32(0x00003f00)
+#define RX_RING_CSR_RXD_WRITEBACK_SIZE FIELD32(0x00070000)
+
+/*
+ * RX_CNTL_CSR
+ */
+#define RX_CNTL_CSR                    0x3458
+#define RX_CNTL_CSR_ENABLE_RX_DMA      FIELD32(0x00000001)
+#define RX_CNTL_CSR_LOAD_RXD           FIELD32(0x00000002)
+
+/*
+ * RXPTR_CSR: Read-only, for debugging.
+ */
+#define RXPTR_CSR                      0x345c
+
+/*
+ * PCI_CFG_CSR
+ */
+#define PCI_CFG_CSR                    0x3460
+
+/*
+ * BUF_FORMAT_CSR
+ */
+#define BUF_FORMAT_CSR                 0x3464
+
+/*
+ * INT_SOURCE_CSR: Interrupt source register.
+ * Write one to clear corresponding bit.
+ */
+#define INT_SOURCE_CSR                 0x3468
+#define INT_SOURCE_CSR_TXDONE          FIELD32(0x00000001)
+#define INT_SOURCE_CSR_RXDONE          FIELD32(0x00000002)
+#define INT_SOURCE_CSR_BEACON_DONE     FIELD32(0x00000004)
+#define INT_SOURCE_CSR_TX_ABORT_DONE   FIELD32(0x00000010)
+#define INT_SOURCE_CSR_AC0_DMA_DONE    FIELD32(0x00010000)
+#define INT_SOURCE_CSR_AC1_DMA_DONE    FIELD32(0x00020000)
+#define INT_SOURCE_CSR_AC2_DMA_DONE    FIELD32(0x00040000)
+#define INT_SOURCE_CSR_AC3_DMA_DONE    FIELD32(0x00080000)
+#define INT_SOURCE_CSR_MGMT_DMA_DONE   FIELD32(0x00100000)
+#define INT_SOURCE_CSR_HCCA_DMA_DONE   FIELD32(0x00200000)
+
+/*
+ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
+ * MITIGATION_PERIOD: Interrupt mitigation in unit of 32 PCI clock.
+ */
+#define INT_MASK_CSR                   0x346c
+#define INT_MASK_CSR_TXDONE            FIELD32(0x00000001)
+#define INT_MASK_CSR_RXDONE            FIELD32(0x00000002)
+#define INT_MASK_CSR_BEACON_DONE       FIELD32(0x00000004)
+#define INT_MASK_CSR_TX_ABORT_DONE     FIELD32(0x00000010)
+#define INT_MASK_CSR_ENABLE_MITIGATION FIELD32(0x00000080)
+#define INT_MASK_CSR_MITIGATION_PERIOD FIELD32(0x0000ff00)
+#define INT_MASK_CSR_AC0_DMA_DONE      FIELD32(0x00010000)
+#define INT_MASK_CSR_AC1_DMA_DONE      FIELD32(0x00020000)
+#define INT_MASK_CSR_AC2_DMA_DONE      FIELD32(0x00040000)
+#define INT_MASK_CSR_AC3_DMA_DONE      FIELD32(0x00080000)
+#define INT_MASK_CSR_MGMT_DMA_DONE     FIELD32(0x00100000)
+#define INT_MASK_CSR_HCCA_DMA_DONE     FIELD32(0x00200000)
+
+/*
+ * E2PROM_CSR: EEPROM control register.
+ * RELOAD: Write 1 to reload eeprom content.
+ * TYPE_93C46: 1: 93c46, 0:93c66.
+ * LOAD_STATUS: 1:loading, 0:done.
+ */
+#define E2PROM_CSR                     0x3470
+#define E2PROM_CSR_RELOAD              FIELD32(0x00000001)
+#define E2PROM_CSR_DATA_CLOCK          FIELD32(0x00000002)
+#define E2PROM_CSR_CHIP_SELECT         FIELD32(0x00000004)
+#define E2PROM_CSR_DATA_IN             FIELD32(0x00000008)
+#define E2PROM_CSR_DATA_OUT            FIELD32(0x00000010)
+#define E2PROM_CSR_TYPE_93C46          FIELD32(0x00000020)
+#define E2PROM_CSR_LOAD_STATUS         FIELD32(0x00000040)
+
+/*
+ * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
+ * AC0_TX_OP: For AC_VO, in unit of 32us.
+ * AC1_TX_OP: For AC_VI, in unit of 32us.
+ */
+#define AC_TXOP_CSR0                   0x3474
+#define AC_TXOP_CSR0_AC0_TX_OP         FIELD32(0x0000ffff)
+#define AC_TXOP_CSR0_AC1_TX_OP         FIELD32(0xffff0000)
+
+/*
+ * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
+ * AC2_TX_OP: For AC_BE, in unit of 32us.
+ * AC3_TX_OP: For AC_BK, in unit of 32us.
+ */
+#define AC_TXOP_CSR1                   0x3478
+#define AC_TXOP_CSR1_AC2_TX_OP         FIELD32(0x0000ffff)
+#define AC_TXOP_CSR1_AC3_TX_OP         FIELD32(0xffff0000)
+
+/*
+ * DMA_STATUS_CSR
+ */
+#define DMA_STATUS_CSR                 0x3480
+
+/*
+ * TEST_MODE_CSR
+ */
+#define TEST_MODE_CSR                  0x3484
+
+/*
+ * UART0_TX_CSR
+ */
+#define UART0_TX_CSR                   0x3488
+
+/*
+ * UART0_RX_CSR
+ */
+#define UART0_RX_CSR                   0x348c
+
+/*
+ * UART0_FRAME_CSR
+ */
+#define UART0_FRAME_CSR                        0x3490
+
+/*
+ * UART0_BUFFER_CSR
+ */
+#define UART0_BUFFER_CSR               0x3494
+
+/*
+ * IO_CNTL_CSR
+ * RF_PS: Set RF interface value to power save
+ */
+#define IO_CNTL_CSR                    0x3498
+#define IO_CNTL_CSR_RF_PS              FIELD32(0x00000004)
+
+/*
+ * UART_INT_SOURCE_CSR
+ */
+#define UART_INT_SOURCE_CSR            0x34a8
+
+/*
+ * UART_INT_MASK_CSR
+ */
+#define UART_INT_MASK_CSR              0x34ac
+
+/*
+ * PBF_QUEUE_CSR
+ */
+#define PBF_QUEUE_CSR                  0x34b0
+
+/*
+ * Firmware DMA registers.
+ * Firmware DMA registers are dedicated for MCU usage
+ * and should not be touched by host driver.
+ * Therefore we skip the definition of these registers.
+ */
+#define FW_TX_BASE_CSR                 0x34c0
+#define FW_TX_START_CSR                        0x34c4
+#define FW_TX_LAST_CSR                 0x34c8
+#define FW_MODE_CNTL_CSR               0x34cc
+#define FW_TXPTR_CSR                   0x34d0
+
+/*
+ * 8051 firmware image.
+ */
+#define FIRMWARE_RT2561                        "rt2561.bin"
+#define FIRMWARE_RT2561s               "rt2561s.bin"
+#define FIRMWARE_RT2661                        "rt2661.bin"
+#define FIRMWARE_IMAGE_BASE            0x4000
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2
+ */
+#define BBP_R2_BG_MODE                 FIELD8(0x20)
+
+/*
+ * R3
+ */
+#define BBP_R3_SMART_MODE              FIELD8(0x01)
+
+/*
+ * R4: RX antenna control
+ * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
+ */
+
+/*
+ * ANTENNA_CONTROL semantics (guessed):
+ * 0x1: Software controlled antenna switching (fixed or SW diversity)
+ * 0x2: Hardware diversity.
+ */
+#define BBP_R4_RX_ANTENNA_CONTROL      FIELD8(0x03)
+#define BBP_R4_RX_FRAME_END            FIELD8(0x20)
+
+/*
+ * R77
+ */
+#define BBP_R77_RX_ANTENNA             FIELD8(0x03)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 3
+ */
+#define RF3_TXPOWER                    FIELD32(0x00003e00)
+
+/*
+ * RF 4
+ */
+#define RF4_FREQ_OFFSET                        FIELD32(0x0003f000)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0              0x0002
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1               0x0003
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2              0x0004
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM antenna.
+ * ANTENNA_NUM: Number of antenna's.
+ * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only.
+ * DYN_TXAGC: Dynamic TX AGC control.
+ * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
+ * RF_TYPE: Rf_type of this adapter.
+ */
+#define EEPROM_ANTENNA                 0x0010
+#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
+#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
+#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
+#define EEPROM_ANTENNA_FRAME_TYPE      FIELD16(0x0040)
+#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
+#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
+#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
+
+/*
+ * EEPROM NIC config.
+ * ENABLE_DIVERSITY: 1:enable, 0:disable.
+ * EXTERNAL_LNA_BG: External LNA enable for 2.4G.
+ * CARDBUS_ACCEL: 0:enable, 1:disable.
+ * EXTERNAL_LNA_A: External LNA enable for 5G.
+ */
+#define EEPROM_NIC                     0x0011
+#define EEPROM_NIC_ENABLE_DIVERSITY    FIELD16(0x0001)
+#define EEPROM_NIC_TX_DIVERSITY                FIELD16(0x0002)
+#define EEPROM_NIC_RX_FIXED            FIELD16(0x0004)
+#define EEPROM_NIC_TX_FIXED            FIELD16(0x0008)
+#define EEPROM_NIC_EXTERNAL_LNA_BG     FIELD16(0x0010)
+#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0020)
+#define EEPROM_NIC_EXTERNAL_LNA_A      FIELD16(0x0040)
+
+/*
+ * EEPROM geography.
+ * GEO_A: Default geographical setting for 5GHz band
+ * GEO: Default geographical setting.
+ */
+#define EEPROM_GEOGRAPHY               0x0012
+#define EEPROM_GEOGRAPHY_GEO_A         FIELD16(0x00ff)
+#define EEPROM_GEOGRAPHY_GEO           FIELD16(0xff00)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START               0x0013
+#define EEPROM_BBP_SIZE                        16
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER 802.11G
+ */
+#define EEPROM_TXPOWER_G_START         0x0023
+#define EEPROM_TXPOWER_G_SIZE          7
+#define EEPROM_TXPOWER_G_1             FIELD16(0x00ff)
+#define EEPROM_TXPOWER_G_2             FIELD16(0xff00)
+
+/*
+ * EEPROM Frequency
+ */
+#define EEPROM_FREQ                    0x002f
+#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
+#define EEPROM_FREQ_SEQ_MASK           FIELD16(0xff00)
+#define EEPROM_FREQ_SEQ                        FIELD16(0x0300)
+
+/*
+ * EEPROM LED.
+ * POLARITY_RDY_G: Polarity RDY_G setting.
+ * POLARITY_RDY_A: Polarity RDY_A setting.
+ * POLARITY_ACT: Polarity ACT setting.
+ * POLARITY_GPIO_0: Polarity GPIO0 setting.
+ * POLARITY_GPIO_1: Polarity GPIO1 setting.
+ * POLARITY_GPIO_2: Polarity GPIO2 setting.
+ * POLARITY_GPIO_3: Polarity GPIO3 setting.
+ * POLARITY_GPIO_4: Polarity GPIO4 setting.
+ * LED_MODE: Led mode.
+ */
+#define EEPROM_LED                     0x0030
+#define EEPROM_LED_POLARITY_RDY_G      FIELD16(0x0001)
+#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
+#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
+#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
+#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
+#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
+#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
+#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
+#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
+
+/*
+ * EEPROM TXPOWER 802.11A
+ */
+#define EEPROM_TXPOWER_A_START         0x0031
+#define EEPROM_TXPOWER_A_SIZE          12
+#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
+#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11BG
+ */
+#define EEPROM_RSSI_OFFSET_BG          0x004d
+#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11A
+ */
+#define EEPROM_RSSI_OFFSET_A           0x004e
+#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
+
+/*
+ * MCU mailbox commands.
+ */
+#define MCU_SLEEP                      0x30
+#define MCU_WAKEUP                     0x31
+#define MCU_LED                                0x50
+#define MCU_LED_STRENGTH               0x52
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  ( 16 * sizeof(__le32) )
+#define TXINFO_SIZE                    ( 6 * sizeof(__le32) )
+#define RXD_DESC_SIZE                  ( 16 * sizeof(__le32) )
+
+/*
+ * TX descriptor format for TX, PRIO and Beacon Ring.
+ */
+
+/*
+ * Word0
+ * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used.
+ * KEY_TABLE: Use per-client pairwise KEY table.
+ * KEY_INDEX:
+ * Key index (0~31) to the pairwise KEY table.
+ * 0~3 to shared KEY table 0 (BSS0).
+ * 4~7 to shared KEY table 1 (BSS1).
+ * 8~11 to shared KEY table 2 (BSS2).
+ * 12~15 to shared KEY table 3 (BSS3).
+ * BURST: Next frame belongs to same "burst" event.
+ */
+#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define TXD_W0_VALID                   FIELD32(0x00000002)
+#define TXD_W0_MORE_FRAG               FIELD32(0x00000004)
+#define TXD_W0_ACK                     FIELD32(0x00000008)
+#define TXD_W0_TIMESTAMP               FIELD32(0x00000010)
+#define TXD_W0_OFDM                    FIELD32(0x00000020)
+#define TXD_W0_IFS                     FIELD32(0x00000040)
+#define TXD_W0_RETRY_MODE              FIELD32(0x00000080)
+#define TXD_W0_TKIP_MIC                        FIELD32(0x00000100)
+#define TXD_W0_KEY_TABLE               FIELD32(0x00000200)
+#define TXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
+#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define TXD_W0_BURST                   FIELD32(0x10000000)
+#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * Word1
+ * HOST_Q_ID: EDCA/HCCA queue ID.
+ * HW_SEQUENCE: MAC overwrites the frame sequence number.
+ * BUFFER_COUNT: Number of buffers in this TXD.
+ */
+#define TXD_W1_HOST_Q_ID               FIELD32(0x0000000f)
+#define TXD_W1_AIFSN                   FIELD32(0x000000f0)
+#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
+#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
+#define TXD_W1_IV_OFFSET               FIELD32(0x003f0000)
+#define TXD_W1_PIGGY_BACK              FIELD32(0x01000000)
+#define TXD_W1_HW_SEQUENCE             FIELD32(0x10000000)
+#define TXD_W1_BUFFER_COUNT            FIELD32(0xe0000000)
+
+/*
+ * Word2: PLCP information
+ */
+#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
+#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
+#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
+#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
+
+/*
+ * Word3
+ */
+#define TXD_W3_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word4
+ */
+#define TXD_W4_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word5
+ * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field).
+ * TXD_W5_PID_SUBTYPE: Driver assigned packet ID index for txdone handler.
+ * TXD_W5_PID_TYPE: Driver assigned packet ID type for txdone handler.
+ * WAITING_DMA_DONE_INT: TXD been filled with data
+ * and waiting for TxDoneISR housekeeping.
+ */
+#define TXD_W5_FRAME_OFFSET            FIELD32(0x000000ff)
+#define TXD_W5_PID_SUBTYPE             FIELD32(0x00001f00)
+#define TXD_W5_PID_TYPE                        FIELD32(0x0000e000)
+#define TXD_W5_TX_POWER                        FIELD32(0x00ff0000)
+#define TXD_W5_WAITING_DMA_DONE_INT    FIELD32(0x01000000)
+
+/*
+ * the above 24-byte is called TXINFO and will be DMAed to MAC block
+ * through TXFIFO. MAC block use this TXINFO to control the transmission
+ * behavior of this frame.
+ * The following fields are not used by MAC block.
+ * They are used by DMA block and HOST driver only.
+ * Once a frame has been DMA to ASIC, all the following fields are useless
+ * to ASIC.
+ */
+
+/*
+ * Word6-10: Buffer physical address
+ */
+#define TXD_W6_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
+#define TXD_W7_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
+#define TXD_W8_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
+#define TXD_W9_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
+#define TXD_W10_BUFFER_PHYSICAL_ADDRESS        FIELD32(0xffffffff)
+
+/*
+ * Word11-13: Buffer length
+ */
+#define TXD_W11_BUFFER_LENGTH0         FIELD32(0x00000fff)
+#define TXD_W11_BUFFER_LENGTH1         FIELD32(0x0fff0000)
+#define TXD_W12_BUFFER_LENGTH2         FIELD32(0x00000fff)
+#define TXD_W12_BUFFER_LENGTH3         FIELD32(0x0fff0000)
+#define TXD_W13_BUFFER_LENGTH4         FIELD32(0x00000fff)
+
+/*
+ * Word14
+ */
+#define TXD_W14_SK_BUFFER              FIELD32(0xffffffff)
+
+/*
+ * Word15
+ */
+#define TXD_W15_NEXT_SK_BUFFER         FIELD32(0xffffffff)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key.
+ * KEY_INDEX: Decryption key actually used.
+ */
+#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define RXD_W0_DROP                    FIELD32(0x00000002)
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000004)
+#define RXD_W0_MULTICAST               FIELD32(0x00000008)
+#define RXD_W0_BROADCAST               FIELD32(0x00000010)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000020)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000040)
+#define RXD_W0_OFDM                    FIELD32(0x00000080)
+#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000300)
+#define RXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
+#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * Word1
+ * SIGNAL: RX raw data rate reported by BBP.
+ */
+#define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
+#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
+#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
+#define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
+
+/*
+ * Word2
+ * IV: Received IV of originally encrypted.
+ */
+#define RXD_W2_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * EIV: Received EIV of originally encrypted.
+ */
+#define RXD_W3_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
+ */
+#define RXD_W4_ICV                     FIELD32(0xffffffff)
+
+/*
+ * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
+ * and passed to the HOST driver.
+ * The following fields are for DMA block and HOST usage only.
+ * Can't be touched by ASIC MAC block.
+ */
+
+/*
+ * Word5
+ */
+#define RXD_W5_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
+
+/*
+ * Word6-15: Reserved
+ */
+#define RXD_W6_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W7_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W8_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W9_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W10_RESERVED               FIELD32(0xffffffff)
+#define RXD_W11_RESERVED               FIELD32(0xffffffff)
+#define RXD_W12_RESERVED               FIELD32(0xffffffff)
+#define RXD_W13_RESERVED               FIELD32(0xffffffff)
+#define RXD_W14_RESERVED               FIELD32(0xffffffff)
+#define RXD_W15_RESERVED               FIELD32(0xffffffff)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_TXPOWER    0
+#define MAX_TXPOWER    31
+#define DEFAULT_TXPOWER        24
+
+#define TXPOWER_FROM_DEV(__txpower) \
+       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
+
+#endif /* RT61PCI_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
new file mode 100644 (file)
index 0000000..7081e13
--- /dev/null
@@ -0,0 +1,2548 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt73usb
+       Abstract: rt73usb device specific routines.
+       Supported chipsets: rt2571W & rt2671.
+ */
+
+#include <linux/crc-itu-t.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "rt2x00.h"
+#include "rt2x00usb.h"
+#include "rt73usb.h"
+
+/*
+ * Allow hardware encryption to be disabled.
+ */
+static bool modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2x00usb_register_read and rt2x00usb_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ * The _lock versions must be used if you already hold the csr_mutex
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+       rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+       rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+
+static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int word, const u8 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
+               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
+
+               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word, u8 *value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the read request into the register.
+        * After the data has been written, we wait until hardware
+        * returns the correct value, if at any time the register
+        * doesn't become available in time, reg will be 0xffffffff
+        * which means we return 0xff to the caller.
+        */
+       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
+
+               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
+
+       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
+                            const unsigned int word, const u32 value)
+{
+       u32 reg;
+
+       mutex_lock(&rt2x00dev->csr_mutex);
+
+       /*
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
+        */
+       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+               reg = 0;
+               rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+               /*
+                * RF5225 and RF2527 contain 21 bits per RF register value,
+                * all others contain 20 bits.
+                */
+               rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
+                                  20 + (rt2x00_rf(rt2x00dev, RF5225) ||
+                                        rt2x00_rf(rt2x00dev, RF2527)));
+               rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
+               rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
+
+               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
+               rt2x00_rf_write(rt2x00dev, word, value);
+       }
+
+       mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+static const struct rt2x00debug rt73usb_rt2x00debug = {
+       .owner  = THIS_MODULE,
+       .csr    = {
+               .read           = rt2x00usb_register_read,
+               .write          = rt2x00usb_register_write,
+               .flags          = RT2X00DEBUGFS_OFFSET,
+               .word_base      = CSR_REG_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = CSR_REG_SIZE / sizeof(u32),
+       },
+       .eeprom = {
+               .read           = rt2x00_eeprom_read,
+               .write          = rt2x00_eeprom_write,
+               .word_base      = EEPROM_BASE,
+               .word_size      = sizeof(u16),
+               .word_count     = EEPROM_SIZE / sizeof(u16),
+       },
+       .bbp    = {
+               .read           = rt73usb_bbp_read,
+               .write          = rt73usb_bbp_write,
+               .word_base      = BBP_BASE,
+               .word_size      = sizeof(u8),
+               .word_count     = BBP_SIZE / sizeof(u8),
+       },
+       .rf     = {
+               .read           = rt2x00_rf_read,
+               .write          = rt73usb_rf_write,
+               .word_base      = RF_BASE,
+               .word_size      = sizeof(u32),
+               .word_count     = RF_SIZE / sizeof(u32),
+       },
+};
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt73usb_brightness_set(struct led_classdev *led_cdev,
+                                  enum led_brightness brightness)
+{
+       struct rt2x00_led *led =
+          container_of(led_cdev, struct rt2x00_led, led_dev);
+       unsigned int enabled = brightness != LED_OFF;
+       unsigned int a_mode =
+           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
+       unsigned int bg_mode =
+           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+
+       if (led->type == LED_TYPE_RADIO) {
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_RADIO_STATUS, enabled);
+
+               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+                                           0, led->rt2x00dev->led_mcu_reg,
+                                           REGISTER_TIMEOUT);
+       } else if (led->type == LED_TYPE_ASSOC) {
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_LINK_BG_STATUS, bg_mode);
+               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
+                                  MCU_LEDCS_LINK_A_STATUS, a_mode);
+
+               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+                                           0, led->rt2x00dev->led_mcu_reg,
+                                           REGISTER_TIMEOUT);
+       } else if (led->type == LED_TYPE_QUALITY) {
+               /*
+                * The brightness is divided into 6 levels (0 - 5),
+                * this means we need to convert the brightness
+                * argument into the matching level within that range.
+                */
+               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
+                                           brightness / (LED_FULL / 6),
+                                           led->rt2x00dev->led_mcu_reg,
+                                           REGISTER_TIMEOUT);
+       }
+}
+
+static int rt73usb_blink_set(struct led_classdev *led_cdev,
+                            unsigned long *delay_on,
+                            unsigned long *delay_off)
+{
+       struct rt2x00_led *led =
+           container_of(led_cdev, struct rt2x00_led, led_dev);
+       u32 reg;
+
+       rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
+       rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
+       rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
+
+       return 0;
+}
+
+static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
+                            struct rt2x00_led *led,
+                            enum led_type type)
+{
+       led->rt2x00dev = rt2x00dev;
+       led->type = type;
+       led->led_dev.brightness_set = rt73usb_brightness_set;
+       led->led_dev.blink_set = rt73usb_blink_set;
+       led->flags = LED_INITIALIZED;
+}
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
+                                    struct rt2x00lib_crypto *crypto,
+                                    struct ieee80211_key_conf *key)
+{
+       struct hw_key_entry key_entry;
+       struct rt2x00_field32 field;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for shared keys. We have 1 register
+                * with key valid bits. The goal is simple, read
+                * the register, if that is full we have no slots
+                * left.
+                * Note that each BSS is allowed to have up to 4
+                * shared keys, so put a mask over the allowed
+                * entries.
+                */
+               mask = (0xf << crypto->bssidx);
+
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+               reg &= mask;
+
+               if (reg && reg == mask)
+                       return -ENOSPC;
+
+               key->hw_key_idx += reg ? ffz(reg) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               reg = SHARED_KEY_ENTRY(key->hw_key_idx);
+               rt2x00usb_register_multiwrite(rt2x00dev, reg,
+                                             &key_entry, sizeof(key_entry));
+
+               /*
+                * The cipher types are stored over 2 registers.
+                * bssidx 0 and 1 keys are stored in SEC_CSR1 and
+                * bssidx 1 and 2 keys are stored in SEC_CSR5.
+                * Using the correct defines correctly will cause overhead,
+                * so just calculate the correct offset.
+                */
+               if (key->hw_key_idx < 8) {
+                       field.bit_offset = (3 * key->hw_key_idx);
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
+               } else {
+                       field.bit_offset = (3 * (key->hw_key_idx - 8));
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
+               }
+
+               /*
+                * The driver does not support the IV/EIV generation
+                * in hardware. However it doesn't support the IV/EIV
+                * inside the ieee80211 frame either, but requires it
+                * to be provided separately for the descriptor.
+                * rt2x00lib will cut the IV/EIV data out of all frames
+                * given to us by mac80211, but we must tell mac80211
+                * to generate the IV/EIV data.
+                */
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       }
+
+       /*
+        * SEC_CSR0 contains only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead we use
+        * a calculation to determine the correct bit directly.
+        */
+       mask = 1 << key->hw_key_idx;
+
+       rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+       if (crypto->cmd == SET_KEY)
+               reg |= mask;
+       else if (crypto->cmd == DISABLE_KEY)
+               reg &= ~mask;
+       rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
+
+       return 0;
+}
+
+static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+                                      struct rt2x00lib_crypto *crypto,
+                                      struct ieee80211_key_conf *key)
+{
+       struct hw_pairwise_ta_entry addr_entry;
+       struct hw_key_entry key_entry;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for pairwise keys. We have 2 registers
+                * with key valid bits. The goal is simple, read
+                * the first register, if that is full move to
+                * the next register.
+                * When both registers are full, we drop the key,
+                * otherwise we use the first invalid entry.
+                */
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (reg && reg == ~0) {
+                       key->hw_key_idx = 32;
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       if (reg && reg == ~0)
+                               return -ENOSPC;
+               }
+
+               key->hw_key_idx += reg ? ffz(reg) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+               rt2x00usb_register_multiwrite(rt2x00dev, reg,
+                                             &key_entry, sizeof(key_entry));
+
+               /*
+                * Send the address and cipher type to the hardware register.
+                */
+               memset(&addr_entry, 0, sizeof(addr_entry));
+               memcpy(&addr_entry, crypto->address, ETH_ALEN);
+               addr_entry.cipher = crypto->cipher;
+
+               reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
+               rt2x00usb_register_multiwrite(rt2x00dev, reg,
+                                           &addr_entry, sizeof(addr_entry));
+
+               /*
+                * Enable pairwise lookup table for given BSS idx,
+                * without this received frames will not be decrypted
+                * by the hardware.
+                */
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+               reg |= (1 << crypto->bssidx);
+               rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
+
+               /*
+                * The driver does not support the IV/EIV generation
+                * in hardware. However it doesn't support the IV/EIV
+                * inside the ieee80211 frame either, but requires it
+                * to be provided separately for the descriptor.
+                * rt2x00lib will cut the IV/EIV data out of all frames
+                * given to us by mac80211, but we must tell mac80211
+                * to generate the IV/EIV data.
+                */
+               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+       }
+
+       /*
+        * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead we use
+        * a calculation to determine the correct bit directly.
+        */
+       if (key->hw_key_idx < 32) {
+               mask = 1 << key->hw_key_idx;
+
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
+       } else {
+               mask = 1 << (key->hw_key_idx - 32);
+
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
+       }
+
+       return 0;
+}
+
+static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
+                                 const unsigned int filter_flags)
+{
+       u32 reg;
+
+       /*
+        * Start configuration steps.
+        * Note that the version error will always be dropped
+        * and broadcast frames will always be accepted since
+        * there is no filter for it at this time.
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
+                          !(filter_flags & FIF_FCSFAIL));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
+                          !(filter_flags & FIF_PLCPFAIL));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
+                          !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
+                          !rt2x00dev->intf_ap_count);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
+                          !(filter_flags & FIF_ALLMULTI));
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
+                          !(filter_flags & FIF_CONTROL));
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+}
+
+static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00_intf *intf,
+                               struct rt2x00intf_conf *conf,
+                               const unsigned int flags)
+{
+       u32 reg;
+
+       if (flags & CONFIG_UPDATE_TYPE) {
+               /*
+                * Enable synchronisation.
+                */
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+       }
+
+       if (flags & CONFIG_UPDATE_MAC) {
+               reg = le32_to_cpu(conf->mac[1]);
+               rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
+               conf->mac[1] = cpu_to_le32(reg);
+
+               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
+                                           conf->mac, sizeof(conf->mac));
+       }
+
+       if (flags & CONFIG_UPDATE_BSSID) {
+               reg = le32_to_cpu(conf->bssid[1]);
+               rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
+               conf->bssid[1] = cpu_to_le32(reg);
+
+               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
+                                           conf->bssid, sizeof(conf->bssid));
+       }
+}
+
+static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
+                              struct rt2x00lib_erp *erp,
+                              u32 changed)
+{
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
+                                  !!erp->short_preamble);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+       }
+
+       if (changed & BSS_CHANGED_BASIC_RATES)
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
+                                        erp->basic_rates);
+
+       if (changed & BSS_CHANGED_BEACON_INT) {
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+                                  erp->beacon_int * 16);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+       }
+
+       if (changed & BSS_CHANGED_ERP_SLOT) {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
+
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+               rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+               rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
+       }
+}
+
+static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
+                                     struct antenna_setup *ant)
+{
+       u8 r3;
+       u8 r4;
+       u8 r77;
+       u8 temp;
+
+       rt73usb_bbp_read(rt2x00dev, 3, &r3);
+       rt73usb_bbp_read(rt2x00dev, 4, &r4);
+       rt73usb_bbp_read(rt2x00dev, 77, &r77);
+
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+               temp = !rt2x00_has_cap_frame_type(rt2x00dev) &&
+                      (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               else
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               else
+                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               break;
+       }
+
+       rt73usb_bbp_write(rt2x00dev, 77, r77);
+       rt73usb_bbp_write(rt2x00dev, 3, r3);
+       rt73usb_bbp_write(rt2x00dev, 4, r4);
+}
+
+static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
+                                     struct antenna_setup *ant)
+{
+       u8 r3;
+       u8 r4;
+       u8 r77;
+
+       rt73usb_bbp_read(rt2x00dev, 3, &r3);
+       rt73usb_bbp_read(rt2x00dev, 4, &r4);
+       rt73usb_bbp_read(rt2x00dev, 77, &r77);
+
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
+       rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
+                         !rt2x00_has_cap_frame_type(rt2x00dev));
+
+       /*
+        * Configure the RX antenna.
+        */
+       switch (ant->rx) {
+       case ANTENNA_HW_DIVERSITY:
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+               break;
+       case ANTENNA_A:
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               break;
+       case ANTENNA_B:
+       default:
+               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+               break;
+       }
+
+       rt73usb_bbp_write(rt2x00dev, 77, r77);
+       rt73usb_bbp_write(rt2x00dev, 3, r3);
+       rt73usb_bbp_write(rt2x00dev, 4, r4);
+}
+
+struct antenna_sel {
+       u8 word;
+       /*
+        * value[0] -> non-LNA
+        * value[1] -> LNA
+        */
+       u8 value[2];
+};
+
+static const struct antenna_sel antenna_sel_a[] = {
+       { 96,  { 0x58, 0x78 } },
+       { 104, { 0x38, 0x48 } },
+       { 75,  { 0xfe, 0x80 } },
+       { 86,  { 0xfe, 0x80 } },
+       { 88,  { 0xfe, 0x80 } },
+       { 35,  { 0x60, 0x60 } },
+       { 97,  { 0x58, 0x58 } },
+       { 98,  { 0x58, 0x58 } },
+};
+
+static const struct antenna_sel antenna_sel_bg[] = {
+       { 96,  { 0x48, 0x68 } },
+       { 104, { 0x2c, 0x3c } },
+       { 75,  { 0xfe, 0x80 } },
+       { 86,  { 0xfe, 0x80 } },
+       { 88,  { 0xfe, 0x80 } },
+       { 35,  { 0x50, 0x50 } },
+       { 97,  { 0x48, 0x48 } },
+       { 98,  { 0x48, 0x48 } },
+};
+
+static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
+                              struct antenna_setup *ant)
+{
+       const struct antenna_sel *sel;
+       unsigned int lna;
+       unsigned int i;
+       u32 reg;
+
+       /*
+        * We should never come here because rt2x00lib is supposed
+        * to catch this and send us the correct antenna explicitely.
+        */
+       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+              ant->tx == ANTENNA_SW_DIVERSITY);
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               sel = antenna_sel_a;
+               lna = rt2x00_has_cap_external_lna_a(rt2x00dev);
+       } else {
+               sel = antenna_sel_bg;
+               lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
+               rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
+
+       rt2x00usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+
+       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+                          (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
+       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+                          (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
+
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
+
+       if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
+               rt73usb_config_antenna_5x(rt2x00dev, ant);
+       else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
+               rt73usb_config_antenna_2x(rt2x00dev, ant);
+}
+
+static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+                                   struct rt2x00lib_conf *libconf)
+{
+       u16 eeprom;
+       short lna_gain = 0;
+
+       if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
+               if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
+                       lna_gain += 14;
+
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+       } else {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+       }
+
+       rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
+                                  struct rf_channel *rf, const int txpower)
+{
+       u8 r3;
+       u8 r94;
+       u8 smart;
+
+       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+       smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
+
+       rt73usb_bbp_read(rt2x00dev, 3, &r3);
+       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+       rt73usb_bbp_write(rt2x00dev, 3, r3);
+
+       r94 = 6;
+       if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+               r94 += txpower - MAX_TXPOWER;
+       else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+               r94 += txpower;
+       rt73usb_bbp_write(rt2x00dev, 94, r94);
+
+       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+       udelay(10);
+}
+
+static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+                                  const int txpower)
+{
+       struct rf_channel rf;
+
+       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+       rt73usb_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+                                      struct rt2x00lib_conf *libconf)
+{
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+                          libconf->conf->long_frame_max_tx_count);
+       rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+                          libconf->conf->short_frame_max_tx_count);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
+
+static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
+                               struct rt2x00lib_conf *libconf)
+{
+       enum dev_state state =
+           (libconf->conf->flags & IEEE80211_CONF_PS) ?
+               STATE_SLEEP : STATE_AWAKE;
+       u32 reg;
+
+       if (state == STATE_SLEEP) {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
+                                  rt2x00dev->beacon_int - 10);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
+                                  libconf->conf->listen_interval - 1);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
+
+               /* We must first disable autowake before it can be enabled */
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_SLEEP, REGISTER_TIMEOUT);
+       } else {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
+               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
+               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
+
+               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
+       }
+}
+
+static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
+                          struct rt2x00lib_conf *libconf,
+                          const unsigned int flags)
+{
+       /* Always recalculate LNA gain before changing configuration */
+       rt73usb_config_lna_gain(rt2x00dev, libconf);
+
+       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+               rt73usb_config_channel(rt2x00dev, &libconf->rf,
+                                      libconf->conf->power_level);
+       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
+               rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt73usb_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt73usb_config_ps(rt2x00dev, libconf);
+}
+
+/*
+ * Link tuning
+ */
+static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual)
+{
+       u32 reg;
+
+       /*
+        * Update FCS error count from register.
+        */
+       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+
+       /*
+        * Update False CCA count from register.
+        */
+       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
+       qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
+}
+
+static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev,
+                                  struct link_qual *qual, u8 vgc_level)
+{
+       if (qual->vgc_level != vgc_level) {
+               rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
+               qual->vgc_level = vgc_level;
+               qual->vgc_level_reg = vgc_level;
+       }
+}
+
+static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                               struct link_qual *qual)
+{
+       rt73usb_set_vgc(rt2x00dev, qual, 0x20);
+}
+
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
+{
+       u8 up_bound;
+       u8 low_bound;
+
+       /*
+        * Determine r17 bounds.
+        */
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               low_bound = 0x28;
+               up_bound = 0x48;
+
+               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
+                       low_bound += 0x10;
+                       up_bound += 0x10;
+               }
+       } else {
+               if (qual->rssi > -82) {
+                       low_bound = 0x1c;
+                       up_bound = 0x40;
+               } else if (qual->rssi > -84) {
+                       low_bound = 0x1c;
+                       up_bound = 0x20;
+               } else {
+                       low_bound = 0x1c;
+                       up_bound = 0x1c;
+               }
+
+               if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+                       low_bound += 0x14;
+                       up_bound += 0x10;
+               }
+       }
+
+       /*
+        * If we are not associated, we should go straight to the
+        * dynamic CCA tuning.
+        */
+       if (!rt2x00dev->intf_associated)
+               goto dynamic_cca_tune;
+
+       /*
+        * Special big-R17 for very short distance
+        */
+       if (qual->rssi > -35) {
+               rt73usb_set_vgc(rt2x00dev, qual, 0x60);
+               return;
+       }
+
+       /*
+        * Special big-R17 for short distance
+        */
+       if (qual->rssi >= -58) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
+               return;
+       }
+
+       /*
+        * Special big-R17 for middle-short distance
+        */
+       if (qual->rssi >= -66) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
+               return;
+       }
+
+       /*
+        * Special mid-R17 for middle distance
+        */
+       if (qual->rssi >= -74) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
+               return;
+       }
+
+       /*
+        * Special case: Change up_bound based on the rssi.
+        * Lower up_bound when rssi is weaker then -74 dBm.
+        */
+       up_bound -= 2 * (-74 - qual->rssi);
+       if (low_bound > up_bound)
+               up_bound = low_bound;
+
+       if (qual->vgc_level > up_bound) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
+               return;
+       }
+
+dynamic_cca_tune:
+
+       /*
+        * r17 does not yet exceed upper limit, continue and base
+        * the r17 tuning on the false CCA count.
+        */
+       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
+               rt73usb_set_vgc(rt2x00dev, qual,
+                               min_t(u8, qual->vgc_level + 4, up_bound));
+       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
+               rt73usb_set_vgc(rt2x00dev, qual,
+                               max_t(u8, qual->vgc_level - 4, low_bound));
+}
+
+/*
+ * Queue handlers.
+ */
+static void rt73usb_start_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+static void rt73usb_stop_queue(struct data_queue *queue)
+{
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+       u32 reg;
+
+       switch (queue->qid) {
+       case QID_RX:
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+               break;
+       case QID_BEACON:
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * Firmware functions
+ */
+static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+{
+       return FIRMWARE_RT2571;
+}
+
+static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev,
+                                 const u8 *data, const size_t len)
+{
+       u16 fw_crc;
+       u16 crc;
+
+       /*
+        * Only support 2kb firmware files.
+        */
+       if (len != 2048)
+               return FW_BAD_LENGTH;
+
+       /*
+        * The last 2 bytes in the firmware array are the crc checksum itself,
+        * this means that we should never pass those 2 bytes to the crc
+        * algorithm.
+        */
+       fw_crc = (data[len - 2] << 8 | data[len - 1]);
+
+       /*
+        * Use the crc itu-t algorithm.
+        */
+       crc = crc_itu_t(0, data, len - 2);
+       crc = crc_itu_t_byte(crc, 0);
+       crc = crc_itu_t_byte(crc, 0);
+
+       return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
+}
+
+static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
+                                const u8 *data, const size_t len)
+{
+       unsigned int i;
+       int status;
+       u32 reg;
+
+       /*
+        * Wait for stable hardware.
+        */
+       for (i = 0; i < 100; i++) {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+               if (reg)
+                       break;
+               msleep(1);
+       }
+
+       if (!reg) {
+               rt2x00_err(rt2x00dev, "Unstable hardware\n");
+               return -EBUSY;
+       }
+
+       /*
+        * Write firmware to device.
+        */
+       rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len);
+
+       /*
+        * Send firmware request to device to load firmware,
+        * we need to specify a long timeout time.
+        */
+       status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
+                                            0, USB_MODE_FIRMWARE,
+                                            REGISTER_TIMEOUT_FIRMWARE);
+       if (status < 0) {
+               rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
+               return status;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialization functions.
+ */
+static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
+       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+
+       /*
+        * CCK TXD BBP registers
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2, 11);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
+       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+
+       /*
+        * OFDM TXD BBP registers
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
+       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
+       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
+       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
+
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
+
+       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
+               return -EBUSY;
+
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
+
+       /*
+        * Invalidate all Shared Keys (SEC_CSR0),
+        * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
+        */
+       rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
+       rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
+       rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+
+       reg = 0x000023b0;
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
+               rt2x00_set_field32(&reg, PHY_CSR1_RF_RPI, 1);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
+
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
+
+       /*
+        * Clear all beacons
+        * For the Beacon base registers we only need to clear
+        * the first byte since that byte contains the VALID and OWNER
+        * bits which (when set to 0) will invalidate the entire beacon.
+        */
+       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+
+       /*
+        * We must clear the error counters.
+        * These registers are cleared on read,
+        * so we may pass a useless variable to store the value.
+        */
+       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
+       rt2x00usb_register_read(rt2x00dev, STA_CSR2, &reg);
+
+       /*
+        * Reset MAC and BBP registers.
+        */
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
+       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
+
+       return 0;
+}
+
+static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u8 value;
+
+       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+               rt73usb_bbp_read(rt2x00dev, 0, &value);
+               if ((value != 0xff) && (value != 0x00))
+                       return 0;
+               udelay(REGISTER_BUSY_DELAY);
+       }
+
+       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
+       return -EACCES;
+}
+
+static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+       unsigned int i;
+       u16 eeprom;
+       u8 reg_id;
+       u8 value;
+
+       if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev)))
+               return -EACCES;
+
+       rt73usb_bbp_write(rt2x00dev, 3, 0x80);
+       rt73usb_bbp_write(rt2x00dev, 15, 0x30);
+       rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
+       rt73usb_bbp_write(rt2x00dev, 22, 0x38);
+       rt73usb_bbp_write(rt2x00dev, 23, 0x06);
+       rt73usb_bbp_write(rt2x00dev, 24, 0xfe);
+       rt73usb_bbp_write(rt2x00dev, 25, 0x0a);
+       rt73usb_bbp_write(rt2x00dev, 26, 0x0d);
+       rt73usb_bbp_write(rt2x00dev, 32, 0x0b);
+       rt73usb_bbp_write(rt2x00dev, 34, 0x12);
+       rt73usb_bbp_write(rt2x00dev, 37, 0x07);
+       rt73usb_bbp_write(rt2x00dev, 39, 0xf8);
+       rt73usb_bbp_write(rt2x00dev, 41, 0x60);
+       rt73usb_bbp_write(rt2x00dev, 53, 0x10);
+       rt73usb_bbp_write(rt2x00dev, 54, 0x18);
+       rt73usb_bbp_write(rt2x00dev, 60, 0x10);
+       rt73usb_bbp_write(rt2x00dev, 61, 0x04);
+       rt73usb_bbp_write(rt2x00dev, 62, 0x04);
+       rt73usb_bbp_write(rt2x00dev, 75, 0xfe);
+       rt73usb_bbp_write(rt2x00dev, 86, 0xfe);
+       rt73usb_bbp_write(rt2x00dev, 88, 0xfe);
+       rt73usb_bbp_write(rt2x00dev, 90, 0x0f);
+       rt73usb_bbp_write(rt2x00dev, 99, 0x00);
+       rt73usb_bbp_write(rt2x00dev, 102, 0x16);
+       rt73usb_bbp_write(rt2x00dev, 107, 0x04);
+
+       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+               if (eeprom != 0xffff && eeprom != 0x0000) {
+                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+                       rt73usb_bbp_write(rt2x00dev, reg_id, value);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Device state switch handlers.
+ */
+static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       /*
+        * Initialize all registers.
+        */
+       if (unlikely(rt73usb_init_registers(rt2x00dev) ||
+                    rt73usb_init_bbp(rt2x00dev)))
+               return -EIO;
+
+       return 0;
+}
+
+static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+
+       /*
+        * Disable synchronisation.
+        */
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
+
+       rt2x00usb_disable_radio(rt2x00dev);
+}
+
+static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
+{
+       u32 reg, reg2;
+       unsigned int i;
+       char put_to_sleep;
+
+       put_to_sleep = (state != STATE_AWAKE);
+
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
+       rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
+
+       /*
+        * Device is not guaranteed to be in the requested state yet.
+        * We must wait until the register indicates that the
+        * device has entered the correct state.
+        */
+       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg2);
+               state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
+               if (state == !put_to_sleep)
+                       return 0;
+               rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
+               msleep(10);
+       }
+
+       return -EBUSY;
+}
+
+static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
+                                   enum dev_state state)
+{
+       int retval = 0;
+
+       switch (state) {
+       case STATE_RADIO_ON:
+               retval = rt73usb_enable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_OFF:
+               rt73usb_disable_radio(rt2x00dev);
+               break;
+       case STATE_RADIO_IRQ_ON:
+       case STATE_RADIO_IRQ_OFF:
+               /* No support, but no error either */
+               break;
+       case STATE_DEEP_SLEEP:
+       case STATE_SLEEP:
+       case STATE_STANDBY:
+       case STATE_AWAKE:
+               retval = rt73usb_set_state(rt2x00dev, state);
+               break;
+       default:
+               retval = -ENOTSUPP;
+               break;
+       }
+
+       if (unlikely(retval))
+               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+                          state, retval);
+
+       return retval;
+}
+
+/*
+ * TX descriptor initialization
+ */
+static void rt73usb_write_tx_desc(struct queue_entry *entry,
+                                 struct txentry_desc *txdesc)
+{
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *txd = (__le32 *) entry->skb->data;
+       u32 word;
+
+       /*
+        * Start writing the descriptor words.
+        */
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_BURST,
+                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
+       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
+                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_ACK,
+                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
+                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_OFDM,
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
+       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
+       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
+                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
+                          test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
+                          test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
+       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
+       rt2x00_set_field32(&word, TXD_W0_BURST2,
+                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
+       rt2x00_desc_write(txd, 0, word);
+
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
+       rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
+       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
+       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
+       rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
+                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
+       rt2x00_desc_write(txd, 1, word);
+
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+                          txdesc->u.plcp.length_low);
+       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+                          txdesc->u.plcp.length_high);
+       rt2x00_desc_write(txd, 2, word);
+
+       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
+       }
+
+       rt2x00_desc_read(txd, 5, &word);
+       rt2x00_set_field32(&word, TXD_W5_TX_POWER,
+                          TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
+       rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
+       rt2x00_desc_write(txd, 5, word);
+
+       /*
+        * Register descriptor details in skb frame descriptor.
+        */
+       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
+       skbdesc->desc = txd;
+       skbdesc->desc_len = TXD_DESC_SIZE;
+}
+
+/*
+ * TX data initialization
+ */
+static void rt73usb_write_beacon(struct queue_entry *entry,
+                                struct txentry_desc *txdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       unsigned int beacon_base;
+       unsigned int padding_len;
+       u32 orig_reg, reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       orig_reg = reg;
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Add space for the descriptor in front of the skb.
+        */
+       skb_push(entry->skb, TXD_DESC_SIZE);
+       memset(entry->skb->data, 0, TXD_DESC_SIZE);
+
+       /*
+        * Write the TX descriptor for the beacon.
+        */
+       rt73usb_write_tx_desc(entry, txdesc);
+
+       /*
+        * Dump beacon to userspace through debugfs.
+        */
+       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
+
+       /*
+        * Write entire beacon with descriptor and padding to register.
+        */
+       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
+       if (padding_len && skb_pad(entry->skb, padding_len)) {
+               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
+               /* skb freed by skb_pad() on failure */
+               entry->skb = NULL;
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+               return;
+       }
+
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
+                                     entry->skb->len + padding_len);
+
+       /*
+        * Enable beaconing again.
+        *
+        * For Wi-Fi faily generated beacons between participating stations.
+        * Set TBTT phase adaptive adjustment step to 8us (default 16us)
+        */
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Clean up the beacon skb.
+        */
+       dev_kfree_skb(entry->skb);
+       entry->skb = NULL;
+}
+
+static void rt73usb_clear_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       unsigned int beacon_base;
+       u32 orig_reg, reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
+       reg = orig_reg;
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Clear beacon.
+        */
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
+
+       /*
+        * Restore beaconing state.
+        */
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+}
+
+static int rt73usb_get_tx_data_len(struct queue_entry *entry)
+{
+       int length;
+
+       /*
+        * The length _must_ be a multiple of 4,
+        * but it must _not_ be a multiple of the USB packet size.
+        */
+       length = roundup(entry->skb->len, 4);
+       length += (4 * !(length % entry->queue->usb_maxpacket));
+
+       return length;
+}
+
+/*
+ * RX control handlers
+ */
+static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+{
+       u8 offset = rt2x00dev->lna_gain;
+       u8 lna;
+
+       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
+       switch (lna) {
+       case 3:
+               offset += 90;
+               break;
+       case 2:
+               offset += 74;
+               break;
+       case 1:
+               offset += 64;
+               break;
+       default:
+               return 0;
+       }
+
+       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
+               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
+                       if (lna == 3 || lna == 2)
+                               offset += 10;
+               } else {
+                       if (lna == 3)
+                               offset += 6;
+                       else if (lna == 2)
+                               offset += 8;
+               }
+       }
+
+       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+}
+
+static void rt73usb_fill_rxdone(struct queue_entry *entry,
+                               struct rxdone_entry_desc *rxdesc)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       __le32 *rxd = (__le32 *)entry->skb->data;
+       u32 word0;
+       u32 word1;
+
+       /*
+        * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
+        * frame data in rt2x00usb.
+        */
+       memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
+       rxd = (__le32 *)skbdesc->desc;
+
+       /*
+        * It is now safe to read the descriptor on all architectures.
+        */
+       rt2x00_desc_read(rxd, 0, &word0);
+       rt2x00_desc_read(rxd, 1, &word1);
+
+       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
+               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+
+       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+       rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
+
+       if (rxdesc->cipher != CIPHER_NONE) {
+               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
+               _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+               rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
+
+               /*
+                * Hardware has stripped IV/EIV data from 802.11 frame during
+                * decryption. It has provided the data separately but rt2x00lib
+                * should decide if it should be reinserted.
+                */
+               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+
+               /*
+                * The hardware has already checked the Michael Mic and has
+                * stripped it from the frame. Signal this to mac80211.
+                */
+               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+
+               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+                       rxdesc->flags |= RX_FLAG_DECRYPTED;
+               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+       }
+
+       /*
+        * Obtain the status about this packet.
+        * When frame was received with an OFDM bitrate,
+        * the signal is the PLCP value. If it was received with
+        * a CCK bitrate the signal is the rate in 100kbit/s.
+        */
+       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
+       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+
+       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
+               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
+       else
+               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
+       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
+               rxdesc->dev_flags |= RXDONE_MY_BSS;
+
+       /*
+        * Set skb pointers, and update frame information.
+        */
+       skb_pull(entry->skb, entry->queue->desc_size);
+       skb_trim(entry->skb, rxdesc->size);
+}
+
+/*
+ * Device probe functions.
+ */
+static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u16 word;
+       u8 *mac;
+       s8 value;
+
+       rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
+
+       /*
+        * Start validation of the data that has been read.
+        */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               eth_random_addr(mac);
+               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+                                  ANTENNA_B);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+                                  ANTENNA_B);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
+               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_ACT, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_0, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_1, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_2, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_3, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_4, 0);
+               rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
+                                  LED_MODE_DEFAULT);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+               rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+       }
+
+       return 0;
+}
+
+static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+       u32 reg;
+       u16 value;
+       u16 eeprom;
+
+       /*
+        * Read EEPROM word for configuration.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+       /*
+        * Identify RF chipset.
+        */
+       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+       rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
+                       value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
+
+       if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
+               rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
+               return -ENODEV;
+       }
+
+       if (!rt2x00_rf(rt2x00dev, RF5226) &&
+           !rt2x00_rf(rt2x00dev, RF2528) &&
+           !rt2x00_rf(rt2x00dev, RF5225) &&
+           !rt2x00_rf(rt2x00dev, RF2527)) {
+               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Identify default antenna configuration.
+        */
+       rt2x00dev->default_ant.tx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
+       rt2x00dev->default_ant.rx =
+           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
+
+       /*
+        * Read the Frame type.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
+               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
+
+       /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+
+       /*
+        * Read frequency offset.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
+
+       /*
+        * Read external LNA informations.
+        */
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+
+       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
+               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
+       }
+
+       /*
+        * Store led settings, for correct led behaviour.
+        */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
+
+       rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+       rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+       if (value == LED_MODE_SIGNAL_STRENGTH)
+               rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
+                                LED_TYPE_QUALITY);
+
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_0));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_1));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_2));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_3));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_GPIO_4));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
+                          rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_RDY_G));
+       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
+                          rt2x00_get_field16(eeprom,
+                                             EEPROM_LED_POLARITY_RDY_A));
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+       return 0;
+}
+
+/*
+ * RF value list for RF2528
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_bg_2528[] = {
+       { 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
+       { 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
+       { 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
+       { 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
+       { 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
+       { 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
+       { 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
+       { 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
+       { 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
+       { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
+       { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
+       { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
+       { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
+       { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
+};
+
+/*
+ * RF value list for RF5226
+ * Supports: 2.4 GHz & 5.2 GHz
+ */
+static const struct rf_channel rf_vals_5226[] = {
+       { 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
+       { 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
+       { 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
+       { 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
+       { 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
+       { 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
+       { 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
+       { 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
+       { 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
+       { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
+       { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
+       { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
+       { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
+       { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00002c0c, 0x0000099a, 0x00098255, 0x000fea23 },
+       { 40, 0x00002c0c, 0x000009a2, 0x00098255, 0x000fea03 },
+       { 44, 0x00002c0c, 0x000009a6, 0x00098255, 0x000fea0b },
+       { 48, 0x00002c0c, 0x000009aa, 0x00098255, 0x000fea13 },
+       { 52, 0x00002c0c, 0x000009ae, 0x00098255, 0x000fea1b },
+       { 56, 0x00002c0c, 0x000009b2, 0x00098255, 0x000fea23 },
+       { 60, 0x00002c0c, 0x000009ba, 0x00098255, 0x000fea03 },
+       { 64, 0x00002c0c, 0x000009be, 0x00098255, 0x000fea0b },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00002c0c, 0x00000a2a, 0x000b8255, 0x000fea03 },
+       { 104, 0x00002c0c, 0x00000a2e, 0x000b8255, 0x000fea0b },
+       { 108, 0x00002c0c, 0x00000a32, 0x000b8255, 0x000fea13 },
+       { 112, 0x00002c0c, 0x00000a36, 0x000b8255, 0x000fea1b },
+       { 116, 0x00002c0c, 0x00000a3a, 0x000b8255, 0x000fea23 },
+       { 120, 0x00002c0c, 0x00000a82, 0x000b8255, 0x000fea03 },
+       { 124, 0x00002c0c, 0x00000a86, 0x000b8255, 0x000fea0b },
+       { 128, 0x00002c0c, 0x00000a8a, 0x000b8255, 0x000fea13 },
+       { 132, 0x00002c0c, 0x00000a8e, 0x000b8255, 0x000fea1b },
+       { 136, 0x00002c0c, 0x00000a92, 0x000b8255, 0x000fea23 },
+
+       /* 802.11 UNII */
+       { 140, 0x00002c0c, 0x00000a9a, 0x000b8255, 0x000fea03 },
+       { 149, 0x00002c0c, 0x00000aa2, 0x000b8255, 0x000fea1f },
+       { 153, 0x00002c0c, 0x00000aa6, 0x000b8255, 0x000fea27 },
+       { 157, 0x00002c0c, 0x00000aae, 0x000b8255, 0x000fea07 },
+       { 161, 0x00002c0c, 0x00000ab2, 0x000b8255, 0x000fea0f },
+       { 165, 0x00002c0c, 0x00000ab6, 0x000b8255, 0x000fea17 },
+
+       /* MMAC(Japan)J52 ch 34,38,42,46 */
+       { 34, 0x00002c0c, 0x0008099a, 0x000da255, 0x000d3a0b },
+       { 38, 0x00002c0c, 0x0008099e, 0x000da255, 0x000d3a13 },
+       { 42, 0x00002c0c, 0x000809a2, 0x000da255, 0x000d3a1b },
+       { 46, 0x00002c0c, 0x000809a6, 0x000da255, 0x000d3a23 },
+};
+
+/*
+ * RF value list for RF5225 & RF2527
+ * Supports: 2.4 GHz & 5.2 GHz
+ */
+static const struct rf_channel rf_vals_5225_2527[] = {
+       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
+       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
+       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
+       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
+       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
+       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
+       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
+       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
+       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
+       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
+       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
+       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
+       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
+       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
+
+       /* 802.11 UNI / HyperLan 2 */
+       { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 },
+       { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 },
+       { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b },
+       { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 },
+       { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b },
+       { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 },
+       { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 },
+       { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b },
+
+       /* 802.11 HyperLan 2 */
+       { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 },
+       { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b },
+       { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 },
+       { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b },
+       { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 },
+       { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 },
+       { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b },
+       { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 },
+       { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b },
+       { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 },
+
+       /* 802.11 UNII */
+       { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 },
+       { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f },
+       { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 },
+       { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 },
+       { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f },
+       { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 },
+
+       /* MMAC(Japan)J52 ch 34,38,42,46 */
+       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b },
+       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 },
+       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b },
+       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 },
+};
+
+
+static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
+       struct channel_info *info;
+       char *tx_power;
+       unsigned int i;
+
+       /*
+        * Initialize all hw fields.
+        *
+        * Don't set IEEE80211_HOST_BROADCAST_PS_BUFFERING unless we are
+        * capable of sending the buffered frames out after the DTIM
+        * transmission using rt2x00lib_beacondone. This will send out
+        * multicast and broadcast traffic immediately instead of buffering it
+        * infinitly and thus dropping it after some time.
+        */
+       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
+       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
+       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+                               rt2x00_eeprom_addr(rt2x00dev,
+                                                  EEPROM_MAC_ADDR_0));
+
+       /*
+        * Initialize hw_mode information.
+        */
+       spec->supported_bands = SUPPORT_BAND_2GHZ;
+       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+       if (rt2x00_rf(rt2x00dev, RF2528)) {
+               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
+               spec->channels = rf_vals_bg_2528;
+       } else if (rt2x00_rf(rt2x00dev, RF5226)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_5226);
+               spec->channels = rf_vals_5226;
+       } else if (rt2x00_rf(rt2x00dev, RF2527)) {
+               spec->num_channels = 14;
+               spec->channels = rf_vals_5225_2527;
+       } else if (rt2x00_rf(rt2x00dev, RF5225)) {
+               spec->supported_bands |= SUPPORT_BAND_5GHZ;
+               spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
+               spec->channels = rf_vals_5225_2527;
+       }
+
+       /*
+        * Create channel information array
+        */
+       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
+       for (i = 0; i < 14; i++) {
+               info[i].max_power = MAX_TXPOWER;
+               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+       }
+
+       if (spec->num_channels > 14) {
+               tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
+               for (i = 14; i < spec->num_channels; i++) {
+                       info[i].max_power = MAX_TXPOWER;
+                       info[i].default_power1 =
+                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
+               }
+       }
+
+       return 0;
+}
+
+static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
+{
+       int retval;
+       u32 reg;
+
+       /*
+        * Allocate eeprom data.
+        */
+       retval = rt73usb_validate_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       retval = rt73usb_init_eeprom(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
+
+       /*
+        * Initialize hw specifications.
+        */
+       retval = rt73usb_probe_hw_mode(rt2x00dev);
+       if (retval)
+               return retval;
+
+       /*
+        * This device has multiple filters for control frames,
+        * but has no a separate filter for PS Poll frames.
+        */
+       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+
+       /*
+        * This device requires firmware.
+        */
+       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+       if (!modparam_nohwcrypt)
+               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+       __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
+       return 0;
+}
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static int rt73usb_conf_tx(struct ieee80211_hw *hw,
+                          struct ieee80211_vif *vif, u16 queue_idx,
+                          const struct ieee80211_tx_queue_params *params)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       struct data_queue *queue;
+       struct rt2x00_field32 field;
+       int retval;
+       u32 reg;
+       u32 offset;
+
+       /*
+        * First pass the configuration through rt2x00lib, that will
+        * update the queue settings and validate the input. After that
+        * we are free to update the registers based on the value
+        * in the queue parameter.
+        */
+       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
+       if (retval)
+               return retval;
+
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues/
+        */
+       if (queue_idx >= 4)
+               return 0;
+
+       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
+
+       /* Update WMM TXOP register */
+       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
+       field.bit_offset = (queue_idx & 1) * 16;
+       field.bit_mask = 0xffff << field.bit_offset;
+
+       rt2x00usb_register_read(rt2x00dev, offset, &reg);
+       rt2x00_set_field32(&reg, field, queue->txop);
+       rt2x00usb_register_write(rt2x00dev, offset, reg);
+
+       /* Update WMM registers */
+       field.bit_offset = queue_idx * 4;
+       field.bit_mask = 0xf << field.bit_offset;
+
+       rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->aifs);
+       rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
+
+       rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_min);
+       rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
+
+       rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
+       rt2x00_set_field32(&reg, field, queue->cw_max);
+       rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
+
+       return 0;
+}
+
+static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct rt2x00_dev *rt2x00dev = hw->priv;
+       u64 tsf;
+       u32 reg;
+
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
+       tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
+       tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
+
+       return tsf;
+}
+
+static const struct ieee80211_ops rt73usb_mac80211_ops = {
+       .tx                     = rt2x00mac_tx,
+       .start                  = rt2x00mac_start,
+       .stop                   = rt2x00mac_stop,
+       .add_interface          = rt2x00mac_add_interface,
+       .remove_interface       = rt2x00mac_remove_interface,
+       .config                 = rt2x00mac_config,
+       .configure_filter       = rt2x00mac_configure_filter,
+       .set_tim                = rt2x00mac_set_tim,
+       .set_key                = rt2x00mac_set_key,
+       .sw_scan_start          = rt2x00mac_sw_scan_start,
+       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
+       .get_stats              = rt2x00mac_get_stats,
+       .bss_info_changed       = rt2x00mac_bss_info_changed,
+       .conf_tx                = rt73usb_conf_tx,
+       .get_tsf                = rt73usb_get_tsf,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
+       .flush                  = rt2x00mac_flush,
+       .set_antenna            = rt2x00mac_set_antenna,
+       .get_antenna            = rt2x00mac_get_antenna,
+       .get_ringparam          = rt2x00mac_get_ringparam,
+       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
+};
+
+static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
+       .probe_hw               = rt73usb_probe_hw,
+       .get_firmware_name      = rt73usb_get_firmware_name,
+       .check_firmware         = rt73usb_check_firmware,
+       .load_firmware          = rt73usb_load_firmware,
+       .initialize             = rt2x00usb_initialize,
+       .uninitialize           = rt2x00usb_uninitialize,
+       .clear_entry            = rt2x00usb_clear_entry,
+       .set_device_state       = rt73usb_set_device_state,
+       .rfkill_poll            = rt73usb_rfkill_poll,
+       .link_stats             = rt73usb_link_stats,
+       .reset_tuner            = rt73usb_reset_tuner,
+       .link_tuner             = rt73usb_link_tuner,
+       .watchdog               = rt2x00usb_watchdog,
+       .start_queue            = rt73usb_start_queue,
+       .kick_queue             = rt2x00usb_kick_queue,
+       .stop_queue             = rt73usb_stop_queue,
+       .flush_queue            = rt2x00usb_flush_queue,
+       .write_tx_desc          = rt73usb_write_tx_desc,
+       .write_beacon           = rt73usb_write_beacon,
+       .clear_beacon           = rt73usb_clear_beacon,
+       .get_tx_data_len        = rt73usb_get_tx_data_len,
+       .fill_rxdone            = rt73usb_fill_rxdone,
+       .config_shared_key      = rt73usb_config_shared_key,
+       .config_pairwise_key    = rt73usb_config_pairwise_key,
+       .config_filter          = rt73usb_config_filter,
+       .config_intf            = rt73usb_config_intf,
+       .config_erp             = rt73usb_config_erp,
+       .config_ant             = rt73usb_config_ant,
+       .config                 = rt73usb_config,
+};
+
+static void rt73usb_queue_init(struct data_queue *queue)
+{
+       switch (queue->qid) {
+       case QID_RX:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = RXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_AC_VO:
+       case QID_AC_VI:
+       case QID_AC_BE:
+       case QID_AC_BK:
+               queue->limit = 32;
+               queue->data_size = DATA_FRAME_SIZE;
+               queue->desc_size = TXD_DESC_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_BEACON:
+               queue->limit = 4;
+               queue->data_size = MGMT_FRAME_SIZE;
+               queue->desc_size = TXINFO_SIZE;
+               queue->priv_size = sizeof(struct queue_entry_priv_usb);
+               break;
+
+       case QID_ATIM:
+               /* fallthrough */
+       default:
+               BUG();
+               break;
+       }
+}
+
+static const struct rt2x00_ops rt73usb_ops = {
+       .name                   = KBUILD_MODNAME,
+       .max_ap_intf            = 4,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .queue_init             = rt73usb_queue_init,
+       .lib                    = &rt73usb_rt2x00_ops,
+       .hw                     = &rt73usb_mac80211_ops,
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+       .debugfs                = &rt73usb_rt2x00debug,
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+};
+
+/*
+ * rt73usb module information.
+ */
+static struct usb_device_id rt73usb_device_table[] = {
+       /* AboCom */
+       { USB_DEVICE(0x07b8, 0xb21b) },
+       { USB_DEVICE(0x07b8, 0xb21c) },
+       { USB_DEVICE(0x07b8, 0xb21d) },
+       { USB_DEVICE(0x07b8, 0xb21e) },
+       { USB_DEVICE(0x07b8, 0xb21f) },
+       /* AL */
+       { USB_DEVICE(0x14b2, 0x3c10) },
+       /* Amigo */
+       { USB_DEVICE(0x148f, 0x9021) },
+       { USB_DEVICE(0x0eb0, 0x9021) },
+       /* AMIT  */
+       { USB_DEVICE(0x18c5, 0x0002) },
+       /* Askey */
+       { USB_DEVICE(0x1690, 0x0722) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x1723) },
+       { USB_DEVICE(0x0b05, 0x1724) },
+       /* Belkin */
+       { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050B ver. 3.x */
+       { USB_DEVICE(0x050d, 0x705a) },
+       { USB_DEVICE(0x050d, 0x905b) },
+       { USB_DEVICE(0x050d, 0x905c) },
+       /* Billionton */
+       { USB_DEVICE(0x1631, 0xc019) },
+       { USB_DEVICE(0x08dd, 0x0120) },
+       /* Buffalo */
+       { USB_DEVICE(0x0411, 0x00d8) },
+       { USB_DEVICE(0x0411, 0x00d9) },
+       { USB_DEVICE(0x0411, 0x00e6) },
+       { USB_DEVICE(0x0411, 0x00f4) },
+       { USB_DEVICE(0x0411, 0x0116) },
+       { USB_DEVICE(0x0411, 0x0119) },
+       { USB_DEVICE(0x0411, 0x0137) },
+       /* CEIVA */
+       { USB_DEVICE(0x178d, 0x02be) },
+       /* CNet */
+       { USB_DEVICE(0x1371, 0x9022) },
+       { USB_DEVICE(0x1371, 0x9032) },
+       /* Conceptronic */
+       { USB_DEVICE(0x14b2, 0x3c22) },
+       /* Corega */
+       { USB_DEVICE(0x07aa, 0x002e) },
+       /* D-Link */
+       { USB_DEVICE(0x07d1, 0x3c03) },
+       { USB_DEVICE(0x07d1, 0x3c04) },
+       { USB_DEVICE(0x07d1, 0x3c06) },
+       { USB_DEVICE(0x07d1, 0x3c07) },
+       /* Edimax */
+       { USB_DEVICE(0x7392, 0x7318) },
+       { USB_DEVICE(0x7392, 0x7618) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x3701) },
+       /* Gemtek */
+       { USB_DEVICE(0x15a9, 0x0004) },
+       /* Gigabyte */
+       { USB_DEVICE(0x1044, 0x8008) },
+       { USB_DEVICE(0x1044, 0x800a) },
+       /* Huawei-3Com */
+       { USB_DEVICE(0x1472, 0x0009) },
+       /* Hercules */
+       { USB_DEVICE(0x06f8, 0xe002) },
+       { USB_DEVICE(0x06f8, 0xe010) },
+       { USB_DEVICE(0x06f8, 0xe020) },
+       /* Linksys */
+       { USB_DEVICE(0x13b1, 0x0020) },
+       { USB_DEVICE(0x13b1, 0x0023) },
+       { USB_DEVICE(0x13b1, 0x0028) },
+       /* MSI */
+       { USB_DEVICE(0x0db0, 0x4600) },
+       { USB_DEVICE(0x0db0, 0x6877) },
+       { USB_DEVICE(0x0db0, 0x6874) },
+       { USB_DEVICE(0x0db0, 0xa861) },
+       { USB_DEVICE(0x0db0, 0xa874) },
+       /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x7318) },
+       /* Ralink */
+       { USB_DEVICE(0x04bb, 0x093d) },
+       { USB_DEVICE(0x148f, 0x2573) },
+       { USB_DEVICE(0x148f, 0x2671) },
+       { USB_DEVICE(0x0812, 0x3101) },
+       /* Qcom */
+       { USB_DEVICE(0x18e8, 0x6196) },
+       { USB_DEVICE(0x18e8, 0x6229) },
+       { USB_DEVICE(0x18e8, 0x6238) },
+       /* Samsung */
+       { USB_DEVICE(0x04e8, 0x4471) },
+       /* Senao */
+       { USB_DEVICE(0x1740, 0x7100) },
+       /* Sitecom */
+       { USB_DEVICE(0x0df6, 0x0024) },
+       { USB_DEVICE(0x0df6, 0x0027) },
+       { USB_DEVICE(0x0df6, 0x002f) },
+       { USB_DEVICE(0x0df6, 0x90ac) },
+       { USB_DEVICE(0x0df6, 0x9712) },
+       /* Surecom */
+       { USB_DEVICE(0x0769, 0x31f3) },
+       /* Tilgin */
+       { USB_DEVICE(0x6933, 0x5001) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x200a) },
+       /* Planex */
+       { USB_DEVICE(0x2019, 0xab01) },
+       { USB_DEVICE(0x2019, 0xab50) },
+       /* WideTell */
+       { USB_DEVICE(0x7167, 0x3840) },
+       /* Zcom */
+       { USB_DEVICE(0x0cde, 0x001c) },
+       /* ZyXEL */
+       { USB_DEVICE(0x0586, 0x3415) },
+       { 0, }
+};
+
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("Ralink RT73 USB Wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Ralink RT2571W & RT2671 USB chipset based cards");
+MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
+MODULE_FIRMWARE(FIRMWARE_RT2571);
+MODULE_LICENSE("GPL");
+
+static int rt73usb_probe(struct usb_interface *usb_intf,
+                        const struct usb_device_id *id)
+{
+       return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
+static struct usb_driver rt73usb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = rt73usb_device_table,
+       .probe          = rt73usb_probe,
+       .disconnect     = rt2x00usb_disconnect,
+       .suspend        = rt2x00usb_suspend,
+       .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
+       .disable_hub_initiated_lpm = 1,
+};
+
+module_usb_driver(rt73usb_driver);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.h b/drivers/net/wireless/ralink/rt2x00/rt73usb.h
new file mode 100644 (file)
index 0000000..4a4f235
--- /dev/null
@@ -0,0 +1,1079 @@
+/*
+       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+       <http://rt2x00.serialmonkey.com>
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+       Module: rt73usb
+       Abstract: Data structures and registers for the rt73usb module.
+       Supported chipsets: rt2571W & rt2671.
+ */
+
+#ifndef RT73USB_H
+#define RT73USB_H
+
+/*
+ * RF chip defines.
+ */
+#define RF5226                         0x0001
+#define RF2528                         0x0002
+#define RF5225                         0x0003
+#define RF2527                         0x0004
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET            120
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE                   0x3000
+#define CSR_REG_SIZE                   0x04b0
+#define EEPROM_BASE                    0x0000
+#define EEPROM_SIZE                    0x0100
+#define BBP_BASE                       0x0000
+#define BBP_SIZE                       0x0080
+#define RF_BASE                                0x0004
+#define RF_SIZE                                0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  4
+
+/*
+ * USB registers.
+ */
+
+/*
+ * MCU_LEDCS: LED control for MCU Mailbox.
+ */
+#define MCU_LEDCS_LED_MODE             FIELD16(0x001f)
+#define MCU_LEDCS_RADIO_STATUS         FIELD16(0x0020)
+#define MCU_LEDCS_LINK_BG_STATUS       FIELD16(0x0040)
+#define MCU_LEDCS_LINK_A_STATUS                FIELD16(0x0080)
+#define MCU_LEDCS_POLARITY_GPIO_0      FIELD16(0x0100)
+#define MCU_LEDCS_POLARITY_GPIO_1      FIELD16(0x0200)
+#define MCU_LEDCS_POLARITY_GPIO_2      FIELD16(0x0400)
+#define MCU_LEDCS_POLARITY_GPIO_3      FIELD16(0x0800)
+#define MCU_LEDCS_POLARITY_GPIO_4      FIELD16(0x1000)
+#define MCU_LEDCS_POLARITY_ACT         FIELD16(0x2000)
+#define MCU_LEDCS_POLARITY_READY_BG    FIELD16(0x4000)
+#define MCU_LEDCS_POLARITY_READY_A     FIELD16(0x8000)
+
+/*
+ * 8051 firmware image.
+ */
+#define FIRMWARE_RT2571                        "rt73.bin"
+#define FIRMWARE_IMAGE_BASE            0x0800
+
+/*
+ * Security key table memory.
+ * 16 entries 32-byte for shared key table
+ * 64 entries 32-byte for pairwise key table
+ * 64 entries 8-byte for pairwise ta key table
+ */
+#define SHARED_KEY_TABLE_BASE          0x1000
+#define PAIRWISE_KEY_TABLE_BASE                0x1200
+#define PAIRWISE_TA_TABLE_BASE         0x1a00
+
+#define SHARED_KEY_ENTRY(__idx) \
+       ( SHARED_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+       ( PAIRWISE_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+       ( PAIRWISE_TA_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
+struct hw_key_entry {
+       u8 key[16];
+       u8 tx_mic[8];
+       u8 rx_mic[8];
+} __packed;
+
+struct hw_pairwise_ta_entry {
+       u8 address[6];
+       u8 cipher;
+       u8 reserved;
+} __packed;
+
+/*
+ * Since NULL frame won't be that long (256 byte),
+ * We steal 16 tail bytes to save debugging settings.
+ */
+#define HW_DEBUG_SETTING_BASE          0x2bf0
+
+/*
+ * On-chip BEACON frame space.
+ */
+#define HW_BEACON_BASE0                        0x2400
+#define HW_BEACON_BASE1                        0x2500
+#define HW_BEACON_BASE2                        0x2600
+#define HW_BEACON_BASE3                        0x2700
+
+#define HW_BEACON_OFFSET(__index) \
+       ( HW_BEACON_BASE0 + (__index * 0x0100) )
+
+/*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ */
+#define MAC_CSR0                       0x3000
+#define MAC_CSR0_REVISION              FIELD32(0x0000000f)
+#define MAC_CSR0_CHIPSET               FIELD32(0x000ffff0)
+
+/*
+ * MAC_CSR1: System control register.
+ * SOFT_RESET: Software reset bit, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset BBP.
+ * HOST_READY: Host is ready after initialization, 1: ready.
+ */
+#define MAC_CSR1                       0x3004
+#define MAC_CSR1_SOFT_RESET            FIELD32(0x00000001)
+#define MAC_CSR1_BBP_RESET             FIELD32(0x00000002)
+#define MAC_CSR1_HOST_READY            FIELD32(0x00000004)
+
+/*
+ * MAC_CSR2: STA MAC register 0.
+ */
+#define MAC_CSR2                       0x3008
+#define MAC_CSR2_BYTE0                 FIELD32(0x000000ff)
+#define MAC_CSR2_BYTE1                 FIELD32(0x0000ff00)
+#define MAC_CSR2_BYTE2                 FIELD32(0x00ff0000)
+#define MAC_CSR2_BYTE3                 FIELD32(0xff000000)
+
+/*
+ * MAC_CSR3: STA MAC register 1.
+ * UNICAST_TO_ME_MASK:
+ *     Used to mask off bits from byte 5 of the MAC address
+ *     to determine the UNICAST_TO_ME bit for RX frames.
+ *     The full mask is complemented by BSS_ID_MASK:
+ *             MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+#define MAC_CSR3                       0x300c
+#define MAC_CSR3_BYTE4                 FIELD32(0x000000ff)
+#define MAC_CSR3_BYTE5                 FIELD32(0x0000ff00)
+#define MAC_CSR3_UNICAST_TO_ME_MASK    FIELD32(0x00ff0000)
+
+/*
+ * MAC_CSR4: BSSID register 0.
+ */
+#define MAC_CSR4                       0x3010
+#define MAC_CSR4_BYTE0                 FIELD32(0x000000ff)
+#define MAC_CSR4_BYTE1                 FIELD32(0x0000ff00)
+#define MAC_CSR4_BYTE2                 FIELD32(0x00ff0000)
+#define MAC_CSR4_BYTE3                 FIELD32(0xff000000)
+
+/*
+ * MAC_CSR5: BSSID register 1.
+ * BSS_ID_MASK:
+ *     This mask is used to mask off bits 0 and 1 of byte 5 of the
+ *     BSSID. This will make sure that those bits will be ignored
+ *     when determining the MY_BSS of RX frames.
+ *             0: 1-BSSID mode (BSS index = 0)
+ *             1: 2-BSSID mode (BSS index: Byte5, bit 0)
+ *             2: 2-BSSID mode (BSS index: byte5, bit 1)
+ *             3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ */
+#define MAC_CSR5                       0x3014
+#define MAC_CSR5_BYTE4                 FIELD32(0x000000ff)
+#define MAC_CSR5_BYTE5                 FIELD32(0x0000ff00)
+#define MAC_CSR5_BSS_ID_MASK           FIELD32(0x00ff0000)
+
+/*
+ * MAC_CSR6: Maximum frame length register.
+ */
+#define MAC_CSR6                       0x3018
+#define MAC_CSR6_MAX_FRAME_UNIT                FIELD32(0x00000fff)
+
+/*
+ * MAC_CSR7: Reserved
+ */
+#define MAC_CSR7                       0x301c
+
+/*
+ * MAC_CSR8: SIFS/EIFS register.
+ * All units are in US.
+ */
+#define MAC_CSR8                       0x3020
+#define MAC_CSR8_SIFS                  FIELD32(0x000000ff)
+#define MAC_CSR8_SIFS_AFTER_RX_OFDM    FIELD32(0x0000ff00)
+#define MAC_CSR8_EIFS                  FIELD32(0xffff0000)
+
+/*
+ * MAC_CSR9: Back-Off control register.
+ * SLOT_TIME: Slot time, default is 20us for 802.11BG.
+ * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1).
+ * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1).
+ * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD.
+ */
+#define MAC_CSR9                       0x3024
+#define MAC_CSR9_SLOT_TIME             FIELD32(0x000000ff)
+#define MAC_CSR9_CWMIN                 FIELD32(0x00000f00)
+#define MAC_CSR9_CWMAX                 FIELD32(0x0000f000)
+#define MAC_CSR9_CW_SELECT             FIELD32(0x00010000)
+
+/*
+ * MAC_CSR10: Power state configuration.
+ */
+#define MAC_CSR10                      0x3028
+
+/*
+ * MAC_CSR11: Power saving transition time register.
+ * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU.
+ * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
+ * WAKEUP_LATENCY: In unit of TU.
+ */
+#define MAC_CSR11                      0x302c
+#define MAC_CSR11_DELAY_AFTER_TBCN     FIELD32(0x000000ff)
+#define MAC_CSR11_TBCN_BEFORE_WAKEUP   FIELD32(0x00007f00)
+#define MAC_CSR11_AUTOWAKE             FIELD32(0x00008000)
+#define MAC_CSR11_WAKEUP_LATENCY       FIELD32(0x000f0000)
+
+/*
+ * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1).
+ * CURRENT_STATE: 0:sleep, 1:awake.
+ * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP.
+ * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake.
+ */
+#define MAC_CSR12                      0x3030
+#define MAC_CSR12_CURRENT_STATE                FIELD32(0x00000001)
+#define MAC_CSR12_PUT_TO_SLEEP         FIELD32(0x00000002)
+#define MAC_CSR12_FORCE_WAKEUP         FIELD32(0x00000004)
+#define MAC_CSR12_BBP_CURRENT_STATE    FIELD32(0x00000008)
+
+/*
+ * MAC_CSR13: GPIO.
+ *     MAC_CSR13_VALx: GPIO value
+ *     MAC_CSR13_DIRx: GPIO direction: 0 = input; 1 = output
+ */
+#define MAC_CSR13                      0x3034
+#define MAC_CSR13_VAL0                 FIELD32(0x00000001)
+#define MAC_CSR13_VAL1                 FIELD32(0x00000002)
+#define MAC_CSR13_VAL2                 FIELD32(0x00000004)
+#define MAC_CSR13_VAL3                 FIELD32(0x00000008)
+#define MAC_CSR13_VAL4                 FIELD32(0x00000010)
+#define MAC_CSR13_VAL5                 FIELD32(0x00000020)
+#define MAC_CSR13_VAL6                 FIELD32(0x00000040)
+#define MAC_CSR13_VAL7                 FIELD32(0x00000080)
+#define MAC_CSR13_DIR0                 FIELD32(0x00000100)
+#define MAC_CSR13_DIR1                 FIELD32(0x00000200)
+#define MAC_CSR13_DIR2                 FIELD32(0x00000400)
+#define MAC_CSR13_DIR3                 FIELD32(0x00000800)
+#define MAC_CSR13_DIR4                 FIELD32(0x00001000)
+#define MAC_CSR13_DIR5                 FIELD32(0x00002000)
+#define MAC_CSR13_DIR6                 FIELD32(0x00004000)
+#define MAC_CSR13_DIR7                 FIELD32(0x00008000)
+
+/*
+ * MAC_CSR14: LED control register.
+ * ON_PERIOD: On period, default 70ms.
+ * OFF_PERIOD: Off period, default 30ms.
+ * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON.
+ * SW_LED: s/w LED, 1: ON, 0: OFF.
+ * HW_LED_POLARITY: 0: active low, 1: active high.
+ */
+#define MAC_CSR14                      0x3038
+#define MAC_CSR14_ON_PERIOD            FIELD32(0x000000ff)
+#define MAC_CSR14_OFF_PERIOD           FIELD32(0x0000ff00)
+#define MAC_CSR14_HW_LED               FIELD32(0x00010000)
+#define MAC_CSR14_SW_LED               FIELD32(0x00020000)
+#define MAC_CSR14_HW_LED_POLARITY      FIELD32(0x00040000)
+#define MAC_CSR14_SW_LED2              FIELD32(0x00080000)
+
+/*
+ * MAC_CSR15: NAV control.
+ */
+#define MAC_CSR15                      0x303c
+
+/*
+ * TXRX control registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * TXRX_CSR0: TX/RX configuration register.
+ * TSF_OFFSET: Default is 24.
+ * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame.
+ * DISABLE_RX: Disable Rx engine.
+ * DROP_CRC: Drop CRC error.
+ * DROP_PHYSICAL: Drop physical error.
+ * DROP_CONTROL: Drop control frame.
+ * DROP_NOT_TO_ME: Drop not to me unicast frame.
+ * DROP_TO_DS: Drop fram ToDs bit is true.
+ * DROP_VERSION_ERROR: Drop version error frame.
+ * DROP_MULTICAST: Drop multicast frames.
+ * DROP_BORADCAST: Drop broadcast frames.
+ * DROP_ACK_CTS: Drop received ACK and CTS.
+ */
+#define TXRX_CSR0                      0x3040
+#define TXRX_CSR0_RX_ACK_TIMEOUT       FIELD32(0x000001ff)
+#define TXRX_CSR0_TSF_OFFSET           FIELD32(0x00007e00)
+#define TXRX_CSR0_AUTO_TX_SEQ          FIELD32(0x00008000)
+#define TXRX_CSR0_DISABLE_RX           FIELD32(0x00010000)
+#define TXRX_CSR0_DROP_CRC             FIELD32(0x00020000)
+#define TXRX_CSR0_DROP_PHYSICAL                FIELD32(0x00040000)
+#define TXRX_CSR0_DROP_CONTROL         FIELD32(0x00080000)
+#define TXRX_CSR0_DROP_NOT_TO_ME       FIELD32(0x00100000)
+#define TXRX_CSR0_DROP_TO_DS           FIELD32(0x00200000)
+#define TXRX_CSR0_DROP_VERSION_ERROR   FIELD32(0x00400000)
+#define TXRX_CSR0_DROP_MULTICAST       FIELD32(0x00800000)
+#define TXRX_CSR0_DROP_BROADCAST       FIELD32(0x01000000)
+#define TXRX_CSR0_DROP_ACK_CTS         FIELD32(0x02000000)
+#define TXRX_CSR0_TX_WITHOUT_WAITING   FIELD32(0x04000000)
+
+/*
+ * TXRX_CSR1
+ */
+#define TXRX_CSR1                      0x3044
+#define TXRX_CSR1_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR1_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR1_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR1_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR1_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR1_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR1_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR1_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR2
+ */
+#define TXRX_CSR2                      0x3048
+#define TXRX_CSR2_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR2_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR2_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR2_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR2_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR2_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR2_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR2_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR3
+ */
+#define TXRX_CSR3                      0x304c
+#define TXRX_CSR3_BBP_ID0              FIELD32(0x0000007f)
+#define TXRX_CSR3_BBP_ID0_VALID                FIELD32(0x00000080)
+#define TXRX_CSR3_BBP_ID1              FIELD32(0x00007f00)
+#define TXRX_CSR3_BBP_ID1_VALID                FIELD32(0x00008000)
+#define TXRX_CSR3_BBP_ID2              FIELD32(0x007f0000)
+#define TXRX_CSR3_BBP_ID2_VALID                FIELD32(0x00800000)
+#define TXRX_CSR3_BBP_ID3              FIELD32(0x7f000000)
+#define TXRX_CSR3_BBP_ID3_VALID                FIELD32(0x80000000)
+
+/*
+ * TXRX_CSR4: Auto-Responder/Tx-retry register.
+ * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble.
+ * OFDM_TX_RATE_DOWN: 1:enable.
+ * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step.
+ * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M.
+ */
+#define TXRX_CSR4                      0x3050
+#define TXRX_CSR4_TX_ACK_TIMEOUT       FIELD32(0x000000ff)
+#define TXRX_CSR4_CNTL_ACK_POLICY      FIELD32(0x00000700)
+#define TXRX_CSR4_ACK_CTS_PSM          FIELD32(0x00010000)
+#define TXRX_CSR4_AUTORESPOND_ENABLE   FIELD32(0x00020000)
+#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000)
+#define TXRX_CSR4_OFDM_TX_RATE_DOWN    FIELD32(0x00080000)
+#define TXRX_CSR4_OFDM_TX_RATE_STEP    FIELD32(0x00300000)
+#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000)
+#define TXRX_CSR4_LONG_RETRY_LIMIT     FIELD32(0x0f000000)
+#define TXRX_CSR4_SHORT_RETRY_LIMIT    FIELD32(0xf0000000)
+
+/*
+ * TXRX_CSR5
+ */
+#define TXRX_CSR5                      0x3054
+
+/*
+ * TXRX_CSR6: ACK/CTS payload consumed time
+ */
+#define TXRX_CSR6                      0x3058
+
+/*
+ * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
+#define TXRX_CSR7                      0x305c
+#define TXRX_CSR7_ACK_CTS_6MBS         FIELD32(0x000000ff)
+#define TXRX_CSR7_ACK_CTS_9MBS         FIELD32(0x0000ff00)
+#define TXRX_CSR7_ACK_CTS_12MBS                FIELD32(0x00ff0000)
+#define TXRX_CSR7_ACK_CTS_18MBS                FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
+#define TXRX_CSR8                      0x3060
+#define TXRX_CSR8_ACK_CTS_24MBS                FIELD32(0x000000ff)
+#define TXRX_CSR8_ACK_CTS_36MBS                FIELD32(0x0000ff00)
+#define TXRX_CSR8_ACK_CTS_48MBS                FIELD32(0x00ff0000)
+#define TXRX_CSR8_ACK_CTS_54MBS                FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR9: Synchronization control register.
+ * BEACON_INTERVAL: In unit of 1/16 TU.
+ * TSF_TICKING: Enable TSF auto counting.
+ * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
+ * BEACON_GEN: Enable beacon generator.
+ */
+#define TXRX_CSR9                      0x3064
+#define TXRX_CSR9_BEACON_INTERVAL      FIELD32(0x0000ffff)
+#define TXRX_CSR9_TSF_TICKING          FIELD32(0x00010000)
+#define TXRX_CSR9_TSF_SYNC             FIELD32(0x00060000)
+#define TXRX_CSR9_TBTT_ENABLE          FIELD32(0x00080000)
+#define TXRX_CSR9_BEACON_GEN           FIELD32(0x00100000)
+#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR10: BEACON alignment.
+ */
+#define TXRX_CSR10                     0x3068
+
+/*
+ * TXRX_CSR11: AES mask.
+ */
+#define TXRX_CSR11                     0x306c
+
+/*
+ * TXRX_CSR12: TSF low 32.
+ */
+#define TXRX_CSR12                     0x3070
+#define TXRX_CSR12_LOW_TSFTIMER                FIELD32(0xffffffff)
+
+/*
+ * TXRX_CSR13: TSF high 32.
+ */
+#define TXRX_CSR13                     0x3074
+#define TXRX_CSR13_HIGH_TSFTIMER       FIELD32(0xffffffff)
+
+/*
+ * TXRX_CSR14: TBTT timer.
+ */
+#define TXRX_CSR14                     0x3078
+
+/*
+ * TXRX_CSR15: TKIP MIC priority byte "AND" mask.
+ */
+#define TXRX_CSR15                     0x307c
+
+/*
+ * PHY control registers.
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * PHY_CSR0: RF/PS control.
+ */
+#define PHY_CSR0                       0x3080
+#define PHY_CSR0_PA_PE_BG              FIELD32(0x00010000)
+#define PHY_CSR0_PA_PE_A               FIELD32(0x00020000)
+
+/*
+ * PHY_CSR1
+ */
+#define PHY_CSR1                       0x3084
+#define PHY_CSR1_RF_RPI                        FIELD32(0x00010000)
+
+/*
+ * PHY_CSR2: Pre-TX BBP control.
+ */
+#define PHY_CSR2                       0x3088
+
+/*
+ * PHY_CSR3: BBP serial control register.
+ * VALUE: Register value to program into BBP.
+ * REG_NUM: Selected BBP register.
+ * READ_CONTROL: 0: Write BBP, 1: Read BBP.
+ * BUSY: 1: ASIC is busy execute BBP programming.
+ */
+#define PHY_CSR3                       0x308c
+#define PHY_CSR3_VALUE                 FIELD32(0x000000ff)
+#define PHY_CSR3_REGNUM                        FIELD32(0x00007f00)
+#define PHY_CSR3_READ_CONTROL          FIELD32(0x00008000)
+#define PHY_CSR3_BUSY                  FIELD32(0x00010000)
+
+/*
+ * PHY_CSR4: RF serial control register
+ * VALUE: Register value (include register id) serial out to RF/IF chip.
+ * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22).
+ * IF_SELECT: 1: select IF to program, 0: select RF to program.
+ * PLL_LD: RF PLL_LD status.
+ * BUSY: 1: ASIC is busy execute RF programming.
+ */
+#define PHY_CSR4                       0x3090
+#define PHY_CSR4_VALUE                 FIELD32(0x00ffffff)
+#define PHY_CSR4_NUMBER_OF_BITS                FIELD32(0x1f000000)
+#define PHY_CSR4_IF_SELECT             FIELD32(0x20000000)
+#define PHY_CSR4_PLL_LD                        FIELD32(0x40000000)
+#define PHY_CSR4_BUSY                  FIELD32(0x80000000)
+
+/*
+ * PHY_CSR5: RX to TX signal switch timing control.
+ */
+#define PHY_CSR5                       0x3094
+#define PHY_CSR5_IQ_FLIP               FIELD32(0x00000004)
+
+/*
+ * PHY_CSR6: TX to RX signal timing control.
+ */
+#define PHY_CSR6                       0x3098
+#define PHY_CSR6_IQ_FLIP               FIELD32(0x00000004)
+
+/*
+ * PHY_CSR7: TX DAC switching timing control.
+ */
+#define PHY_CSR7                       0x309c
+
+/*
+ * Security control register.
+ */
+
+/*
+ * SEC_CSR0: Shared key table control.
+ */
+#define SEC_CSR0                       0x30a0
+#define SEC_CSR0_BSS0_KEY0_VALID       FIELD32(0x00000001)
+#define SEC_CSR0_BSS0_KEY1_VALID       FIELD32(0x00000002)
+#define SEC_CSR0_BSS0_KEY2_VALID       FIELD32(0x00000004)
+#define SEC_CSR0_BSS0_KEY3_VALID       FIELD32(0x00000008)
+#define SEC_CSR0_BSS1_KEY0_VALID       FIELD32(0x00000010)
+#define SEC_CSR0_BSS1_KEY1_VALID       FIELD32(0x00000020)
+#define SEC_CSR0_BSS1_KEY2_VALID       FIELD32(0x00000040)
+#define SEC_CSR0_BSS1_KEY3_VALID       FIELD32(0x00000080)
+#define SEC_CSR0_BSS2_KEY0_VALID       FIELD32(0x00000100)
+#define SEC_CSR0_BSS2_KEY1_VALID       FIELD32(0x00000200)
+#define SEC_CSR0_BSS2_KEY2_VALID       FIELD32(0x00000400)
+#define SEC_CSR0_BSS2_KEY3_VALID       FIELD32(0x00000800)
+#define SEC_CSR0_BSS3_KEY0_VALID       FIELD32(0x00001000)
+#define SEC_CSR0_BSS3_KEY1_VALID       FIELD32(0x00002000)
+#define SEC_CSR0_BSS3_KEY2_VALID       FIELD32(0x00004000)
+#define SEC_CSR0_BSS3_KEY3_VALID       FIELD32(0x00008000)
+
+/*
+ * SEC_CSR1: Shared key table security mode register.
+ */
+#define SEC_CSR1                       0x30a4
+#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG  FIELD32(0x00000007)
+#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG  FIELD32(0x00000070)
+#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG  FIELD32(0x00000700)
+#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG  FIELD32(0x00007000)
+#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG  FIELD32(0x00070000)
+#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG  FIELD32(0x00700000)
+#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG  FIELD32(0x07000000)
+#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG  FIELD32(0x70000000)
+
+/*
+ * Pairwise key table valid bitmap registers.
+ * SEC_CSR2: pairwise key table valid bitmap 0.
+ * SEC_CSR3: pairwise key table valid bitmap 1.
+ */
+#define SEC_CSR2                       0x30a8
+#define SEC_CSR3                       0x30ac
+
+/*
+ * SEC_CSR4: Pairwise key table lookup control.
+ */
+#define SEC_CSR4                       0x30b0
+#define SEC_CSR4_ENABLE_BSS0           FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1           FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2           FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3           FIELD32(0x00000008)
+
+/*
+ * SEC_CSR5: shared key table security mode register.
+ */
+#define SEC_CSR5                       0x30b4
+#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG  FIELD32(0x00000007)
+#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG  FIELD32(0x00000070)
+#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG  FIELD32(0x00000700)
+#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG  FIELD32(0x00007000)
+#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG  FIELD32(0x00070000)
+#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG  FIELD32(0x00700000)
+#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG  FIELD32(0x07000000)
+#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG  FIELD32(0x70000000)
+
+/*
+ * STA control registers.
+ */
+
+/*
+ * STA_CSR0: RX PLCP error count & RX FCS error count.
+ */
+#define STA_CSR0                       0x30c0
+#define STA_CSR0_FCS_ERROR             FIELD32(0x0000ffff)
+#define STA_CSR0_PLCP_ERROR            FIELD32(0xffff0000)
+
+/*
+ * STA_CSR1: RX False CCA count & RX LONG frame count.
+ */
+#define STA_CSR1                       0x30c4
+#define STA_CSR1_PHYSICAL_ERROR                FIELD32(0x0000ffff)
+#define STA_CSR1_FALSE_CCA_ERROR       FIELD32(0xffff0000)
+
+/*
+ * STA_CSR2: TX Beacon count and RX FIFO overflow count.
+ */
+#define STA_CSR2                       0x30c8
+#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT        FIELD32(0x0000ffff)
+#define STA_CSR2_RX_OVERFLOW_COUNT     FIELD32(0xffff0000)
+
+/*
+ * STA_CSR3: TX Beacon count.
+ */
+#define STA_CSR3                       0x30cc
+#define STA_CSR3_TX_BEACON_COUNT       FIELD32(0x0000ffff)
+
+/*
+ * STA_CSR4: TX Retry count.
+ */
+#define STA_CSR4                       0x30d0
+#define STA_CSR4_TX_NO_RETRY_COUNT     FIELD32(0x0000ffff)
+#define STA_CSR4_TX_ONE_RETRY_COUNT    FIELD32(0xffff0000)
+
+/*
+ * STA_CSR5: TX Retry count.
+ */
+#define STA_CSR5                       0x30d4
+#define STA_CSR4_TX_MULTI_RETRY_COUNT  FIELD32(0x0000ffff)
+#define STA_CSR4_TX_RETRY_FAIL_COUNT   FIELD32(0xffff0000)
+
+/*
+ * QOS control registers.
+ */
+
+/*
+ * QOS_CSR1: TXOP holder MAC address register.
+ */
+#define QOS_CSR1                       0x30e4
+#define QOS_CSR1_BYTE4                 FIELD32(0x000000ff)
+#define QOS_CSR1_BYTE5                 FIELD32(0x0000ff00)
+
+/*
+ * QOS_CSR2: TXOP holder timeout register.
+ */
+#define QOS_CSR2                       0x30e8
+
+/*
+ * RX QOS-CFPOLL MAC address register.
+ * QOS_CSR3: RX QOS-CFPOLL MAC address 0.
+ * QOS_CSR4: RX QOS-CFPOLL MAC address 1.
+ */
+#define QOS_CSR3                       0x30ec
+#define QOS_CSR4                       0x30f0
+
+/*
+ * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL.
+ */
+#define QOS_CSR5                       0x30f4
+
+/*
+ * WMM Scheduler Register
+ */
+
+/*
+ * AIFSN_CSR: AIFSN for each EDCA AC.
+ * AIFSN0: For AC_VO.
+ * AIFSN1: For AC_VI.
+ * AIFSN2: For AC_BE.
+ * AIFSN3: For AC_BK.
+ */
+#define AIFSN_CSR                      0x0400
+#define AIFSN_CSR_AIFSN0               FIELD32(0x0000000f)
+#define AIFSN_CSR_AIFSN1               FIELD32(0x000000f0)
+#define AIFSN_CSR_AIFSN2               FIELD32(0x00000f00)
+#define AIFSN_CSR_AIFSN3               FIELD32(0x0000f000)
+
+/*
+ * CWMIN_CSR: CWmin for each EDCA AC.
+ * CWMIN0: For AC_VO.
+ * CWMIN1: For AC_VI.
+ * CWMIN2: For AC_BE.
+ * CWMIN3: For AC_BK.
+ */
+#define CWMIN_CSR                      0x0404
+#define CWMIN_CSR_CWMIN0               FIELD32(0x0000000f)
+#define CWMIN_CSR_CWMIN1               FIELD32(0x000000f0)
+#define CWMIN_CSR_CWMIN2               FIELD32(0x00000f00)
+#define CWMIN_CSR_CWMIN3               FIELD32(0x0000f000)
+
+/*
+ * CWMAX_CSR: CWmax for each EDCA AC.
+ * CWMAX0: For AC_VO.
+ * CWMAX1: For AC_VI.
+ * CWMAX2: For AC_BE.
+ * CWMAX3: For AC_BK.
+ */
+#define CWMAX_CSR                      0x0408
+#define CWMAX_CSR_CWMAX0               FIELD32(0x0000000f)
+#define CWMAX_CSR_CWMAX1               FIELD32(0x000000f0)
+#define CWMAX_CSR_CWMAX2               FIELD32(0x00000f00)
+#define CWMAX_CSR_CWMAX3               FIELD32(0x0000f000)
+
+/*
+ * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
+ * AC0_TX_OP: For AC_VO, in unit of 32us.
+ * AC1_TX_OP: For AC_VI, in unit of 32us.
+ */
+#define AC_TXOP_CSR0                   0x040c
+#define AC_TXOP_CSR0_AC0_TX_OP         FIELD32(0x0000ffff)
+#define AC_TXOP_CSR0_AC1_TX_OP         FIELD32(0xffff0000)
+
+/*
+ * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
+ * AC2_TX_OP: For AC_BE, in unit of 32us.
+ * AC3_TX_OP: For AC_BK, in unit of 32us.
+ */
+#define AC_TXOP_CSR1                   0x0410
+#define AC_TXOP_CSR1_AC2_TX_OP         FIELD32(0x0000ffff)
+#define AC_TXOP_CSR1_AC3_TX_OP         FIELD32(0xffff0000)
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2
+ */
+#define BBP_R2_BG_MODE                 FIELD8(0x20)
+
+/*
+ * R3
+ */
+#define BBP_R3_SMART_MODE              FIELD8(0x01)
+
+/*
+ * R4: RX antenna control
+ * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
+ */
+
+/*
+ * ANTENNA_CONTROL semantics (guessed):
+ * 0x1: Software controlled antenna switching (fixed or SW diversity)
+ * 0x2: Hardware diversity.
+ */
+#define BBP_R4_RX_ANTENNA_CONTROL      FIELD8(0x03)
+#define BBP_R4_RX_FRAME_END            FIELD8(0x20)
+
+/*
+ * R77
+ */
+#define BBP_R77_RX_ANTENNA             FIELD8(0x03)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 3
+ */
+#define RF3_TXPOWER                    FIELD32(0x00003e00)
+
+/*
+ * RF 4
+ */
+#define RF4_FREQ_OFFSET                        FIELD32(0x0003f000)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0              0x0002
+#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1               0x0003
+#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2              0x0004
+#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
+
+/*
+ * EEPROM antenna.
+ * ANTENNA_NUM: Number of antennas.
+ * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
+ * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only.
+ * DYN_TXAGC: Dynamic TX AGC control.
+ * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
+ * RF_TYPE: Rf_type of this adapter.
+ */
+#define EEPROM_ANTENNA                 0x0010
+#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
+#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
+#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
+#define EEPROM_ANTENNA_FRAME_TYPE      FIELD16(0x0040)
+#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
+#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
+#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
+
+/*
+ * EEPROM NIC config.
+ * EXTERNAL_LNA: External LNA.
+ */
+#define EEPROM_NIC                     0x0011
+#define EEPROM_NIC_EXTERNAL_LNA                FIELD16(0x0010)
+
+/*
+ * EEPROM geography.
+ * GEO_A: Default geographical setting for 5GHz band
+ * GEO: Default geographical setting.
+ */
+#define EEPROM_GEOGRAPHY               0x0012
+#define EEPROM_GEOGRAPHY_GEO_A         FIELD16(0x00ff)
+#define EEPROM_GEOGRAPHY_GEO           FIELD16(0xff00)
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START               0x0013
+#define EEPROM_BBP_SIZE                        16
+#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER 802.11G
+ */
+#define EEPROM_TXPOWER_G_START         0x0023
+#define EEPROM_TXPOWER_G_SIZE          7
+#define EEPROM_TXPOWER_G_1             FIELD16(0x00ff)
+#define EEPROM_TXPOWER_G_2             FIELD16(0xff00)
+
+/*
+ * EEPROM Frequency
+ */
+#define EEPROM_FREQ                    0x002f
+#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
+#define EEPROM_FREQ_SEQ_MASK           FIELD16(0xff00)
+#define EEPROM_FREQ_SEQ                        FIELD16(0x0300)
+
+/*
+ * EEPROM LED.
+ * POLARITY_RDY_G: Polarity RDY_G setting.
+ * POLARITY_RDY_A: Polarity RDY_A setting.
+ * POLARITY_ACT: Polarity ACT setting.
+ * POLARITY_GPIO_0: Polarity GPIO0 setting.
+ * POLARITY_GPIO_1: Polarity GPIO1 setting.
+ * POLARITY_GPIO_2: Polarity GPIO2 setting.
+ * POLARITY_GPIO_3: Polarity GPIO3 setting.
+ * POLARITY_GPIO_4: Polarity GPIO4 setting.
+ * LED_MODE: Led mode.
+ */
+#define EEPROM_LED                     0x0030
+#define EEPROM_LED_POLARITY_RDY_G      FIELD16(0x0001)
+#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
+#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
+#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
+#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
+#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
+#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
+#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
+#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
+
+/*
+ * EEPROM TXPOWER 802.11A
+ */
+#define EEPROM_TXPOWER_A_START         0x0031
+#define EEPROM_TXPOWER_A_SIZE          12
+#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
+#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11BG
+ */
+#define EEPROM_RSSI_OFFSET_BG          0x004d
+#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11A
+ */
+#define EEPROM_RSSI_OFFSET_A           0x004e
+#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXD_DESC_SIZE                  ( 6 * sizeof(__le32) )
+#define TXINFO_SIZE                    ( 6 * sizeof(__le32) )
+#define RXD_DESC_SIZE                  ( 6 * sizeof(__le32) )
+
+/*
+ * TX descriptor format for TX, PRIO and Beacon Ring.
+ */
+
+/*
+ * Word0
+ * BURST: Next frame belongs to same "burst" event.
+ * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used.
+ * KEY_TABLE: Use per-client pairwise KEY table.
+ * KEY_INDEX:
+ * Key index (0~31) to the pairwise KEY table.
+ * 0~3 to shared KEY table 0 (BSS0).
+ * 4~7 to shared KEY table 1 (BSS1).
+ * 8~11 to shared KEY table 2 (BSS2).
+ * 12~15 to shared KEY table 3 (BSS3).
+ * BURST2: For backward compatibility, set to same value as BURST.
+ */
+#define TXD_W0_BURST                   FIELD32(0x00000001)
+#define TXD_W0_VALID                   FIELD32(0x00000002)
+#define TXD_W0_MORE_FRAG               FIELD32(0x00000004)
+#define TXD_W0_ACK                     FIELD32(0x00000008)
+#define TXD_W0_TIMESTAMP               FIELD32(0x00000010)
+#define TXD_W0_OFDM                    FIELD32(0x00000020)
+#define TXD_W0_IFS                     FIELD32(0x00000040)
+#define TXD_W0_RETRY_MODE              FIELD32(0x00000080)
+#define TXD_W0_TKIP_MIC                        FIELD32(0x00000100)
+#define TXD_W0_KEY_TABLE               FIELD32(0x00000200)
+#define TXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
+#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define TXD_W0_BURST2                  FIELD32(0x10000000)
+#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * Word1
+ * HOST_Q_ID: EDCA/HCCA queue ID.
+ * HW_SEQUENCE: MAC overwrites the frame sequence number.
+ * BUFFER_COUNT: Number of buffers in this TXD.
+ */
+#define TXD_W1_HOST_Q_ID               FIELD32(0x0000000f)
+#define TXD_W1_AIFSN                   FIELD32(0x000000f0)
+#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
+#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
+#define TXD_W1_IV_OFFSET               FIELD32(0x003f0000)
+#define TXD_W1_HW_SEQUENCE             FIELD32(0x10000000)
+#define TXD_W1_BUFFER_COUNT            FIELD32(0xe0000000)
+
+/*
+ * Word2: PLCP information
+ */
+#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
+#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
+#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
+#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
+
+/*
+ * Word3
+ */
+#define TXD_W3_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word4
+ */
+#define TXD_W4_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word5
+ * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field).
+ * PACKET_ID: Driver assigned packet ID to categorize TXResult in interrupt.
+ * WAITING_DMA_DONE_INT: TXD been filled with data
+ * and waiting for TxDoneISR housekeeping.
+ */
+#define TXD_W5_FRAME_OFFSET            FIELD32(0x000000ff)
+#define TXD_W5_PACKET_ID               FIELD32(0x0000ff00)
+#define TXD_W5_TX_POWER                        FIELD32(0x00ff0000)
+#define TXD_W5_WAITING_DMA_DONE_INT    FIELD32(0x01000000)
+
+/*
+ * RX descriptor format for RX Ring.
+ */
+
+/*
+ * Word0
+ * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key.
+ * KEY_INDEX: Decryption key actually used.
+ */
+#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
+#define RXD_W0_DROP                    FIELD32(0x00000002)
+#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000004)
+#define RXD_W0_MULTICAST               FIELD32(0x00000008)
+#define RXD_W0_BROADCAST               FIELD32(0x00000010)
+#define RXD_W0_MY_BSS                  FIELD32(0x00000020)
+#define RXD_W0_CRC_ERROR               FIELD32(0x00000040)
+#define RXD_W0_OFDM                    FIELD32(0x00000080)
+#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000300)
+#define RXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
+#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
+#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
+
+/*
+ * WORD1
+ * SIGNAL: RX raw data rate reported by BBP.
+ * RSSI: RSSI reported by BBP.
+ */
+#define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
+#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
+#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
+#define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
+
+/*
+ * Word2
+ * IV: Received IV of originally encrypted.
+ */
+#define RXD_W2_IV                      FIELD32(0xffffffff)
+
+/*
+ * Word3
+ * EIV: Received EIV of originally encrypted.
+ */
+#define RXD_W3_EIV                     FIELD32(0xffffffff)
+
+/*
+ * Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
+ */
+#define RXD_W4_ICV                     FIELD32(0xffffffff)
+
+/*
+ * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
+ * and passed to the HOST driver.
+ * The following fields are for DMA block and HOST usage only.
+ * Can't be touched by ASIC MAC block.
+ */
+
+/*
+ * Word5
+ */
+#define RXD_W5_RESERVED                        FIELD32(0xffffffff)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_TXPOWER    0
+#define MAX_TXPOWER    31
+#define DEFAULT_TXPOWER        24
+
+#define TXPOWER_FROM_DEV(__txpower) \
+       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
+
+#endif /* RT73USB_H */
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
deleted file mode 100644 (file)
index de62f5d..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-menuconfig RT2X00
-       tristate "Ralink driver support"
-       depends on MAC80211 && HAS_DMA
-       ---help---
-         This will enable the support for the Ralink drivers,
-         developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
-
-         These drivers make use of the mac80211 stack.
-
-         When building one of the individual drivers, the rt2x00 library
-         will also be created. That library (when the driver is built as
-         a module) will be called rt2x00lib.
-
-         Additionally PCI and USB libraries will also be build depending
-         on the types of drivers being selected, these libraries will be
-         called rt2x00pci and rt2x00usb.
-
-if RT2X00
-
-config RT2400PCI
-       tristate "Ralink rt2400 (PCI/PCMCIA) support"
-       depends on PCI
-       select RT2X00_LIB_MMIO
-       select RT2X00_LIB_PCI
-       select EEPROM_93CX6
-       ---help---
-         This adds support for rt2400 wireless chipset family.
-         Supported chips: RT2460.
-
-         When compiled as a module, this driver will be called rt2400pci.
-
-config RT2500PCI
-       tristate "Ralink rt2500 (PCI/PCMCIA) support"
-       depends on PCI
-       select RT2X00_LIB_MMIO
-       select RT2X00_LIB_PCI
-       select EEPROM_93CX6
-       ---help---
-         This adds support for rt2500 wireless chipset family.
-         Supported chips: RT2560.
-
-         When compiled as a module, this driver will be called rt2500pci.
-
-config RT61PCI
-       tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
-       depends on PCI
-       select RT2X00_LIB_PCI
-       select RT2X00_LIB_MMIO
-       select RT2X00_LIB_FIRMWARE
-       select RT2X00_LIB_CRYPTO
-       select CRC_ITU_T
-       select EEPROM_93CX6
-       ---help---
-         This adds support for rt2501 wireless chipset family.
-         Supported chips: RT2561, RT2561S & RT2661.
-
-         When compiled as a module, this driver will be called rt61pci.
-
-config RT2800PCI
-       tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
-       depends on PCI
-       select RT2800_LIB
-       select RT2800_LIB_MMIO
-       select RT2X00_LIB_MMIO
-       select RT2X00_LIB_PCI
-       select RT2X00_LIB_FIRMWARE
-       select RT2X00_LIB_CRYPTO
-       select CRC_CCITT
-       select EEPROM_93CX6
-       ---help---
-         This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
-         Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052,
-                          RT3090, RT3091 & RT3092
-
-         When compiled as a module, this driver will be called "rt2800pci.ko".
-
-if RT2800PCI
-
-config RT2800PCI_RT33XX
-       bool "rt2800pci - Include support for rt33xx devices"
-       default y
-       ---help---
-         This adds support for rt33xx wireless chipset family to the
-         rt2800pci driver.
-         Supported chips: RT3390
-
-config RT2800PCI_RT35XX
-       bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
-       default y
-       ---help---
-         This adds support for rt35xx wireless chipset family to the
-         rt2800pci driver.
-         Supported chips: RT3060, RT3062, RT3562, RT3592
-
-
-config RT2800PCI_RT53XX
-       bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
-       default y
-       ---help---
-         This adds support for rt53xx wireless chipset family to the
-         rt2800pci driver.
-         Supported chips: RT5390
-
-config RT2800PCI_RT3290
-       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
-       default y
-       ---help---
-         This adds support for rt3290 wireless chipset family to the
-         rt2800pci driver.
-         Supported chips: RT3290
-endif
-
-config RT2500USB
-       tristate "Ralink rt2500 (USB) support"
-       depends on USB
-       select RT2X00_LIB_USB
-       select RT2X00_LIB_CRYPTO
-       ---help---
-         This adds support for rt2500 wireless chipset family.
-         Supported chips: RT2571 & RT2572.
-
-         When compiled as a module, this driver will be called rt2500usb.
-
-config RT73USB
-       tristate "Ralink rt2501/rt73 (USB) support"
-       depends on USB
-       select RT2X00_LIB_USB
-       select RT2X00_LIB_FIRMWARE
-       select RT2X00_LIB_CRYPTO
-       select CRC_ITU_T
-       ---help---
-         This adds support for rt2501 wireless chipset family.
-         Supported chips: RT2571W, RT2573 & RT2671.
-
-         When compiled as a module, this driver will be called rt73usb.
-
-config RT2800USB
-       tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support"
-       depends on USB
-       select RT2800_LIB
-       select RT2X00_LIB_USB
-       select RT2X00_LIB_FIRMWARE
-       select RT2X00_LIB_CRYPTO
-       select CRC_CCITT
-       ---help---
-         This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
-         Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072
-
-         When compiled as a module, this driver will be called "rt2800usb.ko".
-
-if RT2800USB
-
-config RT2800USB_RT33XX
-       bool "rt2800usb - Include support for rt33xx devices"
-       default y
-       ---help---
-         This adds support for rt33xx wireless chipset family to the
-         rt2800usb driver.
-         Supported chips: RT3370
-
-config RT2800USB_RT35XX
-       bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
-       default y
-       ---help---
-         This adds support for rt35xx wireless chipset family to the
-         rt2800usb driver.
-         Supported chips: RT3572
-
-config RT2800USB_RT3573
-       bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)"
-       ---help---
-         This enables support for RT3573 chipset based wireless USB devices
-         in the rt2800usb driver.
-
-config RT2800USB_RT53XX
-       bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
-       ---help---
-         This adds support for rt53xx wireless chipset family to the
-         rt2800usb driver.
-         Supported chips: RT5370
-
-config RT2800USB_RT55XX
-       bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)"
-       ---help---
-         This adds support for rt55xx wireless chipset family to the
-         rt2800usb driver.
-         Supported chips: RT5572
-
-config RT2800USB_UNKNOWN
-       bool "rt2800usb - Include support for unknown (USB) devices"
-       default n
-       ---help---
-         This adds support for rt2800usb devices that are known to
-         have a rt28xx family compatible chipset, but for which the exact
-         chipset is unknown.
-
-         Support status for these devices is unknown, and enabling these
-         devices may or may not work.
-
-endif
-
-config RT2800SOC
-       tristate "Ralink WiSoC support"
-       depends on SOC_RT288X || SOC_RT305X
-       select RT2X00_LIB_SOC
-       select RT2X00_LIB_MMIO
-       select RT2X00_LIB_CRYPTO
-       select RT2X00_LIB_FIRMWARE
-       select RT2800_LIB
-       select RT2800_LIB_MMIO
-       ---help---
-         This adds support for Ralink WiSoC devices.
-         Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
-
-         When compiled as a module, this driver will be called rt2800soc.
-
-
-config RT2800_LIB
-       tristate
-
-config RT2800_LIB_MMIO
-       tristate
-       select RT2X00_LIB_MMIO
-       select RT2800_LIB
-
-config RT2X00_LIB_MMIO
-       tristate
-
-config RT2X00_LIB_PCI
-       tristate
-       select RT2X00_LIB
-
-config RT2X00_LIB_SOC
-       tristate
-       select RT2X00_LIB
-
-config RT2X00_LIB_USB
-       tristate
-       select RT2X00_LIB
-
-config RT2X00_LIB
-       tristate
-
-config RT2X00_LIB_FIRMWARE
-       bool
-       select FW_LOADER
-
-config RT2X00_LIB_CRYPTO
-       bool
-
-config RT2X00_LIB_LEDS
-       bool
-       default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
-
-config RT2X00_LIB_DEBUGFS
-       bool "Ralink debugfs support"
-       depends on RT2X00_LIB && MAC80211_DEBUGFS
-       ---help---
-         Enable creation of debugfs files for the rt2x00 drivers.
-         These debugfs files support both reading and writing of the
-         most important register types of the rt2x00 hardware.
-
-config RT2X00_DEBUG
-       bool "Ralink debug output"
-       depends on RT2X00_LIB
-       ---help---
-         Enable debugging output for all rt2x00 modules
-
-endif
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
deleted file mode 100644 (file)
index 24a6601..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-rt2x00lib-y                            += rt2x00dev.o
-rt2x00lib-y                            += rt2x00mac.o
-rt2x00lib-y                            += rt2x00config.o
-rt2x00lib-y                            += rt2x00queue.o
-rt2x00lib-y                            += rt2x00link.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)  += rt2x00crypto.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)        += rt2x00firmware.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)    += rt2x00leds.o
-
-obj-$(CONFIG_RT2X00_LIB)               += rt2x00lib.o
-obj-$(CONFIG_RT2X00_LIB_MMIO)          += rt2x00mmio.o
-obj-$(CONFIG_RT2X00_LIB_PCI)           += rt2x00pci.o
-obj-$(CONFIG_RT2X00_LIB_SOC)           += rt2x00soc.o
-obj-$(CONFIG_RT2X00_LIB_USB)           += rt2x00usb.o
-obj-$(CONFIG_RT2800_LIB)               += rt2800lib.o
-obj-$(CONFIG_RT2800_LIB_MMIO)          += rt2800mmio.o
-obj-$(CONFIG_RT2400PCI)                        += rt2400pci.o
-obj-$(CONFIG_RT2500PCI)                        += rt2500pci.o
-obj-$(CONFIG_RT61PCI)                  += rt61pci.o
-obj-$(CONFIG_RT2800PCI)                        += rt2800pci.o
-obj-$(CONFIG_RT2500USB)                        += rt2500usb.o
-obj-$(CONFIG_RT73USB)                  += rt73usb.o
-obj-$(CONFIG_RT2800USB)                        += rt2800usb.o
-obj-$(CONFIG_RT2800SOC)                        += rt2800soc.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
deleted file mode 100644 (file)
index 9a3966c..0000000
+++ /dev/null
@@ -1,1850 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2400pci
-       Abstract: rt2400pci device specific routines.
-       Supported chipsets: RT2460.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2x00pci.h"
-#include "rt2400pci.h"
-
-/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2x00mmio_register_read and rt2x00mmio_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attempt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
-
-static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
-                               const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
-               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
-               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
-               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
-               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
-               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
-
-               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
-
-               WAIT_FOR_BBP(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, const u32 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, RFCSR_VALUE, value);
-               rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
-               rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
-               rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
-
-       eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
-       eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
-       eeprom->reg_data_clock =
-           !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
-       eeprom->reg_chip_select =
-           !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
-}
-
-static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg = 0;
-
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_CLOCK,
-                          !!eeprom->reg_data_clock);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
-                          !!eeprom->reg_chip_select);
-
-       rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt2400pci_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = rt2x00mmio_register_read,
-               .write          = rt2x00mmio_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = CSR_REG_SIZE / sizeof(u32),
-       },
-       .eeprom = {
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt2400pci_bbp_read,
-               .write          = rt2400pci_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt2400pci_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
-       return rt2x00_get_field32(reg, GPIOCSR_VAL0);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
-                                    enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       u32 reg;
-
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
-
-       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-               rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
-       else if (led->type == LED_TYPE_ACTIVITY)
-               rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
-
-       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
-}
-
-static int rt2400pci_blink_set(struct led_classdev *led_cdev,
-                              unsigned long *delay_on,
-                              unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u32 reg;
-
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
-       rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
-       rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
-       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
-
-       return 0;
-}
-
-static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00_led *led,
-                              enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt2400pci_brightness_set;
-       led->led_dev.blink_set = rt2400pci_blink_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int filter_flags)
-{
-       u32 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * since there is no filter for it at this time.
-        */
-       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-                          !rt2x00dev->intf_ap_count);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-}
-
-static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
-                                 struct rt2x00_intf *intf,
-                                 struct rt2x00intf_conf *conf,
-                                 const unsigned int flags)
-{
-       unsigned int bcn_preload;
-       u32 reg;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable beacon config
-                */
-               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
-               rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
-               rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
-
-               /*
-                * Enable synchronisation.
-                */
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-       }
-
-       if (flags & CONFIG_UPDATE_MAC)
-               rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
-                                              conf->mac, sizeof(conf->mac));
-
-       if (flags & CONFIG_UPDATE_BSSID)
-               rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
-                                              conf->bssid,
-                                              sizeof(conf->bssid));
-}
-
-static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
-                                struct rt2x00lib_erp *erp,
-                                u32 changed)
-{
-       int preamble_mask;
-       u32 reg;
-
-       /*
-        * When short preamble is enabled, we should set bit 0x08
-        */
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               preamble_mask = erp->short_preamble << 3;
-
-               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
-               rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
-               rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
-               rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-               rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
-               rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
-               rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 10));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
-               rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 20));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
-               rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 55));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
-               rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 110));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES)
-               rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-               rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
-               rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
-               rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
-               rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
-               rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
-               rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
-               rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
-               rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
-       }
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
-               rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
-                                  erp->beacon_int * 16);
-               rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
-                                  erp->beacon_int * 16);
-               rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
-       }
-}
-
-static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
-                                struct antenna_setup *ant)
-{
-       u8 r1;
-       u8 r4;
-
-       /*
-        * We should never come here because rt2x00lib is supposed
-        * to catch this and send us the correct antenna explicitely.
-        */
-       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-              ant->tx == ANTENNA_SW_DIVERSITY);
-
-       rt2400pci_bbp_read(rt2x00dev, 4, &r4);
-       rt2400pci_bbp_read(rt2x00dev, 1, &r1);
-
-       /*
-        * Configure the TX antenna.
-        */
-       switch (ant->tx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
-               break;
-       }
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
-               break;
-       }
-
-       rt2400pci_bbp_write(rt2x00dev, 4, r4);
-       rt2400pci_bbp_write(rt2x00dev, 1, r1);
-}
-
-static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
-                                    struct rf_channel *rf)
-{
-       /*
-        * Switch on tuning bits.
-        */
-       rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
-       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
-
-       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
-
-       /*
-        * RF2420 chipset don't need any additional actions.
-        */
-       if (rt2x00_rf(rt2x00dev, RF2420))
-               return;
-
-       /*
-        * For the RT2421 chipsets we need to write an invalid
-        * reference clock rate to activate auto_tune.
-        * After that we set the value back to the correct channel.
-        */
-       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32);
-       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
-
-       msleep(1);
-
-       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
-
-       msleep(1);
-
-       /*
-        * Switch off tuning bits.
-        */
-       rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
-       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
-
-       rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
-
-       /*
-        * Clear false CRC during channel switch.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
-}
-
-static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
-{
-       rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
-}
-
-static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
-                                        struct rt2x00lib_conf *libconf)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-       rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
-                          libconf->conf->long_frame_max_tx_count);
-       rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
-                          libconf->conf->short_frame_max_tx_count);
-       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-}
-
-static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u32 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
-               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
-                                  (rt2x00dev->beacon_int - 20) * 16);
-               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
-                                  libconf->conf->listen_interval - 1);
-
-               /* We must first disable autowake before it can be enabled */
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-       } else {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-       }
-
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-}
-
-static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_conf *libconf,
-                            const unsigned int flags)
-{
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt2400pci_config_channel(rt2x00dev, &libconf->rf);
-       if (flags & IEEE80211_CONF_CHANGE_POWER)
-               rt2400pci_config_txpower(rt2x00dev,
-                                        libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
-               rt2400pci_config_retry_limit(rt2x00dev, libconf);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt2400pci_config_ps(rt2x00dev, libconf);
-}
-
-static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
-                               const int cw_min, const int cw_max)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-       rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
-       rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
-       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-}
-
-/*
- * Link tuning
- */
-static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
-                                struct link_qual *qual)
-{
-       u32 reg;
-       u8 bbp;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
-
-       /*
-        * Update False CCA count from register.
-        */
-       rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
-       qual->false_cca = bbp;
-}
-
-static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
-                                    struct link_qual *qual, u8 vgc_level)
-{
-       if (qual->vgc_level_reg != vgc_level) {
-               rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
-               qual->vgc_level = vgc_level;
-               qual->vgc_level_reg = vgc_level;
-       }
-}
-
-static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
-                                 struct link_qual *qual)
-{
-       rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
-}
-
-static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
-                                struct link_qual *qual, const u32 count)
-{
-       /*
-        * The link tuner should not run longer then 60 seconds,
-        * and should run once every 2 seconds.
-        */
-       if (count > 60 || !(count & 1))
-               return;
-
-       /*
-        * Base r13 link tuning on the false cca count.
-        */
-       if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
-               rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
-       else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
-               rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
-}
-
-/*
- * Queue handlers.
- */
-static void rt2400pci_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
-               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-               rt2x00_set_field32(&reg, CSR14_TBCN, 1);
-               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2400pci_kick_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2400pci_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
-               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-               rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-               /*
-                * Wait for possibly running tbtt tasklets.
-                */
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * Initialization functions.
- */
-static bool rt2400pci_get_entry_state(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                       rt2x00_get_field32(word, TXD_W0_VALID));
-       }
-}
-
-static void rt2400pci_clear_entry(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 2, &word);
-               rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
-               rt2x00_desc_write(entry_priv->desc, 2, word);
-
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
-               rt2x00_desc_write(entry_priv->desc, 1, word);
-
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       }
-}
-
-static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct queue_entry_priv_mmio *entry_priv;
-       u32 reg;
-
-       /*
-        * Initialize registers.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
-       rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
-
-       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
-       rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
-
-       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
-       rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
-
-       entry_priv = rt2x00dev->atim->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
-       rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
-
-       entry_priv = rt2x00dev->bcn->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
-       rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
-       rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
-       rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
-
-       entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
-       rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
-
-       return 0;
-}
-
-static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
-
-       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
-       rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
-       rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
-       rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
-       rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
-       rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
-                          (rt2x00dev->rx->data_size / 128));
-       rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
-       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
-
-       rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
-       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
-       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
-       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
-       rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
-       rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 36); /* Rssi */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               return -EBUSY;
-
-       rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
-       rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
-
-       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
-       rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
-       rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
-       rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
-       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
-       rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
-       rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
-       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
-       rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
-       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
-
-       /*
-        * We must clear the FCS and FIFO error count.
-        * These registers are cleared on read,
-        * so we may pass a useless variable to store the value.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
-
-       return 0;
-}
-
-static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2400pci_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
-       u8 value;
-
-       if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev)))
-               return -EACCES;
-
-       rt2400pci_bbp_write(rt2x00dev, 1, 0x00);
-       rt2400pci_bbp_write(rt2x00dev, 3, 0x27);
-       rt2400pci_bbp_write(rt2x00dev, 4, 0x08);
-       rt2400pci_bbp_write(rt2x00dev, 10, 0x0f);
-       rt2400pci_bbp_write(rt2x00dev, 15, 0x72);
-       rt2400pci_bbp_write(rt2x00dev, 16, 0x74);
-       rt2400pci_bbp_write(rt2x00dev, 17, 0x20);
-       rt2400pci_bbp_write(rt2x00dev, 18, 0x72);
-       rt2400pci_bbp_write(rt2x00dev, 19, 0x0b);
-       rt2400pci_bbp_write(rt2x00dev, 20, 0x00);
-       rt2400pci_bbp_write(rt2x00dev, 28, 0x11);
-       rt2400pci_bbp_write(rt2x00dev, 29, 0x04);
-       rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
-       rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt2400pci_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
-                                enum dev_state state)
-{
-       int mask = (state == STATE_RADIO_IRQ_OFF);
-       u32 reg;
-       unsigned long flags;
-
-       /*
-        * When interrupts are being enabled, the interrupt registers
-        * should clear the register to assure a clean state.
-        */
-       if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
-               rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
-       }
-
-       /*
-        * Only toggle the interrupts bits we are going to use.
-        * Non-checked interrupt bits are disabled by default.
-        */
-       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
-
-       if (state == STATE_RADIO_IRQ_OFF) {
-               /*
-                * Ensure that all tasklets are finished before
-                * disabling the interrupts.
-                */
-               tasklet_kill(&rt2x00dev->txstatus_tasklet);
-               tasklet_kill(&rt2x00dev->rxdone_tasklet);
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-       }
-}
-
-static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Initialize all registers.
-        */
-       if (unlikely(rt2400pci_init_queues(rt2x00dev) ||
-                    rt2400pci_init_registers(rt2x00dev) ||
-                    rt2400pci_init_bbp(rt2x00dev)))
-               return -EIO;
-
-       return 0;
-}
-
-static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Disable power
-        */
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
-}
-
-static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       u32 reg, reg2;
-       unsigned int i;
-       char put_to_sleep;
-       char bbp_state;
-       char rf_state;
-
-       put_to_sleep = (state != STATE_AWAKE);
-
-       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
-       rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-       rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
-       rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
-       rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
-
-       /*
-        * Device is not guaranteed to be in the requested state yet.
-        * We must wait until the register indicates that the
-        * device has entered the correct state.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
-               bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
-               rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
-               if (bbp_state == state && rf_state == state)
-                       return 0;
-               rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
-               msleep(10);
-       }
-
-       return -EBUSY;
-}
-
-static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt2400pci_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               rt2400pci_disable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               rt2400pci_toggle_irq(rt2x00dev, state);
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt2400pci_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * TX descriptor initialization
- */
-static void rt2400pci_write_tx_desc(struct queue_entry *entry,
-                                   struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       __le32 *txd = entry_priv->desc;
-       u32 word;
-
-       /*
-        * Start writing the descriptor words.
-        */
-       rt2x00_desc_read(txd, 1, &word);
-       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
-       rt2x00_desc_write(txd, 1, word);
-
-       rt2x00_desc_read(txd, 2, &word);
-       rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
-       rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
-       rt2x00_desc_write(txd, 2, word);
-
-       rt2x00_desc_read(txd, 3, &word);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
-       rt2x00_desc_write(txd, 3, word);
-
-       rt2x00_desc_read(txd, 4, &word);
-       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
-                          txdesc->u.plcp.length_low);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
-       rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
-                          txdesc->u.plcp.length_high);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
-       rt2x00_desc_write(txd, 4, word);
-
-       /*
-        * Writing TXD word 0 must the last to prevent a race condition with
-        * the device, whereby the device may take hold of the TXD before we
-        * finished updating it.
-        */
-       rt2x00_desc_read(txd, 0, &word);
-       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
-       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
-       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_RTS,
-                          test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
-       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
-                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-       rt2x00_desc_write(txd, 0, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->desc = txd;
-       skbdesc->desc_len = TXD_DESC_SIZE;
-}
-
-/*
- * TX data initialization
- */
-static void rt2400pci_write_beacon(struct queue_entry *entry,
-                                  struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       u32 reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-       if (rt2x00queue_map_txskb(entry)) {
-               rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
-               goto out;
-       }
-       /*
-        * Enable beaconing again.
-        */
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
-       /*
-        * Write the TX descriptor for the beacon.
-        */
-       rt2400pci_write_tx_desc(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-out:
-       /*
-        * Enable beaconing again.
-        */
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-}
-
-/*
- * RX control handlers
- */
-static void rt2400pci_fill_rxdone(struct queue_entry *entry,
-                                 struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word0;
-       u32 word2;
-       u32 word3;
-       u32 word4;
-       u64 tsf;
-       u32 rx_low;
-       u32 rx_high;
-
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 2, &word2);
-       rt2x00_desc_read(entry_priv->desc, 3, &word3);
-       rt2x00_desc_read(entry_priv->desc, 4, &word4);
-
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
-       /*
-        * We only get the lower 32bits from the timestamp,
-        * to get the full 64bits we must complement it with
-        * the timestamp from get_tsf().
-        * Note that when a wraparound of the lower 32bits
-        * has occurred between the frame arrival and the get_tsf()
-        * call, we must decrease the higher 32bits with 1 to get
-        * to correct value.
-        */
-       tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
-       rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
-       rx_high = upper_32_bits(tsf);
-
-       if ((u32)tsf <= rx_low)
-               rx_high--;
-
-       /*
-        * Obtain the status about this packet.
-        * The signal is the PLCP value, and needs to be stripped
-        * of the preamble bit (0x08).
-        */
-       rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;
-       rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
-       rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) -
-           entry->queue->rt2x00dev->rssi_offset;
-       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
-       rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-}
-
-/*
- * Interrupt functions.
- */
-static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
-                            const enum data_queue_qid queue_idx)
-{
-       struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-       struct queue_entry_priv_mmio *entry_priv;
-       struct queue_entry *entry;
-       struct txdone_entry_desc txdesc;
-       u32 word;
-
-       while (!rt2x00queue_empty(queue)) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                   !rt2x00_get_field32(word, TXD_W0_VALID))
-                       break;
-
-               /*
-                * Obtain the status about this packet.
-                */
-               txdesc.flags = 0;
-               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
-               case 0: /* Success */
-               case 1: /* Success with retry */
-                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
-                       break;
-               case 2: /* Failure, excessive retries */
-                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
-                       /* Don't break, this is a failed frame! */
-               default: /* Failure */
-                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
-               }
-               txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-
-               rt2x00lib_txdone(entry, &txdesc);
-       }
-}
-
-static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                             struct rt2x00_field32 irq_field)
-{
-       u32 reg;
-
-       /*
-        * Enable a single interrupt. The interrupt mask register
-        * access needs locking.
-        */
-       spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, irq_field, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-static void rt2400pci_txstatus_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       u32 reg;
-
-       /*
-        * Handle all tx queues.
-        */
-       rt2400pci_txdone(rt2x00dev, QID_ATIM);
-       rt2400pci_txdone(rt2x00dev, QID_AC_VO);
-       rt2400pci_txdone(rt2x00dev, QID_AC_VI);
-
-       /*
-        * Enable all TXDONE interrupts again.
-        */
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
-               spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-               spin_unlock_irq(&rt2x00dev->irqmask_lock);
-       }
-}
-
-static void rt2400pci_tbtt_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt2x00lib_beacondone(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
-}
-
-static void rt2400pci_rxdone_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       if (rt2x00mmio_rxdone(rt2x00dev))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
-}
-
-static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
-{
-       struct rt2x00_dev *rt2x00dev = dev_instance;
-       u32 reg, mask;
-
-       /*
-        * Get the interrupt sources & saved to local variable.
-        * Write register value back to clear pending interrupts.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
-       rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
-
-       if (!reg)
-               return IRQ_NONE;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return IRQ_HANDLED;
-
-       mask = reg;
-
-       /*
-        * Schedule tasklets for interrupt handling.
-        */
-       if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
-
-       if (rt2x00_get_field32(reg, CSR7_RXDONE))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-
-       if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
-           rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
-           rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
-               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-               /*
-                * Mask out all txdone interrupts.
-                */
-               rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
-               rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
-               rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
-       }
-
-       /*
-        * Disable all interrupts for which a tasklet was scheduled right now,
-        * the tasklet will reenable the appropriate interrupts.
-        */
-       spin_lock(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       reg |= mask;
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock(&rt2x00dev->irqmask_lock);
-
-
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Device probe functions.
- */
-static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       struct eeprom_93cx6 eeprom;
-       u32 reg;
-       u16 word;
-       u8 *mac;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
-
-       eeprom.data = rt2x00dev;
-       eeprom.register_read = rt2400pci_eepromregister_read;
-       eeprom.register_write = rt2400pci_eepromregister_write;
-       eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?
-           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
-       eeprom.reg_data_in = 0;
-       eeprom.reg_data_out = 0;
-       eeprom.reg_data_clock = 0;
-       eeprom.reg_chip_select = 0;
-
-       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
-                              EEPROM_SIZE / sizeof(u16));
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-       if (word == 0xffff) {
-               rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 value;
-       u16 eeprom;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-       /*
-        * Identify RF chipset.
-        */
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, RT2460, value,
-                       rt2x00_get_field32(reg, CSR0_REVISION));
-
-       if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
-               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
-               return -ENODEV;
-       }
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->default_ant.rx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
-
-       /*
-        * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
-        * I am not 100% sure about this, but the legacy drivers do not
-        * indicate antenna swapping in software is required when
-        * diversity is enabled.
-        */
-       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
-       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
-
-       /*
-        * Store led mode, for correct led behaviour.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-
-       rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY ||
-           value == LED_MODE_DEFAULT ||
-           value == LED_MODE_ASUS)
-               rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
-                                  LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       /*
-        * Detect if this device has an hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-
-       /*
-        * Check if the BBP tuning should be enabled.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
-               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
-
-       return 0;
-}
-
-/*
- * RF value list for RF2420 & RF2421
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_b[] = {
-       { 1,  0x00022058, 0x000c1fda, 0x00000101, 0 },
-       { 2,  0x00022058, 0x000c1fee, 0x00000101, 0 },
-       { 3,  0x00022058, 0x000c2002, 0x00000101, 0 },
-       { 4,  0x00022058, 0x000c2016, 0x00000101, 0 },
-       { 5,  0x00022058, 0x000c202a, 0x00000101, 0 },
-       { 6,  0x00022058, 0x000c203e, 0x00000101, 0 },
-       { 7,  0x00022058, 0x000c2052, 0x00000101, 0 },
-       { 8,  0x00022058, 0x000c2066, 0x00000101, 0 },
-       { 9,  0x00022058, 0x000c207a, 0x00000101, 0 },
-       { 10, 0x00022058, 0x000c208e, 0x00000101, 0 },
-       { 11, 0x00022058, 0x000c20a2, 0x00000101, 0 },
-       { 12, 0x00022058, 0x000c20b6, 0x00000101, 0 },
-       { 13, 0x00022058, 0x000c20ca, 0x00000101, 0 },
-       { 14, 0x00022058, 0x000c20fa, 0x00000101, 0 },
-};
-
-static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *tx_power;
-       unsigned int i;
-
-       /*
-        * Initialize all hw fields.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2x00_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       spec->supported_rates = SUPPORT_RATE_CCK;
-
-       spec->num_channels = ARRAY_SIZE(rf_vals_b);
-       spec->channels = rf_vals_b;
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-       for (i = 0; i < 14; i++) {
-               info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
-               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
-       }
-
-       return 0;
-}
-
-static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u32 reg;
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt2400pci_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt2400pci_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
-       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
-       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt2400pci_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * This device requires the atim queue and DMA-mapped skbs.
-        */
-       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-
-/*
- * IEEE80211 stack callback functions.
- */
-static int rt2400pci_conf_tx(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif, u16 queue,
-                            const struct ieee80211_tx_queue_params *params)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * We don't support variating cw_min and cw_max variables
-        * per queue. So by default we only configure the TX queue,
-        * and ignore all other configurations.
-        */
-       if (queue != 0)
-               return -EINVAL;
-
-       if (rt2x00mac_conf_tx(hw, vif, queue, params))
-               return -EINVAL;
-
-       /*
-        * Write configuration to register.
-        */
-       rt2400pci_config_cw(rt2x00dev,
-                           rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
-
-       return 0;
-}
-
-static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u64 tsf;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
-       tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
-       tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
-
-       return tsf;
-}
-
-static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
-       return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
-}
-
-static const struct ieee80211_ops rt2400pci_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2400pci_conf_tx,
-       .get_tsf                = rt2400pci_get_tsf,
-       .tx_last_beacon         = rt2400pci_tx_last_beacon,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .flush                  = rt2x00mac_flush,
-       .set_antenna            = rt2x00mac_set_antenna,
-       .get_antenna            = rt2x00mac_get_antenna,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
-       .irq_handler            = rt2400pci_interrupt,
-       .txstatus_tasklet       = rt2400pci_txstatus_tasklet,
-       .tbtt_tasklet           = rt2400pci_tbtt_tasklet,
-       .rxdone_tasklet         = rt2400pci_rxdone_tasklet,
-       .probe_hw               = rt2400pci_probe_hw,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt2400pci_get_entry_state,
-       .clear_entry            = rt2400pci_clear_entry,
-       .set_device_state       = rt2400pci_set_device_state,
-       .rfkill_poll            = rt2400pci_rfkill_poll,
-       .link_stats             = rt2400pci_link_stats,
-       .reset_tuner            = rt2400pci_reset_tuner,
-       .link_tuner             = rt2400pci_link_tuner,
-       .start_queue            = rt2400pci_start_queue,
-       .kick_queue             = rt2400pci_kick_queue,
-       .stop_queue             = rt2400pci_stop_queue,
-       .flush_queue            = rt2x00mmio_flush_queue,
-       .write_tx_desc          = rt2400pci_write_tx_desc,
-       .write_beacon           = rt2400pci_write_beacon,
-       .fill_rxdone            = rt2400pci_fill_rxdone,
-       .config_filter          = rt2400pci_config_filter,
-       .config_intf            = rt2400pci_config_intf,
-       .config_erp             = rt2400pci_config_erp,
-       .config_ant             = rt2400pci_config_ant,
-       .config                 = rt2400pci_config,
-};
-
-static void rt2400pci_queue_init(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 24;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 24;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 1;
-               queue->data_size = MGMT_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_ATIM:
-               queue->limit = 8;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt2400pci_ops = {
-       .name                   = KBUILD_MODNAME,
-       .max_ap_intf            = 1,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2400pci_queue_init,
-       .lib                    = &rt2400pci_rt2x00_ops,
-       .hw                     = &rt2400pci_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2400pci_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * RT2400pci module information.
- */
-static const struct pci_device_id rt2400pci_device_table[] = {
-       { PCI_DEVICE(0x1814, 0x0101) },
-       { 0, }
-};
-
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
-MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
-MODULE_LICENSE("GPL");
-
-static int rt2400pci_probe(struct pci_dev *pci_dev,
-                          const struct pci_device_id *id)
-{
-       return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
-}
-
-static struct pci_driver rt2400pci_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt2400pci_device_table,
-       .probe          = rt2400pci_probe,
-       .remove         = rt2x00pci_remove,
-       .suspend        = rt2x00pci_suspend,
-       .resume         = rt2x00pci_resume,
-};
-
-module_pci_driver(rt2400pci_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
deleted file mode 100644 (file)
index 0fd3a9d..0000000
+++ /dev/null
@@ -1,961 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2400pci
-       Abstract: Data structures and registers for the rt2400pci module.
-       Supported chipsets: RT2460.
- */
-
-#ifndef RT2400PCI_H
-#define RT2400PCI_H
-
-/*
- * RF chip defines.
- */
-#define RF2420                         0x0000
-#define RF2421                         0x0001
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET            100
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x0000
-#define CSR_REG_SIZE                   0x014c
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x0100
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x0020
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x000c
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  2
-
-/*
- * Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * CSR0: ASIC revision number.
- */
-#define CSR0                           0x0000
-#define CSR0_REVISION                  FIELD32(0x0000ffff)
-
-/*
- * CSR1: System control register.
- * SOFT_RESET: Software reset, 1: reset, 0: normal.
- * BBP_RESET: Hardware reset, 1: reset, 0, release.
- * HOST_READY: Host ready after initialization.
- */
-#define CSR1                           0x0004
-#define CSR1_SOFT_RESET                        FIELD32(0x00000001)
-#define CSR1_BBP_RESET                 FIELD32(0x00000002)
-#define CSR1_HOST_READY                        FIELD32(0x00000004)
-
-/*
- * CSR2: System admin status register (invalid).
- */
-#define CSR2                           0x0008
-
-/*
- * CSR3: STA MAC address register 0.
- */
-#define CSR3                           0x000c
-#define CSR3_BYTE0                     FIELD32(0x000000ff)
-#define CSR3_BYTE1                     FIELD32(0x0000ff00)
-#define CSR3_BYTE2                     FIELD32(0x00ff0000)
-#define CSR3_BYTE3                     FIELD32(0xff000000)
-
-/*
- * CSR4: STA MAC address register 1.
- */
-#define CSR4                           0x0010
-#define CSR4_BYTE4                     FIELD32(0x000000ff)
-#define CSR4_BYTE5                     FIELD32(0x0000ff00)
-
-/*
- * CSR5: BSSID register 0.
- */
-#define CSR5                           0x0014
-#define CSR5_BYTE0                     FIELD32(0x000000ff)
-#define CSR5_BYTE1                     FIELD32(0x0000ff00)
-#define CSR5_BYTE2                     FIELD32(0x00ff0000)
-#define CSR5_BYTE3                     FIELD32(0xff000000)
-
-/*
- * CSR6: BSSID register 1.
- */
-#define CSR6                           0x0018
-#define CSR6_BYTE4                     FIELD32(0x000000ff)
-#define CSR6_BYTE5                     FIELD32(0x0000ff00)
-
-/*
- * CSR7: Interrupt source register.
- * Write 1 to clear interrupt.
- * TBCN_EXPIRE: Beacon timer expired interrupt.
- * TWAKE_EXPIRE: Wakeup timer expired interrupt.
- * TATIMW_EXPIRE: Timer of atim window expired interrupt.
- * TXDONE_TXRING: Tx ring transmit done interrupt.
- * TXDONE_ATIMRING: Atim ring transmit done interrupt.
- * TXDONE_PRIORING: Priority ring transmit done interrupt.
- * RXDONE: Receive done interrupt.
- */
-#define CSR7                           0x001c
-#define CSR7_TBCN_EXPIRE               FIELD32(0x00000001)
-#define CSR7_TWAKE_EXPIRE              FIELD32(0x00000002)
-#define CSR7_TATIMW_EXPIRE             FIELD32(0x00000004)
-#define CSR7_TXDONE_TXRING             FIELD32(0x00000008)
-#define CSR7_TXDONE_ATIMRING           FIELD32(0x00000010)
-#define CSR7_TXDONE_PRIORING           FIELD32(0x00000020)
-#define CSR7_RXDONE                    FIELD32(0x00000040)
-
-/*
- * CSR8: Interrupt mask register.
- * Write 1 to mask interrupt.
- * TBCN_EXPIRE: Beacon timer expired interrupt.
- * TWAKE_EXPIRE: Wakeup timer expired interrupt.
- * TATIMW_EXPIRE: Timer of atim window expired interrupt.
- * TXDONE_TXRING: Tx ring transmit done interrupt.
- * TXDONE_ATIMRING: Atim ring transmit done interrupt.
- * TXDONE_PRIORING: Priority ring transmit done interrupt.
- * RXDONE: Receive done interrupt.
- */
-#define CSR8                           0x0020
-#define CSR8_TBCN_EXPIRE               FIELD32(0x00000001)
-#define CSR8_TWAKE_EXPIRE              FIELD32(0x00000002)
-#define CSR8_TATIMW_EXPIRE             FIELD32(0x00000004)
-#define CSR8_TXDONE_TXRING             FIELD32(0x00000008)
-#define CSR8_TXDONE_ATIMRING           FIELD32(0x00000010)
-#define CSR8_TXDONE_PRIORING           FIELD32(0x00000020)
-#define CSR8_RXDONE                    FIELD32(0x00000040)
-
-/*
- * CSR9: Maximum frame length register.
- * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12.
- */
-#define CSR9                           0x0024
-#define CSR9_MAX_FRAME_UNIT            FIELD32(0x00000f80)
-
-/*
- * CSR11: Back-off control register.
- * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1).
- * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1).
- * SLOT_TIME: Slot time, default is 20us for 802.11b.
- * LONG_RETRY: Long retry count.
- * SHORT_RETRY: Short retry count.
- */
-#define CSR11                          0x002c
-#define CSR11_CWMIN                    FIELD32(0x0000000f)
-#define CSR11_CWMAX                    FIELD32(0x000000f0)
-#define CSR11_SLOT_TIME                        FIELD32(0x00001f00)
-#define CSR11_LONG_RETRY               FIELD32(0x00ff0000)
-#define CSR11_SHORT_RETRY              FIELD32(0xff000000)
-
-/*
- * CSR12: Synchronization configuration register 0.
- * All units in 1/16 TU.
- * BEACON_INTERVAL: Beacon interval, default is 100 TU.
- * CFPMAX_DURATION: Cfp maximum duration, default is 100 TU.
- */
-#define CSR12                          0x0030
-#define CSR12_BEACON_INTERVAL          FIELD32(0x0000ffff)
-#define CSR12_CFP_MAX_DURATION         FIELD32(0xffff0000)
-
-/*
- * CSR13: Synchronization configuration register 1.
- * All units in 1/16 TU.
- * ATIMW_DURATION: Atim window duration.
- * CFP_PERIOD: Cfp period, default is 0 TU.
- */
-#define CSR13                          0x0034
-#define CSR13_ATIMW_DURATION           FIELD32(0x0000ffff)
-#define CSR13_CFP_PERIOD               FIELD32(0x00ff0000)
-
-/*
- * CSR14: Synchronization control register.
- * TSF_COUNT: Enable tsf auto counting.
- * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
- * TBCN: Enable tbcn with reload value.
- * TCFP: Enable tcfp & cfp / cp switching.
- * TATIMW: Enable tatimw & atim window switching.
- * BEACON_GEN: Enable beacon generator.
- * CFP_COUNT_PRELOAD: Cfp count preload value.
- * TBCM_PRELOAD: Tbcn preload value in units of 64us.
- */
-#define CSR14                          0x0038
-#define CSR14_TSF_COUNT                        FIELD32(0x00000001)
-#define CSR14_TSF_SYNC                 FIELD32(0x00000006)
-#define CSR14_TBCN                     FIELD32(0x00000008)
-#define CSR14_TCFP                     FIELD32(0x00000010)
-#define CSR14_TATIMW                   FIELD32(0x00000020)
-#define CSR14_BEACON_GEN               FIELD32(0x00000040)
-#define CSR14_CFP_COUNT_PRELOAD                FIELD32(0x0000ff00)
-#define CSR14_TBCM_PRELOAD             FIELD32(0xffff0000)
-
-/*
- * CSR15: Synchronization status register.
- * CFP: ASIC is in contention-free period.
- * ATIMW: ASIC is in ATIM window.
- * BEACON_SENT: Beacon is send.
- */
-#define CSR15                          0x003c
-#define CSR15_CFP                      FIELD32(0x00000001)
-#define CSR15_ATIMW                    FIELD32(0x00000002)
-#define CSR15_BEACON_SENT              FIELD32(0x00000004)
-
-/*
- * CSR16: TSF timer register 0.
- */
-#define CSR16                          0x0040
-#define CSR16_LOW_TSFTIMER             FIELD32(0xffffffff)
-
-/*
- * CSR17: TSF timer register 1.
- */
-#define CSR17                          0x0044
-#define CSR17_HIGH_TSFTIMER            FIELD32(0xffffffff)
-
-/*
- * CSR18: IFS timer register 0.
- * SIFS: Sifs, default is 10 us.
- * PIFS: Pifs, default is 30 us.
- */
-#define CSR18                          0x0048
-#define CSR18_SIFS                     FIELD32(0x0000ffff)
-#define CSR18_PIFS                     FIELD32(0xffff0000)
-
-/*
- * CSR19: IFS timer register 1.
- * DIFS: Difs, default is 50 us.
- * EIFS: Eifs, default is 364 us.
- */
-#define CSR19                          0x004c
-#define CSR19_DIFS                     FIELD32(0x0000ffff)
-#define CSR19_EIFS                     FIELD32(0xffff0000)
-
-/*
- * CSR20: Wakeup timer register.
- * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU.
- * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
- * AUTOWAKE: Enable auto wakeup / sleep mechanism.
- */
-#define CSR20                          0x0050
-#define CSR20_DELAY_AFTER_TBCN         FIELD32(0x0000ffff)
-#define CSR20_TBCN_BEFORE_WAKEUP       FIELD32(0x00ff0000)
-#define CSR20_AUTOWAKE                 FIELD32(0x01000000)
-
-/*
- * CSR21: EEPROM control register.
- * RELOAD: Write 1 to reload eeprom content.
- * TYPE_93C46: 1: 93c46, 0:93c66.
- */
-#define CSR21                          0x0054
-#define CSR21_RELOAD                   FIELD32(0x00000001)
-#define CSR21_EEPROM_DATA_CLOCK                FIELD32(0x00000002)
-#define CSR21_EEPROM_CHIP_SELECT       FIELD32(0x00000004)
-#define CSR21_EEPROM_DATA_IN           FIELD32(0x00000008)
-#define CSR21_EEPROM_DATA_OUT          FIELD32(0x00000010)
-#define CSR21_TYPE_93C46               FIELD32(0x00000020)
-
-/*
- * CSR22: CFP control register.
- * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU.
- * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain.
- */
-#define CSR22                          0x0058
-#define CSR22_CFP_DURATION_REMAIN      FIELD32(0x0000ffff)
-#define CSR22_RELOAD_CFP_DURATION      FIELD32(0x00010000)
-
-/*
- * Transmit related CSRs.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * TXCSR0: TX Control Register.
- * KICK_TX: Kick tx ring.
- * KICK_ATIM: Kick atim ring.
- * KICK_PRIO: Kick priority ring.
- * ABORT: Abort all transmit related ring operation.
- */
-#define TXCSR0                         0x0060
-#define TXCSR0_KICK_TX                 FIELD32(0x00000001)
-#define TXCSR0_KICK_ATIM               FIELD32(0x00000002)
-#define TXCSR0_KICK_PRIO               FIELD32(0x00000004)
-#define TXCSR0_ABORT                   FIELD32(0x00000008)
-
-/*
- * TXCSR1: TX Configuration Register.
- * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps.
- * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps.
- * TSF_OFFSET: Insert tsf offset.
- * AUTORESPONDER: Enable auto responder which include ack & cts.
- */
-#define TXCSR1                         0x0064
-#define TXCSR1_ACK_TIMEOUT             FIELD32(0x000001ff)
-#define TXCSR1_ACK_CONSUME_TIME                FIELD32(0x0003fe00)
-#define TXCSR1_TSF_OFFSET              FIELD32(0x00fc0000)
-#define TXCSR1_AUTORESPONDER           FIELD32(0x01000000)
-
-/*
- * TXCSR2: Tx descriptor configuration register.
- * TXD_SIZE: Tx descriptor size, default is 48.
- * NUM_TXD: Number of tx entries in ring.
- * NUM_ATIM: Number of atim entries in ring.
- * NUM_PRIO: Number of priority entries in ring.
- */
-#define TXCSR2                         0x0068
-#define TXCSR2_TXD_SIZE                        FIELD32(0x000000ff)
-#define TXCSR2_NUM_TXD                 FIELD32(0x0000ff00)
-#define TXCSR2_NUM_ATIM                        FIELD32(0x00ff0000)
-#define TXCSR2_NUM_PRIO                        FIELD32(0xff000000)
-
-/*
- * TXCSR3: TX Ring Base address register.
- */
-#define TXCSR3                         0x006c
-#define TXCSR3_TX_RING_REGISTER                FIELD32(0xffffffff)
-
-/*
- * TXCSR4: TX Atim Ring Base address register.
- */
-#define TXCSR4                         0x0070
-#define TXCSR4_ATIM_RING_REGISTER      FIELD32(0xffffffff)
-
-/*
- * TXCSR5: TX Prio Ring Base address register.
- */
-#define TXCSR5                         0x0074
-#define TXCSR5_PRIO_RING_REGISTER      FIELD32(0xffffffff)
-
-/*
- * TXCSR6: Beacon Base address register.
- */
-#define TXCSR6                         0x0078
-#define TXCSR6_BEACON_RING_REGISTER    FIELD32(0xffffffff)
-
-/*
- * TXCSR7: Auto responder control register.
- * AR_POWERMANAGEMENT: Auto responder power management bit.
- */
-#define TXCSR7                         0x007c
-#define TXCSR7_AR_POWERMANAGEMENT      FIELD32(0x00000001)
-
-/*
- * Receive related CSRs.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * RXCSR0: RX Control Register.
- * DISABLE_RX: Disable rx engine.
- * DROP_CRC: Drop crc error.
- * DROP_PHYSICAL: Drop physical error.
- * DROP_CONTROL: Drop control frame.
- * DROP_NOT_TO_ME: Drop not to me unicast frame.
- * DROP_TODS: Drop frame tods bit is true.
- * DROP_VERSION_ERROR: Drop version error frame.
- * PASS_CRC: Pass all packets with crc attached.
- */
-#define RXCSR0                         0x0080
-#define RXCSR0_DISABLE_RX              FIELD32(0x00000001)
-#define RXCSR0_DROP_CRC                        FIELD32(0x00000002)
-#define RXCSR0_DROP_PHYSICAL           FIELD32(0x00000004)
-#define RXCSR0_DROP_CONTROL            FIELD32(0x00000008)
-#define RXCSR0_DROP_NOT_TO_ME          FIELD32(0x00000010)
-#define RXCSR0_DROP_TODS               FIELD32(0x00000020)
-#define RXCSR0_DROP_VERSION_ERROR      FIELD32(0x00000040)
-#define RXCSR0_PASS_CRC                        FIELD32(0x00000080)
-
-/*
- * RXCSR1: RX descriptor configuration register.
- * RXD_SIZE: Rx descriptor size, default is 32b.
- * NUM_RXD: Number of rx entries in ring.
- */
-#define RXCSR1                         0x0084
-#define RXCSR1_RXD_SIZE                        FIELD32(0x000000ff)
-#define RXCSR1_NUM_RXD                 FIELD32(0x0000ff00)
-
-/*
- * RXCSR2: RX Ring base address register.
- */
-#define RXCSR2                         0x0088
-#define RXCSR2_RX_RING_REGISTER                FIELD32(0xffffffff)
-
-/*
- * RXCSR3: BBP ID register for Rx operation.
- * BBP_ID#: BBP register # id.
- * BBP_ID#_VALID: BBP register # id is valid or not.
- */
-#define RXCSR3                         0x0090
-#define RXCSR3_BBP_ID0                 FIELD32(0x0000007f)
-#define RXCSR3_BBP_ID0_VALID           FIELD32(0x00000080)
-#define RXCSR3_BBP_ID1                 FIELD32(0x00007f00)
-#define RXCSR3_BBP_ID1_VALID           FIELD32(0x00008000)
-#define RXCSR3_BBP_ID2                 FIELD32(0x007f0000)
-#define RXCSR3_BBP_ID2_VALID           FIELD32(0x00800000)
-#define RXCSR3_BBP_ID3                 FIELD32(0x7f000000)
-#define RXCSR3_BBP_ID3_VALID           FIELD32(0x80000000)
-
-/*
- * RXCSR4: BBP ID register for Rx operation.
- * BBP_ID#: BBP register # id.
- * BBP_ID#_VALID: BBP register # id is valid or not.
- */
-#define RXCSR4                         0x0094
-#define RXCSR4_BBP_ID4                 FIELD32(0x0000007f)
-#define RXCSR4_BBP_ID4_VALID           FIELD32(0x00000080)
-#define RXCSR4_BBP_ID5                 FIELD32(0x00007f00)
-#define RXCSR4_BBP_ID5_VALID           FIELD32(0x00008000)
-
-/*
- * ARCSR0: Auto Responder PLCP config register 0.
- * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data.
- * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id.
- */
-#define ARCSR0                         0x0098
-#define ARCSR0_AR_BBP_DATA0            FIELD32(0x000000ff)
-#define ARCSR0_AR_BBP_ID0              FIELD32(0x0000ff00)
-#define ARCSR0_AR_BBP_DATA1            FIELD32(0x00ff0000)
-#define ARCSR0_AR_BBP_ID1              FIELD32(0xff000000)
-
-/*
- * ARCSR1: Auto Responder PLCP config register 1.
- * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data.
- * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id.
- */
-#define ARCSR1                         0x009c
-#define ARCSR1_AR_BBP_DATA2            FIELD32(0x000000ff)
-#define ARCSR1_AR_BBP_ID2              FIELD32(0x0000ff00)
-#define ARCSR1_AR_BBP_DATA3            FIELD32(0x00ff0000)
-#define ARCSR1_AR_BBP_ID3              FIELD32(0xff000000)
-
-/*
- * Miscellaneous Registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * PCICSR: PCI control register.
- * BIG_ENDIAN: 1: big endian, 0: little endian.
- * RX_TRESHOLD: Rx threshold in dw to start pci access
- * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
- * TX_TRESHOLD: Tx threshold in dw to start pci access
- * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward.
- * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw.
- * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational.
- */
-#define PCICSR                         0x008c
-#define PCICSR_BIG_ENDIAN              FIELD32(0x00000001)
-#define PCICSR_RX_TRESHOLD             FIELD32(0x00000006)
-#define PCICSR_TX_TRESHOLD             FIELD32(0x00000018)
-#define PCICSR_BURST_LENTH             FIELD32(0x00000060)
-#define PCICSR_ENABLE_CLK              FIELD32(0x00000080)
-
-/*
- * CNT0: FCS error count.
- * FCS_ERROR: FCS error count, cleared when read.
- */
-#define CNT0                           0x00a0
-#define CNT0_FCS_ERROR                 FIELD32(0x0000ffff)
-
-/*
- * Statistic Register.
- * CNT1: PLCP error count.
- * CNT2: Long error count.
- * CNT3: CCA false alarm count.
- * CNT4: Rx FIFO overflow count.
- * CNT5: Tx FIFO underrun count.
- */
-#define TIMECSR2                       0x00a8
-#define CNT1                           0x00ac
-#define CNT2                           0x00b0
-#define TIMECSR3                       0x00b4
-#define CNT3                           0x00b8
-#define CNT4                           0x00bc
-#define CNT5                           0x00c0
-
-/*
- * Baseband Control Register.
- */
-
-/*
- * PWRCSR0: Power mode configuration register.
- */
-#define PWRCSR0                                0x00c4
-
-/*
- * Power state transition time registers.
- */
-#define PSCSR0                         0x00c8
-#define PSCSR1                         0x00cc
-#define PSCSR2                         0x00d0
-#define PSCSR3                         0x00d4
-
-/*
- * PWRCSR1: Manual power control / status register.
- * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
- * SET_STATE: Set state. Write 1 to trigger, self cleared.
- * BBP_DESIRE_STATE: BBP desired state.
- * RF_DESIRE_STATE: RF desired state.
- * BBP_CURR_STATE: BBP current state.
- * RF_CURR_STATE: RF current state.
- * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
- */
-#define PWRCSR1                                0x00d8
-#define PWRCSR1_SET_STATE              FIELD32(0x00000001)
-#define PWRCSR1_BBP_DESIRE_STATE       FIELD32(0x00000006)
-#define PWRCSR1_RF_DESIRE_STATE                FIELD32(0x00000018)
-#define PWRCSR1_BBP_CURR_STATE         FIELD32(0x00000060)
-#define PWRCSR1_RF_CURR_STATE          FIELD32(0x00000180)
-#define PWRCSR1_PUT_TO_SLEEP           FIELD32(0x00000200)
-
-/*
- * TIMECSR: Timer control register.
- * US_COUNT: 1 us timer count in units of clock cycles.
- * US_64_COUNT: 64 us timer count in units of 1 us timer.
- * BEACON_EXPECT: Beacon expect window.
- */
-#define TIMECSR                                0x00dc
-#define TIMECSR_US_COUNT               FIELD32(0x000000ff)
-#define TIMECSR_US_64_COUNT            FIELD32(0x0000ff00)
-#define TIMECSR_BEACON_EXPECT          FIELD32(0x00070000)
-
-/*
- * MACCSR0: MAC configuration register 0.
- */
-#define MACCSR0                                0x00e0
-
-/*
- * MACCSR1: MAC configuration register 1.
- * KICK_RX: Kick one-shot rx in one-shot rx mode.
- * ONESHOT_RXMODE: Enable one-shot rx mode for debugging.
- * BBPRX_RESET_MODE: Ralink bbp rx reset mode.
- * AUTO_TXBBP: Auto tx logic access bbp control register.
- * AUTO_RXBBP: Auto rx logic access bbp control register.
- * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd.
- * INTERSIL_IF: Intersil if calibration pin.
- */
-#define MACCSR1                                0x00e4
-#define MACCSR1_KICK_RX                        FIELD32(0x00000001)
-#define MACCSR1_ONESHOT_RXMODE         FIELD32(0x00000002)
-#define MACCSR1_BBPRX_RESET_MODE       FIELD32(0x00000004)
-#define MACCSR1_AUTO_TXBBP             FIELD32(0x00000008)
-#define MACCSR1_AUTO_RXBBP             FIELD32(0x00000010)
-#define MACCSR1_LOOPBACK               FIELD32(0x00000060)
-#define MACCSR1_INTERSIL_IF            FIELD32(0x00000080)
-
-/*
- * RALINKCSR: Ralink Rx auto-reset BBCR.
- * AR_BBP_DATA#: Auto reset BBP register # data.
- * AR_BBP_ID#: Auto reset BBP register # id.
- */
-#define RALINKCSR                      0x00e8
-#define RALINKCSR_AR_BBP_DATA0         FIELD32(0x000000ff)
-#define RALINKCSR_AR_BBP_ID0           FIELD32(0x0000ff00)
-#define RALINKCSR_AR_BBP_DATA1         FIELD32(0x00ff0000)
-#define RALINKCSR_AR_BBP_ID1           FIELD32(0xff000000)
-
-/*
- * BCNCSR: Beacon interval control register.
- * CHANGE: Write one to change beacon interval.
- * DELTATIME: The delta time value.
- * NUM_BEACON: Number of beacon according to mode.
- * MODE: Please refer to asic specs.
- * PLUS: Plus or minus delta time value.
- */
-#define BCNCSR                         0x00ec
-#define BCNCSR_CHANGE                  FIELD32(0x00000001)
-#define BCNCSR_DELTATIME               FIELD32(0x0000001e)
-#define BCNCSR_NUM_BEACON              FIELD32(0x00001fe0)
-#define BCNCSR_MODE                    FIELD32(0x00006000)
-#define BCNCSR_PLUS                    FIELD32(0x00008000)
-
-/*
- * BBP / RF / IF Control Register.
- */
-
-/*
- * BBPCSR: BBP serial control register.
- * VALUE: Register value to program into BBP.
- * REGNUM: Selected BBP register.
- * BUSY: 1: asic is busy execute BBP programming.
- * WRITE_CONTROL: 1: write BBP, 0: read BBP.
- */
-#define BBPCSR                         0x00f0
-#define BBPCSR_VALUE                   FIELD32(0x000000ff)
-#define BBPCSR_REGNUM                  FIELD32(0x00007f00)
-#define BBPCSR_BUSY                    FIELD32(0x00008000)
-#define BBPCSR_WRITE_CONTROL           FIELD32(0x00010000)
-
-/*
- * RFCSR: RF serial control register.
- * VALUE: Register value + id to program into rf/if.
- * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
- * IF_SELECT: Chip to program: 0: rf, 1: if.
- * PLL_LD: Rf pll_ld status.
- * BUSY: 1: asic is busy execute rf programming.
- */
-#define RFCSR                          0x00f4
-#define RFCSR_VALUE                    FIELD32(0x00ffffff)
-#define RFCSR_NUMBER_OF_BITS           FIELD32(0x1f000000)
-#define RFCSR_IF_SELECT                        FIELD32(0x20000000)
-#define RFCSR_PLL_LD                   FIELD32(0x40000000)
-#define RFCSR_BUSY                     FIELD32(0x80000000)
-
-/*
- * LEDCSR: LED control register.
- * ON_PERIOD: On period, default 70ms.
- * OFF_PERIOD: Off period, default 30ms.
- * LINK: 0: linkoff, 1: linkup.
- * ACTIVITY: 0: idle, 1: active.
- */
-#define LEDCSR                         0x00f8
-#define LEDCSR_ON_PERIOD               FIELD32(0x000000ff)
-#define LEDCSR_OFF_PERIOD              FIELD32(0x0000ff00)
-#define LEDCSR_LINK                    FIELD32(0x00010000)
-#define LEDCSR_ACTIVITY                        FIELD32(0x00020000)
-
-/*
- * ASIC pointer information.
- * RXPTR: Current RX ring address.
- * TXPTR: Current Tx ring address.
- * PRIPTR: Current Priority ring address.
- * ATIMPTR: Current ATIM ring address.
- */
-#define RXPTR                          0x0100
-#define TXPTR                          0x0104
-#define PRIPTR                         0x0108
-#define ATIMPTR                                0x010c
-
-/*
- * GPIO and others.
- */
-
-/*
- * GPIOCSR: GPIO control register.
- *     GPIOCSR_VALx: Actual GPIO pin x value
- *     GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
- */
-#define GPIOCSR                                0x0120
-#define GPIOCSR_VAL0                   FIELD32(0x00000001)
-#define GPIOCSR_VAL1                   FIELD32(0x00000002)
-#define GPIOCSR_VAL2                   FIELD32(0x00000004)
-#define GPIOCSR_VAL3                   FIELD32(0x00000008)
-#define GPIOCSR_VAL4                   FIELD32(0x00000010)
-#define GPIOCSR_VAL5                   FIELD32(0x00000020)
-#define GPIOCSR_VAL6                   FIELD32(0x00000040)
-#define GPIOCSR_VAL7                   FIELD32(0x00000080)
-#define GPIOCSR_DIR0                   FIELD32(0x00000100)
-#define GPIOCSR_DIR1                   FIELD32(0x00000200)
-#define GPIOCSR_DIR2                   FIELD32(0x00000400)
-#define GPIOCSR_DIR3                   FIELD32(0x00000800)
-#define GPIOCSR_DIR4                   FIELD32(0x00001000)
-#define GPIOCSR_DIR5                   FIELD32(0x00002000)
-#define GPIOCSR_DIR6                   FIELD32(0x00004000)
-#define GPIOCSR_DIR7                   FIELD32(0x00008000)
-
-/*
- * BBPPCSR: BBP Pin control register.
- */
-#define BBPPCSR                                0x0124
-
-/*
- * BCNCSR1: Tx BEACON offset time control register.
- * PRELOAD: Beacon timer offset in units of usec.
- */
-#define BCNCSR1                                0x0130
-#define BCNCSR1_PRELOAD                        FIELD32(0x0000ffff)
-
-/*
- * MACCSR2: TX_PE to RX_PE turn-around time control register
- * DELAY: RX_PE low width, in units of pci clock cycle.
- */
-#define MACCSR2                                0x0134
-#define MACCSR2_DELAY                  FIELD32(0x000000ff)
-
-/*
- * ARCSR2: 1 Mbps ACK/CTS PLCP.
- */
-#define ARCSR2                         0x013c
-#define ARCSR2_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR2_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR2_LENGTH_LOW              FIELD32(0x00ff0000)
-#define ARCSR2_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR3: 2 Mbps ACK/CTS PLCP.
- */
-#define ARCSR3                         0x0140
-#define ARCSR3_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR3_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR3_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR4: 5.5 Mbps ACK/CTS PLCP.
- */
-#define ARCSR4                         0x0144
-#define ARCSR4_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR4_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR4_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR5: 11 Mbps ACK/CTS PLCP.
- */
-#define ARCSR5                         0x0148
-#define ARCSR5_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR5_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR5_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * R1: TX antenna control
- */
-#define BBP_R1_TX_ANTENNA              FIELD8(0x03)
-
-/*
- * R4: RX antenna control
- */
-#define BBP_R4_RX_ANTENNA              FIELD8(0x06)
-
-/*
- * RF registers
- */
-
-/*
- * RF 1
- */
-#define RF1_TUNER                      FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TUNER                      FIELD32(0x00000100)
-#define RF3_TXPOWER                    FIELD32(0x00003e00)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0              0x0002
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR1               0x0003
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2              0x0004
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM antenna.
- * ANTENNA_NUM: Number of antenna's.
- * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RF_TYPE: Rf_type of this adapter.
- * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd.
- * RX_AGCVGC: 0: disable, 1:enable BBP R13 tuning.
- * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
- */
-#define EEPROM_ANTENNA                 0x0b
-#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
-#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
-#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
-#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0x0040)
-#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x0180)
-#define EEPROM_ANTENNA_RX_AGCVGC_TUNING        FIELD16(0x0200)
-#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START               0x0c
-#define EEPROM_BBP_SIZE                        7
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER
- */
-#define EEPROM_TXPOWER_START           0x13
-#define EEPROM_TXPOWER_SIZE            7
-#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
-#define EEPROM_TXPOWER_2               FIELD16(0xff00)
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  (8 * sizeof(__le32))
-#define RXD_DESC_SIZE                  (8 * sizeof(__le32))
-
-/*
- * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define TXD_W0_VALID                   FIELD32(0x00000002)
-#define TXD_W0_RESULT                  FIELD32(0x0000001c)
-#define TXD_W0_RETRY_COUNT             FIELD32(0x000000e0)
-#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
-#define TXD_W0_ACK                     FIELD32(0x00000200)
-#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
-#define TXD_W0_RTS                     FIELD32(0x00000800)
-#define TXD_W0_IFS                     FIELD32(0x00006000)
-#define TXD_W0_RETRY_MODE              FIELD32(0x00008000)
-#define TXD_W0_AGC                     FIELD32(0x00ff0000)
-#define TXD_W0_R2                      FIELD32(0xff000000)
-
-/*
- * Word1
- */
-#define TXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
-
-/*
- * Word2
- */
-#define TXD_W2_BUFFER_LENGTH           FIELD32(0x0000ffff)
-#define TXD_W2_DATABYTE_COUNT          FIELD32(0xffff0000)
-
-/*
- * Word3 & 4: PLCP information
- * The PLCP values should be treated as if they were BBP values.
- */
-#define TXD_W3_PLCP_SIGNAL             FIELD32(0x000000ff)
-#define TXD_W3_PLCP_SIGNAL_REGNUM      FIELD32(0x00007f00)
-#define TXD_W3_PLCP_SIGNAL_BUSY                FIELD32(0x00008000)
-#define TXD_W3_PLCP_SERVICE            FIELD32(0x00ff0000)
-#define TXD_W3_PLCP_SERVICE_REGNUM     FIELD32(0x7f000000)
-#define TXD_W3_PLCP_SERVICE_BUSY       FIELD32(0x80000000)
-
-#define TXD_W4_PLCP_LENGTH_LOW         FIELD32(0x000000ff)
-#define TXD_W3_PLCP_LENGTH_LOW_REGNUM  FIELD32(0x00007f00)
-#define TXD_W3_PLCP_LENGTH_LOW_BUSY    FIELD32(0x00008000)
-#define TXD_W4_PLCP_LENGTH_HIGH                FIELD32(0x00ff0000)
-#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM FIELD32(0x7f000000)
-#define TXD_W3_PLCP_LENGTH_HIGH_BUSY   FIELD32(0x80000000)
-
-/*
- * Word5
- */
-#define TXD_W5_BBCR4                   FIELD32(0x0000ffff)
-#define TXD_W5_AGC_REG                 FIELD32(0x007f0000)
-#define TXD_W5_AGC_REG_VALID           FIELD32(0x00800000)
-#define TXD_W5_XXX_REG                 FIELD32(0x7f000000)
-#define TXD_W5_XXX_REG_VALID           FIELD32(0x80000000)
-
-/*
- * Word6
- */
-#define TXD_W6_SK_BUFF                 FIELD32(0xffffffff)
-
-/*
- * Word7
- */
-#define TXD_W7_RESERVED                        FIELD32(0xffffffff)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- */
-#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
-#define RXD_W0_MULTICAST               FIELD32(0x00000004)
-#define RXD_W0_BROADCAST               FIELD32(0x00000008)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
-#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
-#define RXD_W0_DATABYTE_COUNT          FIELD32(0xffff0000)
-
-/*
- * Word1
- */
-#define RXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
-
-/*
- * Word2
- */
-#define RXD_W2_BUFFER_LENGTH           FIELD32(0x0000ffff)
-#define RXD_W2_BBR0                    FIELD32(0x00ff0000)
-#define RXD_W2_SIGNAL                  FIELD32(0xff000000)
-
-/*
- * Word3
- */
-#define RXD_W3_RSSI                    FIELD32(0x000000ff)
-#define RXD_W3_BBR3                    FIELD32(0x0000ff00)
-#define RXD_W3_BBR4                    FIELD32(0x00ff0000)
-#define RXD_W3_BBR5                    FIELD32(0xff000000)
-
-/*
- * Word4
- */
-#define RXD_W4_RX_END_TIME             FIELD32(0xffffffff)
-
-/*
- * Word5 & 6 & 7: Reserved
- */
-#define RXD_W5_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W6_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W7_RESERVED                        FIELD32(0xffffffff)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- * NOTE: Logics in rt2400pci for txpower are reversed
- * compared to the other rt2x00 drivers. A higher txpower
- * value means that the txpower must be lowered. This is
- * important when converting the value coming from the
- * mac80211 stack to the rt2400 acceptable value.
- */
-#define MIN_TXPOWER    31
-#define MAX_TXPOWER    62
-#define DEFAULT_TXPOWER        39
-
-#define __CLAMP_TX(__txpower) \
-       clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER)
-
-#define TXPOWER_FROM_DEV(__txpower) \
-       ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
-
-#define TXPOWER_TO_DEV(__txpower) \
-       (MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER))
-
-#endif /* RT2400PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
deleted file mode 100644 (file)
index 1a6740b..0000000
+++ /dev/null
@@ -1,2148 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2500pci
-       Abstract: rt2500pci device specific routines.
-       Supported chipsets: RT2560.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2x00pci.h"
-#include "rt2500pci.h"
-
-/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2x00mmio_register_read and rt2x00mmio_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
-
-static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
-                               const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
-               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
-               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
-               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
-               rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
-               rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
-
-               rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
-
-               WAIT_FOR_BBP(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, BBPCSR_VALUE);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, const u32 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, RFCSR_VALUE, value);
-               rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
-               rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
-               rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
-
-       eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
-       eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
-       eeprom->reg_data_clock =
-           !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
-       eeprom->reg_chip_select =
-           !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
-}
-
-static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg = 0;
-
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_DATA_CLOCK,
-                          !!eeprom->reg_data_clock);
-       rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
-                          !!eeprom->reg_chip_select);
-
-       rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt2500pci_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = rt2x00mmio_register_read,
-               .write          = rt2x00mmio_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = CSR_REG_SIZE / sizeof(u32),
-       },
-       .eeprom = {
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt2500pci_bbp_read,
-               .write          = rt2500pci_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt2500pci_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
-       return rt2x00_get_field32(reg, GPIOCSR_VAL0);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
-                                    enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       u32 reg;
-
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
-
-       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-               rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
-       else if (led->type == LED_TYPE_ACTIVITY)
-               rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
-
-       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
-}
-
-static int rt2500pci_blink_set(struct led_classdev *led_cdev,
-                              unsigned long *delay_on,
-                              unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u32 reg;
-
-       rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
-       rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
-       rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
-       rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
-
-       return 0;
-}
-
-static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00_led *led,
-                              enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt2500pci_brightness_set;
-       led->led_dev.blink_set = rt2500pci_blink_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int filter_flags)
-{
-       u32 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * and broadcast frames will always be accepted since
-        * there is no filter for it at this time.
-        */
-       rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-                          !rt2x00dev->intf_ap_count);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-       rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
-                          !(filter_flags & FIF_ALLMULTI));
-       rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-}
-
-static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
-                                 struct rt2x00_intf *intf,
-                                 struct rt2x00intf_conf *conf,
-                                 const unsigned int flags)
-{
-       struct data_queue *queue = rt2x00dev->bcn;
-       unsigned int bcn_preload;
-       u32 reg;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable beacon config
-                */
-               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
-               rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
-               rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
-               rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
-
-               /*
-                * Enable synchronisation.
-                */
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-       }
-
-       if (flags & CONFIG_UPDATE_MAC)
-               rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
-                                             conf->mac, sizeof(conf->mac));
-
-       if (flags & CONFIG_UPDATE_BSSID)
-               rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
-                                             conf->bssid, sizeof(conf->bssid));
-}
-
-static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
-                                struct rt2x00lib_erp *erp,
-                                u32 changed)
-{
-       int preamble_mask;
-       u32 reg;
-
-       /*
-        * When short preamble is enabled, we should set bit 0x08
-        */
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               preamble_mask = erp->short_preamble << 3;
-
-               rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
-               rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
-               rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
-               rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
-               rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
-               rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
-               rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 10));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
-               rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 20));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
-               rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 55));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
-               rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
-               rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
-               rt2x00_set_field32(&reg, ARCSR2_LENGTH,
-                                  GET_DURATION(ACK_SIZE, 110));
-               rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES)
-               rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-               rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
-               rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
-               rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
-               rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
-               rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
-               rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
-               rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
-               rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
-       }
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
-               rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
-                                  erp->beacon_int * 16);
-               rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
-                                  erp->beacon_int * 16);
-               rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
-       }
-
-}
-
-static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
-                                struct antenna_setup *ant)
-{
-       u32 reg;
-       u8 r14;
-       u8 r2;
-
-       /*
-        * We should never come here because rt2x00lib is supposed
-        * to catch this and send us the correct antenna explicitely.
-        */
-       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-              ant->tx == ANTENNA_SW_DIVERSITY);
-
-       rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
-       rt2500pci_bbp_read(rt2x00dev, 14, &r14);
-       rt2500pci_bbp_read(rt2x00dev, 2, &r2);
-
-       /*
-        * Configure the TX antenna.
-        */
-       switch (ant->tx) {
-       case ANTENNA_A:
-               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
-               rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
-               rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
-               rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
-               rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
-               break;
-       }
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_A:
-               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
-               break;
-       }
-
-       /*
-        * RT2525E and RT5222 need to flip TX I/Q
-        */
-       if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
-               rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
-               rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
-               rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
-
-               /*
-                * RT2525E does not need RX I/Q Flip.
-                */
-               if (rt2x00_rf(rt2x00dev, RF2525E))
-                       rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
-       } else {
-               rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
-               rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
-       }
-
-       rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg);
-       rt2500pci_bbp_write(rt2x00dev, 14, r14);
-       rt2500pci_bbp_write(rt2x00dev, 2, r2);
-}
-
-static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
-                                    struct rf_channel *rf, const int txpower)
-{
-       u8 r70;
-
-       /*
-        * Set TXpower.
-        */
-       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-
-       /*
-        * Switch on tuning bits.
-        * For RT2523 devices we do not need to update the R1 register.
-        */
-       if (!rt2x00_rf(rt2x00dev, RF2523))
-               rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
-       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
-
-       /*
-        * For RT2525 we should first set the channel to half band higher.
-        */
-       if (rt2x00_rf(rt2x00dev, RF2525)) {
-               static const u32 vals[] = {
-                       0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a,
-                       0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a,
-                       0x00080d1e, 0x00080d22, 0x00080d26, 0x00080d2a,
-                       0x00080d2e, 0x00080d3a
-               };
-
-               rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
-               rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
-               rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
-               if (rf->rf4)
-                       rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
-       }
-
-       rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2500pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
-       if (rf->rf4)
-               rt2500pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-       /*
-        * Channel 14 requires the Japan filter bit to be set.
-        */
-       r70 = 0x46;
-       rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14);
-       rt2500pci_bbp_write(rt2x00dev, 70, r70);
-
-       msleep(1);
-
-       /*
-        * Switch off tuning bits.
-        * For RT2523 devices we do not need to update the R1 register.
-        */
-       if (!rt2x00_rf(rt2x00dev, RF2523)) {
-               rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
-               rt2500pci_rf_write(rt2x00dev, 1, rf->rf1);
-       }
-
-       rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
-       rt2500pci_rf_write(rt2x00dev, 3, rf->rf3);
-
-       /*
-        * Clear false CRC during channel switch.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
-}
-
-static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                    const int txpower)
-{
-       u32 rf3;
-
-       rt2x00_rf_read(rt2x00dev, 3, &rf3);
-       rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-       rt2500pci_rf_write(rt2x00dev, 3, rf3);
-}
-
-static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
-                                        struct rt2x00lib_conf *libconf)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-       rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
-                          libconf->conf->long_frame_max_tx_count);
-       rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
-                          libconf->conf->short_frame_max_tx_count);
-       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-}
-
-static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u32 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
-               rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
-                                  (rt2x00dev->beacon_int - 20) * 16);
-               rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
-                                  libconf->conf->listen_interval - 1);
-
-               /* We must first disable autowake before it can be enabled */
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-       } else {
-               rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
-               rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
-       }
-
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-}
-
-static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_conf *libconf,
-                            const unsigned int flags)
-{
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt2500pci_config_channel(rt2x00dev, &libconf->rf,
-                                        libconf->conf->power_level);
-       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
-           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
-               rt2500pci_config_txpower(rt2x00dev,
-                                        libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
-               rt2500pci_config_retry_limit(rt2x00dev, libconf);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt2500pci_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
-                                struct link_qual *qual)
-{
-       u32 reg;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
-
-       /*
-        * Update False CCA count from register.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
-       qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
-}
-
-static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev,
-                                    struct link_qual *qual, u8 vgc_level)
-{
-       if (qual->vgc_level_reg != vgc_level) {
-               rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
-               qual->vgc_level = vgc_level;
-               qual->vgc_level_reg = vgc_level;
-       }
-}
-
-static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
-                                 struct link_qual *qual)
-{
-       rt2500pci_set_vgc(rt2x00dev, qual, 0x48);
-}
-
-static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev,
-                                struct link_qual *qual, const u32 count)
-{
-       /*
-        * To prevent collisions with MAC ASIC on chipsets
-        * up to version C the link tuning should halt after 20
-        * seconds while being associated.
-        */
-       if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D &&
-           rt2x00dev->intf_associated && count > 20)
-               return;
-
-       /*
-        * Chipset versions C and lower should directly continue
-        * to the dynamic CCA tuning. Chipset version D and higher
-        * should go straight to dynamic CCA tuning when they
-        * are not associated.
-        */
-       if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D ||
-           !rt2x00dev->intf_associated)
-               goto dynamic_cca_tune;
-
-       /*
-        * A too low RSSI will cause too much false CCA which will
-        * then corrupt the R17 tuning. To remidy this the tuning should
-        * be stopped (While making sure the R17 value will not exceed limits)
-        */
-       if (qual->rssi < -80 && count > 20) {
-               if (qual->vgc_level_reg >= 0x41)
-                       rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
-               return;
-       }
-
-       /*
-        * Special big-R17 for short distance
-        */
-       if (qual->rssi >= -58) {
-               rt2500pci_set_vgc(rt2x00dev, qual, 0x50);
-               return;
-       }
-
-       /*
-        * Special mid-R17 for middle distance
-        */
-       if (qual->rssi >= -74) {
-               rt2500pci_set_vgc(rt2x00dev, qual, 0x41);
-               return;
-       }
-
-       /*
-        * Leave short or middle distance condition, restore r17
-        * to the dynamic tuning range.
-        */
-       if (qual->vgc_level_reg >= 0x41) {
-               rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level);
-               return;
-       }
-
-dynamic_cca_tune:
-
-       /*
-        * R17 is inside the dynamic tuning range,
-        * start tuning the link based on the false cca counter.
-        */
-       if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40)
-               rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg);
-       else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32)
-               rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
-}
-
-/*
- * Queue handlers.
- */
-static void rt2500pci_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
-               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-               rt2x00_set_field32(&reg, CSR14_TBCN, 1);
-               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2500pci_kick_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2500pci_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_ATIM:
-               rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
-               rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
-               break;
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
-               rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
-               rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-               rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-               rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-               rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-               /*
-                * Wait for possibly running tbtt tasklets.
-                */
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * Initialization functions.
- */
-static bool rt2500pci_get_entry_state(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                       rt2x00_get_field32(word, TXD_W0_VALID));
-       }
-}
-
-static void rt2500pci_clear_entry(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
-               rt2x00_desc_write(entry_priv->desc, 1, word);
-
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       }
-}
-
-static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct queue_entry_priv_mmio *entry_priv;
-       u32 reg;
-
-       /*
-        * Initialize registers.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
-       rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
-       rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
-
-       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
-       rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
-
-       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
-       rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
-
-       entry_priv = rt2x00dev->atim->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
-       rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
-
-       entry_priv = rt2x00dev->bcn->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
-       rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
-       rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
-       rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
-
-       entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
-       rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
-
-       return 0;
-}
-
-static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
-       rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
-
-       rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
-       rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
-       rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
-       rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
-       rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
-       rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
-                          rt2x00dev->rx->data_size / 128);
-       rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
-
-       /*
-        * Always use CWmin and CWmax set in descriptor.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
-       rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
-       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
-
-       rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID0, 10);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID1, 11);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID2, 13);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID3, 12);
-       rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
-       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_1MBS, 112);
-       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_2MBS, 56);
-       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_5_5MBS, 20);
-       rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_11MBS, 10);
-       rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
-       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_6MBS, 45);
-       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_9MBS, 37);
-       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_12MBS, 33);
-       rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_18MBS, 29);
-       rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
-       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_24MBS, 29);
-       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_36MBS, 25);
-       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_48MBS, 25);
-       rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_54MBS, 25);
-       rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 47); /* CCK Signal */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 51); /* Rssi */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 42); /* OFDM Rate */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID3, 51); /* RSSI */
-       rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
-       rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
-       rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
-       rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
-       rt2x00_set_field32(&reg, PCICSR_BURST_LENTH, 1);
-       rt2x00_set_field32(&reg, PCICSR_ENABLE_CLK, 1);
-       rt2x00_set_field32(&reg, PCICSR_READ_MULTIPLE, 1);
-       rt2x00_set_field32(&reg, PCICSR_WRITE_INVALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, PCICSR, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
-
-       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
-       rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0);
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               return -EBUSY;
-
-       rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
-       rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
-
-       rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
-       rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
-       rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 26);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID0, 1);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 26);
-       rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID1, 1);
-       rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200);
-
-       rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
-       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
-       rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
-       rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
-       rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
-       rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
-       rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
-
-       /*
-        * We must clear the FCS and FIFO error count.
-        * These registers are cleared on read,
-        * so we may pass a useless variable to store the value.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
-
-       return 0;
-}
-
-static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2500pci_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
-       u8 value;
-
-       if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev)))
-               return -EACCES;
-
-       rt2500pci_bbp_write(rt2x00dev, 3, 0x02);
-       rt2500pci_bbp_write(rt2x00dev, 4, 0x19);
-       rt2500pci_bbp_write(rt2x00dev, 14, 0x1c);
-       rt2500pci_bbp_write(rt2x00dev, 15, 0x30);
-       rt2500pci_bbp_write(rt2x00dev, 16, 0xac);
-       rt2500pci_bbp_write(rt2x00dev, 18, 0x18);
-       rt2500pci_bbp_write(rt2x00dev, 19, 0xff);
-       rt2500pci_bbp_write(rt2x00dev, 20, 0x1e);
-       rt2500pci_bbp_write(rt2x00dev, 21, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 22, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 23, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 24, 0x70);
-       rt2500pci_bbp_write(rt2x00dev, 25, 0x40);
-       rt2500pci_bbp_write(rt2x00dev, 26, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 27, 0x23);
-       rt2500pci_bbp_write(rt2x00dev, 30, 0x10);
-       rt2500pci_bbp_write(rt2x00dev, 31, 0x2b);
-       rt2500pci_bbp_write(rt2x00dev, 32, 0xb9);
-       rt2500pci_bbp_write(rt2x00dev, 34, 0x12);
-       rt2500pci_bbp_write(rt2x00dev, 35, 0x50);
-       rt2500pci_bbp_write(rt2x00dev, 39, 0xc4);
-       rt2500pci_bbp_write(rt2x00dev, 40, 0x02);
-       rt2500pci_bbp_write(rt2x00dev, 41, 0x60);
-       rt2500pci_bbp_write(rt2x00dev, 53, 0x10);
-       rt2500pci_bbp_write(rt2x00dev, 54, 0x18);
-       rt2500pci_bbp_write(rt2x00dev, 56, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 57, 0x10);
-       rt2500pci_bbp_write(rt2x00dev, 58, 0x08);
-       rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
-       rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt2500pci_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
-                                enum dev_state state)
-{
-       int mask = (state == STATE_RADIO_IRQ_OFF);
-       u32 reg;
-       unsigned long flags;
-
-       /*
-        * When interrupts are being enabled, the interrupt registers
-        * should clear the register to assure a clean state.
-        */
-       if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
-               rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
-       }
-
-       /*
-        * Only toggle the interrupts bits we are going to use.
-        * Non-checked interrupt bits are disabled by default.
-        */
-       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
-
-       if (state == STATE_RADIO_IRQ_OFF) {
-               /*
-                * Ensure that all tasklets are finished.
-                */
-               tasklet_kill(&rt2x00dev->txstatus_tasklet);
-               tasklet_kill(&rt2x00dev->rxdone_tasklet);
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-       }
-}
-
-static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Initialize all registers.
-        */
-       if (unlikely(rt2500pci_init_queues(rt2x00dev) ||
-                    rt2500pci_init_registers(rt2x00dev) ||
-                    rt2500pci_init_bbp(rt2x00dev)))
-               return -EIO;
-
-       return 0;
-}
-
-static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Disable power
-        */
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
-}
-
-static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       u32 reg, reg2;
-       unsigned int i;
-       char put_to_sleep;
-       char bbp_state;
-       char rf_state;
-
-       put_to_sleep = (state != STATE_AWAKE);
-
-       rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
-       rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
-       rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
-       rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
-       rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
-       rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
-
-       /*
-        * Device is not guaranteed to be in the requested state yet.
-        * We must wait until the register indicates that the
-        * device has entered the correct state.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
-               bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
-               rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
-               if (bbp_state == state && rf_state == state)
-                       return 0;
-               rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
-               msleep(10);
-       }
-
-       return -EBUSY;
-}
-
-static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt2500pci_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               rt2500pci_disable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               rt2500pci_toggle_irq(rt2x00dev, state);
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt2500pci_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * TX descriptor initialization
- */
-static void rt2500pci_write_tx_desc(struct queue_entry *entry,
-                                   struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       __le32 *txd = entry_priv->desc;
-       u32 word;
-
-       /*
-        * Start writing the descriptor words.
-        */
-       rt2x00_desc_read(txd, 1, &word);
-       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
-       rt2x00_desc_write(txd, 1, word);
-
-       rt2x00_desc_read(txd, 2, &word);
-       rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
-       rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
-       rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
-       rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
-       rt2x00_desc_write(txd, 2, word);
-
-       rt2x00_desc_read(txd, 3, &word);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
-                          txdesc->u.plcp.length_low);
-       rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH,
-                          txdesc->u.plcp.length_high);
-       rt2x00_desc_write(txd, 3, word);
-
-       rt2x00_desc_read(txd, 10, &word);
-       rt2x00_set_field32(&word, TXD_W10_RTS,
-                          test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
-       rt2x00_desc_write(txd, 10, word);
-
-       /*
-        * Writing TXD word 0 must the last to prevent a race condition with
-        * the device, whereby the device may take hold of the TXD before we
-        * finished updating it.
-        */
-       rt2x00_desc_read(txd, 0, &word);
-       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
-       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
-       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          (txdesc->rate_mode == RATE_MODE_OFDM));
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
-       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
-       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
-                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
-       rt2x00_desc_write(txd, 0, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->desc = txd;
-       skbdesc->desc_len = TXD_DESC_SIZE;
-}
-
-/*
- * TX data initialization
- */
-static void rt2500pci_write_beacon(struct queue_entry *entry,
-                                  struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       u32 reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-
-       if (rt2x00queue_map_txskb(entry)) {
-               rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
-               goto out;
-       }
-
-       /*
-        * Write the TX descriptor for the beacon.
-        */
-       rt2500pci_write_tx_desc(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-out:
-       /*
-        * Enable beaconing again.
-        */
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
-       rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
-}
-
-/*
- * RX control handlers
- */
-static void rt2500pci_fill_rxdone(struct queue_entry *entry,
-                                 struct rxdone_entry_desc *rxdesc)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word0;
-       u32 word2;
-
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 2, &word2);
-
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
-       /*
-        * Obtain the status about this packet.
-        * When frame was received with an OFDM bitrate,
-        * the signal is the PLCP value. If it was received with
-        * a CCK bitrate the signal is the rate in 100kbit/s.
-        */
-       rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-       rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
-           entry->queue->rt2x00dev->rssi_offset;
-       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
-       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-       else
-               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
-       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-}
-
-/*
- * Interrupt functions.
- */
-static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
-                            const enum data_queue_qid queue_idx)
-{
-       struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-       struct queue_entry_priv_mmio *entry_priv;
-       struct queue_entry *entry;
-       struct txdone_entry_desc txdesc;
-       u32 word;
-
-       while (!rt2x00queue_empty(queue)) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                   !rt2x00_get_field32(word, TXD_W0_VALID))
-                       break;
-
-               /*
-                * Obtain the status about this packet.
-                */
-               txdesc.flags = 0;
-               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
-               case 0: /* Success */
-               case 1: /* Success with retry */
-                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
-                       break;
-               case 2: /* Failure, excessive retries */
-                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
-                       /* Don't break, this is a failed frame! */
-               default: /* Failure */
-                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
-               }
-               txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-
-               rt2x00lib_txdone(entry, &txdesc);
-       }
-}
-
-static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                             struct rt2x00_field32 irq_field)
-{
-       u32 reg;
-
-       /*
-        * Enable a single interrupt. The interrupt mask register
-        * access needs locking.
-        */
-       spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, irq_field, 0);
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-static void rt2500pci_txstatus_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       u32 reg;
-
-       /*
-        * Handle all tx queues.
-        */
-       rt2500pci_txdone(rt2x00dev, QID_ATIM);
-       rt2500pci_txdone(rt2x00dev, QID_AC_VO);
-       rt2500pci_txdone(rt2x00dev, QID_AC_VI);
-
-       /*
-        * Enable all TXDONE interrupts again.
-        */
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
-               spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-               rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
-               rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
-               rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-               spin_unlock_irq(&rt2x00dev->irqmask_lock);
-       }
-}
-
-static void rt2500pci_tbtt_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt2x00lib_beacondone(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
-}
-
-static void rt2500pci_rxdone_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       if (rt2x00mmio_rxdone(rt2x00dev))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
-}
-
-static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
-{
-       struct rt2x00_dev *rt2x00dev = dev_instance;
-       u32 reg, mask;
-
-       /*
-        * Get the interrupt sources & saved to local variable.
-        * Write register value back to clear pending interrupts.
-        */
-       rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
-       rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
-
-       if (!reg)
-               return IRQ_NONE;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return IRQ_HANDLED;
-
-       mask = reg;
-
-       /*
-        * Schedule tasklets for interrupt handling.
-        */
-       if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
-
-       if (rt2x00_get_field32(reg, CSR7_RXDONE))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-
-       if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
-           rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
-           rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
-               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-               /*
-                * Mask out all txdone interrupts.
-                */
-               rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
-               rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
-               rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
-       }
-
-       /*
-        * Disable all interrupts for which a tasklet was scheduled right now,
-        * the tasklet will reenable the appropriate interrupts.
-        */
-       spin_lock(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
-       reg |= mask;
-       rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
-
-       spin_unlock(&rt2x00dev->irqmask_lock);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Device probe functions.
- */
-static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       struct eeprom_93cx6 eeprom;
-       u32 reg;
-       u16 word;
-       u8 *mac;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
-
-       eeprom.data = rt2x00dev;
-       eeprom.register_read = rt2500pci_eepromregister_read;
-       eeprom.register_write = rt2500pci_eepromregister_write;
-       eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ?
-           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
-       eeprom.reg_data_in = 0;
-       eeprom.reg_data_out = 0;
-       eeprom.reg_data_clock = 0;
-       eeprom.reg_chip_select = 0;
-
-       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
-                              EEPROM_SIZE / sizeof(u16));
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
-                                  ANTENNA_SW_DIVERSITY);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
-                                  ANTENNA_SW_DIVERSITY);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
-                                  LED_MODE_DEFAULT);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
-                                  DEFAULT_RSSI_OFFSET);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
-                                 word);
-       }
-
-       return 0;
-}
-
-static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 value;
-       u16 eeprom;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-       /*
-        * Identify RF chipset.
-        */
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, RT2560, value,
-                       rt2x00_get_field32(reg, CSR0_REVISION));
-
-       if (!rt2x00_rf(rt2x00dev, RF2522) &&
-           !rt2x00_rf(rt2x00dev, RF2523) &&
-           !rt2x00_rf(rt2x00dev, RF2524) &&
-           !rt2x00_rf(rt2x00dev, RF2525) &&
-           !rt2x00_rf(rt2x00dev, RF2525E) &&
-           !rt2x00_rf(rt2x00dev, RF5222)) {
-               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
-               return -ENODEV;
-       }
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->default_ant.rx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
-
-       /*
-        * Store led mode, for correct led behaviour.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-
-       rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY ||
-           value == LED_MODE_DEFAULT ||
-           value == LED_MODE_ASUS)
-               rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
-                                  LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       /*
-        * Detect if this device has an hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) {
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-               /*
-                * On this device RFKILL initialized during probe does not work.
-                */
-               __set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags);
-       }
-
-       /*
-        * Check if the BBP tuning should be enabled.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
-       if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
-               __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
-
-       /*
-        * Read the RSSI <-> dBm offset information.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
-       rt2x00dev->rssi_offset =
-           rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
-
-       return 0;
-}
-
-/*
- * RF value list for RF2522
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2522[] = {
-       { 1,  0x00002050, 0x000c1fda, 0x00000101, 0 },
-       { 2,  0x00002050, 0x000c1fee, 0x00000101, 0 },
-       { 3,  0x00002050, 0x000c2002, 0x00000101, 0 },
-       { 4,  0x00002050, 0x000c2016, 0x00000101, 0 },
-       { 5,  0x00002050, 0x000c202a, 0x00000101, 0 },
-       { 6,  0x00002050, 0x000c203e, 0x00000101, 0 },
-       { 7,  0x00002050, 0x000c2052, 0x00000101, 0 },
-       { 8,  0x00002050, 0x000c2066, 0x00000101, 0 },
-       { 9,  0x00002050, 0x000c207a, 0x00000101, 0 },
-       { 10, 0x00002050, 0x000c208e, 0x00000101, 0 },
-       { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 },
-       { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 },
-       { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 },
-       { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 },
-};
-
-/*
- * RF value list for RF2523
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2523[] = {
-       { 1,  0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b },
-       { 2,  0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b },
-       { 3,  0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b },
-       { 4,  0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b },
-       { 5,  0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b },
-       { 6,  0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b },
-       { 7,  0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b },
-       { 8,  0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b },
-       { 9,  0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b },
-       { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b },
-       { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b },
-       { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b },
-       { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b },
-       { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2524
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2524[] = {
-       { 1,  0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b },
-       { 2,  0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b },
-       { 3,  0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b },
-       { 4,  0x00032020, 0x00000caa, 0x00000101, 0x00000a1b },
-       { 5,  0x00032020, 0x00000cae, 0x00000101, 0x00000a1b },
-       { 6,  0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b },
-       { 7,  0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b },
-       { 8,  0x00032020, 0x00000cba, 0x00000101, 0x00000a1b },
-       { 9,  0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b },
-       { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b },
-       { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b },
-       { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b },
-       { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b },
-       { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2525
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2525[] = {
-       { 1,  0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b },
-       { 2,  0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b },
-       { 3,  0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b },
-       { 4,  0x00022020, 0x00080caa, 0x00060111, 0x00000a1b },
-       { 5,  0x00022020, 0x00080cae, 0x00060111, 0x00000a1b },
-       { 6,  0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b },
-       { 7,  0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b },
-       { 8,  0x00022020, 0x00080cba, 0x00060111, 0x00000a1b },
-       { 9,  0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b },
-       { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b },
-       { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b },
-       { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b },
-       { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b },
-       { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2525e
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2525e[] = {
-       { 1,  0x00022020, 0x00081136, 0x00060111, 0x00000a0b },
-       { 2,  0x00022020, 0x0008113a, 0x00060111, 0x00000a0b },
-       { 3,  0x00022020, 0x0008113e, 0x00060111, 0x00000a0b },
-       { 4,  0x00022020, 0x00081182, 0x00060111, 0x00000a0b },
-       { 5,  0x00022020, 0x00081186, 0x00060111, 0x00000a0b },
-       { 6,  0x00022020, 0x0008118a, 0x00060111, 0x00000a0b },
-       { 7,  0x00022020, 0x0008118e, 0x00060111, 0x00000a0b },
-       { 8,  0x00022020, 0x00081192, 0x00060111, 0x00000a0b },
-       { 9,  0x00022020, 0x00081196, 0x00060111, 0x00000a0b },
-       { 10, 0x00022020, 0x0008119a, 0x00060111, 0x00000a0b },
-       { 11, 0x00022020, 0x0008119e, 0x00060111, 0x00000a0b },
-       { 12, 0x00022020, 0x000811a2, 0x00060111, 0x00000a0b },
-       { 13, 0x00022020, 0x000811a6, 0x00060111, 0x00000a0b },
-       { 14, 0x00022020, 0x000811ae, 0x00060111, 0x00000a1b },
-};
-
-/*
- * RF value list for RF5222
- * Supports: 2.4 GHz & 5.2 GHz
- */
-static const struct rf_channel rf_vals_5222[] = {
-       { 1,  0x00022020, 0x00001136, 0x00000101, 0x00000a0b },
-       { 2,  0x00022020, 0x0000113a, 0x00000101, 0x00000a0b },
-       { 3,  0x00022020, 0x0000113e, 0x00000101, 0x00000a0b },
-       { 4,  0x00022020, 0x00001182, 0x00000101, 0x00000a0b },
-       { 5,  0x00022020, 0x00001186, 0x00000101, 0x00000a0b },
-       { 6,  0x00022020, 0x0000118a, 0x00000101, 0x00000a0b },
-       { 7,  0x00022020, 0x0000118e, 0x00000101, 0x00000a0b },
-       { 8,  0x00022020, 0x00001192, 0x00000101, 0x00000a0b },
-       { 9,  0x00022020, 0x00001196, 0x00000101, 0x00000a0b },
-       { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b },
-       { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b },
-       { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b },
-       { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b },
-       { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f },
-       { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f },
-       { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f },
-       { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f },
-       { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f },
-       { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f },
-       { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f },
-       { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f },
-       { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f },
-       { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f },
-       { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f },
-       { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f },
-       { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f },
-       { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f },
-       { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f },
-       { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f },
-       { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f },
-
-       /* 802.11 UNII */
-       { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f },
-       { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 },
-       { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 },
-       { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 },
-       { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
-};
-
-static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *tx_power;
-       unsigned int i;
-
-       /*
-        * Initialize all hw fields.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2x00_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * Disable powersaving as default.
-        */
-       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-       if (rt2x00_rf(rt2x00dev, RF2522)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
-               spec->channels = rf_vals_bg_2522;
-       } else if (rt2x00_rf(rt2x00dev, RF2523)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
-               spec->channels = rf_vals_bg_2523;
-       } else if (rt2x00_rf(rt2x00dev, RF2524)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
-               spec->channels = rf_vals_bg_2524;
-       } else if (rt2x00_rf(rt2x00dev, RF2525)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
-               spec->channels = rf_vals_bg_2525;
-       } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
-               spec->channels = rf_vals_bg_2525e;
-       } else if (rt2x00_rf(rt2x00dev, RF5222)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_5222);
-               spec->channels = rf_vals_5222;
-       }
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-       for (i = 0; i < 14; i++) {
-               info[i].max_power = MAX_TXPOWER;
-               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
-       }
-
-       if (spec->num_channels > 14) {
-               for (i = 14; i < spec->num_channels; i++) {
-                       info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 = DEFAULT_TXPOWER;
-               }
-       }
-
-       return 0;
-}
-
-static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u32 reg;
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt2500pci_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt2500pci_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
-       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
-       rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt2500pci_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * This device requires the atim queue and DMA-mapped skbs.
-        */
-       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-
-/*
- * IEEE80211 stack callback functions.
- */
-static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u64 tsf;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
-       tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
-       tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
-
-       return tsf;
-}
-
-static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
-       return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
-}
-
-static const struct ieee80211_ops rt2500pci_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2x00mac_conf_tx,
-       .get_tsf                = rt2500pci_get_tsf,
-       .tx_last_beacon         = rt2500pci_tx_last_beacon,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .flush                  = rt2x00mac_flush,
-       .set_antenna            = rt2x00mac_set_antenna,
-       .get_antenna            = rt2x00mac_get_antenna,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
-       .irq_handler            = rt2500pci_interrupt,
-       .txstatus_tasklet       = rt2500pci_txstatus_tasklet,
-       .tbtt_tasklet           = rt2500pci_tbtt_tasklet,
-       .rxdone_tasklet         = rt2500pci_rxdone_tasklet,
-       .probe_hw               = rt2500pci_probe_hw,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt2500pci_get_entry_state,
-       .clear_entry            = rt2500pci_clear_entry,
-       .set_device_state       = rt2500pci_set_device_state,
-       .rfkill_poll            = rt2500pci_rfkill_poll,
-       .link_stats             = rt2500pci_link_stats,
-       .reset_tuner            = rt2500pci_reset_tuner,
-       .link_tuner             = rt2500pci_link_tuner,
-       .start_queue            = rt2500pci_start_queue,
-       .kick_queue             = rt2500pci_kick_queue,
-       .stop_queue             = rt2500pci_stop_queue,
-       .flush_queue            = rt2x00mmio_flush_queue,
-       .write_tx_desc          = rt2500pci_write_tx_desc,
-       .write_beacon           = rt2500pci_write_beacon,
-       .fill_rxdone            = rt2500pci_fill_rxdone,
-       .config_filter          = rt2500pci_config_filter,
-       .config_intf            = rt2500pci_config_intf,
-       .config_erp             = rt2500pci_config_erp,
-       .config_ant             = rt2500pci_config_ant,
-       .config                 = rt2500pci_config,
-};
-
-static void rt2500pci_queue_init(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 1;
-               queue->data_size = MGMT_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_ATIM:
-               queue->limit = 8;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt2500pci_ops = {
-       .name                   = KBUILD_MODNAME,
-       .max_ap_intf            = 1,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2500pci_queue_init,
-       .lib                    = &rt2500pci_rt2x00_ops,
-       .hw                     = &rt2500pci_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2500pci_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * RT2500pci module information.
- */
-static const struct pci_device_id rt2500pci_device_table[] = {
-       { PCI_DEVICE(0x1814, 0x0201) },
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2500 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
-MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
-MODULE_LICENSE("GPL");
-
-static int rt2500pci_probe(struct pci_dev *pci_dev,
-                          const struct pci_device_id *id)
-{
-       return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
-}
-
-static struct pci_driver rt2500pci_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt2500pci_device_table,
-       .probe          = rt2500pci_probe,
-       .remove         = rt2x00pci_remove,
-       .suspend        = rt2x00pci_suspend,
-       .resume         = rt2x00pci_resume,
-};
-
-module_pci_driver(rt2500pci_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
deleted file mode 100644 (file)
index 573e87b..0000000
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2500pci
-       Abstract: Data structures and registers for the rt2500pci module.
-       Supported chipsets: RT2560.
- */
-
-#ifndef RT2500PCI_H
-#define RT2500PCI_H
-
-/*
- * RF chip defines.
- */
-#define RF2522                         0x0000
-#define RF2523                         0x0001
-#define RF2524                         0x0002
-#define RF2525                         0x0003
-#define RF2525E                                0x0004
-#define RF5222                         0x0010
-
-/*
- * RT2560 version
- */
-#define RT2560_VERSION_B               2
-#define RT2560_VERSION_C               3
-#define RT2560_VERSION_D               4
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET            121
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x0000
-#define CSR_REG_SIZE                   0x0174
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x0200
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x0040
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  2
-
-/*
- * Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * CSR0: ASIC revision number.
- */
-#define CSR0                           0x0000
-#define CSR0_REVISION                  FIELD32(0x0000ffff)
-
-/*
- * CSR1: System control register.
- * SOFT_RESET: Software reset, 1: reset, 0: normal.
- * BBP_RESET: Hardware reset, 1: reset, 0, release.
- * HOST_READY: Host ready after initialization.
- */
-#define CSR1                           0x0004
-#define CSR1_SOFT_RESET                        FIELD32(0x00000001)
-#define CSR1_BBP_RESET                 FIELD32(0x00000002)
-#define CSR1_HOST_READY                        FIELD32(0x00000004)
-
-/*
- * CSR2: System admin status register (invalid).
- */
-#define CSR2                           0x0008
-
-/*
- * CSR3: STA MAC address register 0.
- */
-#define CSR3                           0x000c
-#define CSR3_BYTE0                     FIELD32(0x000000ff)
-#define CSR3_BYTE1                     FIELD32(0x0000ff00)
-#define CSR3_BYTE2                     FIELD32(0x00ff0000)
-#define CSR3_BYTE3                     FIELD32(0xff000000)
-
-/*
- * CSR4: STA MAC address register 1.
- */
-#define CSR4                           0x0010
-#define CSR4_BYTE4                     FIELD32(0x000000ff)
-#define CSR4_BYTE5                     FIELD32(0x0000ff00)
-
-/*
- * CSR5: BSSID register 0.
- */
-#define CSR5                           0x0014
-#define CSR5_BYTE0                     FIELD32(0x000000ff)
-#define CSR5_BYTE1                     FIELD32(0x0000ff00)
-#define CSR5_BYTE2                     FIELD32(0x00ff0000)
-#define CSR5_BYTE3                     FIELD32(0xff000000)
-
-/*
- * CSR6: BSSID register 1.
- */
-#define CSR6                           0x0018
-#define CSR6_BYTE4                     FIELD32(0x000000ff)
-#define CSR6_BYTE5                     FIELD32(0x0000ff00)
-
-/*
- * CSR7: Interrupt source register.
- * Write 1 to clear.
- * TBCN_EXPIRE: Beacon timer expired interrupt.
- * TWAKE_EXPIRE: Wakeup timer expired interrupt.
- * TATIMW_EXPIRE: Timer of atim window expired interrupt.
- * TXDONE_TXRING: Tx ring transmit done interrupt.
- * TXDONE_ATIMRING: Atim ring transmit done interrupt.
- * TXDONE_PRIORING: Priority ring transmit done interrupt.
- * RXDONE: Receive done interrupt.
- * DECRYPTION_DONE: Decryption done interrupt.
- * ENCRYPTION_DONE: Encryption done interrupt.
- * UART1_TX_TRESHOLD: UART1 TX reaches threshold.
- * UART1_RX_TRESHOLD: UART1 RX reaches threshold.
- * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold.
- * UART1_TX_BUFF_ERROR: UART1 TX buffer error.
- * UART1_RX_BUFF_ERROR: UART1 RX buffer error.
- * UART2_TX_TRESHOLD: UART2 TX reaches threshold.
- * UART2_RX_TRESHOLD: UART2 RX reaches threshold.
- * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold.
- * UART2_TX_BUFF_ERROR: UART2 TX buffer error.
- * UART2_RX_BUFF_ERROR: UART2 RX buffer error.
- * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period).
-
- */
-#define CSR7                           0x001c
-#define CSR7_TBCN_EXPIRE               FIELD32(0x00000001)
-#define CSR7_TWAKE_EXPIRE              FIELD32(0x00000002)
-#define CSR7_TATIMW_EXPIRE             FIELD32(0x00000004)
-#define CSR7_TXDONE_TXRING             FIELD32(0x00000008)
-#define CSR7_TXDONE_ATIMRING           FIELD32(0x00000010)
-#define CSR7_TXDONE_PRIORING           FIELD32(0x00000020)
-#define CSR7_RXDONE                    FIELD32(0x00000040)
-#define CSR7_DECRYPTION_DONE           FIELD32(0x00000080)
-#define CSR7_ENCRYPTION_DONE           FIELD32(0x00000100)
-#define CSR7_UART1_TX_TRESHOLD         FIELD32(0x00000200)
-#define CSR7_UART1_RX_TRESHOLD         FIELD32(0x00000400)
-#define CSR7_UART1_IDLE_TRESHOLD       FIELD32(0x00000800)
-#define CSR7_UART1_TX_BUFF_ERROR       FIELD32(0x00001000)
-#define CSR7_UART1_RX_BUFF_ERROR       FIELD32(0x00002000)
-#define CSR7_UART2_TX_TRESHOLD         FIELD32(0x00004000)
-#define CSR7_UART2_RX_TRESHOLD         FIELD32(0x00008000)
-#define CSR7_UART2_IDLE_TRESHOLD       FIELD32(0x00010000)
-#define CSR7_UART2_TX_BUFF_ERROR       FIELD32(0x00020000)
-#define CSR7_UART2_RX_BUFF_ERROR       FIELD32(0x00040000)
-#define CSR7_TIMER_CSR3_EXPIRE         FIELD32(0x00080000)
-
-/*
- * CSR8: Interrupt mask register.
- * Write 1 to mask interrupt.
- * TBCN_EXPIRE: Beacon timer expired interrupt.
- * TWAKE_EXPIRE: Wakeup timer expired interrupt.
- * TATIMW_EXPIRE: Timer of atim window expired interrupt.
- * TXDONE_TXRING: Tx ring transmit done interrupt.
- * TXDONE_ATIMRING: Atim ring transmit done interrupt.
- * TXDONE_PRIORING: Priority ring transmit done interrupt.
- * RXDONE: Receive done interrupt.
- * DECRYPTION_DONE: Decryption done interrupt.
- * ENCRYPTION_DONE: Encryption done interrupt.
- * UART1_TX_TRESHOLD: UART1 TX reaches threshold.
- * UART1_RX_TRESHOLD: UART1 RX reaches threshold.
- * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold.
- * UART1_TX_BUFF_ERROR: UART1 TX buffer error.
- * UART1_RX_BUFF_ERROR: UART1 RX buffer error.
- * UART2_TX_TRESHOLD: UART2 TX reaches threshold.
- * UART2_RX_TRESHOLD: UART2 RX reaches threshold.
- * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold.
- * UART2_TX_BUFF_ERROR: UART2 TX buffer error.
- * UART2_RX_BUFF_ERROR: UART2 RX buffer error.
- * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period).
- */
-#define CSR8                           0x0020
-#define CSR8_TBCN_EXPIRE               FIELD32(0x00000001)
-#define CSR8_TWAKE_EXPIRE              FIELD32(0x00000002)
-#define CSR8_TATIMW_EXPIRE             FIELD32(0x00000004)
-#define CSR8_TXDONE_TXRING             FIELD32(0x00000008)
-#define CSR8_TXDONE_ATIMRING           FIELD32(0x00000010)
-#define CSR8_TXDONE_PRIORING           FIELD32(0x00000020)
-#define CSR8_RXDONE                    FIELD32(0x00000040)
-#define CSR8_DECRYPTION_DONE           FIELD32(0x00000080)
-#define CSR8_ENCRYPTION_DONE           FIELD32(0x00000100)
-#define CSR8_UART1_TX_TRESHOLD         FIELD32(0x00000200)
-#define CSR8_UART1_RX_TRESHOLD         FIELD32(0x00000400)
-#define CSR8_UART1_IDLE_TRESHOLD       FIELD32(0x00000800)
-#define CSR8_UART1_TX_BUFF_ERROR       FIELD32(0x00001000)
-#define CSR8_UART1_RX_BUFF_ERROR       FIELD32(0x00002000)
-#define CSR8_UART2_TX_TRESHOLD         FIELD32(0x00004000)
-#define CSR8_UART2_RX_TRESHOLD         FIELD32(0x00008000)
-#define CSR8_UART2_IDLE_TRESHOLD       FIELD32(0x00010000)
-#define CSR8_UART2_TX_BUFF_ERROR       FIELD32(0x00020000)
-#define CSR8_UART2_RX_BUFF_ERROR       FIELD32(0x00040000)
-#define CSR8_TIMER_CSR3_EXPIRE         FIELD32(0x00080000)
-
-/*
- * CSR9: Maximum frame length register.
- * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12.
- */
-#define CSR9                           0x0024
-#define CSR9_MAX_FRAME_UNIT            FIELD32(0x00000f80)
-
-/*
- * SECCSR0: WEP control register.
- * KICK_DECRYPT: Kick decryption engine, self-clear.
- * ONE_SHOT: 0: ring mode, 1: One shot only mode.
- * DESC_ADDRESS: Descriptor physical address of frame.
- */
-#define SECCSR0                                0x0028
-#define SECCSR0_KICK_DECRYPT           FIELD32(0x00000001)
-#define SECCSR0_ONE_SHOT               FIELD32(0x00000002)
-#define SECCSR0_DESC_ADDRESS           FIELD32(0xfffffffc)
-
-/*
- * CSR11: Back-off control register.
- * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1).
- * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1).
- * SLOT_TIME: Slot time, default is 20us for 802.11b
- * CW_SELECT: CWmin/CWmax selection, 1: Register, 0: TXD.
- * LONG_RETRY: Long retry count.
- * SHORT_RETRY: Short retry count.
- */
-#define CSR11                          0x002c
-#define CSR11_CWMIN                    FIELD32(0x0000000f)
-#define CSR11_CWMAX                    FIELD32(0x000000f0)
-#define CSR11_SLOT_TIME                        FIELD32(0x00001f00)
-#define CSR11_CW_SELECT                        FIELD32(0x00002000)
-#define CSR11_LONG_RETRY               FIELD32(0x00ff0000)
-#define CSR11_SHORT_RETRY              FIELD32(0xff000000)
-
-/*
- * CSR12: Synchronization configuration register 0.
- * All units in 1/16 TU.
- * BEACON_INTERVAL: Beacon interval, default is 100 TU.
- * CFP_MAX_DURATION: Cfp maximum duration, default is 100 TU.
- */
-#define CSR12                          0x0030
-#define CSR12_BEACON_INTERVAL          FIELD32(0x0000ffff)
-#define CSR12_CFP_MAX_DURATION         FIELD32(0xffff0000)
-
-/*
- * CSR13: Synchronization configuration register 1.
- * All units in 1/16 TU.
- * ATIMW_DURATION: Atim window duration.
- * CFP_PERIOD: Cfp period, default is 0 TU.
- */
-#define CSR13                          0x0034
-#define CSR13_ATIMW_DURATION           FIELD32(0x0000ffff)
-#define CSR13_CFP_PERIOD               FIELD32(0x00ff0000)
-
-/*
- * CSR14: Synchronization control register.
- * TSF_COUNT: Enable tsf auto counting.
- * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
- * TBCN: Enable tbcn with reload value.
- * TCFP: Enable tcfp & cfp / cp switching.
- * TATIMW: Enable tatimw & atim window switching.
- * BEACON_GEN: Enable beacon generator.
- * CFP_COUNT_PRELOAD: Cfp count preload value.
- * TBCM_PRELOAD: Tbcn preload value in units of 64us.
- */
-#define CSR14                          0x0038
-#define CSR14_TSF_COUNT                        FIELD32(0x00000001)
-#define CSR14_TSF_SYNC                 FIELD32(0x00000006)
-#define CSR14_TBCN                     FIELD32(0x00000008)
-#define CSR14_TCFP                     FIELD32(0x00000010)
-#define CSR14_TATIMW                   FIELD32(0x00000020)
-#define CSR14_BEACON_GEN               FIELD32(0x00000040)
-#define CSR14_CFP_COUNT_PRELOAD                FIELD32(0x0000ff00)
-#define CSR14_TBCM_PRELOAD             FIELD32(0xffff0000)
-
-/*
- * CSR15: Synchronization status register.
- * CFP: ASIC is in contention-free period.
- * ATIMW: ASIC is in ATIM window.
- * BEACON_SENT: Beacon is send.
- */
-#define CSR15                          0x003c
-#define CSR15_CFP                      FIELD32(0x00000001)
-#define CSR15_ATIMW                    FIELD32(0x00000002)
-#define CSR15_BEACON_SENT              FIELD32(0x00000004)
-
-/*
- * CSR16: TSF timer register 0.
- */
-#define CSR16                          0x0040
-#define CSR16_LOW_TSFTIMER             FIELD32(0xffffffff)
-
-/*
- * CSR17: TSF timer register 1.
- */
-#define CSR17                          0x0044
-#define CSR17_HIGH_TSFTIMER            FIELD32(0xffffffff)
-
-/*
- * CSR18: IFS timer register 0.
- * SIFS: Sifs, default is 10 us.
- * PIFS: Pifs, default is 30 us.
- */
-#define CSR18                          0x0048
-#define CSR18_SIFS                     FIELD32(0x000001ff)
-#define CSR18_PIFS                     FIELD32(0x001f0000)
-
-/*
- * CSR19: IFS timer register 1.
- * DIFS: Difs, default is 50 us.
- * EIFS: Eifs, default is 364 us.
- */
-#define CSR19                          0x004c
-#define CSR19_DIFS                     FIELD32(0x0000ffff)
-#define CSR19_EIFS                     FIELD32(0xffff0000)
-
-/*
- * CSR20: Wakeup timer register.
- * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU.
- * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
- * AUTOWAKE: Enable auto wakeup / sleep mechanism.
- */
-#define CSR20                          0x0050
-#define CSR20_DELAY_AFTER_TBCN         FIELD32(0x0000ffff)
-#define CSR20_TBCN_BEFORE_WAKEUP       FIELD32(0x00ff0000)
-#define CSR20_AUTOWAKE                 FIELD32(0x01000000)
-
-/*
- * CSR21: EEPROM control register.
- * RELOAD: Write 1 to reload eeprom content.
- * TYPE_93C46: 1: 93c46, 0:93c66.
- */
-#define CSR21                          0x0054
-#define CSR21_RELOAD                   FIELD32(0x00000001)
-#define CSR21_EEPROM_DATA_CLOCK                FIELD32(0x00000002)
-#define CSR21_EEPROM_CHIP_SELECT       FIELD32(0x00000004)
-#define CSR21_EEPROM_DATA_IN           FIELD32(0x00000008)
-#define CSR21_EEPROM_DATA_OUT          FIELD32(0x00000010)
-#define CSR21_TYPE_93C46               FIELD32(0x00000020)
-
-/*
- * CSR22: CFP control register.
- * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU.
- * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain.
- */
-#define CSR22                          0x0058
-#define CSR22_CFP_DURATION_REMAIN      FIELD32(0x0000ffff)
-#define CSR22_RELOAD_CFP_DURATION      FIELD32(0x00010000)
-
-/*
- * Transmit related CSRs.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * TXCSR0: TX Control Register.
- * KICK_TX: Kick tx ring.
- * KICK_ATIM: Kick atim ring.
- * KICK_PRIO: Kick priority ring.
- * ABORT: Abort all transmit related ring operation.
- */
-#define TXCSR0                         0x0060
-#define TXCSR0_KICK_TX                 FIELD32(0x00000001)
-#define TXCSR0_KICK_ATIM               FIELD32(0x00000002)
-#define TXCSR0_KICK_PRIO               FIELD32(0x00000004)
-#define TXCSR0_ABORT                   FIELD32(0x00000008)
-
-/*
- * TXCSR1: TX Configuration Register.
- * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps.
- * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps.
- * TSF_OFFSET: Insert tsf offset.
- * AUTORESPONDER: Enable auto responder which include ack & cts.
- */
-#define TXCSR1                         0x0064
-#define TXCSR1_ACK_TIMEOUT             FIELD32(0x000001ff)
-#define TXCSR1_ACK_CONSUME_TIME                FIELD32(0x0003fe00)
-#define TXCSR1_TSF_OFFSET              FIELD32(0x00fc0000)
-#define TXCSR1_AUTORESPONDER           FIELD32(0x01000000)
-
-/*
- * TXCSR2: Tx descriptor configuration register.
- * TXD_SIZE: Tx descriptor size, default is 48.
- * NUM_TXD: Number of tx entries in ring.
- * NUM_ATIM: Number of atim entries in ring.
- * NUM_PRIO: Number of priority entries in ring.
- */
-#define TXCSR2                         0x0068
-#define TXCSR2_TXD_SIZE                        FIELD32(0x000000ff)
-#define TXCSR2_NUM_TXD                 FIELD32(0x0000ff00)
-#define TXCSR2_NUM_ATIM                        FIELD32(0x00ff0000)
-#define TXCSR2_NUM_PRIO                        FIELD32(0xff000000)
-
-/*
- * TXCSR3: TX Ring Base address register.
- */
-#define TXCSR3                         0x006c
-#define TXCSR3_TX_RING_REGISTER                FIELD32(0xffffffff)
-
-/*
- * TXCSR4: TX Atim Ring Base address register.
- */
-#define TXCSR4                         0x0070
-#define TXCSR4_ATIM_RING_REGISTER      FIELD32(0xffffffff)
-
-/*
- * TXCSR5: TX Prio Ring Base address register.
- */
-#define TXCSR5                         0x0074
-#define TXCSR5_PRIO_RING_REGISTER      FIELD32(0xffffffff)
-
-/*
- * TXCSR6: Beacon Base address register.
- */
-#define TXCSR6                         0x0078
-#define TXCSR6_BEACON_RING_REGISTER    FIELD32(0xffffffff)
-
-/*
- * TXCSR7: Auto responder control register.
- * AR_POWERMANAGEMENT: Auto responder power management bit.
- */
-#define TXCSR7                         0x007c
-#define TXCSR7_AR_POWERMANAGEMENT      FIELD32(0x00000001)
-
-/*
- * TXCSR8: CCK Tx BBP register.
- */
-#define TXCSR8                         0x0098
-#define TXCSR8_BBP_ID0                 FIELD32(0x0000007f)
-#define TXCSR8_BBP_ID0_VALID           FIELD32(0x00000080)
-#define TXCSR8_BBP_ID1                 FIELD32(0x00007f00)
-#define TXCSR8_BBP_ID1_VALID           FIELD32(0x00008000)
-#define TXCSR8_BBP_ID2                 FIELD32(0x007f0000)
-#define TXCSR8_BBP_ID2_VALID           FIELD32(0x00800000)
-#define TXCSR8_BBP_ID3                 FIELD32(0x7f000000)
-#define TXCSR8_BBP_ID3_VALID           FIELD32(0x80000000)
-
-/*
- * TXCSR9: OFDM TX BBP registers
- * OFDM_SIGNAL: BBP rate field address for OFDM.
- * OFDM_SERVICE: BBP service field address for OFDM.
- * OFDM_LENGTH_LOW: BBP length low byte address for OFDM.
- * OFDM_LENGTH_HIGH: BBP length high byte address for OFDM.
- */
-#define TXCSR9                         0x0094
-#define TXCSR9_OFDM_RATE               FIELD32(0x000000ff)
-#define TXCSR9_OFDM_SERVICE            FIELD32(0x0000ff00)
-#define TXCSR9_OFDM_LENGTH_LOW         FIELD32(0x00ff0000)
-#define TXCSR9_OFDM_LENGTH_HIGH                FIELD32(0xff000000)
-
-/*
- * Receive related CSRs.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * RXCSR0: RX Control Register.
- * DISABLE_RX: Disable rx engine.
- * DROP_CRC: Drop crc error.
- * DROP_PHYSICAL: Drop physical error.
- * DROP_CONTROL: Drop control frame.
- * DROP_NOT_TO_ME: Drop not to me unicast frame.
- * DROP_TODS: Drop frame tods bit is true.
- * DROP_VERSION_ERROR: Drop version error frame.
- * PASS_CRC: Pass all packets with crc attached.
- * PASS_CRC: Pass all packets with crc attached.
- * PASS_PLCP: Pass all packets with 4 bytes PLCP attached.
- * DROP_MCAST: Drop multicast frames.
- * DROP_BCAST: Drop broadcast frames.
- * ENABLE_QOS: Accept QOS data frame and parse QOS field.
- */
-#define RXCSR0                         0x0080
-#define RXCSR0_DISABLE_RX              FIELD32(0x00000001)
-#define RXCSR0_DROP_CRC                        FIELD32(0x00000002)
-#define RXCSR0_DROP_PHYSICAL           FIELD32(0x00000004)
-#define RXCSR0_DROP_CONTROL            FIELD32(0x00000008)
-#define RXCSR0_DROP_NOT_TO_ME          FIELD32(0x00000010)
-#define RXCSR0_DROP_TODS               FIELD32(0x00000020)
-#define RXCSR0_DROP_VERSION_ERROR      FIELD32(0x00000040)
-#define RXCSR0_PASS_CRC                        FIELD32(0x00000080)
-#define RXCSR0_PASS_PLCP               FIELD32(0x00000100)
-#define RXCSR0_DROP_MCAST              FIELD32(0x00000200)
-#define RXCSR0_DROP_BCAST              FIELD32(0x00000400)
-#define RXCSR0_ENABLE_QOS              FIELD32(0x00000800)
-
-/*
- * RXCSR1: RX descriptor configuration register.
- * RXD_SIZE: Rx descriptor size, default is 32b.
- * NUM_RXD: Number of rx entries in ring.
- */
-#define RXCSR1                         0x0084
-#define RXCSR1_RXD_SIZE                        FIELD32(0x000000ff)
-#define RXCSR1_NUM_RXD                 FIELD32(0x0000ff00)
-
-/*
- * RXCSR2: RX Ring base address register.
- */
-#define RXCSR2                         0x0088
-#define RXCSR2_RX_RING_REGISTER                FIELD32(0xffffffff)
-
-/*
- * RXCSR3: BBP ID register for Rx operation.
- * BBP_ID#: BBP register # id.
- * BBP_ID#_VALID: BBP register # id is valid or not.
- */
-#define RXCSR3                         0x0090
-#define RXCSR3_BBP_ID0                 FIELD32(0x0000007f)
-#define RXCSR3_BBP_ID0_VALID           FIELD32(0x00000080)
-#define RXCSR3_BBP_ID1                 FIELD32(0x00007f00)
-#define RXCSR3_BBP_ID1_VALID           FIELD32(0x00008000)
-#define RXCSR3_BBP_ID2                 FIELD32(0x007f0000)
-#define RXCSR3_BBP_ID2_VALID           FIELD32(0x00800000)
-#define RXCSR3_BBP_ID3                 FIELD32(0x7f000000)
-#define RXCSR3_BBP_ID3_VALID           FIELD32(0x80000000)
-
-/*
- * ARCSR1: Auto Responder PLCP config register 1.
- * AR_BBP_DATA#: Auto responder BBP register # data.
- * AR_BBP_ID#: Auto responder BBP register # Id.
- */
-#define ARCSR1                         0x009c
-#define ARCSR1_AR_BBP_DATA2            FIELD32(0x000000ff)
-#define ARCSR1_AR_BBP_ID2              FIELD32(0x0000ff00)
-#define ARCSR1_AR_BBP_DATA3            FIELD32(0x00ff0000)
-#define ARCSR1_AR_BBP_ID3              FIELD32(0xff000000)
-
-/*
- * Miscellaneous Registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
-
- */
-
-/*
- * PCICSR: PCI control register.
- * BIG_ENDIAN: 1: big endian, 0: little endian.
- * RX_TRESHOLD: Rx threshold in dw to start pci access
- * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
- * TX_TRESHOLD: Tx threshold in dw to start pci access
- * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward.
- * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw.
- * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational.
- * READ_MULTIPLE: Enable memory read multiple.
- * WRITE_INVALID: Enable memory write & invalid.
- */
-#define PCICSR                         0x008c
-#define PCICSR_BIG_ENDIAN              FIELD32(0x00000001)
-#define PCICSR_RX_TRESHOLD             FIELD32(0x00000006)
-#define PCICSR_TX_TRESHOLD             FIELD32(0x00000018)
-#define PCICSR_BURST_LENTH             FIELD32(0x00000060)
-#define PCICSR_ENABLE_CLK              FIELD32(0x00000080)
-#define PCICSR_READ_MULTIPLE           FIELD32(0x00000100)
-#define PCICSR_WRITE_INVALID           FIELD32(0x00000200)
-
-/*
- * CNT0: FCS error count.
- * FCS_ERROR: FCS error count, cleared when read.
- */
-#define CNT0                           0x00a0
-#define CNT0_FCS_ERROR                 FIELD32(0x0000ffff)
-
-/*
- * Statistic Register.
- * CNT1: PLCP error count.
- * CNT2: Long error count.
- */
-#define TIMECSR2                       0x00a8
-#define CNT1                           0x00ac
-#define CNT2                           0x00b0
-#define TIMECSR3                       0x00b4
-
-/*
- * CNT3: CCA false alarm count.
- */
-#define CNT3                           0x00b8
-#define CNT3_FALSE_CCA                 FIELD32(0x0000ffff)
-
-/*
- * Statistic Register.
- * CNT4: Rx FIFO overflow count.
- * CNT5: Tx FIFO underrun count.
- */
-#define CNT4                           0x00bc
-#define CNT5                           0x00c0
-
-/*
- * Baseband Control Register.
- */
-
-/*
- * PWRCSR0: Power mode configuration register.
- */
-#define PWRCSR0                                0x00c4
-
-/*
- * Power state transition time registers.
- */
-#define PSCSR0                         0x00c8
-#define PSCSR1                         0x00cc
-#define PSCSR2                         0x00d0
-#define PSCSR3                         0x00d4
-
-/*
- * PWRCSR1: Manual power control / status register.
- * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
- * SET_STATE: Set state. Write 1 to trigger, self cleared.
- * BBP_DESIRE_STATE: BBP desired state.
- * RF_DESIRE_STATE: RF desired state.
- * BBP_CURR_STATE: BBP current state.
- * RF_CURR_STATE: RF current state.
- * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
- */
-#define PWRCSR1                                0x00d8
-#define PWRCSR1_SET_STATE              FIELD32(0x00000001)
-#define PWRCSR1_BBP_DESIRE_STATE       FIELD32(0x00000006)
-#define PWRCSR1_RF_DESIRE_STATE                FIELD32(0x00000018)
-#define PWRCSR1_BBP_CURR_STATE         FIELD32(0x00000060)
-#define PWRCSR1_RF_CURR_STATE          FIELD32(0x00000180)
-#define PWRCSR1_PUT_TO_SLEEP           FIELD32(0x00000200)
-
-/*
- * TIMECSR: Timer control register.
- * US_COUNT: 1 us timer count in units of clock cycles.
- * US_64_COUNT: 64 us timer count in units of 1 us timer.
- * BEACON_EXPECT: Beacon expect window.
- */
-#define TIMECSR                                0x00dc
-#define TIMECSR_US_COUNT               FIELD32(0x000000ff)
-#define TIMECSR_US_64_COUNT            FIELD32(0x0000ff00)
-#define TIMECSR_BEACON_EXPECT          FIELD32(0x00070000)
-
-/*
- * MACCSR0: MAC configuration register 0.
- */
-#define MACCSR0                                0x00e0
-
-/*
- * MACCSR1: MAC configuration register 1.
- * KICK_RX: Kick one-shot rx in one-shot rx mode.
- * ONESHOT_RXMODE: Enable one-shot rx mode for debugging.
- * BBPRX_RESET_MODE: Ralink bbp rx reset mode.
- * AUTO_TXBBP: Auto tx logic access bbp control register.
- * AUTO_RXBBP: Auto rx logic access bbp control register.
- * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd.
- * INTERSIL_IF: Intersil if calibration pin.
- */
-#define MACCSR1                                0x00e4
-#define MACCSR1_KICK_RX                        FIELD32(0x00000001)
-#define MACCSR1_ONESHOT_RXMODE         FIELD32(0x00000002)
-#define MACCSR1_BBPRX_RESET_MODE       FIELD32(0x00000004)
-#define MACCSR1_AUTO_TXBBP             FIELD32(0x00000008)
-#define MACCSR1_AUTO_RXBBP             FIELD32(0x00000010)
-#define MACCSR1_LOOPBACK               FIELD32(0x00000060)
-#define MACCSR1_INTERSIL_IF            FIELD32(0x00000080)
-
-/*
- * RALINKCSR: Ralink Rx auto-reset BBCR.
- * AR_BBP_DATA#: Auto reset BBP register # data.
- * AR_BBP_ID#: Auto reset BBP register # id.
- */
-#define RALINKCSR                      0x00e8
-#define RALINKCSR_AR_BBP_DATA0         FIELD32(0x000000ff)
-#define RALINKCSR_AR_BBP_ID0           FIELD32(0x00007f00)
-#define RALINKCSR_AR_BBP_VALID0                FIELD32(0x00008000)
-#define RALINKCSR_AR_BBP_DATA1         FIELD32(0x00ff0000)
-#define RALINKCSR_AR_BBP_ID1           FIELD32(0x7f000000)
-#define RALINKCSR_AR_BBP_VALID1                FIELD32(0x80000000)
-
-/*
- * BCNCSR: Beacon interval control register.
- * CHANGE: Write one to change beacon interval.
- * DELTATIME: The delta time value.
- * NUM_BEACON: Number of beacon according to mode.
- * MODE: Please refer to asic specs.
- * PLUS: Plus or minus delta time value.
- */
-#define BCNCSR                         0x00ec
-#define BCNCSR_CHANGE                  FIELD32(0x00000001)
-#define BCNCSR_DELTATIME               FIELD32(0x0000001e)
-#define BCNCSR_NUM_BEACON              FIELD32(0x00001fe0)
-#define BCNCSR_MODE                    FIELD32(0x00006000)
-#define BCNCSR_PLUS                    FIELD32(0x00008000)
-
-/*
- * BBP / RF / IF Control Register.
- */
-
-/*
- * BBPCSR: BBP serial control register.
- * VALUE: Register value to program into BBP.
- * REGNUM: Selected BBP register.
- * BUSY: 1: asic is busy execute BBP programming.
- * WRITE_CONTROL: 1: write BBP, 0: read BBP.
- */
-#define BBPCSR                         0x00f0
-#define BBPCSR_VALUE                   FIELD32(0x000000ff)
-#define BBPCSR_REGNUM                  FIELD32(0x00007f00)
-#define BBPCSR_BUSY                    FIELD32(0x00008000)
-#define BBPCSR_WRITE_CONTROL           FIELD32(0x00010000)
-
-/*
- * RFCSR: RF serial control register.
- * VALUE: Register value + id to program into rf/if.
- * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
- * IF_SELECT: Chip to program: 0: rf, 1: if.
- * PLL_LD: Rf pll_ld status.
- * BUSY: 1: asic is busy execute rf programming.
- */
-#define RFCSR                          0x00f4
-#define RFCSR_VALUE                    FIELD32(0x00ffffff)
-#define RFCSR_NUMBER_OF_BITS           FIELD32(0x1f000000)
-#define RFCSR_IF_SELECT                        FIELD32(0x20000000)
-#define RFCSR_PLL_LD                   FIELD32(0x40000000)
-#define RFCSR_BUSY                     FIELD32(0x80000000)
-
-/*
- * LEDCSR: LED control register.
- * ON_PERIOD: On period, default 70ms.
- * OFF_PERIOD: Off period, default 30ms.
- * LINK: 0: linkoff, 1: linkup.
- * ACTIVITY: 0: idle, 1: active.
- * LINK_POLARITY: 0: active low, 1: active high.
- * ACTIVITY_POLARITY: 0: active low, 1: active high.
- * LED_DEFAULT: LED state for "enable" 0: ON, 1: OFF.
- */
-#define LEDCSR                         0x00f8
-#define LEDCSR_ON_PERIOD               FIELD32(0x000000ff)
-#define LEDCSR_OFF_PERIOD              FIELD32(0x0000ff00)
-#define LEDCSR_LINK                    FIELD32(0x00010000)
-#define LEDCSR_ACTIVITY                        FIELD32(0x00020000)
-#define LEDCSR_LINK_POLARITY           FIELD32(0x00040000)
-#define LEDCSR_ACTIVITY_POLARITY       FIELD32(0x00080000)
-#define LEDCSR_LED_DEFAULT             FIELD32(0x00100000)
-
-/*
- * SECCSR3: AES control register.
- */
-#define SECCSR3                                0x00fc
-
-/*
- * ASIC pointer information.
- * RXPTR: Current RX ring address.
- * TXPTR: Current Tx ring address.
- * PRIPTR: Current Priority ring address.
- * ATIMPTR: Current ATIM ring address.
- */
-#define RXPTR                          0x0100
-#define TXPTR                          0x0104
-#define PRIPTR                         0x0108
-#define ATIMPTR                                0x010c
-
-/*
- * TXACKCSR0: TX ACK timeout.
- */
-#define TXACKCSR0                      0x0110
-
-/*
- * ACK timeout count registers.
- * ACKCNT0: TX ACK timeout count.
- * ACKCNT1: RX ACK timeout count.
- */
-#define ACKCNT0                                0x0114
-#define ACKCNT1                                0x0118
-
-/*
- * GPIO and others.
- */
-
-/*
- * GPIOCSR: GPIO control register.
- *     GPIOCSR_VALx: GPIO value
- *     GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input
- */
-#define GPIOCSR                                0x0120
-#define GPIOCSR_VAL0                   FIELD32(0x00000001)
-#define GPIOCSR_VAL1                   FIELD32(0x00000002)
-#define GPIOCSR_VAL2                   FIELD32(0x00000004)
-#define GPIOCSR_VAL3                   FIELD32(0x00000008)
-#define GPIOCSR_VAL4                   FIELD32(0x00000010)
-#define GPIOCSR_VAL5                   FIELD32(0x00000020)
-#define GPIOCSR_VAL6                   FIELD32(0x00000040)
-#define GPIOCSR_VAL7                   FIELD32(0x00000080)
-#define GPIOCSR_DIR0                   FIELD32(0x00000100)
-#define GPIOCSR_DIR1                   FIELD32(0x00000200)
-#define GPIOCSR_DIR2                   FIELD32(0x00000400)
-#define GPIOCSR_DIR3                   FIELD32(0x00000800)
-#define GPIOCSR_DIR4                   FIELD32(0x00001000)
-#define GPIOCSR_DIR5                   FIELD32(0x00002000)
-#define GPIOCSR_DIR6                   FIELD32(0x00004000)
-#define GPIOCSR_DIR7                   FIELD32(0x00008000)
-
-/*
- * FIFO pointer registers.
- * FIFOCSR0: TX FIFO pointer.
- * FIFOCSR1: RX FIFO pointer.
- */
-#define FIFOCSR0                       0x0128
-#define FIFOCSR1                       0x012c
-
-/*
- * BCNCSR1: Tx BEACON offset time control register.
- * PRELOAD: Beacon timer offset in units of usec.
- * BEACON_CWMIN: 2^CwMin.
- */
-#define BCNCSR1                                0x0130
-#define BCNCSR1_PRELOAD                        FIELD32(0x0000ffff)
-#define BCNCSR1_BEACON_CWMIN           FIELD32(0x000f0000)
-
-/*
- * MACCSR2: TX_PE to RX_PE turn-around time control register
- * DELAY: RX_PE low width, in units of pci clock cycle.
- */
-#define MACCSR2                                0x0134
-#define MACCSR2_DELAY                  FIELD32(0x000000ff)
-
-/*
- * TESTCSR: TEST mode selection register.
- */
-#define TESTCSR                                0x0138
-
-/*
- * ARCSR2: 1 Mbps ACK/CTS PLCP.
- */
-#define ARCSR2                         0x013c
-#define ARCSR2_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR2_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR2_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR3: 2 Mbps ACK/CTS PLCP.
- */
-#define ARCSR3                         0x0140
-#define ARCSR3_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR3_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR3_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR4: 5.5 Mbps ACK/CTS PLCP.
- */
-#define ARCSR4                         0x0144
-#define ARCSR4_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR4_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR4_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARCSR5: 11 Mbps ACK/CTS PLCP.
- */
-#define ARCSR5                         0x0148
-#define ARCSR5_SIGNAL                  FIELD32(0x000000ff)
-#define ARCSR5_SERVICE                 FIELD32(0x0000ff00)
-#define ARCSR5_LENGTH                  FIELD32(0xffff0000)
-
-/*
- * ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps.
- */
-#define ARTCSR0                                0x014c
-#define ARTCSR0_ACK_CTS_11MBS          FIELD32(0x000000ff)
-#define ARTCSR0_ACK_CTS_5_5MBS         FIELD32(0x0000ff00)
-#define ARTCSR0_ACK_CTS_2MBS           FIELD32(0x00ff0000)
-#define ARTCSR0_ACK_CTS_1MBS           FIELD32(0xff000000)
-
-
-/*
- * ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
- */
-#define ARTCSR1                                0x0150
-#define ARTCSR1_ACK_CTS_6MBS           FIELD32(0x000000ff)
-#define ARTCSR1_ACK_CTS_9MBS           FIELD32(0x0000ff00)
-#define ARTCSR1_ACK_CTS_12MBS          FIELD32(0x00ff0000)
-#define ARTCSR1_ACK_CTS_18MBS          FIELD32(0xff000000)
-
-/*
- * ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
- */
-#define ARTCSR2                                0x0154
-#define ARTCSR2_ACK_CTS_24MBS          FIELD32(0x000000ff)
-#define ARTCSR2_ACK_CTS_36MBS          FIELD32(0x0000ff00)
-#define ARTCSR2_ACK_CTS_48MBS          FIELD32(0x00ff0000)
-#define ARTCSR2_ACK_CTS_54MBS          FIELD32(0xff000000)
-
-/*
- * SECCSR1: WEP control register.
- * KICK_ENCRYPT: Kick encryption engine, self-clear.
- * ONE_SHOT: 0: ring mode, 1: One shot only mode.
- * DESC_ADDRESS: Descriptor physical address of frame.
- */
-#define SECCSR1                                0x0158
-#define SECCSR1_KICK_ENCRYPT           FIELD32(0x00000001)
-#define SECCSR1_ONE_SHOT               FIELD32(0x00000002)
-#define SECCSR1_DESC_ADDRESS           FIELD32(0xfffffffc)
-
-/*
- * BBPCSR1: BBP TX configuration.
- */
-#define BBPCSR1                                0x015c
-#define BBPCSR1_CCK                    FIELD32(0x00000003)
-#define BBPCSR1_CCK_FLIP               FIELD32(0x00000004)
-#define BBPCSR1_OFDM                   FIELD32(0x00030000)
-#define BBPCSR1_OFDM_FLIP              FIELD32(0x00040000)
-
-/*
- * Dual band configuration registers.
- * DBANDCSR0: Dual band configuration register 0.
- * DBANDCSR1: Dual band configuration register 1.
- */
-#define DBANDCSR0                      0x0160
-#define DBANDCSR1                      0x0164
-
-/*
- * BBPPCSR: BBP Pin control register.
- */
-#define BBPPCSR                                0x0168
-
-/*
- * MAC special debug mode selection registers.
- * DBGSEL0: MAC special debug mode selection register 0.
- * DBGSEL1: MAC special debug mode selection register 1.
- */
-#define DBGSEL0                                0x016c
-#define DBGSEL1                                0x0170
-
-/*
- * BISTCSR: BBP BIST register.
- */
-#define BISTCSR                                0x0174
-
-/*
- * Multicast filter registers.
- * MCAST0: Multicast filter register 0.
- * MCAST1: Multicast filter register 1.
- */
-#define MCAST0                         0x0178
-#define MCAST1                         0x017c
-
-/*
- * UART registers.
- * UARTCSR0: UART1 TX register.
- * UARTCSR1: UART1 RX register.
- * UARTCSR3: UART1 frame control register.
- * UARTCSR4: UART1 buffer control register.
- * UART2CSR0: UART2 TX register.
- * UART2CSR1: UART2 RX register.
- * UART2CSR3: UART2 frame control register.
- * UART2CSR4: UART2 buffer control register.
- */
-#define UARTCSR0                       0x0180
-#define UARTCSR1                       0x0184
-#define UARTCSR3                       0x0188
-#define UARTCSR4                       0x018c
-#define UART2CSR0                      0x0190
-#define UART2CSR1                      0x0194
-#define UART2CSR3                      0x0198
-#define UART2CSR4                      0x019c
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * R2: TX antenna control
- */
-#define BBP_R2_TX_ANTENNA              FIELD8(0x03)
-#define BBP_R2_TX_IQ_FLIP              FIELD8(0x04)
-
-/*
- * R14: RX antenna control
- */
-#define BBP_R14_RX_ANTENNA             FIELD8(0x03)
-#define BBP_R14_RX_IQ_FLIP             FIELD8(0x04)
-
-/*
- * BBP_R70
- */
-#define BBP_R70_JAPAN_FILTER           FIELD8(0x08)
-
-/*
- * RF registers
- */
-
-/*
- * RF 1
- */
-#define RF1_TUNER                      FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TUNER                      FIELD32(0x00000100)
-#define RF3_TXPOWER                    FIELD32(0x00003e00)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0              0x0002
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR1               0x0003
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2              0x0004
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM antenna.
- * ANTENNA_NUM: Number of antenna's.
- * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd.
- * DYN_TXAGC: Dynamic TX AGC control.
- * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
- * RF_TYPE: Rf_type of this adapter.
- */
-#define EEPROM_ANTENNA                 0x10
-#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
-#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
-#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
-#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x01c0)
-#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
-#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
-#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
-
-/*
- * EEPROM NIC config.
- * CARDBUS_ACCEL: 0: enable, 1: disable.
- * DYN_BBP_TUNE: 0: enable, 1: disable.
- * CCK_TX_POWER: CCK TX power compensation.
- */
-#define EEPROM_NIC                     0x11
-#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0001)
-#define EEPROM_NIC_DYN_BBP_TUNE                FIELD16(0x0002)
-#define EEPROM_NIC_CCK_TX_POWER                FIELD16(0x000c)
-
-/*
- * EEPROM geography.
- * GEO: Default geography setting for device.
- */
-#define EEPROM_GEOGRAPHY               0x12
-#define EEPROM_GEOGRAPHY_GEO           FIELD16(0x0f00)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START               0x13
-#define EEPROM_BBP_SIZE                        16
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER
- */
-#define EEPROM_TXPOWER_START           0x23
-#define EEPROM_TXPOWER_SIZE            7
-#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
-#define EEPROM_TXPOWER_2               FIELD16(0xff00)
-
-/*
- * RSSI <-> dBm offset calibration
- */
-#define EEPROM_CALIBRATE_OFFSET                0x3e
-#define EEPROM_CALIBRATE_OFFSET_RSSI   FIELD16(0x00ff)
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  (11 * sizeof(__le32))
-#define RXD_DESC_SIZE                  (11 * sizeof(__le32))
-
-/*
- * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define TXD_W0_VALID                   FIELD32(0x00000002)
-#define TXD_W0_RESULT                  FIELD32(0x0000001c)
-#define TXD_W0_RETRY_COUNT             FIELD32(0x000000e0)
-#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
-#define TXD_W0_ACK                     FIELD32(0x00000200)
-#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
-#define TXD_W0_OFDM                    FIELD32(0x00000800)
-#define TXD_W0_CIPHER_OWNER            FIELD32(0x00001000)
-#define TXD_W0_IFS                     FIELD32(0x00006000)
-#define TXD_W0_RETRY_MODE              FIELD32(0x00008000)
-#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * Word1
- */
-#define TXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
-
-/*
- * Word2
- */
-#define TXD_W2_IV_OFFSET               FIELD32(0x0000003f)
-#define TXD_W2_AIFS                    FIELD32(0x000000c0)
-#define TXD_W2_CWMIN                   FIELD32(0x00000f00)
-#define TXD_W2_CWMAX                   FIELD32(0x0000f000)
-
-/*
- * Word3: PLCP information
- */
-#define TXD_W3_PLCP_SIGNAL             FIELD32(0x000000ff)
-#define TXD_W3_PLCP_SERVICE            FIELD32(0x0000ff00)
-#define TXD_W3_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
-#define TXD_W3_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
-
-/*
- * Word4
- */
-#define TXD_W4_IV                      FIELD32(0xffffffff)
-
-/*
- * Word5
- */
-#define TXD_W5_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word6-9: Key
- */
-#define TXD_W6_KEY                     FIELD32(0xffffffff)
-#define TXD_W7_KEY                     FIELD32(0xffffffff)
-#define TXD_W8_KEY                     FIELD32(0xffffffff)
-#define TXD_W9_KEY                     FIELD32(0xffffffff)
-
-/*
- * Word10
- */
-#define TXD_W10_RTS                    FIELD32(0x00000001)
-#define TXD_W10_TX_RATE                        FIELD32(0x000000fe)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- */
-#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
-#define RXD_W0_MULTICAST               FIELD32(0x00000004)
-#define RXD_W0_BROADCAST               FIELD32(0x00000008)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
-#define RXD_W0_OFDM                    FIELD32(0x00000040)
-#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
-#define RXD_W0_CIPHER_OWNER            FIELD32(0x00000100)
-#define RXD_W0_ICV_ERROR               FIELD32(0x00000200)
-#define RXD_W0_IV_OFFSET               FIELD32(0x0000fc00)
-#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * Word1
- */
-#define RXD_W1_BUFFER_ADDRESS          FIELD32(0xffffffff)
-
-/*
- * Word2
- */
-#define RXD_W2_SIGNAL                  FIELD32(0x000000ff)
-#define RXD_W2_RSSI                    FIELD32(0x0000ff00)
-#define RXD_W2_TA                      FIELD32(0xffff0000)
-
-/*
- * Word3
- */
-#define RXD_W3_TA                      FIELD32(0xffffffff)
-
-/*
- * Word4
- */
-#define RXD_W4_IV                      FIELD32(0xffffffff)
-
-/*
- * Word5
- */
-#define RXD_W5_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word6-9: Key
- */
-#define RXD_W6_KEY                     FIELD32(0xffffffff)
-#define RXD_W7_KEY                     FIELD32(0xffffffff)
-#define RXD_W8_KEY                     FIELD32(0xffffffff)
-#define RXD_W9_KEY                     FIELD32(0xffffffff)
-
-/*
- * Word10
- */
-#define RXD_W10_DROP                   FIELD32(0x00000001)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_TXPOWER    0
-#define MAX_TXPOWER    31
-#define DEFAULT_TXPOWER        24
-
-#define TXPOWER_FROM_DEV(__txpower) \
-       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_TO_DEV(__txpower) \
-       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
-
-#endif /* RT2500PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
deleted file mode 100644 (file)
index b50d873..0000000
+++ /dev/null
@@ -1,2001 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2500usb
-       Abstract: rt2500usb device specific routines.
-       Supported chipsets: RT2570.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "rt2x00.h"
-#include "rt2x00usb.h"
-#include "rt2500usb.h"
-
-/*
- * Allow hardware encryption to be disabled.
- */
-static bool modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2500usb_register_read and rt2500usb_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_USB_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- * If the csr_mutex is already held then the _lock variants must
- * be used instead.
- */
-static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int offset,
-                                          u16 *value)
-{
-       __le16 reg;
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     &reg, sizeof(reg));
-       *value = le16_to_cpu(reg);
-}
-
-static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               u16 *value)
-{
-       __le16 reg;
-       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
-                                      USB_VENDOR_REQUEST_IN, offset,
-                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
-       *value = le16_to_cpu(reg);
-}
-
-static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               void *value, const u16 length)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     value, length);
-}
-
-static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
-                                           const unsigned int offset,
-                                           u16 value)
-{
-       __le16 reg = cpu_to_le16(value);
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     &reg, sizeof(reg));
-}
-
-static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                u16 value)
-{
-       __le16 reg = cpu_to_le16(value);
-       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
-                                      USB_VENDOR_REQUEST_OUT, offset,
-                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
-}
-
-static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                void *value, const u16 length)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     value, length);
-}
-
-static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int offset,
-                                 struct rt2x00_field16 field,
-                                 u16 *reg)
-{
-       unsigned int i;
-
-       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_register_read_lock(rt2x00dev, offset, reg);
-               if (!rt2x00_get_field16(*reg, field))
-                       return 1;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
-                  offset, *reg);
-       *reg = ~0;
-
-       return 0;
-}
-
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
-
-static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
-                               const unsigned int word, const u8 value)
-{
-       u16 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field16(&reg, PHY_CSR7_DATA, value);
-               rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
-               rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
-
-               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, u8 *value)
-{
-       u16 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
-               rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
-
-               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
-
-               if (WAIT_FOR_BBP(rt2x00dev, &reg))
-                       rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
-       }
-
-       *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, const u32 value)
-{
-       u16 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
-               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
-
-               reg = 0;
-               rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
-               rt2x00_set_field16(&reg, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
-               rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
-               rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
-
-               rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                    const unsigned int offset,
-                                    u32 *value)
-{
-       rt2500usb_register_read(rt2x00dev, offset, (u16 *)value);
-}
-
-static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
-                                     const unsigned int offset,
-                                     u32 value)
-{
-       rt2500usb_register_write(rt2x00dev, offset, value);
-}
-
-static const struct rt2x00debug rt2500usb_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = _rt2500usb_register_read,
-               .write          = _rt2500usb_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = CSR_REG_SIZE / sizeof(u16),
-       },
-       .eeprom = {
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt2500usb_bbp_read,
-               .write          = rt2500usb_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt2500usb_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u16 reg;
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
-       return rt2x00_get_field16(reg, MAC_CSR19_VAL7);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
-                                    enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       u16 reg;
-
-       rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
-
-       if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-               rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
-       else if (led->type == LED_TYPE_ACTIVITY)
-               rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, enabled);
-
-       rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
-}
-
-static int rt2500usb_blink_set(struct led_classdev *led_cdev,
-                              unsigned long *delay_on,
-                              unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u16 reg;
-
-       rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
-       rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
-       rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
-
-       return 0;
-}
-
-static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00_led *led,
-                              enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt2500usb_brightness_set;
-       led->led_dev.blink_set = rt2500usb_blink_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-
-/*
- * rt2500usb does not differentiate between shared and pairwise
- * keys, so we should use the same function for both key types.
- */
-static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_crypto *crypto,
-                               struct ieee80211_key_conf *key)
-{
-       u32 mask;
-       u16 reg;
-       enum cipher curr_cipher;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * Disallow to set WEP key other than with index 0,
-                * it is known that not work at least on some hardware.
-                * SW crypto will be used in that case.
-                */
-               if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-                    key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
-                   key->keyidx != 0)
-                       return -EOPNOTSUPP;
-
-               /*
-                * Pairwise key will always be entry 0, but this
-                * could collide with a shared key on the same
-                * position...
-                */
-               mask = TXRX_CSR0_KEY_ID.bit_mask;
-
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-               curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
-               reg &= mask;
-
-               if (reg && reg == mask)
-                       return -ENOSPC;
-
-               reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
-
-               key->hw_key_idx += reg ? ffz(reg) : 0;
-               /*
-                * Hardware requires that all keys use the same cipher
-                * (e.g. TKIP-only, AES-only, but not TKIP+AES).
-                * If this is not the first key, compare the cipher with the
-                * first one and fall back to SW crypto if not the same.
-                */
-               if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
-                       return -EOPNOTSUPP;
-
-               rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx),
-                                             crypto->key, sizeof(crypto->key));
-
-               /*
-                * The driver does not support the IV/EIV generation
-                * in hardware. However it demands the data to be provided
-                * both separately as well as inside the frame.
-                * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
-                * to ensure rt2x00lib will not strip the data from the
-                * frame after the copy, now we must tell mac80211
-                * to generate the IV/EIV data.
-                */
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-       }
-
-       /*
-        * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
-        * a particular key is valid.
-        */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
-       rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
-
-       mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
-       if (crypto->cmd == SET_KEY)
-               mask |= 1 << key->hw_key_idx;
-       else if (crypto->cmd == DISABLE_KEY)
-               mask &= ~(1 << key->hw_key_idx);
-       rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, mask);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       return 0;
-}
-
-static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int filter_flags)
-{
-       u16 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * and broadcast frames will always be accepted since
-        * there is no filter for it at this time.
-        */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
-                          !rt2x00dev->intf_ap_count);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
-                          !(filter_flags & FIF_ALLMULTI));
-       rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-}
-
-static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
-                                 struct rt2x00_intf *intf,
-                                 struct rt2x00intf_conf *conf,
-                                 const unsigned int flags)
-{
-       unsigned int bcn_preload;
-       u16 reg;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable beacon config
-                */
-               bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
-               rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
-                                  2 * (conf->type != NL80211_IFTYPE_STATION));
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
-
-               /*
-                * Enable synchronisation.
-                */
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR18_OFFSET, 0);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
-
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-       }
-
-       if (flags & CONFIG_UPDATE_MAC)
-               rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
-                                             (3 * sizeof(__le16)));
-
-       if (flags & CONFIG_UPDATE_BSSID)
-               rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
-                                             (3 * sizeof(__le16)));
-}
-
-static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
-                                struct rt2x00lib_erp *erp,
-                                u32 changed)
-{
-       u16 reg;
-
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
-                                  !!erp->short_preamble);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES)
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR11,
-                                        erp->basic_rates);
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
-                                  erp->beacon_int * 4);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
-       }
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
-               rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
-               rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
-       }
-}
-
-static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
-                                struct antenna_setup *ant)
-{
-       u8 r2;
-       u8 r14;
-       u16 csr5;
-       u16 csr6;
-
-       /*
-        * We should never come here because rt2x00lib is supposed
-        * to catch this and send us the correct antenna explicitely.
-        */
-       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-              ant->tx == ANTENNA_SW_DIVERSITY);
-
-       rt2500usb_bbp_read(rt2x00dev, 2, &r2);
-       rt2500usb_bbp_read(rt2x00dev, 14, &r14);
-       rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
-       rt2500usb_register_read(rt2x00dev, PHY_CSR6, &csr6);
-
-       /*
-        * Configure the TX antenna.
-        */
-       switch (ant->tx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1);
-               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1);
-               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
-               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
-               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
-               rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
-               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
-               break;
-       }
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
-               break;
-       }
-
-       /*
-        * RT2525E and RT5222 need to flip TX I/Q
-        */
-       if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) {
-               rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
-               rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1);
-               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1);
-
-               /*
-                * RT2525E does not need RX I/Q Flip.
-                */
-               if (rt2x00_rf(rt2x00dev, RF2525E))
-                       rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
-       } else {
-               rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0);
-               rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 0);
-       }
-
-       rt2500usb_bbp_write(rt2x00dev, 2, r2);
-       rt2500usb_bbp_write(rt2x00dev, 14, r14);
-       rt2500usb_register_write(rt2x00dev, PHY_CSR5, csr5);
-       rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6);
-}
-
-static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
-                                    struct rf_channel *rf, const int txpower)
-{
-       /*
-        * Set TXpower.
-        */
-       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-
-       /*
-        * For RT2525E we should first set the channel to half band higher.
-        */
-       if (rt2x00_rf(rt2x00dev, RF2525E)) {
-               static const u32 vals[] = {
-                       0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
-                       0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
-                       0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
-                       0x00000902, 0x00000906
-               };
-
-               rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
-               if (rf->rf4)
-                       rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
-       }
-
-       rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
-       if (rf->rf4)
-               rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
-}
-
-static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                    const int txpower)
-{
-       u32 rf3;
-
-       rt2x00_rf_read(rt2x00dev, 3, &rf3);
-       rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-       rt2500usb_rf_write(rt2x00dev, 3, rf3);
-}
-
-static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u16 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
-               rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON,
-                                  rt2x00dev->beacon_int - 20);
-               rt2x00_set_field16(&reg, MAC_CSR18_BEACONS_BEFORE_WAKEUP,
-                                  libconf->conf->listen_interval - 1);
-
-               /* We must first disable autowake before it can be enabled */
-               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
-               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
-
-               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 1);
-               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
-       } else {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
-               rt2x00_set_field16(&reg, MAC_CSR18_AUTO_WAKE, 0);
-               rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
-       }
-
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-}
-
-static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_conf *libconf,
-                            const unsigned int flags)
-{
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt2500usb_config_channel(rt2x00dev, &libconf->rf,
-                                        libconf->conf->power_level);
-       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
-           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
-               rt2500usb_config_txpower(rt2x00dev,
-                                        libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt2500usb_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
-                                struct link_qual *qual)
-{
-       u16 reg;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
-
-       /*
-        * Update False CCA count from register.
-        */
-       rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
-       qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
-}
-
-static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
-                                 struct link_qual *qual)
-{
-       u16 eeprom;
-       u16 value;
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom);
-       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW);
-       rt2500usb_bbp_write(rt2x00dev, 24, value);
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom);
-       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW);
-       rt2500usb_bbp_write(rt2x00dev, 25, value);
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom);
-       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW);
-       rt2500usb_bbp_write(rt2x00dev, 61, value);
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom);
-       value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER);
-       rt2500usb_bbp_write(rt2x00dev, 17, value);
-
-       qual->vgc_level = value;
-}
-
-/*
- * Queue handlers.
- */
-static void rt2500usb_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u16 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-               break;
-       case QID_BEACON:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
-               rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2500usb_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u16 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-               break;
-       case QID_BEACON:
-               rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
-               rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
-               rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-               rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * Initialization functions.
- */
-static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u16 reg;
-
-       rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001,
-                                   USB_MODE_TEST, REGISTER_TIMEOUT);
-       rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308,
-                                   0x00f0, REGISTER_TIMEOUT);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-
-       rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 1);
-       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 1);
-       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
-       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
-       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 0);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR5, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0, 13);
-       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID0_VALID, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1, 12);
-       rt2x00_set_field16(&reg, TXRX_CSR5_BBP_ID1_VALID, 1);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR6, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0, 10);
-       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID0_VALID, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1, 11);
-       rt2x00_set_field16(&reg, TXRX_CSR6_BBP_ID1_VALID, 1);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0, 7);
-       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID0_VALID, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1, 6);
-       rt2x00_set_field16(&reg, TXRX_CSR7_BBP_ID1_VALID, 1);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0, 5);
-       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID0_VALID, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               return -EBUSY;
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR1_SOFT_RESET, 0);
-       rt2x00_set_field16(&reg, MAC_CSR1_BBP_RESET, 0);
-       rt2x00_set_field16(&reg, MAC_CSR1_HOST_READY, 1);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) {
-               rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
-               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
-       } else {
-               reg = 0;
-               rt2x00_set_field16(&reg, PHY_CSR2_LNA, 1);
-               rt2x00_set_field16(&reg, PHY_CSR2_LNA_MODE, 3);
-       }
-       rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg);
-
-       rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0002);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR22, 0x0053);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000);
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR8, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR8_MAX_FRAME_UNIT,
-                          rt2x00dev->rx->data_size);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
-       rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
-       rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR18_DELAY_AFTER_BEACON, 90);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg);
-
-       rt2500usb_register_read(rt2x00dev, PHY_CSR4, &reg);
-       rt2x00_set_field16(&reg, PHY_CSR4_LOW_RF_LE, 1);
-       rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg);
-
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR1_AUTO_SEQUENCE, 1);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
-
-       return 0;
-}
-
-static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 value;
-       u8 reg_id;
-
-       if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev)))
-               return -EACCES;
-
-       rt2500usb_bbp_write(rt2x00dev, 3, 0x02);
-       rt2500usb_bbp_write(rt2x00dev, 4, 0x19);
-       rt2500usb_bbp_write(rt2x00dev, 14, 0x1c);
-       rt2500usb_bbp_write(rt2x00dev, 15, 0x30);
-       rt2500usb_bbp_write(rt2x00dev, 16, 0xac);
-       rt2500usb_bbp_write(rt2x00dev, 18, 0x18);
-       rt2500usb_bbp_write(rt2x00dev, 19, 0xff);
-       rt2500usb_bbp_write(rt2x00dev, 20, 0x1e);
-       rt2500usb_bbp_write(rt2x00dev, 21, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 22, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 23, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 24, 0x80);
-       rt2500usb_bbp_write(rt2x00dev, 25, 0x50);
-       rt2500usb_bbp_write(rt2x00dev, 26, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 27, 0x23);
-       rt2500usb_bbp_write(rt2x00dev, 30, 0x10);
-       rt2500usb_bbp_write(rt2x00dev, 31, 0x2b);
-       rt2500usb_bbp_write(rt2x00dev, 32, 0xb9);
-       rt2500usb_bbp_write(rt2x00dev, 34, 0x12);
-       rt2500usb_bbp_write(rt2x00dev, 35, 0x50);
-       rt2500usb_bbp_write(rt2x00dev, 39, 0xc4);
-       rt2500usb_bbp_write(rt2x00dev, 40, 0x02);
-       rt2500usb_bbp_write(rt2x00dev, 41, 0x60);
-       rt2500usb_bbp_write(rt2x00dev, 53, 0x10);
-       rt2500usb_bbp_write(rt2x00dev, 54, 0x18);
-       rt2500usb_bbp_write(rt2x00dev, 56, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 57, 0x10);
-       rt2500usb_bbp_write(rt2x00dev, 58, 0x08);
-       rt2500usb_bbp_write(rt2x00dev, 61, 0x60);
-       rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
-       rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt2500usb_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Initialize all registers.
-        */
-       if (unlikely(rt2500usb_init_registers(rt2x00dev) ||
-                    rt2500usb_init_bbp(rt2x00dev)))
-               return -EIO;
-
-       return 0;
-}
-
-static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
-
-       /*
-        * Disable synchronisation.
-        */
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
-
-       rt2x00usb_disable_radio(rt2x00dev);
-}
-
-static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       u16 reg;
-       u16 reg2;
-       unsigned int i;
-       char put_to_sleep;
-       char bbp_state;
-       char rf_state;
-
-       put_to_sleep = (state != STATE_AWAKE);
-
-       reg = 0;
-       rt2x00_set_field16(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
-       rt2x00_set_field16(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
-       rt2x00_set_field16(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
-       rt2x00_set_field16(&reg, MAC_CSR17_SET_STATE, 1);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
-
-       /*
-        * Device is not guaranteed to be in the requested state yet.
-        * We must wait until the register indicates that the
-        * device has entered the correct state.
-        */
-       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2500usb_register_read(rt2x00dev, MAC_CSR17, &reg2);
-               bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
-               rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
-               if (bbp_state == state && rf_state == state)
-                       return 0;
-               rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg);
-               msleep(30);
-       }
-
-       return -EBUSY;
-}
-
-static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt2500usb_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               rt2500usb_disable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               /* No support, but no error either */
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt2500usb_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * TX descriptor initialization
- */
-static void rt2500usb_write_tx_desc(struct queue_entry *entry,
-                                   struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *txd = (__le32 *) entry->skb->data;
-       u32 word;
-
-       /*
-        * Start writing the descriptor words.
-        */
-       rt2x00_desc_read(txd, 0, &word);
-       rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
-       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          (txdesc->rate_mode == RATE_MODE_OFDM));
-       rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
-                          test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
-       rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
-       rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
-       rt2x00_desc_write(txd, 0, word);
-
-       rt2x00_desc_read(txd, 1, &word);
-       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
-       rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
-       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
-       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
-       rt2x00_desc_write(txd, 1, word);
-
-       rt2x00_desc_read(txd, 2, &word);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
-                          txdesc->u.plcp.length_low);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
-                          txdesc->u.plcp.length_high);
-       rt2x00_desc_write(txd, 2, word);
-
-       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
-               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
-       }
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
-       skbdesc->desc = txd;
-       skbdesc->desc_len = TXD_DESC_SIZE;
-}
-
-/*
- * TX data initialization
- */
-static void rt2500usb_beacondone(struct urb *urb);
-
-static void rt2500usb_write_beacon(struct queue_entry *entry,
-                                  struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
-       int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
-       int length;
-       u16 reg, reg0;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-
-       /*
-        * Add space for the descriptor in front of the skb.
-        */
-       skb_push(entry->skb, TXD_DESC_SIZE);
-       memset(entry->skb->data, 0, TXD_DESC_SIZE);
-
-       /*
-        * Write the TX descriptor for the beacon.
-        */
-       rt2500usb_write_tx_desc(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
-       /*
-        * USB devices cannot blindly pass the skb->len as the
-        * length of the data to usb_fill_bulk_urb. Pass the skb
-        * to the driver to determine what the length should be.
-        */
-       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
-
-       usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
-                         entry->skb->data, length, rt2500usb_beacondone,
-                         entry);
-
-       /*
-        * Second we need to create the guardian byte.
-        * We only need a single byte, so lets recycle
-        * the 'flags' field we are not using for beacons.
-        */
-       bcn_priv->guardian_data = 0;
-       usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
-                         &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
-                         entry);
-
-       /*
-        * Send out the guardian byte.
-        */
-       usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
-
-       /*
-        * Enable beaconing again.
-        */
-       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
-       reg0 = reg;
-       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
-       /*
-        * Beacon generation will fail initially.
-        * To prevent this we need to change the TXRX_CSR19
-        * register several times (reg0 is the same as reg
-        * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
-        * and 1 in reg).
-        */
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-}
-
-static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
-{
-       int length;
-
-       /*
-        * The length _must_ be a multiple of 2,
-        * but it must _not_ be a multiple of the USB packet size.
-        */
-       length = roundup(entry->skb->len, 2);
-       length += (2 * !(length % entry->queue->usb_maxpacket));
-
-       return length;
-}
-
-/*
- * RX control handlers
- */
-static void rt2500usb_fill_rxdone(struct queue_entry *entry,
-                                 struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *rxd =
-           (__le32 *)(entry->skb->data +
-                      (entry_priv->urb->actual_length -
-                       entry->queue->desc_size));
-       u32 word0;
-       u32 word1;
-
-       /*
-        * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
-        * frame data in rt2x00usb.
-        */
-       memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
-       rxd = (__le32 *)skbdesc->desc;
-
-       /*
-        * It is now safe to read the descriptor on all architectures.
-        */
-       rt2x00_desc_read(rxd, 0, &word0);
-       rt2x00_desc_read(rxd, 1, &word1);
-
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-       if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
-       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
-       if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
-               rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
-
-       if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
-               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
-
-               /* ICV is located at the end of frame */
-
-               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
-                       rxdesc->flags |= RX_FLAG_DECRYPTED;
-               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
-                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
-       }
-
-       /*
-        * Obtain the status about this packet.
-        * When frame was received with an OFDM bitrate,
-        * the signal is the PLCP value. If it was received with
-        * a CCK bitrate the signal is the rate in 100kbit/s.
-        */
-       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       rxdesc->rssi =
-           rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset;
-       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
-       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-       else
-               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
-       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-
-       /*
-        * Adjust the skb memory window to the frame boundaries.
-        */
-       skb_trim(entry->skb, rxdesc->size);
-}
-
-/*
- * Interrupt functions.
- */
-static void rt2500usb_beacondone(struct urb *urb)
-{
-       struct queue_entry *entry = (struct queue_entry *)urb->context;
-       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
-               return;
-
-       /*
-        * Check if this was the guardian beacon,
-        * if that was the case we need to send the real beacon now.
-        * Otherwise we should free the sk_buffer, the device
-        * should be doing the rest of the work now.
-        */
-       if (bcn_priv->guardian_urb == urb) {
-               usb_submit_urb(bcn_priv->urb, GFP_ATOMIC);
-       } else if (bcn_priv->urb == urb) {
-               dev_kfree_skb(entry->skb);
-               entry->skb = NULL;
-       }
-}
-
-/*
- * Device probe functions.
- */
-static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u16 word;
-       u8 *mac;
-       u8 bbp;
-
-       rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
-                                  ANTENNA_SW_DIVERSITY);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
-                                  ANTENNA_SW_DIVERSITY);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
-                                  LED_MODE_DEFAULT);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
-                                  DEFAULT_RSSI_OFFSET);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
-                                 word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);
-       }
-
-       /*
-        * Switch lower vgc bound to current BBP R17 value,
-        * lower the value a bit for better quality.
-        */
-       rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
-       bbp -= 6;
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
-       } else {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
-               rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
-       }
-
-       return 0;
-}
-
-static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u16 reg;
-       u16 value;
-       u16 eeprom;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-       /*
-        * Identify RF chipset.
-        */
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
-
-       if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
-               rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
-               return -ENODEV;
-       }
-
-       if (!rt2x00_rf(rt2x00dev, RF2522) &&
-           !rt2x00_rf(rt2x00dev, RF2523) &&
-           !rt2x00_rf(rt2x00dev, RF2524) &&
-           !rt2x00_rf(rt2x00dev, RF2525) &&
-           !rt2x00_rf(rt2x00dev, RF2525E) &&
-           !rt2x00_rf(rt2x00dev, RF5222)) {
-               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
-               return -ENODEV;
-       }
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->default_ant.rx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
-
-       /*
-        * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
-        * I am not 100% sure about this, but the legacy drivers do not
-        * indicate antenna swapping in software is required when
-        * diversity is enabled.
-        */
-       if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
-       if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
-
-       /*
-        * Store led mode, for correct led behaviour.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-
-       rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       if (value == LED_MODE_TXRX_ACTIVITY ||
-           value == LED_MODE_DEFAULT ||
-           value == LED_MODE_ASUS)
-               rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
-                                  LED_TYPE_ACTIVITY);
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       /*
-        * Detect if this device has an hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-
-       /*
-        * Read the RSSI <-> dBm offset information.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
-       rt2x00dev->rssi_offset =
-           rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
-
-       return 0;
-}
-
-/*
- * RF value list for RF2522
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2522[] = {
-       { 1,  0x00002050, 0x000c1fda, 0x00000101, 0 },
-       { 2,  0x00002050, 0x000c1fee, 0x00000101, 0 },
-       { 3,  0x00002050, 0x000c2002, 0x00000101, 0 },
-       { 4,  0x00002050, 0x000c2016, 0x00000101, 0 },
-       { 5,  0x00002050, 0x000c202a, 0x00000101, 0 },
-       { 6,  0x00002050, 0x000c203e, 0x00000101, 0 },
-       { 7,  0x00002050, 0x000c2052, 0x00000101, 0 },
-       { 8,  0x00002050, 0x000c2066, 0x00000101, 0 },
-       { 9,  0x00002050, 0x000c207a, 0x00000101, 0 },
-       { 10, 0x00002050, 0x000c208e, 0x00000101, 0 },
-       { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 },
-       { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 },
-       { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 },
-       { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 },
-};
-
-/*
- * RF value list for RF2523
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2523[] = {
-       { 1,  0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b },
-       { 2,  0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b },
-       { 3,  0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b },
-       { 4,  0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b },
-       { 5,  0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b },
-       { 6,  0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b },
-       { 7,  0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b },
-       { 8,  0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b },
-       { 9,  0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b },
-       { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b },
-       { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b },
-       { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b },
-       { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b },
-       { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2524
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2524[] = {
-       { 1,  0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b },
-       { 2,  0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b },
-       { 3,  0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b },
-       { 4,  0x00032020, 0x00000caa, 0x00000101, 0x00000a1b },
-       { 5,  0x00032020, 0x00000cae, 0x00000101, 0x00000a1b },
-       { 6,  0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b },
-       { 7,  0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b },
-       { 8,  0x00032020, 0x00000cba, 0x00000101, 0x00000a1b },
-       { 9,  0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b },
-       { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b },
-       { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b },
-       { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b },
-       { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b },
-       { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2525
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2525[] = {
-       { 1,  0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b },
-       { 2,  0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b },
-       { 3,  0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b },
-       { 4,  0x00022020, 0x00080caa, 0x00060111, 0x00000a1b },
-       { 5,  0x00022020, 0x00080cae, 0x00060111, 0x00000a1b },
-       { 6,  0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b },
-       { 7,  0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b },
-       { 8,  0x00022020, 0x00080cba, 0x00060111, 0x00000a1b },
-       { 9,  0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b },
-       { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b },
-       { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b },
-       { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b },
-       { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b },
-       { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 },
-};
-
-/*
- * RF value list for RF2525e
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2525e[] = {
-       { 1,  0x00022010, 0x0000089a, 0x00060111, 0x00000e1b },
-       { 2,  0x00022010, 0x0000089e, 0x00060111, 0x00000e07 },
-       { 3,  0x00022010, 0x0000089e, 0x00060111, 0x00000e1b },
-       { 4,  0x00022010, 0x000008a2, 0x00060111, 0x00000e07 },
-       { 5,  0x00022010, 0x000008a2, 0x00060111, 0x00000e1b },
-       { 6,  0x00022010, 0x000008a6, 0x00060111, 0x00000e07 },
-       { 7,  0x00022010, 0x000008a6, 0x00060111, 0x00000e1b },
-       { 8,  0x00022010, 0x000008aa, 0x00060111, 0x00000e07 },
-       { 9,  0x00022010, 0x000008aa, 0x00060111, 0x00000e1b },
-       { 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 },
-       { 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b },
-       { 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 },
-       { 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b },
-       { 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 },
-};
-
-/*
- * RF value list for RF5222
- * Supports: 2.4 GHz & 5.2 GHz
- */
-static const struct rf_channel rf_vals_5222[] = {
-       { 1,  0x00022020, 0x00001136, 0x00000101, 0x00000a0b },
-       { 2,  0x00022020, 0x0000113a, 0x00000101, 0x00000a0b },
-       { 3,  0x00022020, 0x0000113e, 0x00000101, 0x00000a0b },
-       { 4,  0x00022020, 0x00001182, 0x00000101, 0x00000a0b },
-       { 5,  0x00022020, 0x00001186, 0x00000101, 0x00000a0b },
-       { 6,  0x00022020, 0x0000118a, 0x00000101, 0x00000a0b },
-       { 7,  0x00022020, 0x0000118e, 0x00000101, 0x00000a0b },
-       { 8,  0x00022020, 0x00001192, 0x00000101, 0x00000a0b },
-       { 9,  0x00022020, 0x00001196, 0x00000101, 0x00000a0b },
-       { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b },
-       { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b },
-       { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b },
-       { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b },
-       { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f },
-       { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f },
-       { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f },
-       { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f },
-       { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f },
-       { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f },
-       { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f },
-       { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f },
-       { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f },
-       { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f },
-       { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f },
-       { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f },
-       { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f },
-       { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f },
-       { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f },
-       { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f },
-       { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f },
-
-       /* 802.11 UNII */
-       { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f },
-       { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 },
-       { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 },
-       { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 },
-       { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
-};
-
-static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *tx_power;
-       unsigned int i;
-
-       /*
-        * Initialize all hw fields.
-        *
-        * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING unless we are
-        * capable of sending the buffered frames out after the DTIM
-        * transmission using rt2x00lib_beacondone. This will send out
-        * multicast and broadcast traffic immediately instead of buffering it
-        * infinitly and thus dropping it after some time.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-       ieee80211_hw_set(rt2x00dev->hw, RX_INCLUDES_FCS);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-
-       /*
-        * Disable powersaving as default.
-        */
-       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2x00_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-       if (rt2x00_rf(rt2x00dev, RF2522)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
-               spec->channels = rf_vals_bg_2522;
-       } else if (rt2x00_rf(rt2x00dev, RF2523)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
-               spec->channels = rf_vals_bg_2523;
-       } else if (rt2x00_rf(rt2x00dev, RF2524)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
-               spec->channels = rf_vals_bg_2524;
-       } else if (rt2x00_rf(rt2x00dev, RF2525)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
-               spec->channels = rf_vals_bg_2525;
-       } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
-               spec->channels = rf_vals_bg_2525e;
-       } else if (rt2x00_rf(rt2x00dev, RF5222)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_5222);
-               spec->channels = rf_vals_5222;
-       }
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-       for (i = 0; i < 14; i++) {
-               info[i].max_power = MAX_TXPOWER;
-               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
-       }
-
-       if (spec->num_channels > 14) {
-               for (i = 14; i < spec->num_channels; i++) {
-                       info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 = DEFAULT_TXPOWER;
-               }
-       }
-
-       return 0;
-}
-
-static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u16 reg;
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt2500usb_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt2500usb_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
-       rt2x00_set_field16(&reg, MAC_CSR19_DIR0, 0);
-       rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt2500usb_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * This device requires the atim queue
-        */
-       __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
-       if (!modparam_nohwcrypt) {
-               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
-               __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
-       }
-       __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-
-static const struct ieee80211_ops rt2500usb_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_tim                = rt2x00mac_set_tim,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2x00mac_conf_tx,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .flush                  = rt2x00mac_flush,
-       .set_antenna            = rt2x00mac_set_antenna,
-       .get_antenna            = rt2x00mac_get_antenna,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
-       .probe_hw               = rt2500usb_probe_hw,
-       .initialize             = rt2x00usb_initialize,
-       .uninitialize           = rt2x00usb_uninitialize,
-       .clear_entry            = rt2x00usb_clear_entry,
-       .set_device_state       = rt2500usb_set_device_state,
-       .rfkill_poll            = rt2500usb_rfkill_poll,
-       .link_stats             = rt2500usb_link_stats,
-       .reset_tuner            = rt2500usb_reset_tuner,
-       .watchdog               = rt2x00usb_watchdog,
-       .start_queue            = rt2500usb_start_queue,
-       .kick_queue             = rt2x00usb_kick_queue,
-       .stop_queue             = rt2500usb_stop_queue,
-       .flush_queue            = rt2x00usb_flush_queue,
-       .write_tx_desc          = rt2500usb_write_tx_desc,
-       .write_beacon           = rt2500usb_write_beacon,
-       .get_tx_data_len        = rt2500usb_get_tx_data_len,
-       .fill_rxdone            = rt2500usb_fill_rxdone,
-       .config_shared_key      = rt2500usb_config_key,
-       .config_pairwise_key    = rt2500usb_config_key,
-       .config_filter          = rt2500usb_config_filter,
-       .config_intf            = rt2500usb_config_intf,
-       .config_erp             = rt2500usb_config_erp,
-       .config_ant             = rt2500usb_config_ant,
-       .config                 = rt2500usb_config,
-};
-
-static void rt2500usb_queue_init(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 1;
-               queue->data_size = MGMT_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn);
-               break;
-
-       case QID_ATIM:
-               queue->limit = 8;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt2500usb_ops = {
-       .name                   = KBUILD_MODNAME,
-       .max_ap_intf            = 1,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2500usb_queue_init,
-       .lib                    = &rt2500usb_rt2x00_ops,
-       .hw                     = &rt2500usb_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2500usb_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * rt2500usb module information.
- */
-static struct usb_device_id rt2500usb_device_table[] = {
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1706) },
-       { USB_DEVICE(0x0b05, 0x1707) },
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050A ver. 2.x */
-       { USB_DEVICE(0x050d, 0x7051) },
-       /* Cisco Systems */
-       { USB_DEVICE(0x13b1, 0x000d) },
-       { USB_DEVICE(0x13b1, 0x0011) },
-       { USB_DEVICE(0x13b1, 0x001a) },
-       /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c02) },
-       /* D-LINK */
-       { USB_DEVICE(0x2001, 0x3c00) },
-       /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x8001) },
-       { USB_DEVICE(0x1044, 0x8007) },
-       /* Hercules */
-       { USB_DEVICE(0x06f8, 0xe000) },
-       /* Melco */
-       { USB_DEVICE(0x0411, 0x005e) },
-       { USB_DEVICE(0x0411, 0x0066) },
-       { USB_DEVICE(0x0411, 0x0067) },
-       { USB_DEVICE(0x0411, 0x008b) },
-       { USB_DEVICE(0x0411, 0x0097) },
-       /* MSI */
-       { USB_DEVICE(0x0db0, 0x6861) },
-       { USB_DEVICE(0x0db0, 0x6865) },
-       { USB_DEVICE(0x0db0, 0x6869) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x1706) },
-       { USB_DEVICE(0x148f, 0x2570) },
-       { USB_DEVICE(0x148f, 0x9020) },
-       /* Sagem */
-       { USB_DEVICE(0x079b, 0x004b) },
-       /* Siemens */
-       { USB_DEVICE(0x0681, 0x3c06) },
-       /* SMC */
-       { USB_DEVICE(0x0707, 0xee13) },
-       /* Spairon */
-       { USB_DEVICE(0x114b, 0x0110) },
-       /* SURECOM */
-       { USB_DEVICE(0x0769, 0x11f3) },
-       /* Trust */
-       { USB_DEVICE(0x0eb0, 0x9020) },
-       /* VTech */
-       { USB_DEVICE(0x0f88, 0x3012) },
-       /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0260) },
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
-MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
-MODULE_LICENSE("GPL");
-
-static int rt2500usb_probe(struct usb_interface *usb_intf,
-                          const struct usb_device_id *id)
-{
-       return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
-}
-
-static struct usb_driver rt2500usb_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt2500usb_device_table,
-       .probe          = rt2500usb_probe,
-       .disconnect     = rt2x00usb_disconnect,
-       .suspend        = rt2x00usb_suspend,
-       .resume         = rt2x00usb_resume,
-       .reset_resume   = rt2x00usb_resume,
-       .disable_hub_initiated_lpm = 1,
-};
-
-module_usb_driver(rt2500usb_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
deleted file mode 100644 (file)
index 78cc035..0000000
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2500usb
-       Abstract: Data structures and registers for the rt2500usb module.
-       Supported chipsets: RT2570.
- */
-
-#ifndef RT2500USB_H
-#define RT2500USB_H
-
-/*
- * RF chip defines.
- */
-#define RF2522                         0x0000
-#define RF2523                         0x0001
-#define RF2524                         0x0002
-#define RF2525                         0x0003
-#define RF2525E                                0x0005
-#define RF5222                         0x0010
-
-/*
- * RT2570 version
- */
-#define RT2570_VERSION_B               2
-#define RT2570_VERSION_C               3
-#define RT2570_VERSION_D               4
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET            120
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x0400
-#define CSR_REG_SIZE                   0x0100
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x006e
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x0060
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  2
-
-/*
- * Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- */
-#define MAC_CSR0                       0x0400
-
-/*
- * MAC_CSR1: System control.
- * SOFT_RESET: Software reset, 1: reset, 0: normal.
- * BBP_RESET: Hardware reset, 1: reset, 0, release.
- * HOST_READY: Host ready after initialization.
- */
-#define MAC_CSR1                       0x0402
-#define MAC_CSR1_SOFT_RESET            FIELD16(0x00000001)
-#define MAC_CSR1_BBP_RESET             FIELD16(0x00000002)
-#define MAC_CSR1_HOST_READY            FIELD16(0x00000004)
-
-/*
- * MAC_CSR2: STA MAC register 0.
- */
-#define MAC_CSR2                       0x0404
-#define MAC_CSR2_BYTE0                 FIELD16(0x00ff)
-#define MAC_CSR2_BYTE1                 FIELD16(0xff00)
-
-/*
- * MAC_CSR3: STA MAC register 1.
- */
-#define MAC_CSR3                       0x0406
-#define MAC_CSR3_BYTE2                 FIELD16(0x00ff)
-#define MAC_CSR3_BYTE3                 FIELD16(0xff00)
-
-/*
- * MAC_CSR4: STA MAC register 2.
- */
-#define MAC_CSR4                       0X0408
-#define MAC_CSR4_BYTE4                 FIELD16(0x00ff)
-#define MAC_CSR4_BYTE5                 FIELD16(0xff00)
-
-/*
- * MAC_CSR5: BSSID register 0.
- */
-#define MAC_CSR5                       0x040a
-#define MAC_CSR5_BYTE0                 FIELD16(0x00ff)
-#define MAC_CSR5_BYTE1                 FIELD16(0xff00)
-
-/*
- * MAC_CSR6: BSSID register 1.
- */
-#define MAC_CSR6                       0x040c
-#define MAC_CSR6_BYTE2                 FIELD16(0x00ff)
-#define MAC_CSR6_BYTE3                 FIELD16(0xff00)
-
-/*
- * MAC_CSR7: BSSID register 2.
- */
-#define MAC_CSR7                       0x040e
-#define MAC_CSR7_BYTE4                 FIELD16(0x00ff)
-#define MAC_CSR7_BYTE5                 FIELD16(0xff00)
-
-/*
- * MAC_CSR8: Max frame length.
- */
-#define MAC_CSR8                       0x0410
-#define MAC_CSR8_MAX_FRAME_UNIT                FIELD16(0x0fff)
-
-/*
- * Misc MAC_CSR registers.
- * MAC_CSR9: Timer control.
- * MAC_CSR10: Slot time.
- * MAC_CSR11: SIFS.
- * MAC_CSR12: EIFS.
- * MAC_CSR13: Power mode0.
- * MAC_CSR14: Power mode1.
- * MAC_CSR15: Power saving transition0
- * MAC_CSR16: Power saving transition1
- */
-#define MAC_CSR9                       0x0412
-#define MAC_CSR10                      0x0414
-#define MAC_CSR11                      0x0416
-#define MAC_CSR12                      0x0418
-#define MAC_CSR13                      0x041a
-#define MAC_CSR14                      0x041c
-#define MAC_CSR15                      0x041e
-#define MAC_CSR16                      0x0420
-
-/*
- * MAC_CSR17: Manual power control / status register.
- * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake.
- * SET_STATE: Set state. Write 1 to trigger, self cleared.
- * BBP_DESIRE_STATE: BBP desired state.
- * RF_DESIRE_STATE: RF desired state.
- * BBP_CURRENT_STATE: BBP current state.
- * RF_CURRENT_STATE: RF current state.
- * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared.
- */
-#define MAC_CSR17                      0x0422
-#define MAC_CSR17_SET_STATE            FIELD16(0x0001)
-#define MAC_CSR17_BBP_DESIRE_STATE     FIELD16(0x0006)
-#define MAC_CSR17_RF_DESIRE_STATE      FIELD16(0x0018)
-#define MAC_CSR17_BBP_CURR_STATE       FIELD16(0x0060)
-#define MAC_CSR17_RF_CURR_STATE                FIELD16(0x0180)
-#define MAC_CSR17_PUT_TO_SLEEP         FIELD16(0x0200)
-
-/*
- * MAC_CSR18: Wakeup timer register.
- * DELAY_AFTER_BEACON: Delay after Tbcn expired in units of 1/16 TU.
- * BEACONS_BEFORE_WAKEUP: Number of beacon before wakeup.
- * AUTO_WAKE: Enable auto wakeup / sleep mechanism.
- */
-#define MAC_CSR18                      0x0424
-#define MAC_CSR18_DELAY_AFTER_BEACON   FIELD16(0x00ff)
-#define MAC_CSR18_BEACONS_BEFORE_WAKEUP        FIELD16(0x7f00)
-#define MAC_CSR18_AUTO_WAKE            FIELD16(0x8000)
-
-/*
- * MAC_CSR19: GPIO control register.
- *     MAC_CSR19_VALx: GPIO value
- *     MAC_CSR19_DIRx: GPIO direction: 0 = input; 1 = output
- */
-#define MAC_CSR19                      0x0426
-#define MAC_CSR19_VAL0                 FIELD16(0x0001)
-#define MAC_CSR19_VAL1                 FIELD16(0x0002)
-#define MAC_CSR19_VAL2                 FIELD16(0x0004)
-#define MAC_CSR19_VAL3                 FIELD16(0x0008)
-#define MAC_CSR19_VAL4                 FIELD16(0x0010)
-#define MAC_CSR19_VAL5                 FIELD16(0x0020)
-#define MAC_CSR19_VAL6                 FIELD16(0x0040)
-#define MAC_CSR19_VAL7                 FIELD16(0x0080)
-#define MAC_CSR19_DIR0                 FIELD16(0x0100)
-#define MAC_CSR19_DIR1                 FIELD16(0x0200)
-#define MAC_CSR19_DIR2                 FIELD16(0x0400)
-#define MAC_CSR19_DIR3                 FIELD16(0x0800)
-#define MAC_CSR19_DIR4                 FIELD16(0x1000)
-#define MAC_CSR19_DIR5                 FIELD16(0x2000)
-#define MAC_CSR19_DIR6                 FIELD16(0x4000)
-#define MAC_CSR19_DIR7                 FIELD16(0x8000)
-
-/*
- * MAC_CSR20: LED control register.
- * ACTIVITY: 0: idle, 1: active.
- * LINK: 0: linkoff, 1: linkup.
- * ACTIVITY_POLARITY: 0: active low, 1: active high.
- */
-#define MAC_CSR20                      0x0428
-#define MAC_CSR20_ACTIVITY             FIELD16(0x0001)
-#define MAC_CSR20_LINK                 FIELD16(0x0002)
-#define MAC_CSR20_ACTIVITY_POLARITY    FIELD16(0x0004)
-
-/*
- * MAC_CSR21: LED control register.
- * ON_PERIOD: On period, default 70ms.
- * OFF_PERIOD: Off period, default 30ms.
- */
-#define MAC_CSR21                      0x042a
-#define MAC_CSR21_ON_PERIOD            FIELD16(0x00ff)
-#define MAC_CSR21_OFF_PERIOD           FIELD16(0xff00)
-
-/*
- * MAC_CSR22: Collision window control register.
- */
-#define MAC_CSR22                      0x042c
-
-/*
- * Transmit related CSRs.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * TXRX_CSR0: Security control register.
- */
-#define TXRX_CSR0                      0x0440
-#define TXRX_CSR0_ALGORITHM            FIELD16(0x0007)
-#define TXRX_CSR0_IV_OFFSET            FIELD16(0x01f8)
-#define TXRX_CSR0_KEY_ID               FIELD16(0x1e00)
-
-/*
- * TXRX_CSR1: TX configuration.
- * ACK_TIMEOUT: ACK Timeout in unit of 1-us.
- * TSF_OFFSET: TSF offset in MAC header.
- * AUTO_SEQUENCE: Let ASIC control frame sequence number.
- */
-#define TXRX_CSR1                      0x0442
-#define TXRX_CSR1_ACK_TIMEOUT          FIELD16(0x00ff)
-#define TXRX_CSR1_TSF_OFFSET           FIELD16(0x7f00)
-#define TXRX_CSR1_AUTO_SEQUENCE                FIELD16(0x8000)
-
-/*
- * TXRX_CSR2: RX control.
- * DISABLE_RX: Disable rx engine.
- * DROP_CRC: Drop crc error.
- * DROP_PHYSICAL: Drop physical error.
- * DROP_CONTROL: Drop control frame.
- * DROP_NOT_TO_ME: Drop not to me unicast frame.
- * DROP_TODS: Drop frame tods bit is true.
- * DROP_VERSION_ERROR: Drop version error frame.
- * DROP_MCAST: Drop multicast frames.
- * DROP_BCAST: Drop broadcast frames.
- */
-#define TXRX_CSR2                      0x0444
-#define        TXRX_CSR2_DISABLE_RX            FIELD16(0x0001)
-#define TXRX_CSR2_DROP_CRC             FIELD16(0x0002)
-#define TXRX_CSR2_DROP_PHYSICAL                FIELD16(0x0004)
-#define TXRX_CSR2_DROP_CONTROL         FIELD16(0x0008)
-#define TXRX_CSR2_DROP_NOT_TO_ME       FIELD16(0x0010)
-#define TXRX_CSR2_DROP_TODS            FIELD16(0x0020)
-#define TXRX_CSR2_DROP_VERSION_ERROR   FIELD16(0x0040)
-#define TXRX_CSR2_DROP_MULTICAST       FIELD16(0x0200)
-#define TXRX_CSR2_DROP_BROADCAST       FIELD16(0x0400)
-
-/*
- * RX BBP ID registers
- * TXRX_CSR3: CCK RX BBP ID.
- * TXRX_CSR4: OFDM RX BBP ID.
- */
-#define TXRX_CSR3                      0x0446
-#define TXRX_CSR4                      0x0448
-
-/*
- * TXRX_CSR5: CCK TX BBP ID0.
- */
-#define TXRX_CSR5                      0x044a
-#define TXRX_CSR5_BBP_ID0              FIELD16(0x007f)
-#define TXRX_CSR5_BBP_ID0_VALID                FIELD16(0x0080)
-#define TXRX_CSR5_BBP_ID1              FIELD16(0x7f00)
-#define TXRX_CSR5_BBP_ID1_VALID                FIELD16(0x8000)
-
-/*
- * TXRX_CSR6: CCK TX BBP ID1.
- */
-#define TXRX_CSR6                      0x044c
-#define TXRX_CSR6_BBP_ID0              FIELD16(0x007f)
-#define TXRX_CSR6_BBP_ID0_VALID                FIELD16(0x0080)
-#define TXRX_CSR6_BBP_ID1              FIELD16(0x7f00)
-#define TXRX_CSR6_BBP_ID1_VALID                FIELD16(0x8000)
-
-/*
- * TXRX_CSR7: OFDM TX BBP ID0.
- */
-#define TXRX_CSR7                      0x044e
-#define TXRX_CSR7_BBP_ID0              FIELD16(0x007f)
-#define TXRX_CSR7_BBP_ID0_VALID                FIELD16(0x0080)
-#define TXRX_CSR7_BBP_ID1              FIELD16(0x7f00)
-#define TXRX_CSR7_BBP_ID1_VALID                FIELD16(0x8000)
-
-/*
- * TXRX_CSR8: OFDM TX BBP ID1.
- */
-#define TXRX_CSR8                      0x0450
-#define TXRX_CSR8_BBP_ID0              FIELD16(0x007f)
-#define TXRX_CSR8_BBP_ID0_VALID                FIELD16(0x0080)
-#define TXRX_CSR8_BBP_ID1              FIELD16(0x7f00)
-#define TXRX_CSR8_BBP_ID1_VALID                FIELD16(0x8000)
-
-/*
- * TXRX_CSR9: TX ACK time-out.
- */
-#define TXRX_CSR9                      0x0452
-
-/*
- * TXRX_CSR10: Auto responder control.
- */
-#define TXRX_CSR10                     0x0454
-#define TXRX_CSR10_AUTORESPOND_PREAMBLE FIELD16(0x0004)
-
-/*
- * TXRX_CSR11: Auto responder basic rate.
- */
-#define TXRX_CSR11                     0x0456
-
-/*
- * ACK/CTS time registers.
- */
-#define TXRX_CSR12                     0x0458
-#define TXRX_CSR13                     0x045a
-#define TXRX_CSR14                     0x045c
-#define TXRX_CSR15                     0x045e
-#define TXRX_CSR16                     0x0460
-#define TXRX_CSR17                     0x0462
-
-/*
- * TXRX_CSR18: Synchronization control register.
- */
-#define TXRX_CSR18                     0x0464
-#define TXRX_CSR18_OFFSET              FIELD16(0x000f)
-#define TXRX_CSR18_INTERVAL            FIELD16(0xfff0)
-
-/*
- * TXRX_CSR19: Synchronization control register.
- * TSF_COUNT: Enable TSF auto counting.
- * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
- * TBCN: Enable Tbcn with reload value.
- * BEACON_GEN: Enable beacon generator.
- */
-#define TXRX_CSR19                     0x0466
-#define TXRX_CSR19_TSF_COUNT           FIELD16(0x0001)
-#define TXRX_CSR19_TSF_SYNC            FIELD16(0x0006)
-#define TXRX_CSR19_TBCN                        FIELD16(0x0008)
-#define TXRX_CSR19_BEACON_GEN          FIELD16(0x0010)
-
-/*
- * TXRX_CSR20: Tx BEACON offset time control register.
- * OFFSET: In units of usec.
- * BCN_EXPECT_WINDOW: Default: 2^CWmin
- */
-#define TXRX_CSR20                     0x0468
-#define TXRX_CSR20_OFFSET              FIELD16(0x1fff)
-#define TXRX_CSR20_BCN_EXPECT_WINDOW   FIELD16(0xe000)
-
-/*
- * TXRX_CSR21
- */
-#define TXRX_CSR21                     0x046a
-
-/*
- * Encryption related CSRs.
- *
- */
-
-/*
- * SEC_CSR0: Shared key 0, word 0
- * SEC_CSR1: Shared key 0, word 1
- * SEC_CSR2: Shared key 0, word 2
- * SEC_CSR3: Shared key 0, word 3
- * SEC_CSR4: Shared key 0, word 4
- * SEC_CSR5: Shared key 0, word 5
- * SEC_CSR6: Shared key 0, word 6
- * SEC_CSR7: Shared key 0, word 7
- */
-#define SEC_CSR0                       0x0480
-#define SEC_CSR1                       0x0482
-#define SEC_CSR2                       0x0484
-#define SEC_CSR3                       0x0486
-#define SEC_CSR4                       0x0488
-#define SEC_CSR5                       0x048a
-#define SEC_CSR6                       0x048c
-#define SEC_CSR7                       0x048e
-
-/*
- * SEC_CSR8: Shared key 1, word 0
- * SEC_CSR9: Shared key 1, word 1
- * SEC_CSR10: Shared key 1, word 2
- * SEC_CSR11: Shared key 1, word 3
- * SEC_CSR12: Shared key 1, word 4
- * SEC_CSR13: Shared key 1, word 5
- * SEC_CSR14: Shared key 1, word 6
- * SEC_CSR15: Shared key 1, word 7
- */
-#define SEC_CSR8                       0x0490
-#define SEC_CSR9                       0x0492
-#define SEC_CSR10                      0x0494
-#define SEC_CSR11                      0x0496
-#define SEC_CSR12                      0x0498
-#define SEC_CSR13                      0x049a
-#define SEC_CSR14                      0x049c
-#define SEC_CSR15                      0x049e
-
-/*
- * SEC_CSR16: Shared key 2, word 0
- * SEC_CSR17: Shared key 2, word 1
- * SEC_CSR18: Shared key 2, word 2
- * SEC_CSR19: Shared key 2, word 3
- * SEC_CSR20: Shared key 2, word 4
- * SEC_CSR21: Shared key 2, word 5
- * SEC_CSR22: Shared key 2, word 6
- * SEC_CSR23: Shared key 2, word 7
- */
-#define SEC_CSR16                      0x04a0
-#define SEC_CSR17                      0x04a2
-#define SEC_CSR18                      0X04A4
-#define SEC_CSR19                      0x04a6
-#define SEC_CSR20                      0x04a8
-#define SEC_CSR21                      0x04aa
-#define SEC_CSR22                      0x04ac
-#define SEC_CSR23                      0x04ae
-
-/*
- * SEC_CSR24: Shared key 3, word 0
- * SEC_CSR25: Shared key 3, word 1
- * SEC_CSR26: Shared key 3, word 2
- * SEC_CSR27: Shared key 3, word 3
- * SEC_CSR28: Shared key 3, word 4
- * SEC_CSR29: Shared key 3, word 5
- * SEC_CSR30: Shared key 3, word 6
- * SEC_CSR31: Shared key 3, word 7
- */
-#define SEC_CSR24                      0x04b0
-#define SEC_CSR25                      0x04b2
-#define SEC_CSR26                      0x04b4
-#define SEC_CSR27                      0x04b6
-#define SEC_CSR28                      0x04b8
-#define SEC_CSR29                      0x04ba
-#define SEC_CSR30                      0x04bc
-#define SEC_CSR31                      0x04be
-
-#define KEY_ENTRY(__idx) \
-       ( SEC_CSR0 + ((__idx) * 16) )
-
-/*
- * PHY control registers.
- */
-
-/*
- * PHY_CSR0: RF switching timing control.
- */
-#define PHY_CSR0                       0x04c0
-
-/*
- * PHY_CSR1: TX PA configuration.
- */
-#define PHY_CSR1                       0x04c2
-
-/*
- * MAC configuration registers.
- */
-
-/*
- * PHY_CSR2: TX MAC configuration.
- * NOTE: Both register fields are complete dummy,
- * documentation and legacy drivers are unclear un
- * what this register means or what fields exists.
- */
-#define PHY_CSR2                       0x04c4
-#define PHY_CSR2_LNA                   FIELD16(0x0002)
-#define PHY_CSR2_LNA_MODE              FIELD16(0x3000)
-
-/*
- * PHY_CSR3: RX MAC configuration.
- */
-#define PHY_CSR3                       0x04c6
-
-/*
- * PHY_CSR4: Interface configuration.
- */
-#define PHY_CSR4                       0x04c8
-#define PHY_CSR4_LOW_RF_LE             FIELD16(0x0001)
-
-/*
- * BBP pre-TX registers.
- * PHY_CSR5: BBP pre-TX CCK.
- */
-#define PHY_CSR5                       0x04ca
-#define PHY_CSR5_CCK                   FIELD16(0x0003)
-#define PHY_CSR5_CCK_FLIP              FIELD16(0x0004)
-
-/*
- * BBP pre-TX registers.
- * PHY_CSR6: BBP pre-TX OFDM.
- */
-#define PHY_CSR6                       0x04cc
-#define PHY_CSR6_OFDM                  FIELD16(0x0003)
-#define PHY_CSR6_OFDM_FLIP             FIELD16(0x0004)
-
-/*
- * PHY_CSR7: BBP access register 0.
- * BBP_DATA: BBP data.
- * BBP_REG_ID: BBP register ID.
- * BBP_READ_CONTROL: 0: write, 1: read.
- */
-#define PHY_CSR7                       0x04ce
-#define PHY_CSR7_DATA                  FIELD16(0x00ff)
-#define PHY_CSR7_REG_ID                        FIELD16(0x7f00)
-#define PHY_CSR7_READ_CONTROL          FIELD16(0x8000)
-
-/*
- * PHY_CSR8: BBP access register 1.
- * BBP_BUSY: ASIC is busy execute BBP programming.
- */
-#define PHY_CSR8                       0x04d0
-#define PHY_CSR8_BUSY                  FIELD16(0x0001)
-
-/*
- * PHY_CSR9: RF access register.
- * RF_VALUE: Register value + id to program into rf/if.
- */
-#define PHY_CSR9                       0x04d2
-#define PHY_CSR9_RF_VALUE              FIELD16(0xffff)
-
-/*
- * PHY_CSR10: RF access register.
- * RF_VALUE: Register value + id to program into rf/if.
- * RF_NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22).
- * RF_IF_SELECT: Chip to program: 0: rf, 1: if.
- * RF_PLL_LD: Rf pll_ld status.
- * RF_BUSY: 1: asic is busy execute rf programming.
- */
-#define PHY_CSR10                      0x04d4
-#define PHY_CSR10_RF_VALUE             FIELD16(0x00ff)
-#define PHY_CSR10_RF_NUMBER_OF_BITS    FIELD16(0x1f00)
-#define PHY_CSR10_RF_IF_SELECT         FIELD16(0x2000)
-#define PHY_CSR10_RF_PLL_LD            FIELD16(0x4000)
-#define PHY_CSR10_RF_BUSY              FIELD16(0x8000)
-
-/*
- * STA_CSR0: FCS error count.
- * FCS_ERROR: FCS error count, cleared when read.
- */
-#define STA_CSR0                       0x04e0
-#define STA_CSR0_FCS_ERROR             FIELD16(0xffff)
-
-/*
- * STA_CSR1: PLCP error count.
- */
-#define STA_CSR1                       0x04e2
-
-/*
- * STA_CSR2: LONG error count.
- */
-#define STA_CSR2                       0x04e4
-
-/*
- * STA_CSR3: CCA false alarm.
- * FALSE_CCA_ERROR: False CCA error count, cleared when read.
- */
-#define STA_CSR3                       0x04e6
-#define STA_CSR3_FALSE_CCA_ERROR       FIELD16(0xffff)
-
-/*
- * STA_CSR4: RX FIFO overflow.
- */
-#define STA_CSR4                       0x04e8
-
-/*
- * STA_CSR5: Beacon sent counter.
- */
-#define STA_CSR5                       0x04ea
-
-/*
- *  Statistics registers
- */
-#define STA_CSR6                       0x04ec
-#define STA_CSR7                       0x04ee
-#define STA_CSR8                       0x04f0
-#define STA_CSR9                       0x04f2
-#define STA_CSR10                      0x04f4
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * R2: TX antenna control
- */
-#define BBP_R2_TX_ANTENNA              FIELD8(0x03)
-#define BBP_R2_TX_IQ_FLIP              FIELD8(0x04)
-
-/*
- * R14: RX antenna control
- */
-#define BBP_R14_RX_ANTENNA             FIELD8(0x03)
-#define BBP_R14_RX_IQ_FLIP             FIELD8(0x04)
-
-/*
- * RF registers.
- */
-
-/*
- * RF 1
- */
-#define RF1_TUNER                      FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TUNER                      FIELD32(0x00000100)
-#define RF3_TXPOWER                    FIELD32(0x00003e00)
-
-/*
- * EEPROM contents.
- */
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0              0x0002
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR1               0x0003
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2              0x0004
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM antenna.
- * ANTENNA_NUM: Number of antenna's.
- * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * LED_MODE: 0: default, 1: TX/RX activity, 2: Single (ignore link), 3: rsvd.
- * DYN_TXAGC: Dynamic TX AGC control.
- * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
- * RF_TYPE: Rf_type of this adapter.
- */
-#define EEPROM_ANTENNA                 0x000b
-#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
-#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
-#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
-#define EEPROM_ANTENNA_LED_MODE                FIELD16(0x01c0)
-#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
-#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
-#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
-
-/*
- * EEPROM NIC config.
- * CARDBUS_ACCEL: 0: enable, 1: disable.
- * DYN_BBP_TUNE: 0: enable, 1: disable.
- * CCK_TX_POWER: CCK TX power compensation.
- */
-#define EEPROM_NIC                     0x000c
-#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0001)
-#define EEPROM_NIC_DYN_BBP_TUNE                FIELD16(0x0002)
-#define EEPROM_NIC_CCK_TX_POWER                FIELD16(0x000c)
-
-/*
- * EEPROM geography.
- * GEO: Default geography setting for device.
- */
-#define EEPROM_GEOGRAPHY               0x000d
-#define EEPROM_GEOGRAPHY_GEO           FIELD16(0x0f00)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START               0x000e
-#define EEPROM_BBP_SIZE                        16
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER
- */
-#define EEPROM_TXPOWER_START           0x001e
-#define EEPROM_TXPOWER_SIZE            7
-#define EEPROM_TXPOWER_1               FIELD16(0x00ff)
-#define EEPROM_TXPOWER_2               FIELD16(0xff00)
-
-/*
- * EEPROM Tuning threshold
- */
-#define EEPROM_BBPTUNE                 0x0030
-#define EEPROM_BBPTUNE_THRESHOLD       FIELD16(0x00ff)
-
-/*
- * EEPROM BBP R24 Tuning.
- */
-#define EEPROM_BBPTUNE_R24             0x0031
-#define EEPROM_BBPTUNE_R24_LOW         FIELD16(0x00ff)
-#define EEPROM_BBPTUNE_R24_HIGH                FIELD16(0xff00)
-
-/*
- * EEPROM BBP R25 Tuning.
- */
-#define EEPROM_BBPTUNE_R25             0x0032
-#define EEPROM_BBPTUNE_R25_LOW         FIELD16(0x00ff)
-#define EEPROM_BBPTUNE_R25_HIGH                FIELD16(0xff00)
-
-/*
- * EEPROM BBP R24 Tuning.
- */
-#define EEPROM_BBPTUNE_R61             0x0033
-#define EEPROM_BBPTUNE_R61_LOW         FIELD16(0x00ff)
-#define EEPROM_BBPTUNE_R61_HIGH                FIELD16(0xff00)
-
-/*
- * EEPROM BBP VGC Tuning.
- */
-#define EEPROM_BBPTUNE_VGC             0x0034
-#define EEPROM_BBPTUNE_VGCUPPER                FIELD16(0x00ff)
-#define EEPROM_BBPTUNE_VGCLOWER                FIELD16(0xff00)
-
-/*
- * EEPROM BBP R17 Tuning.
- */
-#define EEPROM_BBPTUNE_R17             0x0035
-#define EEPROM_BBPTUNE_R17_LOW         FIELD16(0x00ff)
-#define EEPROM_BBPTUNE_R17_HIGH                FIELD16(0xff00)
-
-/*
- * RSSI <-> dBm offset calibration
- */
-#define EEPROM_CALIBRATE_OFFSET                0x0036
-#define EEPROM_CALIBRATE_OFFSET_RSSI   FIELD16(0x00ff)
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  ( 5 * sizeof(__le32) )
-#define RXD_DESC_SIZE                  ( 4 * sizeof(__le32) )
-
-/*
- * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_PACKET_ID               FIELD32(0x0000000f)
-#define TXD_W0_RETRY_LIMIT             FIELD32(0x000000f0)
-#define TXD_W0_MORE_FRAG               FIELD32(0x00000100)
-#define TXD_W0_ACK                     FIELD32(0x00000200)
-#define TXD_W0_TIMESTAMP               FIELD32(0x00000400)
-#define TXD_W0_OFDM                    FIELD32(0x00000800)
-#define TXD_W0_NEW_SEQ                 FIELD32(0x00001000)
-#define TXD_W0_IFS                     FIELD32(0x00006000)
-#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define TXD_W0_CIPHER                  FIELD32(0x20000000)
-#define TXD_W0_KEY_ID                  FIELD32(0xc0000000)
-
-/*
- * Word1
- */
-#define TXD_W1_IV_OFFSET               FIELD32(0x0000003f)
-#define TXD_W1_AIFS                    FIELD32(0x000000c0)
-#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
-#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
-
-/*
- * Word2: PLCP information
- */
-#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
-#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
-#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
-#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
-
-/*
- * Word3
- */
-#define TXD_W3_IV                      FIELD32(0xffffffff)
-
-/*
- * Word4
- */
-#define TXD_W4_EIV                     FIELD32(0xffffffff)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- */
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000002)
-#define RXD_W0_MULTICAST               FIELD32(0x00000004)
-#define RXD_W0_BROADCAST               FIELD32(0x00000008)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000010)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000020)
-#define RXD_W0_OFDM                    FIELD32(0x00000040)
-#define RXD_W0_PHYSICAL_ERROR          FIELD32(0x00000080)
-#define RXD_W0_CIPHER                  FIELD32(0x00000100)
-#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000200)
-#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-
-/*
- * Word1
- */
-#define RXD_W1_RSSI                    FIELD32(0x000000ff)
-#define RXD_W1_SIGNAL                  FIELD32(0x0000ff00)
-
-/*
- * Word2
- */
-#define RXD_W2_IV                      FIELD32(0xffffffff)
-
-/*
- * Word3
- */
-#define RXD_W3_EIV                     FIELD32(0xffffffff)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_TXPOWER    0
-#define MAX_TXPOWER    31
-#define DEFAULT_TXPOWER        24
-
-#define TXPOWER_FROM_DEV(__txpower) \
-       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_TO_DEV(__txpower) \
-       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
-
-#endif /* RT2500USB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
deleted file mode 100644 (file)
index 95c1d7c..0000000
+++ /dev/null
@@ -1,2986 +0,0 @@
-/*
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
-       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
-       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
-       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800
-       Abstract: Data structures and registers for the rt2800 modules.
-       Supported chipsets: RT2800E, RT2800ED & RT2800U.
- */
-
-#ifndef RT2800_H
-#define RT2800_H
-
-/*
- * RF chip defines.
- *
- * RF2820 2.4G 2T3R
- * RF2850 2.4G/5G 2T3R
- * RF2720 2.4G 1T2R
- * RF2750 2.4G/5G 1T2R
- * RF3020 2.4G 1T1R
- * RF2020 2.4G B/G
- * RF3021 2.4G 1T2R
- * RF3022 2.4G 2T2R
- * RF3052 2.4G/5G 2T2R
- * 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)
- * RF5592 2.4G/5G 2T2R
- * RF3070 2.4G 1T1R
- * RF5360 2.4G 1T1R
- * RF5362 2.4G 1T1R
- * RF5370 2.4G 1T1R
- * RF5390 2.4G 1T1R
- */
-#define RF2820                         0x0001
-#define RF2850                         0x0002
-#define RF2720                         0x0003
-#define RF2750                         0x0004
-#define RF3020                         0x0005
-#define RF2020                         0x0006
-#define RF3021                         0x0007
-#define RF3022                         0x0008
-#define RF3052                         0x0009
-#define RF2853                         0x000a
-#define RF3320                         0x000b
-#define RF3322                         0x000c
-#define RF3053                         0x000d
-#define RF5592                         0x000f
-#define RF3070                         0x3070
-#define RF3290                         0x3290
-#define RF5360                         0x5360
-#define RF5362                         0x5362
-#define RF5370                         0x5370
-#define RF5372                         0x5372
-#define RF5390                         0x5390
-#define RF5392                         0x5392
-
-/*
- * Chipset revisions.
- */
-#define REV_RT2860C                    0x0100
-#define REV_RT2860D                    0x0101
-#define REV_RT2872E                    0x0200
-#define REV_RT3070E                    0x0200
-#define REV_RT3070F                    0x0201
-#define REV_RT3071E                    0x0211
-#define REV_RT3090E                    0x0211
-#define REV_RT3390E                    0x0211
-#define REV_RT3593E                    0x0211
-#define REV_RT5390F                    0x0502
-#define REV_RT5390R                    0x1502
-#define REV_RT5592C                    0x0221
-
-#define DEFAULT_RSSI_OFFSET            120
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x1000
-#define CSR_REG_SIZE                   0x0800
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x0200
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x00ff
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x0010
-#define RFCSR_BASE                     0x0000
-#define RFCSR_SIZE                     0x0040
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  4
-
-/*
- * Registers.
- */
-
-
-/*
- * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number.
- */
-#define MAC_CSR0_3290                  0x0000
-
-/*
- * E2PROM_CSR: PCI EEPROM control register.
- * RELOAD: Write 1 to reload eeprom content.
- * TYPE: 0: 93c46, 1:93c66.
- * LOAD_STATUS: 1:loading, 0:done.
- */
-#define E2PROM_CSR                     0x0004
-#define E2PROM_CSR_DATA_CLOCK          FIELD32(0x00000001)
-#define E2PROM_CSR_CHIP_SELECT         FIELD32(0x00000002)
-#define E2PROM_CSR_DATA_IN             FIELD32(0x00000004)
-#define E2PROM_CSR_DATA_OUT            FIELD32(0x00000008)
-#define E2PROM_CSR_TYPE                        FIELD32(0x00000030)
-#define E2PROM_CSR_LOAD_STATUS         FIELD32(0x00000040)
-#define E2PROM_CSR_RELOAD              FIELD32(0x00000080)
-
-/*
- * CMB_CTRL_CFG
- */
-#define CMB_CTRL               0x0020
-#define AUX_OPT_BIT0           FIELD32(0x00000001)
-#define AUX_OPT_BIT1           FIELD32(0x00000002)
-#define AUX_OPT_BIT2           FIELD32(0x00000004)
-#define AUX_OPT_BIT3           FIELD32(0x00000008)
-#define AUX_OPT_BIT4           FIELD32(0x00000010)
-#define AUX_OPT_BIT5           FIELD32(0x00000020)
-#define AUX_OPT_BIT6           FIELD32(0x00000040)
-#define AUX_OPT_BIT7           FIELD32(0x00000080)
-#define AUX_OPT_BIT8           FIELD32(0x00000100)
-#define AUX_OPT_BIT9           FIELD32(0x00000200)
-#define AUX_OPT_BIT10          FIELD32(0x00000400)
-#define AUX_OPT_BIT11          FIELD32(0x00000800)
-#define AUX_OPT_BIT12          FIELD32(0x00001000)
-#define AUX_OPT_BIT13          FIELD32(0x00002000)
-#define AUX_OPT_BIT14          FIELD32(0x00004000)
-#define AUX_OPT_BIT15          FIELD32(0x00008000)
-#define LDO25_LEVEL            FIELD32(0x00030000)
-#define LDO25_LARGEA           FIELD32(0x00040000)
-#define LDO25_FRC_ON           FIELD32(0x00080000)
-#define CMB_RSV                        FIELD32(0x00300000)
-#define XTAL_RDY               FIELD32(0x00400000)
-#define PLL_LD                 FIELD32(0x00800000)
-#define LDO_CORE_LEVEL         FIELD32(0x0F000000)
-#define LDO_BGSEL              FIELD32(0x30000000)
-#define LDO3_EN                        FIELD32(0x40000000)
-#define LDO0_EN                        FIELD32(0x80000000)
-
-/*
- * EFUSE_CSR_3290: RT3290 EEPROM
- */
-#define EFUSE_CTRL_3290                        0x0024
-
-/*
- * EFUSE_DATA3 of 3290
- */
-#define EFUSE_DATA3_3290               0x0028
-
-/*
- * EFUSE_DATA2 of 3290
- */
-#define EFUSE_DATA2_3290               0x002c
-
-/*
- * EFUSE_DATA1 of 3290
- */
-#define EFUSE_DATA1_3290               0x0030
-
-/*
- * EFUSE_DATA0 of 3290
- */
-#define EFUSE_DATA0_3290               0x0034
-
-/*
- * OSC_CTRL_CFG
- * Ring oscillator configuration
- */
-#define OSC_CTRL               0x0038
-#define OSC_REF_CYCLE          FIELD32(0x00001fff)
-#define OSC_RSV                        FIELD32(0x0000e000)
-#define OSC_CAL_CNT            FIELD32(0x0fff0000)
-#define OSC_CAL_ACK            FIELD32(0x10000000)
-#define OSC_CLK_32K_VLD                FIELD32(0x20000000)
-#define OSC_CAL_REQ            FIELD32(0x40000000)
-#define OSC_ROSC_EN            FIELD32(0x80000000)
-
-/*
- * COEX_CFG_0
- */
-#define COEX_CFG0              0x0040
-#define COEX_CFG_ANT           FIELD32(0xff000000)
-/*
- * COEX_CFG_1
- */
-#define COEX_CFG1              0x0044
-
-/*
- * COEX_CFG_2
- */
-#define COEX_CFG2              0x0048
-#define BT_COEX_CFG1           FIELD32(0xff000000)
-#define BT_COEX_CFG0           FIELD32(0x00ff0000)
-#define WL_COEX_CFG1           FIELD32(0x0000ff00)
-#define WL_COEX_CFG0           FIELD32(0x000000ff)
-/*
- * PLL_CTRL_CFG
- * PLL configuration register
- */
-#define PLL_CTRL               0x0050
-#define PLL_RESERVED_INPUT1    FIELD32(0x000000ff)
-#define PLL_RESERVED_INPUT2    FIELD32(0x0000ff00)
-#define PLL_CONTROL            FIELD32(0x00070000)
-#define PLL_LPF_R1             FIELD32(0x00080000)
-#define PLL_LPF_C1_CTRL                FIELD32(0x00300000)
-#define PLL_LPF_C2_CTRL                FIELD32(0x00c00000)
-#define PLL_CP_CURRENT_CTRL    FIELD32(0x03000000)
-#define PLL_PFD_DELAY_CTRL     FIELD32(0x0c000000)
-#define PLL_LOCK_CTRL          FIELD32(0x70000000)
-#define PLL_VBGBK_EN           FIELD32(0x80000000)
-
-
-/*
- * WLAN_CTRL_CFG
- * RT3290 wlan configuration
- */
-#define WLAN_FUN_CTRL                  0x0080
-#define WLAN_EN                                FIELD32(0x00000001)
-#define WLAN_CLK_EN                    FIELD32(0x00000002)
-#define WLAN_RSV1                      FIELD32(0x00000004)
-#define WLAN_RESET                     FIELD32(0x00000008)
-#define PCIE_APP0_CLK_REQ              FIELD32(0x00000010)
-#define FRC_WL_ANT_SET                 FIELD32(0x00000020)
-#define INV_TR_SW0                     FIELD32(0x00000040)
-#define WLAN_GPIO_IN_BIT0              FIELD32(0x00000100)
-#define WLAN_GPIO_IN_BIT1              FIELD32(0x00000200)
-#define WLAN_GPIO_IN_BIT2              FIELD32(0x00000400)
-#define WLAN_GPIO_IN_BIT3              FIELD32(0x00000800)
-#define WLAN_GPIO_IN_BIT4              FIELD32(0x00001000)
-#define WLAN_GPIO_IN_BIT5              FIELD32(0x00002000)
-#define WLAN_GPIO_IN_BIT6              FIELD32(0x00004000)
-#define WLAN_GPIO_IN_BIT7              FIELD32(0x00008000)
-#define WLAN_GPIO_IN_BIT_ALL           FIELD32(0x0000ff00)
-#define WLAN_GPIO_OUT_BIT0             FIELD32(0x00010000)
-#define WLAN_GPIO_OUT_BIT1             FIELD32(0x00020000)
-#define WLAN_GPIO_OUT_BIT2             FIELD32(0x00040000)
-#define WLAN_GPIO_OUT_BIT3             FIELD32(0x00050000)
-#define WLAN_GPIO_OUT_BIT4             FIELD32(0x00100000)
-#define WLAN_GPIO_OUT_BIT5             FIELD32(0x00200000)
-#define WLAN_GPIO_OUT_BIT6             FIELD32(0x00400000)
-#define WLAN_GPIO_OUT_BIT7             FIELD32(0x00800000)
-#define WLAN_GPIO_OUT_BIT_ALL          FIELD32(0x00ff0000)
-#define WLAN_GPIO_OUT_OE_BIT0          FIELD32(0x01000000)
-#define WLAN_GPIO_OUT_OE_BIT1          FIELD32(0x02000000)
-#define WLAN_GPIO_OUT_OE_BIT2          FIELD32(0x04000000)
-#define WLAN_GPIO_OUT_OE_BIT3          FIELD32(0x08000000)
-#define WLAN_GPIO_OUT_OE_BIT4          FIELD32(0x10000000)
-#define WLAN_GPIO_OUT_OE_BIT5          FIELD32(0x20000000)
-#define WLAN_GPIO_OUT_OE_BIT6          FIELD32(0x40000000)
-#define WLAN_GPIO_OUT_OE_BIT7          FIELD32(0x80000000)
-#define WLAN_GPIO_OUT_OE_BIT_ALL       FIELD32(0xff000000)
-
-/*
- * AUX_CTRL: Aux/PCI-E related configuration
- */
-#define AUX_CTRL                       0x10c
-#define AUX_CTRL_WAKE_PCIE_EN          FIELD32(0x00000002)
-#define AUX_CTRL_FORCE_PCIE_CLK                FIELD32(0x00000400)
-
-/*
- * OPT_14: Unknown register used by rt3xxx devices.
- */
-#define OPT_14_CSR                     0x0114
-#define OPT_14_CSR_BIT0                        FIELD32(0x00000001)
-
-/*
- * INT_SOURCE_CSR: Interrupt source register.
- * Write one to clear corresponding bit.
- * TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO
- */
-#define INT_SOURCE_CSR                 0x0200
-#define INT_SOURCE_CSR_RXDELAYINT      FIELD32(0x00000001)
-#define INT_SOURCE_CSR_TXDELAYINT      FIELD32(0x00000002)
-#define INT_SOURCE_CSR_RX_DONE         FIELD32(0x00000004)
-#define INT_SOURCE_CSR_AC0_DMA_DONE    FIELD32(0x00000008)
-#define INT_SOURCE_CSR_AC1_DMA_DONE    FIELD32(0x00000010)
-#define INT_SOURCE_CSR_AC2_DMA_DONE    FIELD32(0x00000020)
-#define INT_SOURCE_CSR_AC3_DMA_DONE    FIELD32(0x00000040)
-#define INT_SOURCE_CSR_HCCA_DMA_DONE   FIELD32(0x00000080)
-#define INT_SOURCE_CSR_MGMT_DMA_DONE   FIELD32(0x00000100)
-#define INT_SOURCE_CSR_MCU_COMMAND     FIELD32(0x00000200)
-#define INT_SOURCE_CSR_RXTX_COHERENT   FIELD32(0x00000400)
-#define INT_SOURCE_CSR_TBTT            FIELD32(0x00000800)
-#define INT_SOURCE_CSR_PRE_TBTT                FIELD32(0x00001000)
-#define INT_SOURCE_CSR_TX_FIFO_STATUS  FIELD32(0x00002000)
-#define INT_SOURCE_CSR_AUTO_WAKEUP     FIELD32(0x00004000)
-#define INT_SOURCE_CSR_GPTIMER         FIELD32(0x00008000)
-#define INT_SOURCE_CSR_RX_COHERENT     FIELD32(0x00010000)
-#define INT_SOURCE_CSR_TX_COHERENT     FIELD32(0x00020000)
-
-/*
- * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
- */
-#define INT_MASK_CSR                   0x0204
-#define INT_MASK_CSR_RXDELAYINT                FIELD32(0x00000001)
-#define INT_MASK_CSR_TXDELAYINT                FIELD32(0x00000002)
-#define INT_MASK_CSR_RX_DONE           FIELD32(0x00000004)
-#define INT_MASK_CSR_AC0_DMA_DONE      FIELD32(0x00000008)
-#define INT_MASK_CSR_AC1_DMA_DONE      FIELD32(0x00000010)
-#define INT_MASK_CSR_AC2_DMA_DONE      FIELD32(0x00000020)
-#define INT_MASK_CSR_AC3_DMA_DONE      FIELD32(0x00000040)
-#define INT_MASK_CSR_HCCA_DMA_DONE     FIELD32(0x00000080)
-#define INT_MASK_CSR_MGMT_DMA_DONE     FIELD32(0x00000100)
-#define INT_MASK_CSR_MCU_COMMAND       FIELD32(0x00000200)
-#define INT_MASK_CSR_RXTX_COHERENT     FIELD32(0x00000400)
-#define INT_MASK_CSR_TBTT              FIELD32(0x00000800)
-#define INT_MASK_CSR_PRE_TBTT          FIELD32(0x00001000)
-#define INT_MASK_CSR_TX_FIFO_STATUS    FIELD32(0x00002000)
-#define INT_MASK_CSR_AUTO_WAKEUP       FIELD32(0x00004000)
-#define INT_MASK_CSR_GPTIMER           FIELD32(0x00008000)
-#define INT_MASK_CSR_RX_COHERENT       FIELD32(0x00010000)
-#define INT_MASK_CSR_TX_COHERENT       FIELD32(0x00020000)
-
-/*
- * WPDMA_GLO_CFG
- */
-#define WPDMA_GLO_CFG                  0x0208
-#define WPDMA_GLO_CFG_ENABLE_TX_DMA    FIELD32(0x00000001)
-#define WPDMA_GLO_CFG_TX_DMA_BUSY      FIELD32(0x00000002)
-#define WPDMA_GLO_CFG_ENABLE_RX_DMA    FIELD32(0x00000004)
-#define WPDMA_GLO_CFG_RX_DMA_BUSY      FIELD32(0x00000008)
-#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE        FIELD32(0x00000030)
-#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE        FIELD32(0x00000040)
-#define WPDMA_GLO_CFG_BIG_ENDIAN       FIELD32(0x00000080)
-#define WPDMA_GLO_CFG_RX_HDR_SCATTER   FIELD32(0x0000ff00)
-#define WPDMA_GLO_CFG_HDR_SEG_LEN      FIELD32(0xffff0000)
-
-/*
- * WPDMA_RST_IDX
- */
-#define WPDMA_RST_IDX                  0x020c
-#define WPDMA_RST_IDX_DTX_IDX0         FIELD32(0x00000001)
-#define WPDMA_RST_IDX_DTX_IDX1         FIELD32(0x00000002)
-#define WPDMA_RST_IDX_DTX_IDX2         FIELD32(0x00000004)
-#define WPDMA_RST_IDX_DTX_IDX3         FIELD32(0x00000008)
-#define WPDMA_RST_IDX_DTX_IDX4         FIELD32(0x00000010)
-#define WPDMA_RST_IDX_DTX_IDX5         FIELD32(0x00000020)
-#define WPDMA_RST_IDX_DRX_IDX0         FIELD32(0x00010000)
-
-/*
- * DELAY_INT_CFG
- */
-#define DELAY_INT_CFG                  0x0210
-#define DELAY_INT_CFG_RXMAX_PTIME      FIELD32(0x000000ff)
-#define DELAY_INT_CFG_RXMAX_PINT       FIELD32(0x00007f00)
-#define DELAY_INT_CFG_RXDLY_INT_EN     FIELD32(0x00008000)
-#define DELAY_INT_CFG_TXMAX_PTIME      FIELD32(0x00ff0000)
-#define DELAY_INT_CFG_TXMAX_PINT       FIELD32(0x7f000000)
-#define DELAY_INT_CFG_TXDLY_INT_EN     FIELD32(0x80000000)
-
-/*
- * WMM_AIFSN_CFG: Aifsn for each EDCA AC
- * AIFSN0: AC_VO
- * AIFSN1: AC_VI
- * AIFSN2: AC_BE
- * AIFSN3: AC_BK
- */
-#define WMM_AIFSN_CFG                  0x0214
-#define WMM_AIFSN_CFG_AIFSN0           FIELD32(0x0000000f)
-#define WMM_AIFSN_CFG_AIFSN1           FIELD32(0x000000f0)
-#define WMM_AIFSN_CFG_AIFSN2           FIELD32(0x00000f00)
-#define WMM_AIFSN_CFG_AIFSN3           FIELD32(0x0000f000)
-
-/*
- * WMM_CWMIN_CSR: CWmin for each EDCA AC
- * CWMIN0: AC_VO
- * CWMIN1: AC_VI
- * CWMIN2: AC_BE
- * CWMIN3: AC_BK
- */
-#define WMM_CWMIN_CFG                  0x0218
-#define WMM_CWMIN_CFG_CWMIN0           FIELD32(0x0000000f)
-#define WMM_CWMIN_CFG_CWMIN1           FIELD32(0x000000f0)
-#define WMM_CWMIN_CFG_CWMIN2           FIELD32(0x00000f00)
-#define WMM_CWMIN_CFG_CWMIN3           FIELD32(0x0000f000)
-
-/*
- * WMM_CWMAX_CSR: CWmax for each EDCA AC
- * CWMAX0: AC_VO
- * CWMAX1: AC_VI
- * CWMAX2: AC_BE
- * CWMAX3: AC_BK
- */
-#define WMM_CWMAX_CFG                  0x021c
-#define WMM_CWMAX_CFG_CWMAX0           FIELD32(0x0000000f)
-#define WMM_CWMAX_CFG_CWMAX1           FIELD32(0x000000f0)
-#define WMM_CWMAX_CFG_CWMAX2           FIELD32(0x00000f00)
-#define WMM_CWMAX_CFG_CWMAX3           FIELD32(0x0000f000)
-
-/*
- * AC_TXOP0: AC_VO/AC_VI TXOP register
- * AC0TXOP: AC_VO in unit of 32us
- * AC1TXOP: AC_VI in unit of 32us
- */
-#define WMM_TXOP0_CFG                  0x0220
-#define WMM_TXOP0_CFG_AC0TXOP          FIELD32(0x0000ffff)
-#define WMM_TXOP0_CFG_AC1TXOP          FIELD32(0xffff0000)
-
-/*
- * AC_TXOP1: AC_BE/AC_BK TXOP register
- * AC2TXOP: AC_BE in unit of 32us
- * AC3TXOP: AC_BK in unit of 32us
- */
-#define WMM_TXOP1_CFG                  0x0224
-#define WMM_TXOP1_CFG_AC2TXOP          FIELD32(0x0000ffff)
-#define WMM_TXOP1_CFG_AC3TXOP          FIELD32(0xffff0000)
-
-/*
- * GPIO_CTRL:
- *     GPIO_CTRL_VALx: GPIO value
- *     GPIO_CTRL_DIRx: GPIO direction: 0 = output; 1 = input
- */
-#define GPIO_CTRL                      0x0228
-#define GPIO_CTRL_VAL0                 FIELD32(0x00000001)
-#define GPIO_CTRL_VAL1                 FIELD32(0x00000002)
-#define GPIO_CTRL_VAL2                 FIELD32(0x00000004)
-#define GPIO_CTRL_VAL3                 FIELD32(0x00000008)
-#define GPIO_CTRL_VAL4                 FIELD32(0x00000010)
-#define GPIO_CTRL_VAL5                 FIELD32(0x00000020)
-#define GPIO_CTRL_VAL6                 FIELD32(0x00000040)
-#define GPIO_CTRL_VAL7                 FIELD32(0x00000080)
-#define GPIO_CTRL_DIR0                 FIELD32(0x00000100)
-#define GPIO_CTRL_DIR1                 FIELD32(0x00000200)
-#define GPIO_CTRL_DIR2                 FIELD32(0x00000400)
-#define GPIO_CTRL_DIR3                 FIELD32(0x00000800)
-#define GPIO_CTRL_DIR4                 FIELD32(0x00001000)
-#define GPIO_CTRL_DIR5                 FIELD32(0x00002000)
-#define GPIO_CTRL_DIR6                 FIELD32(0x00004000)
-#define GPIO_CTRL_DIR7                 FIELD32(0x00008000)
-#define GPIO_CTRL_VAL8                 FIELD32(0x00010000)
-#define GPIO_CTRL_VAL9                 FIELD32(0x00020000)
-#define GPIO_CTRL_VAL10                        FIELD32(0x00040000)
-#define GPIO_CTRL_DIR8                 FIELD32(0x01000000)
-#define GPIO_CTRL_DIR9                 FIELD32(0x02000000)
-#define GPIO_CTRL_DIR10                        FIELD32(0x04000000)
-
-/*
- * MCU_CMD_CFG
- */
-#define MCU_CMD_CFG                    0x022c
-
-/*
- * AC_VO register offsets
- */
-#define TX_BASE_PTR0                   0x0230
-#define TX_MAX_CNT0                    0x0234
-#define TX_CTX_IDX0                    0x0238
-#define TX_DTX_IDX0                    0x023c
-
-/*
- * AC_VI register offsets
- */
-#define TX_BASE_PTR1                   0x0240
-#define TX_MAX_CNT1                    0x0244
-#define TX_CTX_IDX1                    0x0248
-#define TX_DTX_IDX1                    0x024c
-
-/*
- * AC_BE register offsets
- */
-#define TX_BASE_PTR2                   0x0250
-#define TX_MAX_CNT2                    0x0254
-#define TX_CTX_IDX2                    0x0258
-#define TX_DTX_IDX2                    0x025c
-
-/*
- * AC_BK register offsets
- */
-#define TX_BASE_PTR3                   0x0260
-#define TX_MAX_CNT3                    0x0264
-#define TX_CTX_IDX3                    0x0268
-#define TX_DTX_IDX3                    0x026c
-
-/*
- * HCCA register offsets
- */
-#define TX_BASE_PTR4                   0x0270
-#define TX_MAX_CNT4                    0x0274
-#define TX_CTX_IDX4                    0x0278
-#define TX_DTX_IDX4                    0x027c
-
-/*
- * MGMT register offsets
- */
-#define TX_BASE_PTR5                   0x0280
-#define TX_MAX_CNT5                    0x0284
-#define TX_CTX_IDX5                    0x0288
-#define TX_DTX_IDX5                    0x028c
-
-/*
- * RX register offsets
- */
-#define RX_BASE_PTR                    0x0290
-#define RX_MAX_CNT                     0x0294
-#define RX_CRX_IDX                     0x0298
-#define RX_DRX_IDX                     0x029c
-
-/*
- * USB_DMA_CFG
- * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns.
- * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes.
- * PHY_CLEAR: phy watch dog enable.
- * TX_CLEAR: Clear USB DMA TX path.
- * TXOP_HALT: Halt TXOP count down when TX buffer is full.
- * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation.
- * RX_BULK_EN: Enable USB DMA Rx.
- * TX_BULK_EN: Enable USB DMA Tx.
- * EP_OUT_VALID: OUT endpoint data valid.
- * RX_BUSY: USB DMA RX FSM busy.
- * TX_BUSY: USB DMA TX FSM busy.
- */
-#define USB_DMA_CFG                    0x02a0
-#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT        FIELD32(0x000000ff)
-#define USB_DMA_CFG_RX_BULK_AGG_LIMIT  FIELD32(0x0000ff00)
-#define USB_DMA_CFG_PHY_CLEAR          FIELD32(0x00010000)
-#define USB_DMA_CFG_TX_CLEAR           FIELD32(0x00080000)
-#define USB_DMA_CFG_TXOP_HALT          FIELD32(0x00100000)
-#define USB_DMA_CFG_RX_BULK_AGG_EN     FIELD32(0x00200000)
-#define USB_DMA_CFG_RX_BULK_EN         FIELD32(0x00400000)
-#define USB_DMA_CFG_TX_BULK_EN         FIELD32(0x00800000)
-#define USB_DMA_CFG_EP_OUT_VALID       FIELD32(0x3f000000)
-#define USB_DMA_CFG_RX_BUSY            FIELD32(0x40000000)
-#define USB_DMA_CFG_TX_BUSY            FIELD32(0x80000000)
-
-/*
- * US_CYC_CNT
- * BT_MODE_EN: Bluetooth mode enable
- * CLOCK CYCLE: Clock cycle count in 1us.
- * PCI:0x21, PCIE:0x7d, USB:0x1e
- */
-#define US_CYC_CNT                     0x02a4
-#define US_CYC_CNT_BT_MODE_EN          FIELD32(0x00000100)
-#define US_CYC_CNT_CLOCK_CYCLE         FIELD32(0x000000ff)
-
-/*
- * PBF_SYS_CTRL
- * HOST_RAM_WRITE: enable Host program ram write selection
- */
-#define PBF_SYS_CTRL                   0x0400
-#define PBF_SYS_CTRL_READY             FIELD32(0x00000080)
-#define PBF_SYS_CTRL_HOST_RAM_WRITE    FIELD32(0x00010000)
-
-/*
- * HOST-MCU shared memory
- */
-#define HOST_CMD_CSR                   0x0404
-#define HOST_CMD_CSR_HOST_COMMAND      FIELD32(0x000000ff)
-
-/*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
- */
-#define PBF_CFG                                0x0408
-#define PBF_MAX_PCNT                   0x040c
-#define PBF_CTRL                       0x0410
-#define PBF_INT_STA                    0x0414
-#define PBF_INT_ENA                    0x0418
-
-/*
- * BCN_OFFSET0:
- */
-#define BCN_OFFSET0                    0x042c
-#define BCN_OFFSET0_BCN0               FIELD32(0x000000ff)
-#define BCN_OFFSET0_BCN1               FIELD32(0x0000ff00)
-#define BCN_OFFSET0_BCN2               FIELD32(0x00ff0000)
-#define BCN_OFFSET0_BCN3               FIELD32(0xff000000)
-
-/*
- * BCN_OFFSET1:
- */
-#define BCN_OFFSET1                    0x0430
-#define BCN_OFFSET1_BCN4               FIELD32(0x000000ff)
-#define BCN_OFFSET1_BCN5               FIELD32(0x0000ff00)
-#define BCN_OFFSET1_BCN6               FIELD32(0x00ff0000)
-#define BCN_OFFSET1_BCN7               FIELD32(0xff000000)
-
-/*
- * TXRXQ_PCNT: PBF register
- * PCNT_TX0Q: Page count for TX hardware queue 0
- * PCNT_TX1Q: Page count for TX hardware queue 1
- * PCNT_TX2Q: Page count for TX hardware queue 2
- * PCNT_RX0Q: Page count for RX hardware queue
- */
-#define TXRXQ_PCNT                     0x0438
-#define TXRXQ_PCNT_TX0Q                        FIELD32(0x000000ff)
-#define TXRXQ_PCNT_TX1Q                        FIELD32(0x0000ff00)
-#define TXRXQ_PCNT_TX2Q                        FIELD32(0x00ff0000)
-#define TXRXQ_PCNT_RX0Q                        FIELD32(0xff000000)
-
-/*
- * PBF register
- * Debug. Driver doesn't touch PBF register.
- */
-#define PBF_DBG                                0x043c
-
-/*
- * RF registers
- */
-#define        RF_CSR_CFG                      0x0500
-#define RF_CSR_CFG_DATA                        FIELD32(0x000000ff)
-#define RF_CSR_CFG_REGNUM              FIELD32(0x00003f00)
-#define RF_CSR_CFG_WRITE               FIELD32(0x00010000)
-#define RF_CSR_CFG_BUSY                        FIELD32(0x00020000)
-
-/*
- * EFUSE_CSR: RT30x0 EEPROM
- */
-#define EFUSE_CTRL                     0x0580
-#define EFUSE_CTRL_ADDRESS_IN          FIELD32(0x03fe0000)
-#define EFUSE_CTRL_MODE                        FIELD32(0x000000c0)
-#define EFUSE_CTRL_KICK                        FIELD32(0x40000000)
-#define EFUSE_CTRL_PRESENT             FIELD32(0x80000000)
-
-/*
- * EFUSE_DATA0
- */
-#define EFUSE_DATA0                    0x0590
-
-/*
- * EFUSE_DATA1
- */
-#define EFUSE_DATA1                    0x0594
-
-/*
- * EFUSE_DATA2
- */
-#define EFUSE_DATA2                    0x0598
-
-/*
- * EFUSE_DATA3
- */
-#define EFUSE_DATA3                    0x059c
-
-/*
- * LDO_CFG0
- */
-#define LDO_CFG0                       0x05d4
-#define LDO_CFG0_DELAY3                        FIELD32(0x000000ff)
-#define LDO_CFG0_DELAY2                        FIELD32(0x0000ff00)
-#define LDO_CFG0_DELAY1                        FIELD32(0x00ff0000)
-#define LDO_CFG0_BGSEL                 FIELD32(0x03000000)
-#define LDO_CFG0_LDO_CORE_VLEVEL       FIELD32(0x1c000000)
-#define LD0_CFG0_LDO25_LEVEL           FIELD32(0x60000000)
-#define LDO_CFG0_LDO25_LARGEA          FIELD32(0x80000000)
-
-/*
- * GPIO_SWITCH
- */
-#define GPIO_SWITCH                    0x05dc
-#define GPIO_SWITCH_0                  FIELD32(0x00000001)
-#define GPIO_SWITCH_1                  FIELD32(0x00000002)
-#define GPIO_SWITCH_2                  FIELD32(0x00000004)
-#define GPIO_SWITCH_3                  FIELD32(0x00000008)
-#define GPIO_SWITCH_4                  FIELD32(0x00000010)
-#define GPIO_SWITCH_5                  FIELD32(0x00000020)
-#define GPIO_SWITCH_6                  FIELD32(0x00000040)
-#define GPIO_SWITCH_7                  FIELD32(0x00000080)
-
-/*
- * FIXME: where the DEBUG_INDEX name come from?
- */
-#define MAC_DEBUG_INDEX                        0x05e8
-#define MAC_DEBUG_INDEX_XTAL           FIELD32(0x80000000)
-
-/*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- * ASIC_REV: 0
- * ASIC_VER: 2860 or 2870
- */
-#define MAC_CSR0                       0x1000
-#define MAC_CSR0_REVISION              FIELD32(0x0000ffff)
-#define MAC_CSR0_CHIPSET               FIELD32(0xffff0000)
-
-/*
- * MAC_SYS_CTRL:
- */
-#define MAC_SYS_CTRL                   0x1004
-#define MAC_SYS_CTRL_RESET_CSR         FIELD32(0x00000001)
-#define MAC_SYS_CTRL_RESET_BBP         FIELD32(0x00000002)
-#define MAC_SYS_CTRL_ENABLE_TX         FIELD32(0x00000004)
-#define MAC_SYS_CTRL_ENABLE_RX         FIELD32(0x00000008)
-#define MAC_SYS_CTRL_CONTINUOUS_TX     FIELD32(0x00000010)
-#define MAC_SYS_CTRL_LOOPBACK          FIELD32(0x00000020)
-#define MAC_SYS_CTRL_WLAN_HALT         FIELD32(0x00000040)
-#define MAC_SYS_CTRL_RX_TIMESTAMP      FIELD32(0x00000080)
-
-/*
- * MAC_ADDR_DW0: STA MAC register 0
- */
-#define MAC_ADDR_DW0                   0x1008
-#define MAC_ADDR_DW0_BYTE0             FIELD32(0x000000ff)
-#define MAC_ADDR_DW0_BYTE1             FIELD32(0x0000ff00)
-#define MAC_ADDR_DW0_BYTE2             FIELD32(0x00ff0000)
-#define MAC_ADDR_DW0_BYTE3             FIELD32(0xff000000)
-
-/*
- * MAC_ADDR_DW1: STA MAC register 1
- * UNICAST_TO_ME_MASK:
- * Used to mask off bits from byte 5 of the MAC address
- * to determine the UNICAST_TO_ME bit for RX frames.
- * The full mask is complemented by BSS_ID_MASK:
- *    MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
-#define MAC_ADDR_DW1                   0x100c
-#define MAC_ADDR_DW1_BYTE4             FIELD32(0x000000ff)
-#define MAC_ADDR_DW1_BYTE5             FIELD32(0x0000ff00)
-#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK        FIELD32(0x00ff0000)
-
-/*
- * MAC_BSSID_DW0: BSSID register 0
- */
-#define MAC_BSSID_DW0                  0x1010
-#define MAC_BSSID_DW0_BYTE0            FIELD32(0x000000ff)
-#define MAC_BSSID_DW0_BYTE1            FIELD32(0x0000ff00)
-#define MAC_BSSID_DW0_BYTE2            FIELD32(0x00ff0000)
-#define MAC_BSSID_DW0_BYTE3            FIELD32(0xff000000)
-
-/*
- * MAC_BSSID_DW1: BSSID register 1
- * BSS_ID_MASK:
- *     0: 1-BSSID mode (BSS index = 0)
- *     1: 2-BSSID mode (BSS index: Byte5, bit 0)
- *     2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- *     3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
- * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
- * BSSID. This will make sure that those bits will be ignored
- * when determining the MY_BSS of RX frames.
- */
-#define MAC_BSSID_DW1                  0x1014
-#define MAC_BSSID_DW1_BYTE4            FIELD32(0x000000ff)
-#define MAC_BSSID_DW1_BYTE5            FIELD32(0x0000ff00)
-#define MAC_BSSID_DW1_BSS_ID_MASK      FIELD32(0x00030000)
-#define MAC_BSSID_DW1_BSS_BCN_NUM      FIELD32(0x001c0000)
-
-/*
- * MAX_LEN_CFG: Maximum frame length register.
- * MAX_MPDU: rt2860b max 16k bytes
- * MAX_PSDU: Maximum PSDU length
- *     (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
- */
-#define MAX_LEN_CFG                    0x1018
-#define MAX_LEN_CFG_MAX_MPDU           FIELD32(0x00000fff)
-#define MAX_LEN_CFG_MAX_PSDU           FIELD32(0x00003000)
-#define MAX_LEN_CFG_MIN_PSDU           FIELD32(0x0000c000)
-#define MAX_LEN_CFG_MIN_MPDU           FIELD32(0x000f0000)
-
-/*
- * BBP_CSR_CFG: BBP serial control register
- * VALUE: Register value to program into BBP
- * REG_NUM: Selected BBP register
- * READ_CONTROL: 0 write BBP, 1 read BBP
- * BUSY: ASIC is busy executing BBP commands
- * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
- * BBP_RW_MODE: 0 serial, 1 parallel
- */
-#define BBP_CSR_CFG                    0x101c
-#define BBP_CSR_CFG_VALUE              FIELD32(0x000000ff)
-#define BBP_CSR_CFG_REGNUM             FIELD32(0x0000ff00)
-#define BBP_CSR_CFG_READ_CONTROL       FIELD32(0x00010000)
-#define BBP_CSR_CFG_BUSY               FIELD32(0x00020000)
-#define BBP_CSR_CFG_BBP_PAR_DUR                FIELD32(0x00040000)
-#define BBP_CSR_CFG_BBP_RW_MODE                FIELD32(0x00080000)
-
-/*
- * RF_CSR_CFG0: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * BITWIDTH: Selected RF register
- * STANDBYMODE: 0 high when standby, 1 low when standby
- * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
- * BUSY: ASIC is busy executing RF commands
- */
-#define RF_CSR_CFG0                    0x1020
-#define RF_CSR_CFG0_REGID_AND_VALUE    FIELD32(0x00ffffff)
-#define RF_CSR_CFG0_BITWIDTH           FIELD32(0x1f000000)
-#define RF_CSR_CFG0_REG_VALUE_BW       FIELD32(0x1fffffff)
-#define RF_CSR_CFG0_STANDBYMODE                FIELD32(0x20000000)
-#define RF_CSR_CFG0_SEL                        FIELD32(0x40000000)
-#define RF_CSR_CFG0_BUSY               FIELD32(0x80000000)
-
-/*
- * RF_CSR_CFG1: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * RFGAP: Gap between BB_CONTROL_RF and RF_LE
- *        0: 3 system clock cycle (37.5usec)
- *        1: 5 system clock cycle (62.5usec)
- */
-#define RF_CSR_CFG1                    0x1024
-#define RF_CSR_CFG1_REGID_AND_VALUE    FIELD32(0x00ffffff)
-#define RF_CSR_CFG1_RFGAP              FIELD32(0x1f000000)
-
-/*
- * RF_CSR_CFG2: RF control register
- * VALUE: Register value to program into RF
- */
-#define RF_CSR_CFG2                    0x1028
-#define RF_CSR_CFG2_VALUE              FIELD32(0x00ffffff)
-
-/*
- * LED_CFG: LED control
- * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1)
- * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1)
- * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)
- * color LED's:
- *   0: off
- *   1: blinking upon TX2
- *   2: periodic slow blinking
- *   3: always on
- * LED polarity:
- *   0: active low
- *   1: active high
- */
-#define LED_CFG                                0x102c
-#define LED_CFG_ON_PERIOD              FIELD32(0x000000ff)
-#define LED_CFG_OFF_PERIOD             FIELD32(0x0000ff00)
-#define LED_CFG_SLOW_BLINK_PERIOD      FIELD32(0x003f0000)
-#define LED_CFG_R_LED_MODE             FIELD32(0x03000000)
-#define LED_CFG_G_LED_MODE             FIELD32(0x0c000000)
-#define LED_CFG_Y_LED_MODE             FIELD32(0x30000000)
-#define LED_CFG_LED_POLAR              FIELD32(0x40000000)
-
-/*
- * AMPDU_BA_WINSIZE: Force BlockAck window size
- * FORCE_WINSIZE_ENABLE:
- *   0: Disable forcing of BlockAck window size
- *   1: Enable forcing of BlockAck window size, overwrites values BlockAck
- *      window size values in the TXWI
- * FORCE_WINSIZE: BlockAck window size
- */
-#define AMPDU_BA_WINSIZE               0x1040
-#define AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE FIELD32(0x00000020)
-#define AMPDU_BA_WINSIZE_FORCE_WINSIZE FIELD32(0x0000001f)
-
-/*
- * XIFS_TIME_CFG: MAC timing
- * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
- * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
- * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
- *     when MAC doesn't reference BBP signal BBRXEND
- * EIFS: unit 1us
- * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
- *
- */
-#define XIFS_TIME_CFG                  0x1100
-#define XIFS_TIME_CFG_CCKM_SIFS_TIME   FIELD32(0x000000ff)
-#define XIFS_TIME_CFG_OFDM_SIFS_TIME   FIELD32(0x0000ff00)
-#define XIFS_TIME_CFG_OFDM_XIFS_TIME   FIELD32(0x000f0000)
-#define XIFS_TIME_CFG_EIFS             FIELD32(0x1ff00000)
-#define XIFS_TIME_CFG_BB_RXEND_ENABLE  FIELD32(0x20000000)
-
-/*
- * BKOFF_SLOT_CFG:
- */
-#define BKOFF_SLOT_CFG                 0x1104
-#define BKOFF_SLOT_CFG_SLOT_TIME       FIELD32(0x000000ff)
-#define BKOFF_SLOT_CFG_CC_DELAY_TIME   FIELD32(0x0000ff00)
-
-/*
- * NAV_TIME_CFG:
- */
-#define NAV_TIME_CFG                   0x1108
-#define NAV_TIME_CFG_SIFS              FIELD32(0x000000ff)
-#define NAV_TIME_CFG_SLOT_TIME         FIELD32(0x0000ff00)
-#define NAV_TIME_CFG_EIFS              FIELD32(0x01ff0000)
-#define NAV_TIME_ZERO_SIFS             FIELD32(0x02000000)
-
-/*
- * CH_TIME_CFG: count as channel busy
- * EIFS_BUSY: Count EIFS as channel busy
- * NAV_BUSY: Count NAS as channel busy
- * RX_BUSY: Count RX as channel busy
- * TX_BUSY: Count TX as channel busy
- * TMR_EN: Enable channel statistics timer
- */
-#define CH_TIME_CFG                    0x110c
-#define CH_TIME_CFG_EIFS_BUSY          FIELD32(0x00000010)
-#define CH_TIME_CFG_NAV_BUSY           FIELD32(0x00000008)
-#define CH_TIME_CFG_RX_BUSY            FIELD32(0x00000004)
-#define CH_TIME_CFG_TX_BUSY            FIELD32(0x00000002)
-#define CH_TIME_CFG_TMR_EN             FIELD32(0x00000001)
-
-/*
- * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
- */
-#define PBF_LIFE_TIMER                 0x1110
-
-/*
- * BCN_TIME_CFG:
- * BEACON_INTERVAL: in unit of 1/16 TU
- * TSF_TICKING: Enable TSF auto counting
- * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
- * BEACON_GEN: Enable beacon generator
- */
-#define BCN_TIME_CFG                   0x1114
-#define BCN_TIME_CFG_BEACON_INTERVAL   FIELD32(0x0000ffff)
-#define BCN_TIME_CFG_TSF_TICKING       FIELD32(0x00010000)
-#define BCN_TIME_CFG_TSF_SYNC          FIELD32(0x00060000)
-#define BCN_TIME_CFG_TBTT_ENABLE       FIELD32(0x00080000)
-#define BCN_TIME_CFG_BEACON_GEN                FIELD32(0x00100000)
-#define BCN_TIME_CFG_TX_TIME_COMPENSATE        FIELD32(0xf0000000)
-
-/*
- * TBTT_SYNC_CFG:
- * BCN_AIFSN: Beacon AIFSN after TBTT interrupt in slots
- * BCN_CWMIN: Beacon CWMin after TBTT interrupt in slots
- */
-#define TBTT_SYNC_CFG                  0x1118
-#define TBTT_SYNC_CFG_TBTT_ADJUST      FIELD32(0x000000ff)
-#define TBTT_SYNC_CFG_BCN_EXP_WIN      FIELD32(0x0000ff00)
-#define TBTT_SYNC_CFG_BCN_AIFSN                FIELD32(0x000f0000)
-#define TBTT_SYNC_CFG_BCN_CWMIN                FIELD32(0x00f00000)
-
-/*
- * TSF_TIMER_DW0: Local lsb TSF timer, read-only
- */
-#define TSF_TIMER_DW0                  0x111c
-#define TSF_TIMER_DW0_LOW_WORD         FIELD32(0xffffffff)
-
-/*
- * TSF_TIMER_DW1: Local msb TSF timer, read-only
- */
-#define TSF_TIMER_DW1                  0x1120
-#define TSF_TIMER_DW1_HIGH_WORD                FIELD32(0xffffffff)
-
-/*
- * TBTT_TIMER: TImer remains till next TBTT, read-only
- */
-#define TBTT_TIMER                     0x1124
-
-/*
- * INT_TIMER_CFG: timer configuration
- * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU
- * GP_TIMER: period of general purpose timer in units of 1/16 TU
- */
-#define INT_TIMER_CFG                  0x1128
-#define INT_TIMER_CFG_PRE_TBTT_TIMER   FIELD32(0x0000ffff)
-#define INT_TIMER_CFG_GP_TIMER         FIELD32(0xffff0000)
-
-/*
- * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
- */
-#define INT_TIMER_EN                   0x112c
-#define INT_TIMER_EN_PRE_TBTT_TIMER    FIELD32(0x00000001)
-#define INT_TIMER_EN_GP_TIMER          FIELD32(0x00000002)
-
-/*
- * CH_IDLE_STA: channel idle time (in us)
- */
-#define CH_IDLE_STA                    0x1130
-
-/*
- * CH_BUSY_STA: channel busy time on primary channel (in us)
- */
-#define CH_BUSY_STA                    0x1134
-
-/*
- * CH_BUSY_STA_SEC: channel busy time on secondary channel in HT40 mode (in us)
- */
-#define CH_BUSY_STA_SEC                        0x1138
-
-/*
- * MAC_STATUS_CFG:
- * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
- *     if 1 or higher one of the 2 registers is busy.
- */
-#define MAC_STATUS_CFG                 0x1200
-#define MAC_STATUS_CFG_BBP_RF_BUSY     FIELD32(0x00000003)
-
-/*
- * PWR_PIN_CFG:
- */
-#define PWR_PIN_CFG                    0x1204
-
-/*
- * AUTOWAKEUP_CFG: Manual power control / status register
- * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
- * AUTOWAKE: 0:sleep, 1:awake
- */
-#define AUTOWAKEUP_CFG                 0x1208
-#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME  FIELD32(0x000000ff)
-#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE        FIELD32(0x00007f00)
-#define AUTOWAKEUP_CFG_AUTOWAKE                FIELD32(0x00008000)
-
-/*
- * EDCA_AC0_CFG:
- */
-#define EDCA_AC0_CFG                   0x1300
-#define EDCA_AC0_CFG_TX_OP             FIELD32(0x000000ff)
-#define EDCA_AC0_CFG_AIFSN             FIELD32(0x00000f00)
-#define EDCA_AC0_CFG_CWMIN             FIELD32(0x0000f000)
-#define EDCA_AC0_CFG_CWMAX             FIELD32(0x000f0000)
-
-/*
- * EDCA_AC1_CFG:
- */
-#define EDCA_AC1_CFG                   0x1304
-#define EDCA_AC1_CFG_TX_OP             FIELD32(0x000000ff)
-#define EDCA_AC1_CFG_AIFSN             FIELD32(0x00000f00)
-#define EDCA_AC1_CFG_CWMIN             FIELD32(0x0000f000)
-#define EDCA_AC1_CFG_CWMAX             FIELD32(0x000f0000)
-
-/*
- * EDCA_AC2_CFG:
- */
-#define EDCA_AC2_CFG                   0x1308
-#define EDCA_AC2_CFG_TX_OP             FIELD32(0x000000ff)
-#define EDCA_AC2_CFG_AIFSN             FIELD32(0x00000f00)
-#define EDCA_AC2_CFG_CWMIN             FIELD32(0x0000f000)
-#define EDCA_AC2_CFG_CWMAX             FIELD32(0x000f0000)
-
-/*
- * EDCA_AC3_CFG:
- */
-#define EDCA_AC3_CFG                   0x130c
-#define EDCA_AC3_CFG_TX_OP             FIELD32(0x000000ff)
-#define EDCA_AC3_CFG_AIFSN             FIELD32(0x00000f00)
-#define EDCA_AC3_CFG_CWMIN             FIELD32(0x0000f000)
-#define EDCA_AC3_CFG_CWMAX             FIELD32(0x000f0000)
-
-/*
- * EDCA_TID_AC_MAP:
- */
-#define EDCA_TID_AC_MAP                        0x1310
-
-/*
- * TX_PWR_CFG:
- */
-#define TX_PWR_CFG_RATE0               FIELD32(0x0000000f)
-#define TX_PWR_CFG_RATE1               FIELD32(0x000000f0)
-#define TX_PWR_CFG_RATE2               FIELD32(0x00000f00)
-#define TX_PWR_CFG_RATE3               FIELD32(0x0000f000)
-#define TX_PWR_CFG_RATE4               FIELD32(0x000f0000)
-#define TX_PWR_CFG_RATE5               FIELD32(0x00f00000)
-#define TX_PWR_CFG_RATE6               FIELD32(0x0f000000)
-#define TX_PWR_CFG_RATE7               FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_0:
- */
-#define TX_PWR_CFG_0                   0x1314
-#define TX_PWR_CFG_0_1MBS              FIELD32(0x0000000f)
-#define TX_PWR_CFG_0_2MBS              FIELD32(0x000000f0)
-#define TX_PWR_CFG_0_55MBS             FIELD32(0x00000f00)
-#define TX_PWR_CFG_0_11MBS             FIELD32(0x0000f000)
-#define TX_PWR_CFG_0_6MBS              FIELD32(0x000f0000)
-#define TX_PWR_CFG_0_9MBS              FIELD32(0x00f00000)
-#define TX_PWR_CFG_0_12MBS             FIELD32(0x0f000000)
-#define TX_PWR_CFG_0_18MBS             FIELD32(0xf0000000)
-/* bits for 3T devices */
-#define TX_PWR_CFG_0_CCK1_CH0          FIELD32(0x0000000f)
-#define TX_PWR_CFG_0_CCK1_CH1          FIELD32(0x000000f0)
-#define TX_PWR_CFG_0_CCK5_CH0          FIELD32(0x00000f00)
-#define TX_PWR_CFG_0_CCK5_CH1          FIELD32(0x0000f000)
-#define TX_PWR_CFG_0_OFDM6_CH0         FIELD32(0x000f0000)
-#define TX_PWR_CFG_0_OFDM6_CH1         FIELD32(0x00f00000)
-#define TX_PWR_CFG_0_OFDM12_CH0                FIELD32(0x0f000000)
-#define TX_PWR_CFG_0_OFDM12_CH1                FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_1:
- */
-#define TX_PWR_CFG_1                   0x1318
-#define TX_PWR_CFG_1_24MBS             FIELD32(0x0000000f)
-#define TX_PWR_CFG_1_36MBS             FIELD32(0x000000f0)
-#define TX_PWR_CFG_1_48MBS             FIELD32(0x00000f00)
-#define TX_PWR_CFG_1_54MBS             FIELD32(0x0000f000)
-#define TX_PWR_CFG_1_MCS0              FIELD32(0x000f0000)
-#define TX_PWR_CFG_1_MCS1              FIELD32(0x00f00000)
-#define TX_PWR_CFG_1_MCS2              FIELD32(0x0f000000)
-#define TX_PWR_CFG_1_MCS3              FIELD32(0xf0000000)
-/* bits for 3T devices */
-#define TX_PWR_CFG_1_OFDM24_CH0                FIELD32(0x0000000f)
-#define TX_PWR_CFG_1_OFDM24_CH1                FIELD32(0x000000f0)
-#define TX_PWR_CFG_1_OFDM48_CH0                FIELD32(0x00000f00)
-#define TX_PWR_CFG_1_OFDM48_CH1                FIELD32(0x0000f000)
-#define TX_PWR_CFG_1_MCS0_CH0          FIELD32(0x000f0000)
-#define TX_PWR_CFG_1_MCS0_CH1          FIELD32(0x00f00000)
-#define TX_PWR_CFG_1_MCS2_CH0          FIELD32(0x0f000000)
-#define TX_PWR_CFG_1_MCS2_CH1          FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_2:
- */
-#define TX_PWR_CFG_2                   0x131c
-#define TX_PWR_CFG_2_MCS4              FIELD32(0x0000000f)
-#define TX_PWR_CFG_2_MCS5              FIELD32(0x000000f0)
-#define TX_PWR_CFG_2_MCS6              FIELD32(0x00000f00)
-#define TX_PWR_CFG_2_MCS7              FIELD32(0x0000f000)
-#define TX_PWR_CFG_2_MCS8              FIELD32(0x000f0000)
-#define TX_PWR_CFG_2_MCS9              FIELD32(0x00f00000)
-#define TX_PWR_CFG_2_MCS10             FIELD32(0x0f000000)
-#define TX_PWR_CFG_2_MCS11             FIELD32(0xf0000000)
-/* bits for 3T devices */
-#define TX_PWR_CFG_2_MCS4_CH0          FIELD32(0x0000000f)
-#define TX_PWR_CFG_2_MCS4_CH1          FIELD32(0x000000f0)
-#define TX_PWR_CFG_2_MCS6_CH0          FIELD32(0x00000f00)
-#define TX_PWR_CFG_2_MCS6_CH1          FIELD32(0x0000f000)
-#define TX_PWR_CFG_2_MCS8_CH0          FIELD32(0x000f0000)
-#define TX_PWR_CFG_2_MCS8_CH1          FIELD32(0x00f00000)
-#define TX_PWR_CFG_2_MCS10_CH0         FIELD32(0x0f000000)
-#define TX_PWR_CFG_2_MCS10_CH1         FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_3:
- */
-#define TX_PWR_CFG_3                   0x1320
-#define TX_PWR_CFG_3_MCS12             FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_MCS13             FIELD32(0x000000f0)
-#define TX_PWR_CFG_3_MCS14             FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_MCS15             FIELD32(0x0000f000)
-#define TX_PWR_CFG_3_UKNOWN1           FIELD32(0x000f0000)
-#define TX_PWR_CFG_3_UKNOWN2           FIELD32(0x00f00000)
-#define TX_PWR_CFG_3_UKNOWN3           FIELD32(0x0f000000)
-#define TX_PWR_CFG_3_UKNOWN4           FIELD32(0xf0000000)
-/* bits for 3T devices */
-#define TX_PWR_CFG_3_MCS12_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_MCS12_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_3_MCS14_CH0         FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_MCS14_CH1         FIELD32(0x0000f000)
-#define TX_PWR_CFG_3_STBC0_CH0         FIELD32(0x000f0000)
-#define TX_PWR_CFG_3_STBC0_CH1         FIELD32(0x00f00000)
-#define TX_PWR_CFG_3_STBC2_CH0         FIELD32(0x0f000000)
-#define TX_PWR_CFG_3_STBC2_CH1         FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_4:
- */
-#define TX_PWR_CFG_4                   0x1324
-#define TX_PWR_CFG_4_UKNOWN5           FIELD32(0x0000000f)
-#define TX_PWR_CFG_4_UKNOWN6           FIELD32(0x000000f0)
-#define TX_PWR_CFG_4_UKNOWN7           FIELD32(0x00000f00)
-#define TX_PWR_CFG_4_UKNOWN8           FIELD32(0x0000f000)
-/* bits for 3T devices */
-#define TX_PWR_CFG_3_STBC4_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_STBC4_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_3_STBC6_CH0         FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_STBC6_CH1         FIELD32(0x0000f000)
-
-/*
- * TX_PIN_CFG:
- */
-#define TX_PIN_CFG                     0x1328
-#define TX_PIN_CFG_PA_PE_DISABLE       0xfcfffff0
-#define TX_PIN_CFG_PA_PE_A0_EN         FIELD32(0x00000001)
-#define TX_PIN_CFG_PA_PE_G0_EN         FIELD32(0x00000002)
-#define TX_PIN_CFG_PA_PE_A1_EN         FIELD32(0x00000004)
-#define TX_PIN_CFG_PA_PE_G1_EN         FIELD32(0x00000008)
-#define TX_PIN_CFG_PA_PE_A0_POL                FIELD32(0x00000010)
-#define TX_PIN_CFG_PA_PE_G0_POL                FIELD32(0x00000020)
-#define TX_PIN_CFG_PA_PE_A1_POL                FIELD32(0x00000040)
-#define TX_PIN_CFG_PA_PE_G1_POL                FIELD32(0x00000080)
-#define TX_PIN_CFG_LNA_PE_A0_EN                FIELD32(0x00000100)
-#define TX_PIN_CFG_LNA_PE_G0_EN                FIELD32(0x00000200)
-#define TX_PIN_CFG_LNA_PE_A1_EN                FIELD32(0x00000400)
-#define TX_PIN_CFG_LNA_PE_G1_EN                FIELD32(0x00000800)
-#define TX_PIN_CFG_LNA_PE_A0_POL       FIELD32(0x00001000)
-#define TX_PIN_CFG_LNA_PE_G0_POL       FIELD32(0x00002000)
-#define TX_PIN_CFG_LNA_PE_A1_POL       FIELD32(0x00004000)
-#define TX_PIN_CFG_LNA_PE_G1_POL       FIELD32(0x00008000)
-#define TX_PIN_CFG_RFTR_EN             FIELD32(0x00010000)
-#define TX_PIN_CFG_RFTR_POL            FIELD32(0x00020000)
-#define TX_PIN_CFG_TRSW_EN             FIELD32(0x00040000)
-#define TX_PIN_CFG_TRSW_POL            FIELD32(0x00080000)
-#define TX_PIN_CFG_PA_PE_A2_EN         FIELD32(0x01000000)
-#define TX_PIN_CFG_PA_PE_G2_EN         FIELD32(0x02000000)
-#define TX_PIN_CFG_PA_PE_A2_POL                FIELD32(0x04000000)
-#define TX_PIN_CFG_PA_PE_G2_POL                FIELD32(0x08000000)
-#define TX_PIN_CFG_LNA_PE_A2_EN                FIELD32(0x10000000)
-#define TX_PIN_CFG_LNA_PE_G2_EN                FIELD32(0x20000000)
-#define TX_PIN_CFG_LNA_PE_A2_POL       FIELD32(0x40000000)
-#define TX_PIN_CFG_LNA_PE_G2_POL       FIELD32(0x80000000)
-
-/*
- * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
- */
-#define TX_BAND_CFG                    0x132c
-#define TX_BAND_CFG_HT40_MINUS         FIELD32(0x00000001)
-#define TX_BAND_CFG_A                  FIELD32(0x00000002)
-#define TX_BAND_CFG_BG                 FIELD32(0x00000004)
-
-/*
- * TX_SW_CFG0:
- */
-#define TX_SW_CFG0                     0x1330
-
-/*
- * TX_SW_CFG1:
- */
-#define TX_SW_CFG1                     0x1334
-
-/*
- * TX_SW_CFG2:
- */
-#define TX_SW_CFG2                     0x1338
-
-/*
- * TXOP_THRES_CFG:
- */
-#define TXOP_THRES_CFG                 0x133c
-
-/*
- * TXOP_CTRL_CFG:
- * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation
- * AC_TRUN_EN: Enable/Disable truncation for AC change
- * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change
- * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode
- * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS
- * RESERVED_TRUN_EN: Reserved
- * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection
- * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz
- *            transmissions if extension CCA is clear).
- * EXT_CCA_DLY: Extension CCA signal delay time (unit: us)
- * EXT_CWMIN: CwMin for extension channel backoff
- *           0: Disabled
- *
- */
-#define TXOP_CTRL_CFG                  0x1340
-#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN  FIELD32(0x00000001)
-#define TXOP_CTRL_CFG_AC_TRUN_EN       FIELD32(0x00000002)
-#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN        FIELD32(0x00000004)
-#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN        FIELD32(0x00000008)
-#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN  FIELD32(0x00000010)
-#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020)
-#define TXOP_CTRL_CFG_LSIG_TXOP_EN     FIELD32(0x00000040)
-#define TXOP_CTRL_CFG_EXT_CCA_EN       FIELD32(0x00000080)
-#define TXOP_CTRL_CFG_EXT_CCA_DLY      FIELD32(0x0000ff00)
-#define TXOP_CTRL_CFG_EXT_CWMIN                FIELD32(0x000f0000)
-
-/*
- * TX_RTS_CFG:
- * RTS_THRES: unit:byte
- * RTS_FBK_EN: enable rts rate fallback
- */
-#define TX_RTS_CFG                     0x1344
-#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT        FIELD32(0x000000ff)
-#define TX_RTS_CFG_RTS_THRES           FIELD32(0x00ffff00)
-#define TX_RTS_CFG_RTS_FBK_EN          FIELD32(0x01000000)
-
-/*
- * TX_TIMEOUT_CFG:
- * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
- * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
- * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
- *                it is recommended that:
- *                (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
- */
-#define TX_TIMEOUT_CFG                 0x1348
-#define TX_TIMEOUT_CFG_MPDU_LIFETIME   FIELD32(0x000000f0)
-#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT  FIELD32(0x0000ff00)
-#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT   FIELD32(0x00ff0000)
-
-/*
- * TX_RTY_CFG:
- * SHORT_RTY_LIMIT: short retry limit
- * LONG_RTY_LIMIT: long retry limit
- * LONG_RTY_THRE: Long retry threshoold
- * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
- *                   0:expired by retry limit, 1: expired by mpdu life timer
- * AGG_RTY_MODE: Aggregate MPDU retry mode
- *               0:expired by retry limit, 1: expired by mpdu life timer
- * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
- */
-#define TX_RTY_CFG                     0x134c
-#define TX_RTY_CFG_SHORT_RTY_LIMIT     FIELD32(0x000000ff)
-#define TX_RTY_CFG_LONG_RTY_LIMIT      FIELD32(0x0000ff00)
-#define TX_RTY_CFG_LONG_RTY_THRE       FIELD32(0x0fff0000)
-#define TX_RTY_CFG_NON_AGG_RTY_MODE    FIELD32(0x10000000)
-#define TX_RTY_CFG_AGG_RTY_MODE                FIELD32(0x20000000)
-#define TX_RTY_CFG_TX_AUTO_FB_ENABLE   FIELD32(0x40000000)
-
-/*
- * TX_LINK_CFG:
- * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
- * MFB_ENABLE: TX apply remote MFB 1:enable
- * REMOTE_UMFS_ENABLE: remote unsolicit  MFB enable
- *                     0: not apply remote remote unsolicit (MFS=7)
- * TX_MRQ_EN: MCS request TX enable
- * TX_RDG_EN: RDG TX enable
- * TX_CF_ACK_EN: Piggyback CF-ACK enable
- * REMOTE_MFB: remote MCS feedback
- * REMOTE_MFS: remote MCS feedback sequence number
- */
-#define TX_LINK_CFG                    0x1350
-#define TX_LINK_CFG_REMOTE_MFB_LIFETIME        FIELD32(0x000000ff)
-#define TX_LINK_CFG_MFB_ENABLE         FIELD32(0x00000100)
-#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200)
-#define TX_LINK_CFG_TX_MRQ_EN          FIELD32(0x00000400)
-#define TX_LINK_CFG_TX_RDG_EN          FIELD32(0x00000800)
-#define TX_LINK_CFG_TX_CF_ACK_EN       FIELD32(0x00001000)
-#define TX_LINK_CFG_REMOTE_MFB         FIELD32(0x00ff0000)
-#define TX_LINK_CFG_REMOTE_MFS         FIELD32(0xff000000)
-
-/*
- * HT_FBK_CFG0:
- */
-#define HT_FBK_CFG0                    0x1354
-#define HT_FBK_CFG0_HTMCS0FBK          FIELD32(0x0000000f)
-#define HT_FBK_CFG0_HTMCS1FBK          FIELD32(0x000000f0)
-#define HT_FBK_CFG0_HTMCS2FBK          FIELD32(0x00000f00)
-#define HT_FBK_CFG0_HTMCS3FBK          FIELD32(0x0000f000)
-#define HT_FBK_CFG0_HTMCS4FBK          FIELD32(0x000f0000)
-#define HT_FBK_CFG0_HTMCS5FBK          FIELD32(0x00f00000)
-#define HT_FBK_CFG0_HTMCS6FBK          FIELD32(0x0f000000)
-#define HT_FBK_CFG0_HTMCS7FBK          FIELD32(0xf0000000)
-
-/*
- * HT_FBK_CFG1:
- */
-#define HT_FBK_CFG1                    0x1358
-#define HT_FBK_CFG1_HTMCS8FBK          FIELD32(0x0000000f)
-#define HT_FBK_CFG1_HTMCS9FBK          FIELD32(0x000000f0)
-#define HT_FBK_CFG1_HTMCS10FBK         FIELD32(0x00000f00)
-#define HT_FBK_CFG1_HTMCS11FBK         FIELD32(0x0000f000)
-#define HT_FBK_CFG1_HTMCS12FBK         FIELD32(0x000f0000)
-#define HT_FBK_CFG1_HTMCS13FBK         FIELD32(0x00f00000)
-#define HT_FBK_CFG1_HTMCS14FBK         FIELD32(0x0f000000)
-#define HT_FBK_CFG1_HTMCS15FBK         FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG0:
- */
-#define LG_FBK_CFG0                    0x135c
-#define LG_FBK_CFG0_OFDMMCS0FBK                FIELD32(0x0000000f)
-#define LG_FBK_CFG0_OFDMMCS1FBK                FIELD32(0x000000f0)
-#define LG_FBK_CFG0_OFDMMCS2FBK                FIELD32(0x00000f00)
-#define LG_FBK_CFG0_OFDMMCS3FBK                FIELD32(0x0000f000)
-#define LG_FBK_CFG0_OFDMMCS4FBK                FIELD32(0x000f0000)
-#define LG_FBK_CFG0_OFDMMCS5FBK                FIELD32(0x00f00000)
-#define LG_FBK_CFG0_OFDMMCS6FBK                FIELD32(0x0f000000)
-#define LG_FBK_CFG0_OFDMMCS7FBK                FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG1:
- */
-#define LG_FBK_CFG1                    0x1360
-#define LG_FBK_CFG0_CCKMCS0FBK         FIELD32(0x0000000f)
-#define LG_FBK_CFG0_CCKMCS1FBK         FIELD32(0x000000f0)
-#define LG_FBK_CFG0_CCKMCS2FBK         FIELD32(0x00000f00)
-#define LG_FBK_CFG0_CCKMCS3FBK         FIELD32(0x0000f000)
-
-/*
- * CCK_PROT_CFG: CCK Protection
- * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
- * PROTECT_CTRL: Protection control frame type for CCK TX
- *               0:none, 1:RTS/CTS, 2:CTS-to-self
- * PROTECT_NAV_SHORT: TXOP protection type for CCK TX with short NAV
- * PROTECT_NAV_LONG: TXOP protection type for CCK TX with long NAV
- * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
- * RTS_TH_EN: RTS threshold enable on CCK TX
- */
-#define CCK_PROT_CFG                   0x1364
-#define CCK_PROT_CFG_PROTECT_RATE      FIELD32(0x0000ffff)
-#define CCK_PROT_CFG_PROTECT_CTRL      FIELD32(0x00030000)
-#define CCK_PROT_CFG_PROTECT_NAV_SHORT FIELD32(0x00040000)
-#define CCK_PROT_CFG_PROTECT_NAV_LONG  FIELD32(0x00080000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_CCK   FIELD32(0x00100000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM  FIELD32(0x00200000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM20  FIELD32(0x00400000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM40  FIELD32(0x00800000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF20  FIELD32(0x01000000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF40  FIELD32(0x02000000)
-#define CCK_PROT_CFG_RTS_TH_EN         FIELD32(0x04000000)
-
-/*
- * OFDM_PROT_CFG: OFDM Protection
- */
-#define OFDM_PROT_CFG                  0x1368
-#define OFDM_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
-#define OFDM_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
-#define OFDM_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
-#define OFDM_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define OFDM_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
-
-/*
- * MM20_PROT_CFG: MM20 Protection
- */
-#define MM20_PROT_CFG                  0x136c
-#define MM20_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
-#define MM20_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
-#define MM20_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
-#define MM20_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM20_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
-
-/*
- * MM40_PROT_CFG: MM40 Protection
- */
-#define MM40_PROT_CFG                  0x1370
-#define MM40_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
-#define MM40_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
-#define MM40_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
-#define MM40_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM40_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
-
-/*
- * GF20_PROT_CFG: GF20 Protection
- */
-#define GF20_PROT_CFG                  0x1374
-#define GF20_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
-#define GF20_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
-#define GF20_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
-#define GF20_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF20_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
-
-/*
- * GF40_PROT_CFG: GF40 Protection
- */
-#define GF40_PROT_CFG                  0x1378
-#define GF40_PROT_CFG_PROTECT_RATE     FIELD32(0x0000ffff)
-#define GF40_PROT_CFG_PROTECT_CTRL     FIELD32(0x00030000)
-#define GF40_PROT_CFG_PROTECT_NAV_SHORT        FIELD32(0x00040000)
-#define GF40_PROT_CFG_PROTECT_NAV_LONG FIELD32(0x00080000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_CCK  FIELD32(0x00100000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF40_PROT_CFG_RTS_TH_EN                FIELD32(0x04000000)
-
-/*
- * EXP_CTS_TIME:
- */
-#define EXP_CTS_TIME                   0x137c
-
-/*
- * EXP_ACK_TIME:
- */
-#define EXP_ACK_TIME                   0x1380
-
-/* TX_PWR_CFG_5 */
-#define TX_PWR_CFG_5                   0x1384
-#define TX_PWR_CFG_5_MCS16_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_5_MCS16_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_5_MCS16_CH2         FIELD32(0x00000f00)
-#define TX_PWR_CFG_5_MCS18_CH0         FIELD32(0x000f0000)
-#define TX_PWR_CFG_5_MCS18_CH1         FIELD32(0x00f00000)
-#define TX_PWR_CFG_5_MCS18_CH2         FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_6 */
-#define TX_PWR_CFG_6                   0x1388
-#define TX_PWR_CFG_6_MCS20_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_6_MCS20_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_6_MCS20_CH2         FIELD32(0x00000f00)
-#define TX_PWR_CFG_6_MCS22_CH0         FIELD32(0x000f0000)
-#define TX_PWR_CFG_6_MCS22_CH1         FIELD32(0x00f00000)
-#define TX_PWR_CFG_6_MCS22_CH2         FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_0_EXT */
-#define TX_PWR_CFG_0_EXT               0x1390
-#define TX_PWR_CFG_0_EXT_CCK1_CH2      FIELD32(0x0000000f)
-#define TX_PWR_CFG_0_EXT_CCK5_CH2      FIELD32(0x00000f00)
-#define TX_PWR_CFG_0_EXT_OFDM6_CH2     FIELD32(0x000f0000)
-#define TX_PWR_CFG_0_EXT_OFDM12_CH2    FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_1_EXT */
-#define TX_PWR_CFG_1_EXT               0x1394
-#define TX_PWR_CFG_1_EXT_OFDM24_CH2    FIELD32(0x0000000f)
-#define TX_PWR_CFG_1_EXT_OFDM48_CH2    FIELD32(0x00000f00)
-#define TX_PWR_CFG_1_EXT_MCS0_CH2      FIELD32(0x000f0000)
-#define TX_PWR_CFG_1_EXT_MCS2_CH2      FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_2_EXT */
-#define TX_PWR_CFG_2_EXT               0x1398
-#define TX_PWR_CFG_2_EXT_MCS4_CH2      FIELD32(0x0000000f)
-#define TX_PWR_CFG_2_EXT_MCS6_CH2      FIELD32(0x00000f00)
-#define TX_PWR_CFG_2_EXT_MCS8_CH2      FIELD32(0x000f0000)
-#define TX_PWR_CFG_2_EXT_MCS10_CH2     FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_3_EXT */
-#define TX_PWR_CFG_3_EXT               0x139c
-#define TX_PWR_CFG_3_EXT_MCS12_CH2     FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_EXT_MCS14_CH2     FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_EXT_STBC0_CH2     FIELD32(0x000f0000)
-#define TX_PWR_CFG_3_EXT_STBC2_CH2     FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_4_EXT */
-#define TX_PWR_CFG_4_EXT               0x13a0
-#define TX_PWR_CFG_4_EXT_STBC4_CH2     FIELD32(0x0000000f)
-#define TX_PWR_CFG_4_EXT_STBC6_CH2     FIELD32(0x00000f00)
-
-/* TX_PWR_CFG_7 */
-#define TX_PWR_CFG_7                   0x13d4
-#define TX_PWR_CFG_7_OFDM54_CH0                FIELD32(0x0000000f)
-#define TX_PWR_CFG_7_OFDM54_CH1                FIELD32(0x000000f0)
-#define TX_PWR_CFG_7_OFDM54_CH2                FIELD32(0x00000f00)
-#define TX_PWR_CFG_7_MCS7_CH0          FIELD32(0x000f0000)
-#define TX_PWR_CFG_7_MCS7_CH1          FIELD32(0x00f00000)
-#define TX_PWR_CFG_7_MCS7_CH2          FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_8 */
-#define TX_PWR_CFG_8                   0x13d8
-#define TX_PWR_CFG_8_MCS15_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_8_MCS15_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_8_MCS15_CH2         FIELD32(0x00000f00)
-#define TX_PWR_CFG_8_MCS23_CH0         FIELD32(0x000f0000)
-#define TX_PWR_CFG_8_MCS23_CH1         FIELD32(0x00f00000)
-#define TX_PWR_CFG_8_MCS23_CH2         FIELD32(0x0f000000)
-
-/* TX_PWR_CFG_9 */
-#define TX_PWR_CFG_9                   0x13dc
-#define TX_PWR_CFG_9_STBC7_CH0         FIELD32(0x0000000f)
-#define TX_PWR_CFG_9_STBC7_CH1         FIELD32(0x000000f0)
-#define TX_PWR_CFG_9_STBC7_CH2         FIELD32(0x00000f00)
-
-/*
- * RX_FILTER_CFG: RX configuration register.
- */
-#define RX_FILTER_CFG                  0x1400
-#define RX_FILTER_CFG_DROP_CRC_ERROR   FIELD32(0x00000001)
-#define RX_FILTER_CFG_DROP_PHY_ERROR   FIELD32(0x00000002)
-#define RX_FILTER_CFG_DROP_NOT_TO_ME   FIELD32(0x00000004)
-#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008)
-#define RX_FILTER_CFG_DROP_VER_ERROR   FIELD32(0x00000010)
-#define RX_FILTER_CFG_DROP_MULTICAST   FIELD32(0x00000020)
-#define RX_FILTER_CFG_DROP_BROADCAST   FIELD32(0x00000040)
-#define RX_FILTER_CFG_DROP_DUPLICATE   FIELD32(0x00000080)
-#define RX_FILTER_CFG_DROP_CF_END_ACK  FIELD32(0x00000100)
-#define RX_FILTER_CFG_DROP_CF_END      FIELD32(0x00000200)
-#define RX_FILTER_CFG_DROP_ACK         FIELD32(0x00000400)
-#define RX_FILTER_CFG_DROP_CTS         FIELD32(0x00000800)
-#define RX_FILTER_CFG_DROP_RTS         FIELD32(0x00001000)
-#define RX_FILTER_CFG_DROP_PSPOLL      FIELD32(0x00002000)
-#define RX_FILTER_CFG_DROP_BA          FIELD32(0x00004000)
-#define RX_FILTER_CFG_DROP_BAR         FIELD32(0x00008000)
-#define RX_FILTER_CFG_DROP_CNTL                FIELD32(0x00010000)
-
-/*
- * AUTO_RSP_CFG:
- * AUTORESPONDER: 0: disable, 1: enable
- * BAC_ACK_POLICY: 0:long, 1:short preamble
- * CTS_40_MMODE: Response CTS 40MHz duplicate mode
- * CTS_40_MREF: Response CTS 40MHz duplicate mode
- * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
- * DUAL_CTS_EN: Power bit value in control frame
- * ACK_CTS_PSM_BIT:Power bit value in control frame
- */
-#define AUTO_RSP_CFG                   0x1404
-#define AUTO_RSP_CFG_AUTORESPONDER     FIELD32(0x00000001)
-#define AUTO_RSP_CFG_BAC_ACK_POLICY    FIELD32(0x00000002)
-#define AUTO_RSP_CFG_CTS_40_MMODE      FIELD32(0x00000004)
-#define AUTO_RSP_CFG_CTS_40_MREF       FIELD32(0x00000008)
-#define AUTO_RSP_CFG_AR_PREAMBLE       FIELD32(0x00000010)
-#define AUTO_RSP_CFG_DUAL_CTS_EN       FIELD32(0x00000040)
-#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT   FIELD32(0x00000080)
-
-/*
- * LEGACY_BASIC_RATE:
- */
-#define LEGACY_BASIC_RATE              0x1408
-
-/*
- * HT_BASIC_RATE:
- */
-#define HT_BASIC_RATE                  0x140c
-
-/*
- * HT_CTRL_CFG:
- */
-#define HT_CTRL_CFG                    0x1410
-
-/*
- * SIFS_COST_CFG:
- */
-#define SIFS_COST_CFG                  0x1414
-
-/*
- * RX_PARSER_CFG:
- * Set NAV for all received frames
- */
-#define RX_PARSER_CFG                  0x1418
-
-/*
- * TX_SEC_CNT0:
- */
-#define TX_SEC_CNT0                    0x1500
-
-/*
- * RX_SEC_CNT0:
- */
-#define RX_SEC_CNT0                    0x1504
-
-/*
- * CCMP_FC_MUTE:
- */
-#define CCMP_FC_MUTE                   0x1508
-
-/*
- * TXOP_HLDR_ADDR0:
- */
-#define TXOP_HLDR_ADDR0                        0x1600
-
-/*
- * TXOP_HLDR_ADDR1:
- */
-#define TXOP_HLDR_ADDR1                        0x1604
-
-/*
- * TXOP_HLDR_ET:
- */
-#define TXOP_HLDR_ET                   0x1608
-
-/*
- * QOS_CFPOLL_RA_DW0:
- */
-#define QOS_CFPOLL_RA_DW0              0x160c
-
-/*
- * QOS_CFPOLL_RA_DW1:
- */
-#define QOS_CFPOLL_RA_DW1              0x1610
-
-/*
- * QOS_CFPOLL_QC:
- */
-#define QOS_CFPOLL_QC                  0x1614
-
-/*
- * RX_STA_CNT0: RX PLCP error count & RX CRC error count
- */
-#define RX_STA_CNT0                    0x1700
-#define RX_STA_CNT0_CRC_ERR            FIELD32(0x0000ffff)
-#define RX_STA_CNT0_PHY_ERR            FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT1: RX False CCA count & RX LONG frame count
- */
-#define RX_STA_CNT1                    0x1704
-#define RX_STA_CNT1_FALSE_CCA          FIELD32(0x0000ffff)
-#define RX_STA_CNT1_PLCP_ERR           FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT2:
- */
-#define RX_STA_CNT2                    0x1708
-#define RX_STA_CNT2_RX_DUPLI_COUNT     FIELD32(0x0000ffff)
-#define RX_STA_CNT2_RX_FIFO_OVERFLOW   FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT0: TX Beacon count
- */
-#define TX_STA_CNT0                    0x170c
-#define TX_STA_CNT0_TX_FAIL_COUNT      FIELD32(0x0000ffff)
-#define TX_STA_CNT0_TX_BEACON_COUNT    FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT1: TX tx count
- */
-#define TX_STA_CNT1                    0x1710
-#define TX_STA_CNT1_TX_SUCCESS         FIELD32(0x0000ffff)
-#define TX_STA_CNT1_TX_RETRANSMIT      FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT2: TX tx count
- */
-#define TX_STA_CNT2                    0x1714
-#define TX_STA_CNT2_TX_ZERO_LEN_COUNT  FIELD32(0x0000ffff)
-#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT        FIELD32(0xffff0000)
-
-/*
- * TX_STA_FIFO: TX Result for specific PID status fifo register.
- *
- * This register is implemented as FIFO with 16 entries in the HW. Each
- * register read fetches the next tx result. If the FIFO is full because
- * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS)
- * triggered, the hw seems to simply drop further tx results.
- *
- * VALID: 1: this tx result is valid
- *        0: no valid tx result -> driver should stop reading
- * PID_TYPE: The PID latched from the PID field in the TXWI, can be used
- *           to match a frame with its tx result (even though the PID is
- *           only 4 bits wide).
- * PID_QUEUE: Part of PID_TYPE, this is the queue index number (0-3)
- * PID_ENTRY: Part of PID_TYPE, this is the queue entry index number (1-3)
- *            This identification number is calculated by ((idx % 3) + 1).
- * TX_SUCCESS: Indicates tx success (1) or failure (0)
- * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0)
- * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0)
- * WCID: The wireless client ID.
- * MCS: The tx rate used during the last transmission of this frame, be it
- *      successful or not.
- * PHYMODE: The phymode used for the transmission.
- */
-#define TX_STA_FIFO                    0x1718
-#define TX_STA_FIFO_VALID              FIELD32(0x00000001)
-#define TX_STA_FIFO_PID_TYPE           FIELD32(0x0000001e)
-#define TX_STA_FIFO_PID_QUEUE          FIELD32(0x00000006)
-#define TX_STA_FIFO_PID_ENTRY          FIELD32(0x00000018)
-#define TX_STA_FIFO_TX_SUCCESS         FIELD32(0x00000020)
-#define TX_STA_FIFO_TX_AGGRE           FIELD32(0x00000040)
-#define TX_STA_FIFO_TX_ACK_REQUIRED    FIELD32(0x00000080)
-#define TX_STA_FIFO_WCID               FIELD32(0x0000ff00)
-#define TX_STA_FIFO_SUCCESS_RATE       FIELD32(0xffff0000)
-#define TX_STA_FIFO_MCS                        FIELD32(0x007f0000)
-#define TX_STA_FIFO_PHYMODE            FIELD32(0xc0000000)
-
-/*
- * TX_AGG_CNT: Debug counter
- */
-#define TX_AGG_CNT                     0x171c
-#define TX_AGG_CNT_NON_AGG_TX_COUNT    FIELD32(0x0000ffff)
-#define TX_AGG_CNT_AGG_TX_COUNT                FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT0:
- */
-#define TX_AGG_CNT0                    0x1720
-#define TX_AGG_CNT0_AGG_SIZE_1_COUNT   FIELD32(0x0000ffff)
-#define TX_AGG_CNT0_AGG_SIZE_2_COUNT   FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT1:
- */
-#define TX_AGG_CNT1                    0x1724
-#define TX_AGG_CNT1_AGG_SIZE_3_COUNT   FIELD32(0x0000ffff)
-#define TX_AGG_CNT1_AGG_SIZE_4_COUNT   FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT2:
- */
-#define TX_AGG_CNT2                    0x1728
-#define TX_AGG_CNT2_AGG_SIZE_5_COUNT   FIELD32(0x0000ffff)
-#define TX_AGG_CNT2_AGG_SIZE_6_COUNT   FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT3:
- */
-#define TX_AGG_CNT3                    0x172c
-#define TX_AGG_CNT3_AGG_SIZE_7_COUNT   FIELD32(0x0000ffff)
-#define TX_AGG_CNT3_AGG_SIZE_8_COUNT   FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT4:
- */
-#define TX_AGG_CNT4                    0x1730
-#define TX_AGG_CNT4_AGG_SIZE_9_COUNT   FIELD32(0x0000ffff)
-#define TX_AGG_CNT4_AGG_SIZE_10_COUNT  FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT5:
- */
-#define TX_AGG_CNT5                    0x1734
-#define TX_AGG_CNT5_AGG_SIZE_11_COUNT  FIELD32(0x0000ffff)
-#define TX_AGG_CNT5_AGG_SIZE_12_COUNT  FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT6:
- */
-#define TX_AGG_CNT6                    0x1738
-#define TX_AGG_CNT6_AGG_SIZE_13_COUNT  FIELD32(0x0000ffff)
-#define TX_AGG_CNT6_AGG_SIZE_14_COUNT  FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT7:
- */
-#define TX_AGG_CNT7                    0x173c
-#define TX_AGG_CNT7_AGG_SIZE_15_COUNT  FIELD32(0x0000ffff)
-#define TX_AGG_CNT7_AGG_SIZE_16_COUNT  FIELD32(0xffff0000)
-
-/*
- * MPDU_DENSITY_CNT:
- * TX_ZERO_DEL: TX zero length delimiter count
- * RX_ZERO_DEL: RX zero length delimiter count
- */
-#define MPDU_DENSITY_CNT               0x1740
-#define MPDU_DENSITY_CNT_TX_ZERO_DEL   FIELD32(0x0000ffff)
-#define MPDU_DENSITY_CNT_RX_ZERO_DEL   FIELD32(0xffff0000)
-
-/*
- * Security key table memory.
- *
- * The pairwise key table shares some memory with the beacon frame
- * buffers 6 and 7. That basically means that when beacon 6 & 7
- * are used we should only use the reduced pairwise key table which
- * has a maximum of 222 entries.
- *
- * ---------------------------------------------
- * |0x4000 | Pairwise Key   | Reduced Pairwise |
- * |       | Table          | Key Table        |
- * |       | Size: 256 * 32 | Size: 222 * 32   |
- * |0x5BC0 |                |-------------------
- * |       |                | Beacon 6         |
- * |0x5DC0 |                |-------------------
- * |       |                | Beacon 7         |
- * |0x5FC0 |                |-------------------
- * |0x5FFF |                |
- * --------------------------
- *
- * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
- * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
- * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
- * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
- * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry
- * SHARED_KEY_MODE_BASE: 4-byte * 16-entry
- */
-#define MAC_WCID_BASE                  0x1800
-#define PAIRWISE_KEY_TABLE_BASE                0x4000
-#define MAC_IVEIV_TABLE_BASE           0x6000
-#define MAC_WCID_ATTRIBUTE_BASE                0x6800
-#define SHARED_KEY_TABLE_BASE          0x6c00
-#define SHARED_KEY_MODE_BASE           0x7000
-
-#define MAC_WCID_ENTRY(__idx) \
-       (MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)))
-#define PAIRWISE_KEY_ENTRY(__idx) \
-       (PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
-#define MAC_IVEIV_ENTRY(__idx) \
-       (MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)))
-#define MAC_WCID_ATTR_ENTRY(__idx) \
-       (MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)))
-#define SHARED_KEY_ENTRY(__idx) \
-       (SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
-#define SHARED_KEY_MODE_ENTRY(__idx) \
-       (SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)))
-
-struct mac_wcid_entry {
-       u8 mac[6];
-       u8 reserved[2];
-} __packed;
-
-struct hw_key_entry {
-       u8 key[16];
-       u8 tx_mic[8];
-       u8 rx_mic[8];
-} __packed;
-
-struct mac_iveiv_entry {
-       u8 iv[8];
-} __packed;
-
-/*
- * MAC_WCID_ATTRIBUTE:
- */
-#define MAC_WCID_ATTRIBUTE_KEYTAB      FIELD32(0x00000001)
-#define MAC_WCID_ATTRIBUTE_CIPHER      FIELD32(0x0000000e)
-#define MAC_WCID_ATTRIBUTE_BSS_IDX     FIELD32(0x00000070)
-#define MAC_WCID_ATTRIBUTE_RX_WIUDF    FIELD32(0x00000380)
-#define MAC_WCID_ATTRIBUTE_CIPHER_EXT  FIELD32(0x00000400)
-#define MAC_WCID_ATTRIBUTE_BSS_IDX_EXT FIELD32(0x00000800)
-#define MAC_WCID_ATTRIBUTE_WAPI_MCBC   FIELD32(0x00008000)
-#define MAC_WCID_ATTRIBUTE_WAPI_KEY_IDX        FIELD32(0xff000000)
-
-/*
- * SHARED_KEY_MODE:
- */
-#define SHARED_KEY_MODE_BSS0_KEY0      FIELD32(0x00000007)
-#define SHARED_KEY_MODE_BSS0_KEY1      FIELD32(0x00000070)
-#define SHARED_KEY_MODE_BSS0_KEY2      FIELD32(0x00000700)
-#define SHARED_KEY_MODE_BSS0_KEY3      FIELD32(0x00007000)
-#define SHARED_KEY_MODE_BSS1_KEY0      FIELD32(0x00070000)
-#define SHARED_KEY_MODE_BSS1_KEY1      FIELD32(0x00700000)
-#define SHARED_KEY_MODE_BSS1_KEY2      FIELD32(0x07000000)
-#define SHARED_KEY_MODE_BSS1_KEY3      FIELD32(0x70000000)
-
-/*
- * HOST-MCU communication
- */
-
-/*
- * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
- * CMD_TOKEN: Command id, 0xff disable status reporting.
- */
-#define H2M_MAILBOX_CSR                        0x7010
-#define H2M_MAILBOX_CSR_ARG0           FIELD32(0x000000ff)
-#define H2M_MAILBOX_CSR_ARG1           FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CSR_CMD_TOKEN      FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CSR_OWNER          FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_CID:
- * Free slots contain 0xff. MCU will store command's token to lowest free slot.
- * If all slots are occupied status will be dropped.
- */
-#define H2M_MAILBOX_CID                        0x7014
-#define H2M_MAILBOX_CID_CMD0           FIELD32(0x000000ff)
-#define H2M_MAILBOX_CID_CMD1           FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CID_CMD2           FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CID_CMD3           FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_STATUS:
- * Command status will be saved to same slot as command id.
- */
-#define H2M_MAILBOX_STATUS             0x701c
-
-/*
- * H2M_INT_SRC:
- */
-#define H2M_INT_SRC                    0x7024
-
-/*
- * H2M_BBP_AGENT:
- */
-#define H2M_BBP_AGENT                  0x7028
-
-/*
- * MCU_LEDCS: LED control for MCU Mailbox.
- */
-#define MCU_LEDCS_LED_MODE             FIELD8(0x1f)
-#define MCU_LEDCS_POLARITY             FIELD8(0x01)
-
-/*
- * HW_CS_CTS_BASE:
- * Carrier-sense CTS frame base address.
- * It's where mac stores carrier-sense frame for carrier-sense function.
- */
-#define HW_CS_CTS_BASE                 0x7700
-
-/*
- * HW_DFS_CTS_BASE:
- * DFS CTS frame base address. It's where mac stores CTS frame for DFS.
- */
-#define HW_DFS_CTS_BASE                        0x7780
-
-/*
- * TXRX control registers - base address 0x3000
- */
-
-/*
- * TXRX_CSR1:
- * rt2860b  UNKNOWN reg use R/O Reg Addr 0x77d0 first..
- */
-#define TXRX_CSR1                      0x77d0
-
-/*
- * HW_DEBUG_SETTING_BASE:
- * since NULL frame won't be that long (256 byte)
- * We steal 16 tail bytes to save debugging settings
- */
-#define HW_DEBUG_SETTING_BASE          0x77f0
-#define HW_DEBUG_SETTING_BASE2         0x7770
-
-/*
- * HW_BEACON_BASE
- * In order to support maximum 8 MBSS and its maximum length
- * is 512 bytes for each beacon
- * Three section discontinue memory segments will be used.
- * 1. The original region for BCN 0~3
- * 2. Extract memory from FCE table for BCN 4~5
- * 3. Extract memory from Pair-wise key table for BCN 6~7
- *    It occupied those memory of wcid 238~253 for BCN 6
- *    and wcid 222~237 for BCN 7 (see Security key table memory
- *    for more info).
- *
- * IMPORTANT NOTE: Not sure why legacy driver does this,
- * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
- */
-#define HW_BEACON_BASE0                        0x7800
-#define HW_BEACON_BASE1                        0x7a00
-#define HW_BEACON_BASE2                        0x7c00
-#define HW_BEACON_BASE3                        0x7e00
-#define HW_BEACON_BASE4                        0x7200
-#define HW_BEACON_BASE5                        0x7400
-#define HW_BEACON_BASE6                        0x5dc0
-#define HW_BEACON_BASE7                        0x5bc0
-
-#define HW_BEACON_BASE(__index) \
-       (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \
-         (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
-         (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
-
-#define BEACON_BASE_TO_OFFSET(_base)   (((_base) - 0x4000) / 64)
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP 1: TX Antenna & Power Control
- * POWER_CTRL:
- * 0 - normal,
- * 1 - drop tx power by 6dBm,
- * 2 - drop tx power by 12dBm,
- * 3 - increase tx power by 6dBm
- */
-#define BBP1_TX_POWER_CTRL             FIELD8(0x03)
-#define BBP1_TX_ANTENNA                        FIELD8(0x18)
-
-/*
- * BBP 3: RX Antenna
- */
-#define BBP3_RX_ADC                    FIELD8(0x03)
-#define BBP3_RX_ANTENNA                        FIELD8(0x18)
-#define BBP3_HT40_MINUS                        FIELD8(0x20)
-#define BBP3_ADC_MODE_SWITCH           FIELD8(0x40)
-#define BBP3_ADC_INIT_MODE             FIELD8(0x80)
-
-/*
- * BBP 4: Bandwidth
- */
-#define BBP4_TX_BF                     FIELD8(0x01)
-#define BBP4_BANDWIDTH                 FIELD8(0x18)
-#define BBP4_MAC_IF_CTRL               FIELD8(0x40)
-
-/* BBP27 */
-#define BBP27_RX_CHAIN_SEL             FIELD8(0x60)
-
-/*
- * BBP 47: Bandwidth
- */
-#define BBP47_TSSI_REPORT_SEL          FIELD8(0x03)
-#define BBP47_TSSI_UPDATE_REQ          FIELD8(0x04)
-#define BBP47_TSSI_TSSI_MODE           FIELD8(0x18)
-#define BBP47_TSSI_ADC6                        FIELD8(0x80)
-
-/*
- * BBP 49
- */
-#define BBP49_UPDATE_FLAG              FIELD8(0x01)
-
-/*
- * BBP 105:
- * - bit0: detect SIG on primary channel only (on 40MHz bandwidth)
- * - bit1: FEQ (Feed Forward Compensation) for independend streams
- * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single
- *        stream)
- * - bit4: channel estimation updates based on remodulation of
- *        L-SIG and HT-SIG symbols
- */
-#define BBP105_DETECT_SIG_ON_PRIMARY   FIELD8(0x01)
-#define BBP105_FEQ                     FIELD8(0x02)
-#define BBP105_MLD                     FIELD8(0x04)
-#define BBP105_SIG_REMODULATION                FIELD8(0x08)
-
-/*
- * BBP 109
- */
-#define BBP109_TX0_POWER               FIELD8(0x0f)
-#define BBP109_TX1_POWER               FIELD8(0xf0)
-
-/* BBP 110 */
-#define BBP110_TX2_POWER               FIELD8(0x0f)
-
-
-/*
- * BBP 138: Unknown
- */
-#define BBP138_RX_ADC1                 FIELD8(0x02)
-#define BBP138_RX_ADC2                 FIELD8(0x04)
-#define BBP138_TX_DAC1                 FIELD8(0x20)
-#define BBP138_TX_DAC2                 FIELD8(0x40)
-
-/*
- * BBP 152: Rx Ant
- */
-#define BBP152_RX_DEFAULT_ANT          FIELD8(0x80)
-
-/*
- * BBP 254: unknown
- */
-#define BBP254_BIT7                    FIELD8(0x80)
-
-/*
- * RFCSR registers
- * The wordsize of the RFCSR is 8 bits.
- */
-
-/*
- * RFCSR 1:
- */
-#define RFCSR1_RF_BLOCK_EN             FIELD8(0x01)
-#define RFCSR1_PLL_PD                  FIELD8(0x02)
-#define RFCSR1_RX0_PD                  FIELD8(0x04)
-#define RFCSR1_TX0_PD                  FIELD8(0x08)
-#define RFCSR1_RX1_PD                  FIELD8(0x10)
-#define RFCSR1_TX1_PD                  FIELD8(0x20)
-#define RFCSR1_RX2_PD                  FIELD8(0x40)
-#define RFCSR1_TX2_PD                  FIELD8(0x80)
-
-/*
- * RFCSR 2:
- */
-#define RFCSR2_RESCAL_EN               FIELD8(0x80)
-
-/*
- * RFCSR 3:
- */
-#define RFCSR3_K                       FIELD8(0x0f)
-/* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */
-#define RFCSR3_PA1_BIAS_CCK            FIELD8(0x70)
-#define RFCSR3_PA2_CASCODE_BIAS_CCKK   FIELD8(0x80)
-/* Bits for RF3290/RF5360/RF5362/RF5370/RF5372/RF5390/RF5392 */
-#define RFCSR3_VCOCAL_EN               FIELD8(0x80)
-/* Bits for RF3050 */
-#define RFCSR3_BIT1                    FIELD8(0x02)
-#define RFCSR3_BIT2                    FIELD8(0x04)
-#define RFCSR3_BIT3                    FIELD8(0x08)
-#define RFCSR3_BIT4                    FIELD8(0x10)
-#define RFCSR3_BIT5                    FIELD8(0x20)
-
-/*
- * FRCSR 5:
- */
-#define RFCSR5_R1                      FIELD8(0x0c)
-
-/*
- * RFCSR 6:
- */
-#define RFCSR6_R1                      FIELD8(0x03)
-#define RFCSR6_R2                      FIELD8(0x40)
-#define RFCSR6_TXDIV                   FIELD8(0x0c)
-/* bits for RF3053 */
-#define RFCSR6_VCO_IC                  FIELD8(0xc0)
-
-/*
- * RFCSR 7:
- */
-#define RFCSR7_RF_TUNING               FIELD8(0x01)
-#define RFCSR7_BIT1                    FIELD8(0x02)
-#define RFCSR7_BIT2                    FIELD8(0x04)
-#define RFCSR7_BIT3                    FIELD8(0x08)
-#define RFCSR7_BIT4                    FIELD8(0x10)
-#define RFCSR7_BIT5                    FIELD8(0x20)
-#define RFCSR7_BITS67                  FIELD8(0xc0)
-
-/*
- * RFCSR 9:
- */
-#define RFCSR9_K                       FIELD8(0x0f)
-#define RFCSR9_N                       FIELD8(0x10)
-#define RFCSR9_UNKNOWN                 FIELD8(0x60)
-#define RFCSR9_MOD                     FIELD8(0x80)
-
-/*
- * RFCSR 11:
- */
-#define RFCSR11_R                      FIELD8(0x03)
-#define RFCSR11_PLL_MOD                        FIELD8(0x0c)
-#define RFCSR11_MOD                    FIELD8(0xc0)
-/* bits for RF3053 */
-/* TODO: verify RFCSR11_MOD usage on other chips */
-#define RFCSR11_PLL_IDOH               FIELD8(0x40)
-
-
-/*
- * RFCSR 12:
- */
-#define RFCSR12_TX_POWER               FIELD8(0x1f)
-#define RFCSR12_DR0                    FIELD8(0xe0)
-
-/*
- * RFCSR 13:
- */
-#define RFCSR13_TX_POWER               FIELD8(0x1f)
-#define RFCSR13_DR0                    FIELD8(0xe0)
-
-/*
- * RFCSR 15:
- */
-#define RFCSR15_TX_LO2_EN              FIELD8(0x08)
-
-/*
- * RFCSR 16:
- */
-#define RFCSR16_TXMIXER_GAIN           FIELD8(0x07)
-
-/*
- * RFCSR 17:
- */
-#define RFCSR17_TXMIXER_GAIN           FIELD8(0x07)
-#define RFCSR17_TX_LO1_EN              FIELD8(0x08)
-#define RFCSR17_R                      FIELD8(0x20)
-#define RFCSR17_CODE                   FIELD8(0x7f)
-
-/* RFCSR 18 */
-#define RFCSR18_XO_TUNE_BYPASS         FIELD8(0x40)
-
-
-/*
- * RFCSR 20:
- */
-#define RFCSR20_RX_LO1_EN              FIELD8(0x08)
-
-/*
- * RFCSR 21:
- */
-#define RFCSR21_RX_LO2_EN              FIELD8(0x08)
-
-/*
- * RFCSR 22:
- */
-#define RFCSR22_BASEBAND_LOOPBACK      FIELD8(0x01)
-
-/*
- * RFCSR 23:
- */
-#define RFCSR23_FREQ_OFFSET            FIELD8(0x7f)
-
-/*
- * RFCSR 24:
- */
-#define RFCSR24_TX_AGC_FC              FIELD8(0x1f)
-#define RFCSR24_TX_H20M                        FIELD8(0x20)
-#define RFCSR24_TX_CALIB               FIELD8(0x7f)
-
-/*
- * RFCSR 27:
- */
-#define RFCSR27_R1                     FIELD8(0x03)
-#define RFCSR27_R2                     FIELD8(0x04)
-#define RFCSR27_R3                     FIELD8(0x30)
-#define RFCSR27_R4                     FIELD8(0x40)
-
-/*
- * RFCSR 29:
- */
-#define RFCSR29_ADC6_TEST              FIELD8(0x01)
-#define RFCSR29_ADC6_INT_TEST          FIELD8(0x02)
-#define RFCSR29_RSSI_RESET             FIELD8(0x04)
-#define RFCSR29_RSSI_ON                        FIELD8(0x08)
-#define RFCSR29_RSSI_RIP_CTRL          FIELD8(0x30)
-#define RFCSR29_RSSI_GAIN              FIELD8(0xc0)
-
-/*
- * RFCSR 30:
- */
-#define RFCSR30_TX_H20M                        FIELD8(0x02)
-#define RFCSR30_RX_H20M                        FIELD8(0x04)
-#define RFCSR30_RX_VCM                 FIELD8(0x18)
-#define RFCSR30_RF_CALIBRATION         FIELD8(0x80)
-
-/*
- * RFCSR 31:
- */
-#define RFCSR31_RX_AGC_FC              FIELD8(0x1f)
-#define RFCSR31_RX_H20M                        FIELD8(0x20)
-#define RFCSR31_RX_CALIB               FIELD8(0x7f)
-
-/* RFCSR 32 bits for RF3053 */
-#define RFCSR32_TX_AGC_FC              FIELD8(0xf8)
-
-/* RFCSR 36 bits for RF3053 */
-#define RFCSR36_RF_BS                  FIELD8(0x80)
-
-/*
- * RFCSR 38:
- */
-#define RFCSR38_RX_LO1_EN              FIELD8(0x20)
-
-/*
- * RFCSR 39:
- */
-#define RFCSR39_RX_DIV                 FIELD8(0x40)
-#define RFCSR39_RX_LO2_EN              FIELD8(0x80)
-
-/*
- * RFCSR 49:
- */
-#define RFCSR49_TX                     FIELD8(0x3f)
-#define RFCSR49_EP                     FIELD8(0xc0)
-/* bits for RT3593 */
-#define RFCSR49_TX_LO1_IC              FIELD8(0x1c)
-#define RFCSR49_TX_DIV                 FIELD8(0x20)
-
-/*
- * RFCSR 50:
- */
-#define RFCSR50_TX                     FIELD8(0x3f)
-#define RFCSR50_EP                     FIELD8(0xc0)
-/* bits for RT3593 */
-#define RFCSR50_TX_LO1_EN              FIELD8(0x20)
-#define RFCSR50_TX_LO2_EN              FIELD8(0x10)
-
-/* RFCSR 51 */
-/* bits for RT3593 */
-#define RFCSR51_BITS01                 FIELD8(0x03)
-#define RFCSR51_BITS24                 FIELD8(0x1c)
-#define RFCSR51_BITS57                 FIELD8(0xe0)
-
-#define RFCSR53_TX_POWER               FIELD8(0x3f)
-#define RFCSR53_UNKNOWN                        FIELD8(0xc0)
-
-#define RFCSR54_TX_POWER               FIELD8(0x3f)
-#define RFCSR54_UNKNOWN                        FIELD8(0xc0)
-
-#define RFCSR55_TX_POWER               FIELD8(0x3f)
-#define RFCSR55_UNKNOWN                        FIELD8(0xc0)
-
-#define RFCSR57_DRV_CC                 FIELD8(0xfc)
-
-
-/*
- * RF registers
- */
-
-/*
- * RF 2
- */
-#define RF2_ANTENNA_RX2                        FIELD32(0x00000040)
-#define RF2_ANTENNA_TX1                        FIELD32(0x00004000)
-#define RF2_ANTENNA_RX1                        FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TXPOWER_G                  FIELD32(0x00003e00)
-#define RF3_TXPOWER_A_7DBM_BOOST       FIELD32(0x00000200)
-#define RF3_TXPOWER_A                  FIELD32(0x00003c00)
-
-/*
- * RF 4
- */
-#define RF4_TXPOWER_G                  FIELD32(0x000007c0)
-#define RF4_TXPOWER_A_7DBM_BOOST       FIELD32(0x00000040)
-#define RF4_TXPOWER_A                  FIELD32(0x00000780)
-#define RF4_FREQ_OFFSET                        FIELD32(0x001f8000)
-#define RF4_HT40                       FIELD32(0x00200000)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-enum rt2800_eeprom_word {
-       EEPROM_CHIP_ID = 0,
-       EEPROM_VERSION,
-       EEPROM_MAC_ADDR_0,
-       EEPROM_MAC_ADDR_1,
-       EEPROM_MAC_ADDR_2,
-       EEPROM_NIC_CONF0,
-       EEPROM_NIC_CONF1,
-       EEPROM_FREQ,
-       EEPROM_LED_AG_CONF,
-       EEPROM_LED_ACT_CONF,
-       EEPROM_LED_POLARITY,
-       EEPROM_NIC_CONF2,
-       EEPROM_LNA,
-       EEPROM_RSSI_BG,
-       EEPROM_RSSI_BG2,
-       EEPROM_TXMIXER_GAIN_BG,
-       EEPROM_RSSI_A,
-       EEPROM_RSSI_A2,
-       EEPROM_TXMIXER_GAIN_A,
-       EEPROM_EIRP_MAX_TX_POWER,
-       EEPROM_TXPOWER_DELTA,
-       EEPROM_TXPOWER_BG1,
-       EEPROM_TXPOWER_BG2,
-       EEPROM_TSSI_BOUND_BG1,
-       EEPROM_TSSI_BOUND_BG2,
-       EEPROM_TSSI_BOUND_BG3,
-       EEPROM_TSSI_BOUND_BG4,
-       EEPROM_TSSI_BOUND_BG5,
-       EEPROM_TXPOWER_A1,
-       EEPROM_TXPOWER_A2,
-       EEPROM_TSSI_BOUND_A1,
-       EEPROM_TSSI_BOUND_A2,
-       EEPROM_TSSI_BOUND_A3,
-       EEPROM_TSSI_BOUND_A4,
-       EEPROM_TSSI_BOUND_A5,
-       EEPROM_TXPOWER_BYRATE,
-       EEPROM_BBP_START,
-
-       /* IDs for extended EEPROM format used by three-chain devices */
-       EEPROM_EXT_LNA2,
-       EEPROM_EXT_TXPOWER_BG3,
-       EEPROM_EXT_TXPOWER_A3,
-
-       /* New values must be added before this */
-       EEPROM_WORD_COUNT
-};
-
-/*
- * EEPROM Version
- */
-#define EEPROM_VERSION_FAE             FIELD16(0x00ff)
-#define EEPROM_VERSION_VERSION         FIELD16(0xff00)
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM NIC Configuration 0
- * RXPATH: 1: 1R, 2: 2R, 3: 3R
- * TXPATH: 1: 1T, 2: 2T, 3: 3T
- * RF_TYPE: RFIC type
- */
-#define EEPROM_NIC_CONF0_RXPATH                FIELD16(0x000f)
-#define EEPROM_NIC_CONF0_TXPATH                FIELD16(0x00f0)
-#define EEPROM_NIC_CONF0_RF_TYPE       FIELD16(0x0f00)
-
-/*
- * EEPROM NIC Configuration 1
- * HW_RADIO: 0: disable, 1: enable
- * EXTERNAL_TX_ALC: 0: disable, 1: enable
- * EXTERNAL_LNA_2G: 0: disable, 1: enable
- * EXTERNAL_LNA_5G: 0: disable, 1: enable
- * CARDBUS_ACCEL: 0: enable, 1: disable
- * BW40M_SB_2G: 0: disable, 1: enable
- * BW40M_SB_5G: 0: disable, 1: enable
- * WPS_PBC: 0: disable, 1: enable
- * BW40M_2G: 0: enable, 1: disable
- * BW40M_5G: 0: enable, 1: disable
- * BROADBAND_EXT_LNA: 0: disable, 1: enable
- * ANT_DIVERSITY: 00: Disable, 01: Diversity,
- *                               10: Main antenna, 11: Aux antenna
- * INTERNAL_TX_ALC: 0: disable, 1: enable
- * BT_COEXIST: 0: disable, 1: enable
- * DAC_TEST: 0: disable, 1: enable
- */
-#define EEPROM_NIC_CONF1_HW_RADIO              FIELD16(0x0001)
-#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC       FIELD16(0x0002)
-#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G       FIELD16(0x0004)
-#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G       FIELD16(0x0008)
-#define EEPROM_NIC_CONF1_CARDBUS_ACCEL         FIELD16(0x0010)
-#define EEPROM_NIC_CONF1_BW40M_SB_2G           FIELD16(0x0020)
-#define EEPROM_NIC_CONF1_BW40M_SB_5G           FIELD16(0x0040)
-#define EEPROM_NIC_CONF1_WPS_PBC               FIELD16(0x0080)
-#define EEPROM_NIC_CONF1_BW40M_2G              FIELD16(0x0100)
-#define EEPROM_NIC_CONF1_BW40M_5G              FIELD16(0x0200)
-#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA     FIELD16(0x400)
-#define EEPROM_NIC_CONF1_ANT_DIVERSITY         FIELD16(0x1800)
-#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)
-
-/*
- * EEPROM frequency
- */
-#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
-#define EEPROM_FREQ_LED_MODE           FIELD16(0x7f00)
-#define EEPROM_FREQ_LED_POLARITY       FIELD16(0x1000)
-
-/*
- * EEPROM LED
- * POLARITY_RDY_G: Polarity RDY_G setting.
- * POLARITY_RDY_A: Polarity RDY_A setting.
- * POLARITY_ACT: Polarity ACT setting.
- * POLARITY_GPIO_0: Polarity GPIO0 setting.
- * POLARITY_GPIO_1: Polarity GPIO1 setting.
- * POLARITY_GPIO_2: Polarity GPIO2 setting.
- * POLARITY_GPIO_3: Polarity GPIO3 setting.
- * POLARITY_GPIO_4: Polarity GPIO4 setting.
- * LED_MODE: Led mode.
- */
-#define EEPROM_LED_POLARITY_RDY_BG     FIELD16(0x0001)
-#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
-#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
-#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
-#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
-#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
-#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
-#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
-#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
-
-/*
- * EEPROM NIC Configuration 2
- * RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
- * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
- * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved
- */
-#define EEPROM_NIC_CONF2_RX_STREAM     FIELD16(0x000f)
-#define EEPROM_NIC_CONF2_TX_STREAM     FIELD16(0x00f0)
-#define EEPROM_NIC_CONF2_CRYSTAL       FIELD16(0x0600)
-
-/*
- * EEPROM LNA
- */
-#define EEPROM_LNA_BG                  FIELD16(0x00ff)
-#define EEPROM_LNA_A0                  FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG offset
- */
-#define EEPROM_RSSI_BG_OFFSET0         FIELD16(0x00ff)
-#define EEPROM_RSSI_BG_OFFSET1         FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG2 offset
- */
-#define EEPROM_RSSI_BG2_OFFSET2                FIELD16(0x00ff)
-#define EEPROM_RSSI_BG2_LNA_A1         FIELD16(0xff00)
-
-/*
- * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2).
- */
-#define EEPROM_TXMIXER_GAIN_BG_VAL     FIELD16(0x0007)
-
-/*
- * EEPROM RSSI A offset
- */
-#define EEPROM_RSSI_A_OFFSET0          FIELD16(0x00ff)
-#define EEPROM_RSSI_A_OFFSET1          FIELD16(0xff00)
-
-/*
- * EEPROM RSSI A2 offset
- */
-#define EEPROM_RSSI_A2_OFFSET2         FIELD16(0x00ff)
-#define EEPROM_RSSI_A2_LNA_A2          FIELD16(0xff00)
-
-/*
- * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2).
- */
-#define EEPROM_TXMIXER_GAIN_A_VAL      FIELD16(0x0007)
-
-/*
- * EEPROM EIRP Maximum TX power values(unit: dbm)
- */
-#define EEPROM_EIRP_MAX_TX_POWER_2GHZ  FIELD16(0x00ff)
-#define EEPROM_EIRP_MAX_TX_POWER_5GHZ  FIELD16(0xff00)
-
-/*
- * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
- * This is delta in 40MHZ.
- * VALUE: Tx Power dalta value, MAX=4(unit: dbm)
- * TYPE: 1: Plus the delta value, 0: minus the delta value
- * ENABLE: enable tx power compensation for 40BW
- */
-#define EEPROM_TXPOWER_DELTA_VALUE_2G  FIELD16(0x003f)
-#define EEPROM_TXPOWER_DELTA_TYPE_2G   FIELD16(0x0040)
-#define EEPROM_TXPOWER_DELTA_ENABLE_2G FIELD16(0x0080)
-#define EEPROM_TXPOWER_DELTA_VALUE_5G  FIELD16(0x3f00)
-#define EEPROM_TXPOWER_DELTA_TYPE_5G   FIELD16(0x4000)
-#define EEPROM_TXPOWER_DELTA_ENABLE_5G FIELD16(0x8000)
-
-/*
- * EEPROM TXPOWER 802.11BG
- */
-#define EEPROM_TXPOWER_BG_SIZE         7
-#define EEPROM_TXPOWER_BG_1            FIELD16(0x00ff)
-#define EEPROM_TXPOWER_BG_2            FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11BG
- * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -4)
- * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -3)
- */
-#define EEPROM_TSSI_BOUND_BG1_MINUS4   FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_BG1_MINUS3   FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11BG
- * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -2)
- * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -1)
- */
-#define EEPROM_TSSI_BOUND_BG2_MINUS2   FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_BG2_MINUS1   FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11BG
- * REF: Reference TSSI value, no tx power changes needed
- * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 1)
- */
-#define EEPROM_TSSI_BOUND_BG3_REF      FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_BG3_PLUS1    FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11BG
- * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 2)
- * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 3)
- */
-#define EEPROM_TSSI_BOUND_BG4_PLUS2    FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_BG4_PLUS3    FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11BG
- * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 4)
- * AGC_STEP: Temperature compensation step.
- */
-#define EEPROM_TSSI_BOUND_BG5_PLUS4    FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER 802.11A
- */
-#define EEPROM_TXPOWER_A_SIZE          6
-#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
-#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
-
-/* EEPROM_TXPOWER_{A,G} fields for RT3593 */
-#define EEPROM_TXPOWER_ALC             FIELD8(0x1f)
-#define EEPROM_TXPOWER_FINE_CTRL       FIELD8(0xe0)
-
-/*
- * EEPROM temperature compensation boundaries 802.11A
- * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -4)
- * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -3)
- */
-#define EEPROM_TSSI_BOUND_A1_MINUS4    FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_A1_MINUS3    FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11A
- * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -2)
- * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
- *         reduced by (agc_step * -1)
- */
-#define EEPROM_TSSI_BOUND_A2_MINUS2    FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_A2_MINUS1    FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11A
- * REF: Reference TSSI value, no tx power changes needed
- * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 1)
- */
-#define EEPROM_TSSI_BOUND_A3_REF       FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_A3_PLUS1     FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11A
- * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 2)
- * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 3)
- */
-#define EEPROM_TSSI_BOUND_A4_PLUS2     FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_A4_PLUS3     FIELD16(0xff00)
-
-/*
- * EEPROM temperature compensation boundaries 802.11A
- * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
- *        increased by (agc_step * 4)
- * AGC_STEP: Temperature compensation step.
- */
-#define EEPROM_TSSI_BOUND_A5_PLUS4     FIELD16(0x00ff)
-#define EEPROM_TSSI_BOUND_A5_AGC_STEP  FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode
- */
-#define EEPROM_TXPOWER_BYRATE_SIZE     9
-
-#define EEPROM_TXPOWER_BYRATE_RATE0    FIELD16(0x000f)
-#define EEPROM_TXPOWER_BYRATE_RATE1    FIELD16(0x00f0)
-#define EEPROM_TXPOWER_BYRATE_RATE2    FIELD16(0x0f00)
-#define EEPROM_TXPOWER_BYRATE_RATE3    FIELD16(0xf000)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_SIZE                        16
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/* EEPROM_EXT_LNA2 */
-#define EEPROM_EXT_LNA2_A1             FIELD16(0x00ff)
-#define EEPROM_EXT_LNA2_A2             FIELD16(0xff00)
-
-/*
- * EEPROM IQ Calibration, unlike other entries those are byte addresses.
- */
-
-#define EEPROM_IQ_GAIN_CAL_TX0_2G                      0x130
-#define EEPROM_IQ_PHASE_CAL_TX0_2G                     0x131
-#define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G                        0x132
-#define EEPROM_IQ_GAIN_CAL_TX1_2G                      0x133
-#define EEPROM_IQ_PHASE_CAL_TX1_2G                     0x134
-#define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G                        0x135
-#define EEPROM_IQ_GAIN_CAL_RX0_2G                      0x136
-#define EEPROM_IQ_PHASE_CAL_RX0_2G                     0x137
-#define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G                        0x138
-#define EEPROM_IQ_GAIN_CAL_RX1_2G                      0x139
-#define EEPROM_IQ_PHASE_CAL_RX1_2G                     0x13A
-#define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G                        0x13B
-#define EEPROM_RF_IQ_COMPENSATION_CONTROL              0x13C
-#define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL    0x13D
-#define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G         0x144
-#define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G                0x145
-#define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G       0X146
-#define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G      0x147
-#define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G       0x148
-#define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G      0x149
-#define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G         0x14A
-#define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G                0x14B
-#define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G       0X14C
-#define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G      0x14D
-#define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G       0x14E
-#define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G      0x14F
-#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G   0x150
-#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G   0x151
-#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G 0x152
-#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G 0x153
-#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G 0x154
-#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G 0x155
-#define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G         0x156
-#define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G                0x157
-#define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G       0X158
-#define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G      0x159
-#define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G       0x15A
-#define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G      0x15B
-#define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G         0x15C
-#define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G                0x15D
-#define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G       0X15E
-#define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G      0x15F
-#define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G       0x160
-#define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G      0x161
-#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G   0x162
-#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G   0x163
-#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G 0x164
-#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G 0x165
-#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G 0x166
-#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G 0x167
-
-/*
- * MCU mailbox commands.
- * MCU_SLEEP - go to power-save mode.
- *             arg1: 1: save as much power as possible, 0: save less power.
- *             status: 1: success, 2: already asleep,
- *                     3: maybe MAC is busy so can't finish this task.
- * MCU_RADIO_OFF
- *             arg0: 0: do power-saving, NOT turn off radio.
- */
-#define MCU_SLEEP                      0x30
-#define MCU_WAKEUP                     0x31
-#define MCU_RADIO_OFF                  0x35
-#define MCU_CURRENT                    0x36
-#define MCU_LED                                0x50
-#define MCU_LED_STRENGTH               0x51
-#define MCU_LED_AG_CONF                        0x52
-#define MCU_LED_ACT_CONF               0x53
-#define MCU_LED_LED_POLARITY           0x54
-#define MCU_RADAR                      0x60
-#define MCU_BOOT_SIGNAL                        0x72
-#define MCU_ANT_SELECT                 0X73
-#define MCU_FREQ_OFFSET                        0x74
-#define MCU_BBP_SIGNAL                 0x80
-#define MCU_POWER_SAVE                 0x83
-#define MCU_BAND_SELECT                        0x91
-
-/*
- * MCU mailbox tokens
- */
-#define TOKEN_SLEEP                    1
-#define TOKEN_RADIO_OFF                        2
-#define TOKEN_WAKEUP                   3
-
-
-/*
- * DMA descriptor defines.
- */
-
-#define TXWI_DESC_SIZE_4WORDS          (4 * sizeof(__le32))
-#define TXWI_DESC_SIZE_5WORDS          (5 * sizeof(__le32))
-
-#define RXWI_DESC_SIZE_4WORDS          (4 * sizeof(__le32))
-#define RXWI_DESC_SIZE_5WORDS          (5 * sizeof(__le32))
-#define RXWI_DESC_SIZE_6WORDS          (6 * sizeof(__le32))
-
-/*
- * TX WI structure
- */
-
-/*
- * Word0
- * FRAG: 1 To inform TKIP engine this is a fragment.
- * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
- * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
- * BW: Channel bandwidth 0:20MHz, 1:40 MHz (for legacy rates this will
- *     duplicate the frame to both channels).
- * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
- * AMPDU: 1: this frame is eligible for AMPDU aggregation, the hw will
- *        aggregate consecutive frames with the same RA and QoS TID. If
- *        a frame A with the same RA and QoS TID but AMPDU=0 is queued
- *        directly after a frame B with AMPDU=1, frame A might still
- *        get aggregated into the AMPDU started by frame B. So, setting
- *        AMPDU to 0 does _not_ necessarily mean the frame is sent as
- *        MPDU, it can still end up in an AMPDU if the previous frame
- *        was tagged as AMPDU.
- */
-#define TXWI_W0_FRAG                   FIELD32(0x00000001)
-#define TXWI_W0_MIMO_PS                        FIELD32(0x00000002)
-#define TXWI_W0_CF_ACK                 FIELD32(0x00000004)
-#define TXWI_W0_TS                     FIELD32(0x00000008)
-#define TXWI_W0_AMPDU                  FIELD32(0x00000010)
-#define TXWI_W0_MPDU_DENSITY           FIELD32(0x000000e0)
-#define TXWI_W0_TX_OP                  FIELD32(0x00000300)
-#define TXWI_W0_MCS                    FIELD32(0x007f0000)
-#define TXWI_W0_BW                     FIELD32(0x00800000)
-#define TXWI_W0_SHORT_GI               FIELD32(0x01000000)
-#define TXWI_W0_STBC                   FIELD32(0x06000000)
-#define TXWI_W0_IFS                    FIELD32(0x08000000)
-#define TXWI_W0_PHYMODE                        FIELD32(0xc0000000)
-
-/*
- * Word1
- * ACK: 0: No Ack needed, 1: Ack needed
- * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number
- * BW_WIN_SIZE: BA windows size of the recipient
- * WIRELESS_CLI_ID: Client ID for WCID table access
- * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame
- * PACKETID: Will be latched into the TX_STA_FIFO register once the according
- *           frame was processed. If multiple frames are aggregated together
- *           (AMPDU==1) the reported tx status will always contain the packet
- *           id of the first frame. 0: Don't report tx status for this frame.
- * PACKETID_QUEUE: Part of PACKETID, This is the queue index (0-3)
- * PACKETID_ENTRY: Part of PACKETID, THis is the queue entry index (1-3)
- *                 This identification number is calculated by ((idx % 3) + 1).
- *                The (+1) is required to prevent PACKETID to become 0.
- */
-#define TXWI_W1_ACK                    FIELD32(0x00000001)
-#define TXWI_W1_NSEQ                   FIELD32(0x00000002)
-#define TXWI_W1_BW_WIN_SIZE            FIELD32(0x000000fc)
-#define TXWI_W1_WIRELESS_CLI_ID                FIELD32(0x0000ff00)
-#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT  FIELD32(0x0fff0000)
-#define TXWI_W1_PACKETID               FIELD32(0xf0000000)
-#define TXWI_W1_PACKETID_QUEUE         FIELD32(0x30000000)
-#define TXWI_W1_PACKETID_ENTRY         FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define TXWI_W2_IV                     FIELD32(0xffffffff)
-
-/*
- * Word3
- */
-#define TXWI_W3_EIV                    FIELD32(0xffffffff)
-
-/*
- * RX WI structure
- */
-
-/*
- * Word0
- */
-#define RXWI_W0_WIRELESS_CLI_ID                FIELD32(0x000000ff)
-#define RXWI_W0_KEY_INDEX              FIELD32(0x00000300)
-#define RXWI_W0_BSSID                  FIELD32(0x00001c00)
-#define RXWI_W0_UDF                    FIELD32(0x0000e000)
-#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT  FIELD32(0x0fff0000)
-#define RXWI_W0_TID                    FIELD32(0xf0000000)
-
-/*
- * Word1
- */
-#define RXWI_W1_FRAG                   FIELD32(0x0000000f)
-#define RXWI_W1_SEQUENCE               FIELD32(0x0000fff0)
-#define RXWI_W1_MCS                    FIELD32(0x007f0000)
-#define RXWI_W1_BW                     FIELD32(0x00800000)
-#define RXWI_W1_SHORT_GI               FIELD32(0x01000000)
-#define RXWI_W1_STBC                   FIELD32(0x06000000)
-#define RXWI_W1_PHYMODE                        FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define RXWI_W2_RSSI0                  FIELD32(0x000000ff)
-#define RXWI_W2_RSSI1                  FIELD32(0x0000ff00)
-#define RXWI_W2_RSSI2                  FIELD32(0x00ff0000)
-
-/*
- * Word3
- */
-#define RXWI_W3_SNR0                   FIELD32(0x000000ff)
-#define RXWI_W3_SNR1                   FIELD32(0x0000ff00)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_G_TXPOWER  0
-#define MIN_A_TXPOWER  -7
-#define MAX_G_TXPOWER  31
-#define MAX_A_TXPOWER  15
-#define DEFAULT_TXPOWER        5
-
-#define MIN_A_TXPOWER_3593     0
-#define MAX_A_TXPOWER_3593     31
-
-#define TXPOWER_G_FROM_DEV(__txpower) \
-       ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_A_FROM_DEV(__txpower) \
-       ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-/*
- *  Board's maximun TX power limitation
- */
-#define EIRP_MAX_TX_POWER_LIMIT        0x50
-
-/*
- * Number of TBTT intervals after which we have to adjust
- * the hw beacon timer.
- */
-#define BCN_TBTT_OFFSET 64
-
-/*
- * Hardware has 255 WCID table entries. First 32 entries are reserved for
- * shared keys. Since parts of the pairwise key table might be shared with
- * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
- */
-#define WCID_START     33
-#define WCID_END       222
-#define STA_IDS_SIZE   (WCID_END - WCID_START + 2)
-
-/*
- * RT2800 driver data structure
- */
-struct rt2800_drv_data {
-       u8 calibration_bw20;
-       u8 calibration_bw40;
-       u8 bbp25;
-       u8 bbp26;
-       u8 txmixer_gain_24g;
-       u8 txmixer_gain_5g;
-       unsigned int tbtt_tick;
-       DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
-};
-
-#endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
deleted file mode 100644 (file)
index 9733b31..0000000
+++ /dev/null
@@ -1,8021 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-       Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-
-       Based on the original rt2800pci.c and rt2800usb.c.
-         Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
-         Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-         Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
-         Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-         Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
-         Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-         <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800lib
-       Abstract: rt2800 generic device routines.
- */
-
-#include <linux/crc-ccitt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2800lib.h"
-#include "rt2800.h"
-
-/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2800_register_read and rt2800_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- * The _lock versions must be used if you already hold the csr_mutex
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RFCSR(__dev, __reg) \
-       rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
-#define WAIT_FOR_MCU(__dev, __reg) \
-       rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
-                           H2M_MAILBOX_CSR_OWNER, (__reg))
-
-static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
-{
-       /* check for rt2872 on SoC */
-       if (!rt2x00_is_soc(rt2x00dev) ||
-           !rt2x00_rt(rt2x00dev, RT2872))
-               return false;
-
-       /* we know for sure that these rf chipsets are used on rt305x boards */
-       if (rt2x00_rf(rt2x00dev, RF3020) ||
-           rt2x00_rf(rt2x00dev, RF3021) ||
-           rt2x00_rf(rt2x00dev, RF3022))
-               return true;
-
-       rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");
-       return false;
-}
-
-static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
-
-               rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
-               rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
-
-               rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
-
-               WAIT_FOR_BBP(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RFCSR becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
-               rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
-               rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
-               rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
-               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RFCSR becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
-               rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
-               rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
-               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
-
-               WAIT_FOR_RFCSR(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int word, const u32 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
-               rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
-               rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
-               rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
-
-               rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
-       [EEPROM_CHIP_ID]                = 0x0000,
-       [EEPROM_VERSION]                = 0x0001,
-       [EEPROM_MAC_ADDR_0]             = 0x0002,
-       [EEPROM_MAC_ADDR_1]             = 0x0003,
-       [EEPROM_MAC_ADDR_2]             = 0x0004,
-       [EEPROM_NIC_CONF0]              = 0x001a,
-       [EEPROM_NIC_CONF1]              = 0x001b,
-       [EEPROM_FREQ]                   = 0x001d,
-       [EEPROM_LED_AG_CONF]            = 0x001e,
-       [EEPROM_LED_ACT_CONF]           = 0x001f,
-       [EEPROM_LED_POLARITY]           = 0x0020,
-       [EEPROM_NIC_CONF2]              = 0x0021,
-       [EEPROM_LNA]                    = 0x0022,
-       [EEPROM_RSSI_BG]                = 0x0023,
-       [EEPROM_RSSI_BG2]               = 0x0024,
-       [EEPROM_TXMIXER_GAIN_BG]        = 0x0024, /* overlaps with RSSI_BG2 */
-       [EEPROM_RSSI_A]                 = 0x0025,
-       [EEPROM_RSSI_A2]                = 0x0026,
-       [EEPROM_TXMIXER_GAIN_A]         = 0x0026, /* overlaps with RSSI_A2 */
-       [EEPROM_EIRP_MAX_TX_POWER]      = 0x0027,
-       [EEPROM_TXPOWER_DELTA]          = 0x0028,
-       [EEPROM_TXPOWER_BG1]            = 0x0029,
-       [EEPROM_TXPOWER_BG2]            = 0x0030,
-       [EEPROM_TSSI_BOUND_BG1]         = 0x0037,
-       [EEPROM_TSSI_BOUND_BG2]         = 0x0038,
-       [EEPROM_TSSI_BOUND_BG3]         = 0x0039,
-       [EEPROM_TSSI_BOUND_BG4]         = 0x003a,
-       [EEPROM_TSSI_BOUND_BG5]         = 0x003b,
-       [EEPROM_TXPOWER_A1]             = 0x003c,
-       [EEPROM_TXPOWER_A2]             = 0x0053,
-       [EEPROM_TSSI_BOUND_A1]          = 0x006a,
-       [EEPROM_TSSI_BOUND_A2]          = 0x006b,
-       [EEPROM_TSSI_BOUND_A3]          = 0x006c,
-       [EEPROM_TSSI_BOUND_A4]          = 0x006d,
-       [EEPROM_TSSI_BOUND_A5]          = 0x006e,
-       [EEPROM_TXPOWER_BYRATE]         = 0x006f,
-       [EEPROM_BBP_START]              = 0x0078,
-};
-
-static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = {
-       [EEPROM_CHIP_ID]                = 0x0000,
-       [EEPROM_VERSION]                = 0x0001,
-       [EEPROM_MAC_ADDR_0]             = 0x0002,
-       [EEPROM_MAC_ADDR_1]             = 0x0003,
-       [EEPROM_MAC_ADDR_2]             = 0x0004,
-       [EEPROM_NIC_CONF0]              = 0x001a,
-       [EEPROM_NIC_CONF1]              = 0x001b,
-       [EEPROM_NIC_CONF2]              = 0x001c,
-       [EEPROM_EIRP_MAX_TX_POWER]      = 0x0020,
-       [EEPROM_FREQ]                   = 0x0022,
-       [EEPROM_LED_AG_CONF]            = 0x0023,
-       [EEPROM_LED_ACT_CONF]           = 0x0024,
-       [EEPROM_LED_POLARITY]           = 0x0025,
-       [EEPROM_LNA]                    = 0x0026,
-       [EEPROM_EXT_LNA2]               = 0x0027,
-       [EEPROM_RSSI_BG]                = 0x0028,
-       [EEPROM_RSSI_BG2]               = 0x0029,
-       [EEPROM_RSSI_A]                 = 0x002a,
-       [EEPROM_RSSI_A2]                = 0x002b,
-       [EEPROM_TXPOWER_BG1]            = 0x0030,
-       [EEPROM_TXPOWER_BG2]            = 0x0037,
-       [EEPROM_EXT_TXPOWER_BG3]        = 0x003e,
-       [EEPROM_TSSI_BOUND_BG1]         = 0x0045,
-       [EEPROM_TSSI_BOUND_BG2]         = 0x0046,
-       [EEPROM_TSSI_BOUND_BG3]         = 0x0047,
-       [EEPROM_TSSI_BOUND_BG4]         = 0x0048,
-       [EEPROM_TSSI_BOUND_BG5]         = 0x0049,
-       [EEPROM_TXPOWER_A1]             = 0x004b,
-       [EEPROM_TXPOWER_A2]             = 0x0065,
-       [EEPROM_EXT_TXPOWER_A3]         = 0x007f,
-       [EEPROM_TSSI_BOUND_A1]          = 0x009a,
-       [EEPROM_TSSI_BOUND_A2]          = 0x009b,
-       [EEPROM_TSSI_BOUND_A3]          = 0x009c,
-       [EEPROM_TSSI_BOUND_A4]          = 0x009d,
-       [EEPROM_TSSI_BOUND_A5]          = 0x009e,
-       [EEPROM_TXPOWER_BYRATE]         = 0x00a0,
-};
-
-static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev,
-                                            const enum rt2800_eeprom_word word)
-{
-       const unsigned int *map;
-       unsigned int index;
-
-       if (WARN_ONCE(word >= EEPROM_WORD_COUNT,
-                     "%s: invalid EEPROM word %d\n",
-                     wiphy_name(rt2x00dev->hw->wiphy), word))
-               return 0;
-
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               map = rt2800_eeprom_map_ext;
-       else
-               map = rt2800_eeprom_map;
-
-       index = map[word];
-
-       /* Index 0 is valid only for EEPROM_CHIP_ID.
-        * Otherwise it means that the offset of the
-        * given word is not initialized in the map,
-        * or that the field is not usable on the
-        * actual chipset.
-        */
-       WARN_ONCE(word != EEPROM_CHIP_ID && index == 0,
-                 "%s: invalid access of EEPROM word %d\n",
-                 wiphy_name(rt2x00dev->hw->wiphy), word);
-
-       return index;
-}
-
-static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev,
-                               const enum rt2800_eeprom_word word)
-{
-       unsigned int index;
-
-       index = rt2800_eeprom_word_index(rt2x00dev, word);
-       return rt2x00_eeprom_addr(rt2x00dev, index);
-}
-
-static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev,
-                              const enum rt2800_eeprom_word word, u16 *data)
-{
-       unsigned int index;
-
-       index = rt2800_eeprom_word_index(rt2x00dev, word);
-       rt2x00_eeprom_read(rt2x00dev, index, data);
-}
-
-static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev,
-                               const enum rt2800_eeprom_word word, u16 data)
-{
-       unsigned int index;
-
-       index = rt2800_eeprom_word_index(rt2x00dev, word);
-       rt2x00_eeprom_write(rt2x00dev, index, data);
-}
-
-static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev,
-                                         const enum rt2800_eeprom_word array,
-                                         unsigned int offset,
-                                         u16 *data)
-{
-       unsigned int index;
-
-       index = rt2800_eeprom_word_index(rt2x00dev, array);
-       rt2x00_eeprom_read(rt2x00dev, index + offset, data);
-}
-
-static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       int i, count;
-
-       rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
-       if (rt2x00_get_field32(reg, WLAN_EN))
-               return 0;
-
-       rt2x00_set_field32(&reg, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
-       rt2x00_set_field32(&reg, FRC_WL_ANT_SET, 1);
-       rt2x00_set_field32(&reg, WLAN_CLK_EN, 0);
-       rt2x00_set_field32(&reg, WLAN_EN, 1);
-       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
-
-       udelay(REGISTER_BUSY_DELAY);
-
-       count = 0;
-       do {
-               /*
-                * Check PLL_LD & XTAL_RDY.
-                */
-               for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-                       rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
-                       if (rt2x00_get_field32(reg, PLL_LD) &&
-                           rt2x00_get_field32(reg, XTAL_RDY))
-                               break;
-                       udelay(REGISTER_BUSY_DELAY);
-               }
-
-               if (i >= REGISTER_BUSY_COUNT) {
-
-                       if (count >= 10)
-                               return -EIO;
-
-                       rt2800_register_write(rt2x00dev, 0x58, 0x018);
-                       udelay(REGISTER_BUSY_DELAY);
-                       rt2800_register_write(rt2x00dev, 0x58, 0x418);
-                       udelay(REGISTER_BUSY_DELAY);
-                       rt2800_register_write(rt2x00dev, 0x58, 0x618);
-                       udelay(REGISTER_BUSY_DELAY);
-                       count++;
-               } else {
-                       count = 0;
-               }
-
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
-               rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 0);
-               rt2x00_set_field32(&reg, WLAN_CLK_EN, 1);
-               rt2x00_set_field32(&reg, WLAN_RESET, 1);
-               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
-               udelay(10);
-               rt2x00_set_field32(&reg, WLAN_RESET, 0);
-               rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
-               udelay(10);
-               rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff);
-       } while (count != 0);
-
-       return 0;
-}
-
-void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
-                       const u8 command, const u8 token,
-                       const u8 arg0, const u8 arg1)
-{
-       u32 reg;
-
-       /*
-        * SOC devices don't support MCU requests.
-        */
-       if (rt2x00_is_soc(rt2x00dev))
-               return;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the MCU becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
-               rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
-
-               reg = 0;
-               rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
-               rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-EXPORT_SYMBOL_GPL(rt2800_mcu_request);
-
-int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i = 0;
-       u32 reg;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-               if (reg && reg != ~0)
-                       return 0;
-               msleep(1);
-       }
-
-       rt2x00_err(rt2x00dev, "Unstable hardware\n");
-       return -EBUSY;
-}
-EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
-
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u32 reg;
-
-       /*
-        * Some devices are really slow to respond here. Wait a whole second
-        * before timing out.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-               if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
-                   !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
-                       return 0;
-
-               msleep(10);
-       }
-
-       rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);
-       return -EACCES;
-}
-EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
-
-void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-}
-EXPORT_SYMBOL_GPL(rt2800_disable_wpdma);
-
-void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
-                              unsigned short *txwi_size,
-                              unsigned short *rxwi_size)
-{
-       switch (rt2x00dev->chip.rt) {
-       case RT3593:
-               *txwi_size = TXWI_DESC_SIZE_4WORDS;
-               *rxwi_size = RXWI_DESC_SIZE_5WORDS;
-               break;
-
-       case RT5592:
-               *txwi_size = TXWI_DESC_SIZE_5WORDS;
-               *rxwi_size = RXWI_DESC_SIZE_6WORDS;
-               break;
-
-       default:
-               *txwi_size = TXWI_DESC_SIZE_4WORDS;
-               *rxwi_size = RXWI_DESC_SIZE_4WORDS;
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size);
-
-static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)
-{
-       u16 fw_crc;
-       u16 crc;
-
-       /*
-        * The last 2 bytes in the firmware array are the crc checksum itself,
-        * this means that we should never pass those 2 bytes to the crc
-        * algorithm.
-        */
-       fw_crc = (data[len - 2] << 8 | data[len - 1]);
-
-       /*
-        * Use the crc ccitt algorithm.
-        * This will return the same value as the legacy driver which
-        * used bit ordering reversion on the both the firmware bytes
-        * before input input as well as on the final output.
-        * Obviously using crc ccitt directly is much more efficient.
-        */
-       crc = crc_ccitt(~0, data, len - 2);
-
-       /*
-        * There is a small difference between the crc-itu-t + bitrev and
-        * the crc-ccitt crc calculation. In the latter method the 2 bytes
-        * will be swapped, use swab16 to convert the crc to the correct
-        * value.
-        */
-       crc = swab16(crc);
-
-       return fw_crc == crc;
-}
-
-int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
-                         const u8 *data, const size_t len)
-{
-       size_t offset = 0;
-       size_t fw_len;
-       bool multiple;
-
-       /*
-        * PCI(e) & SOC devices require firmware with a length
-        * of 8kb. USB devices require firmware files with a length
-        * of 4kb. Certain USB chipsets however require different firmware,
-        * which Ralink only provides attached to the original firmware
-        * file. Thus for USB devices, firmware files have a length
-        * which is a multiple of 4kb. The firmware for rt3290 chip also
-        * have a length which is a multiple of 4kb.
-        */
-       if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))
-               fw_len = 4096;
-       else
-               fw_len = 8192;
-
-       multiple = true;
-       /*
-        * Validate the firmware length
-        */
-       if (len != fw_len && (!multiple || (len % fw_len) != 0))
-               return FW_BAD_LENGTH;
-
-       /*
-        * Check if the chipset requires one of the upper parts
-        * of the firmware.
-        */
-       if (rt2x00_is_usb(rt2x00dev) &&
-           !rt2x00_rt(rt2x00dev, RT2860) &&
-           !rt2x00_rt(rt2x00dev, RT2872) &&
-           !rt2x00_rt(rt2x00dev, RT3070) &&
-           ((len / fw_len) == 1))
-               return FW_BAD_VERSION;
-
-       /*
-        * 8kb firmware files must be checked as if it were
-        * 2 separate firmware files.
-        */
-       while (offset < len) {
-               if (!rt2800_check_firmware_crc(data + offset, fw_len))
-                       return FW_BAD_CRC;
-
-               offset += fw_len;
-       }
-
-       return FW_OK;
-}
-EXPORT_SYMBOL_GPL(rt2800_check_firmware);
-
-int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
-                        const u8 *data, const size_t len)
-{
-       unsigned int i;
-       u32 reg;
-       int retval;
-
-       if (rt2x00_rt(rt2x00dev, RT3290)) {
-               retval = rt2800_enable_wlan_rt3290(rt2x00dev);
-               if (retval)
-                       return -EBUSY;
-       }
-
-       /*
-        * If driver doesn't wake up firmware here,
-        * rt2800_load_firmware will hang forever when interface is up again.
-        */
-       rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
-
-       /*
-        * Wait for stable hardware.
-        */
-       if (rt2800_wait_csr_ready(rt2x00dev))
-               return -EBUSY;
-
-       if (rt2x00_is_pci(rt2x00dev)) {
-               if (rt2x00_rt(rt2x00dev, RT3290) ||
-                   rt2x00_rt(rt2x00dev, RT3572) ||
-                   rt2x00_rt(rt2x00dev, RT5390) ||
-                   rt2x00_rt(rt2x00dev, RT5392)) {
-                       rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
-                       rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
-                       rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
-                       rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
-               }
-               rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
-       }
-
-       rt2800_disable_wpdma(rt2x00dev);
-
-       /*
-        * Write firmware to the device.
-        */
-       rt2800_drv_write_firmware(rt2x00dev, data, len);
-
-       /*
-        * Wait for device to stabilize.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-               if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
-                       break;
-               msleep(1);
-       }
-
-       if (i == REGISTER_BUSY_COUNT) {
-               rt2x00_err(rt2x00dev, "PBF system register not ready\n");
-               return -EBUSY;
-       }
-
-       /*
-        * Disable DMA, will be reenabled later when enabling
-        * the radio.
-        */
-       rt2800_disable_wpdma(rt2x00dev);
-
-       /*
-        * Initialize firmware.
-        */
-       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-       if (rt2x00_is_usb(rt2x00dev)) {
-               rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
-               rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-       }
-       msleep(1);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_load_firmware);
-
-void rt2800_write_tx_data(struct queue_entry *entry,
-                         struct txentry_desc *txdesc)
-{
-       __le32 *txwi = rt2800_drv_get_txwi(entry);
-       u32 word;
-       int i;
-
-       /*
-        * Initialize TX Info descriptor
-        */
-       rt2x00_desc_read(txwi, 0, &word);
-       rt2x00_set_field32(&word, TXWI_W0_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_MIMO_PS,
-                          test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
-       rt2x00_set_field32(&word, TXWI_W0_TS,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_AMPDU,
-                          test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,
-                          txdesc->u.ht.mpdu_density);
-       rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);
-       rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);
-       rt2x00_set_field32(&word, TXWI_W0_BW,
-                          test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
-                          test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);
-       rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
-       rt2x00_desc_write(txwi, 0, word);
-
-       rt2x00_desc_read(txwi, 1, &word);
-       rt2x00_set_field32(&word, TXWI_W1_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W1_NSEQ,
-                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
-       rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
-       rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
-                          test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
-                          txdesc->key_idx : txdesc->u.ht.wcid);
-       rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
-                          txdesc->length);
-       rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
-       rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
-       rt2x00_desc_write(txwi, 1, word);
-
-       /*
-        * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert
-        * the IV from the IVEIV register when TXD_W3_WIV is set to 0.
-        * When TXD_W3_WIV is set to 1 it will use the IV data
-        * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
-        * crypto entry in the registers should be used to encrypt the frame.
-        *
-        * Nulify all remaining words as well, we don't know how to program them.
-        */
-       for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++)
-               _rt2x00_desc_write(txwi, i, 0);
-}
-EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
-
-static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)
-{
-       s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0);
-       s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1);
-       s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);
-       u16 eeprom;
-       u8 offset0;
-       u8 offset1;
-       u8 offset2;
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);
-               offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);
-               offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
-               offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);
-       } else {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);
-               offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);
-               offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
-               offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);
-       }
-
-       /*
-        * Convert the value from the descriptor into the RSSI value
-        * If the value in the descriptor is 0, it is considered invalid
-        * and the default (extremely low) rssi value is assumed
-        */
-       rssi0 = (rssi0) ? (-12 - offset0 - rt2x00dev->lna_gain - rssi0) : -128;
-       rssi1 = (rssi1) ? (-12 - offset1 - rt2x00dev->lna_gain - rssi1) : -128;
-       rssi2 = (rssi2) ? (-12 - offset2 - rt2x00dev->lna_gain - rssi2) : -128;
-
-       /*
-        * mac80211 only accepts a single RSSI value. Calculating the
-        * average doesn't deliver a fair answer either since -60:-60 would
-        * be considered equally good as -50:-70 while the second is the one
-        * which gives less energy...
-        */
-       rssi0 = max(rssi0, rssi1);
-       return (int)max(rssi0, rssi2);
-}
-
-void rt2800_process_rxwi(struct queue_entry *entry,
-                        struct rxdone_entry_desc *rxdesc)
-{
-       __le32 *rxwi = (__le32 *) entry->skb->data;
-       u32 word;
-
-       rt2x00_desc_read(rxwi, 0, &word);
-
-       rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);
-       rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
-
-       rt2x00_desc_read(rxwi, 1, &word);
-
-       if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))
-               rxdesc->flags |= RX_FLAG_SHORT_GI;
-
-       if (rt2x00_get_field32(word, RXWI_W1_BW))
-               rxdesc->flags |= RX_FLAG_40MHZ;
-
-       /*
-        * Detect RX rate, always use MCS as signal type.
-        */
-       rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
-       rxdesc->signal = rt2x00_get_field32(word, RXWI_W1_MCS);
-       rxdesc->rate_mode = rt2x00_get_field32(word, RXWI_W1_PHYMODE);
-
-       /*
-        * Mask of 0x8 bit to remove the short preamble flag.
-        */
-       if (rxdesc->rate_mode == RATE_MODE_CCK)
-               rxdesc->signal &= ~0x8;
-
-       rt2x00_desc_read(rxwi, 2, &word);
-
-       /*
-        * Convert descriptor AGC value to RSSI value.
-        */
-       rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
-       /*
-        * Remove RXWI descriptor from start of the buffer.
-        */
-       skb_pull(entry->skb, entry->queue->winfo_size);
-}
-EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
-
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct txdone_entry_desc txdesc;
-       u32 word;
-       u16 mcs, real_mcs;
-       int aggr, ampdu;
-
-       /*
-        * Obtain the status about this packet.
-        */
-       txdesc.flags = 0;
-       rt2x00_desc_read(txwi, 0, &word);
-
-       mcs = rt2x00_get_field32(word, TXWI_W0_MCS);
-       ampdu = rt2x00_get_field32(word, TXWI_W0_AMPDU);
-
-       real_mcs = rt2x00_get_field32(status, TX_STA_FIFO_MCS);
-       aggr = rt2x00_get_field32(status, TX_STA_FIFO_TX_AGGRE);
-
-       /*
-        * If a frame was meant to be sent as a single non-aggregated MPDU
-        * but ended up in an aggregate the used tx rate doesn't correlate
-        * with the one specified in the TXWI as the whole aggregate is sent
-        * with the same rate.
-        *
-        * For example: two frames are sent to rt2x00, the first one sets
-        * AMPDU=1 and requests MCS7 whereas the second frame sets AMDPU=0
-        * and requests MCS15. If the hw aggregates both frames into one
-        * AMDPU the tx status for both frames will contain MCS7 although
-        * the frame was sent successfully.
-        *
-        * Hence, replace the requested rate with the real tx rate to not
-        * confuse the rate control algortihm by providing clearly wrong
-        * data.
-        */
-       if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
-               skbdesc->tx_rate_idx = real_mcs;
-               mcs = real_mcs;
-       }
-
-       if (aggr == 1 || ampdu == 1)
-               __set_bit(TXDONE_AMPDU, &txdesc.flags);
-
-       /*
-        * Ralink has a retry mechanism using a global fallback
-        * table. We setup this fallback table to try the immediate
-        * lower rate for all rates. In the TX_STA_FIFO, the MCS field
-        * always contains the MCS used for the last transmission, be
-        * it successful or not.
-        */
-       if (rt2x00_get_field32(status, TX_STA_FIFO_TX_SUCCESS)) {
-               /*
-                * Transmission succeeded. The number of retries is
-                * mcs - real_mcs
-                */
-               __set_bit(TXDONE_SUCCESS, &txdesc.flags);
-               txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0);
-       } else {
-               /*
-                * Transmission failed. The number of retries is
-                * always 7 in this case (for a total number of 8
-                * frames sent).
-                */
-               __set_bit(TXDONE_FAILURE, &txdesc.flags);
-               txdesc.retry = rt2x00dev->long_retry;
-       }
-
-       /*
-        * the frame was retried at least once
-        * -> hw used fallback rates
-        */
-       if (txdesc.retry)
-               __set_bit(TXDONE_FALLBACK, &txdesc.flags);
-
-       rt2x00lib_txdone(entry, &txdesc);
-}
-EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
-
-static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
-                                         unsigned int index)
-{
-       return HW_BEACON_BASE(index);
-}
-
-static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev,
-                                         unsigned int index)
-{
-       return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
-}
-
-static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue = rt2x00dev->bcn;
-       struct queue_entry *entry;
-       int i, bcn_num = 0;
-       u64 off, reg = 0;
-       u32 bssid_dw1;
-
-       /*
-        * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
-        */
-       for (i = 0; i < queue->limit; i++) {
-               entry = &queue->entries[i];
-               if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
-                       continue;
-               off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
-               reg |= off << (8 * bcn_num);
-               bcn_num++;
-       }
-
-       WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
-
-       rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
-       rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
-
-       /*
-        * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
-        */
-       rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
-       rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
-                          bcn_num > 0 ? bcn_num - 1 : 0);
-       rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
-}
-
-void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       unsigned int beacon_base;
-       unsigned int padding_len;
-       u32 orig_reg, reg;
-       const int txwi_desc_size = entry->queue->winfo_size;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-       orig_reg = reg;
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-       /*
-        * Add space for the TXWI in front of the skb.
-        */
-       memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
-       skbdesc->desc = entry->skb->data;
-       skbdesc->desc_len = txwi_desc_size;
-
-       /*
-        * Add the TXWI for the beacon to the skb.
-        */
-       rt2800_write_tx_data(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
-       /*
-        * Write entire beacon with TXWI and padding to register.
-        */
-       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-       if (padding_len && skb_pad(entry->skb, padding_len)) {
-               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
-               /* skb freed by skb_pad() on failure */
-               entry->skb = NULL;
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
-               return;
-       }
-
-       beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
-
-       rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
-                                  entry->skb->len + padding_len);
-       __set_bit(ENTRY_BCN_ENABLED, &entry->flags);
-
-       /*
-        * Change global beacons settings.
-        */
-       rt2800_update_beacons_setup(rt2x00dev);
-
-       /*
-        * Restore beaconing state.
-        */
-       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
-
-       /*
-        * Clean up beacon skb.
-        */
-       dev_kfree_skb_any(entry->skb);
-       entry->skb = NULL;
-}
-EXPORT_SYMBOL_GPL(rt2800_write_beacon);
-
-static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
-                                               unsigned int index)
-{
-       int i;
-       const int txwi_desc_size = rt2x00dev->bcn->winfo_size;
-       unsigned int beacon_base;
-
-       beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
-
-       /*
-        * For the Beacon base registers we only need to clear
-        * the whole TXWI which (when set to 0) will invalidate
-        * the entire beacon.
-        */
-       for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
-               rt2800_register_write(rt2x00dev, beacon_base + i, 0);
-}
-
-void rt2800_clear_beacon(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       u32 orig_reg, reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg);
-       reg = orig_reg;
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-       /*
-        * Clear beacon.
-        */
-       rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
-       __clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
-
-       /*
-        * Change global beacons settings.
-        */
-       rt2800_update_beacons_setup(rt2x00dev);
-       /*
-        * Restore beaconing state.
-        */
-       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
-}
-EXPORT_SYMBOL_GPL(rt2800_clear_beacon);
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-const struct rt2x00debug rt2800_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = rt2800_register_read,
-               .write          = rt2800_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = CSR_REG_SIZE / sizeof(u32),
-       },
-       .eeprom = {
-               /* NOTE: The local EEPROM access functions can't
-                * be used here, use the generic versions instead.
-                */
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt2800_bbp_read,
-               .write          = rt2800_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt2800_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-       .rfcsr  = {
-               .read           = rt2800_rfcsr_read,
-               .write          = rt2800_rfcsr_write,
-               .word_base      = RFCSR_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = RFCSR_SIZE / sizeof(u8),
-       },
-};
-EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       if (rt2x00_rt(rt2x00dev, RT3290)) {
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
-               return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
-       } else {
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-               return rt2x00_get_field32(reg, GPIO_CTRL_VAL2);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2800_brightness_set(struct led_classdev *led_cdev,
-                                 enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       unsigned int bg_mode =
-           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-       unsigned int polarity =
-               rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
-                                  EEPROM_FREQ_LED_POLARITY);
-       unsigned int ledmode =
-               rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
-                                  EEPROM_FREQ_LED_MODE);
-       u32 reg;
-
-       /* Check for SoC (SOC devices don't support MCU requests) */
-       if (rt2x00_is_soc(led->rt2x00dev)) {
-               rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
-
-               /* Set LED Polarity */
-               rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
-
-               /* Set LED Mode */
-               if (led->type == LED_TYPE_RADIO) {
-                       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
-                                          enabled ? 3 : 0);
-               } else if (led->type == LED_TYPE_ASSOC) {
-                       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
-                                          enabled ? 3 : 0);
-               } else if (led->type == LED_TYPE_QUALITY) {
-                       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
-                                          enabled ? 3 : 0);
-               }
-
-               rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
-
-       } else {
-               if (led->type == LED_TYPE_RADIO) {
-                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-                                             enabled ? 0x20 : 0);
-               } else if (led->type == LED_TYPE_ASSOC) {
-                       rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-                                             enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
-               } else if (led->type == LED_TYPE_QUALITY) {
-                       /*
-                        * The brightness is divided into 6 levels (0 - 5),
-                        * The specs tell us the following levels:
-                        *      0, 1 ,3, 7, 15, 31
-                        * to determine the level in a simple way we can simply
-                        * work with bitshifting:
-                        *      (1 << level) - 1
-                        */
-                       rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-                                             (1 << brightness / (LED_FULL / 6)) - 1,
-                                             polarity);
-               }
-       }
-}
-
-static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
-                    struct rt2x00_led *led, enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt2800_brightness_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev,
-                              const u8 *address,
-                              int wcid)
-{
-       struct mac_wcid_entry wcid_entry;
-       u32 offset;
-
-       offset = MAC_WCID_ENTRY(wcid);
-
-       memset(&wcid_entry, 0xff, sizeof(wcid_entry));
-       if (address)
-               memcpy(wcid_entry.mac, address, ETH_ALEN);
-
-       rt2800_register_multiwrite(rt2x00dev, offset,
-                                     &wcid_entry, sizeof(wcid_entry));
-}
-
-static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
-{
-       u32 offset;
-       offset = MAC_WCID_ATTR_ENTRY(wcid);
-       rt2800_register_write(rt2x00dev, offset, 0);
-}
-
-static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
-                                          int wcid, u32 bssidx)
-{
-       u32 offset = MAC_WCID_ATTR_ENTRY(wcid);
-       u32 reg;
-
-       /*
-        * 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_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
-       rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
-                          (bssidx & 0x8) >> 3);
-       rt2800_register_write(rt2x00dev, offset, reg);
-}
-
-static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
-                                          struct rt2x00lib_crypto *crypto,
-                                          struct ieee80211_key_conf *key)
-{
-       struct mac_iveiv_entry iveiv_entry;
-       u32 offset;
-       u32 reg;
-
-       offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
-
-       if (crypto->cmd == SET_KEY) {
-               rt2800_register_read(rt2x00dev, offset, &reg);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
-                                  !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
-               /*
-                * Both the cipher as the BSS Idx numbers are split in a main
-                * value of 3 bits, and a extended field for adding one additional
-                * bit to the value.
-                */
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
-                                  (crypto->cipher & 0x7));
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT,
-                                  (crypto->cipher & 0x8) >> 3);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
-               rt2800_register_write(rt2x00dev, offset, reg);
-       } else {
-               /* Delete the cipher without touching the bssidx */
-               rt2800_register_read(rt2x00dev, offset, &reg);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB, 0);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER, 0);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0);
-               rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
-               rt2800_register_write(rt2x00dev, offset, reg);
-       }
-
-       offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
-
-       memset(&iveiv_entry, 0, sizeof(iveiv_entry));
-       if ((crypto->cipher == CIPHER_TKIP) ||
-           (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
-           (crypto->cipher == CIPHER_AES))
-               iveiv_entry.iv[3] |= 0x20;
-       iveiv_entry.iv[3] |= key->keyidx << 6;
-       rt2800_register_multiwrite(rt2x00dev, offset,
-                                     &iveiv_entry, sizeof(iveiv_entry));
-}
-
-int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_crypto *crypto,
-                            struct ieee80211_key_conf *key)
-{
-       struct hw_key_entry key_entry;
-       struct rt2x00_field32 field;
-       u32 offset;
-       u32 reg;
-
-       if (crypto->cmd == SET_KEY) {
-               key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
-
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               offset = SHARED_KEY_ENTRY(key->hw_key_idx);
-               rt2800_register_multiwrite(rt2x00dev, offset,
-                                             &key_entry, sizeof(key_entry));
-       }
-
-       /*
-        * The cipher types are stored over multiple registers
-        * starting with SHARED_KEY_MODE_BASE each word will have
-        * 32 bits and contains the cipher types for 2 bssidx each.
-        * Using the correct defines correctly will cause overhead,
-        * so just calculate the correct offset.
-        */
-       field.bit_offset = 4 * (key->hw_key_idx % 8);
-       field.bit_mask = 0x7 << field.bit_offset;
-
-       offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
-
-       rt2800_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, field,
-                          (crypto->cmd == SET_KEY) * crypto->cipher);
-       rt2800_register_write(rt2x00dev, offset, reg);
-
-       /*
-        * Update WCID information
-        */
-       rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx);
-       rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx,
-                                      crypto->bssidx);
-       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
-
-int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00lib_crypto *crypto,
-                              struct ieee80211_key_conf *key)
-{
-       struct hw_key_entry key_entry;
-       u32 offset;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * Allow key configuration only for STAs that are
-                * known by the hw.
-                */
-               if (crypto->wcid > WCID_END)
-                       return -ENOSPC;
-               key->hw_key_idx = crypto->wcid;
-
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
-               rt2800_register_multiwrite(rt2x00dev, offset,
-                                             &key_entry, sizeof(key_entry));
-       }
-
-       /*
-        * Update WCID information
-        */
-       rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
-
-int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
-                  struct ieee80211_sta *sta)
-{
-       int wcid;
-       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-
-       /*
-        * Search for the first free WCID entry and return the corresponding
-        * index.
-        */
-       wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START;
-
-       /*
-        * Store selected wcid even if it is invalid so that we can
-        * later decide if the STA is uploaded into the hw.
-        */
-       sta_priv->wcid = wcid;
-
-       /*
-        * No space left in the device, however, we can still communicate
-        * with the STA -> No error.
-        */
-       if (wcid > WCID_END)
-               return 0;
-
-       __set_bit(wcid - WCID_START, drv_data->sta_ids);
-
-       /*
-        * Clean up WCID attributes and write STA address to the device.
-        */
-       rt2800_delete_wcid_attr(rt2x00dev, wcid);
-       rt2800_config_wcid(rt2x00dev, sta->addr, wcid);
-       rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid,
-                                      rt2x00lib_get_bssidx(rt2x00dev, vif));
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_sta_add);
-
-int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-
-       if (wcid > WCID_END)
-               return 0;
-       /*
-        * Remove WCID entry, no need to clean the attributes as they will
-        * get renewed when the WCID is reused.
-        */
-       rt2800_config_wcid(rt2x00dev, NULL, wcid);
-       __clear_bit(wcid - WCID_START, drv_data->sta_ids);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_sta_remove);
-
-void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
-                         const unsigned int filter_flags)
-{
-       u32 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * and broadcast frames will always be accepted since
-        * there is no filter for it at this time.
-        */
-       rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
-                          !(filter_flags & FIF_ALLMULTI));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
-                          !(filter_flags & FIF_PSPOLL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 0);
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
-                          !(filter_flags & FIF_CONTROL));
-       rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg);
-}
-EXPORT_SYMBOL_GPL(rt2800_config_filter);
-
-void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
-                       struct rt2x00intf_conf *conf, const unsigned int flags)
-{
-       u32 reg;
-       bool update_bssid = false;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable synchronisation.
-                */
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-               if (conf->sync == TSF_SYNC_AP_NONE) {
-                       /*
-                        * Tune beacon queue transmit parameters for AP mode
-                        */
-                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
-                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
-               } else {
-                       rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
-                       rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
-                       rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
-               }
-       }
-
-       if (flags & CONFIG_UPDATE_MAC) {
-               if (flags & CONFIG_UPDATE_TYPE &&
-                   conf->sync == TSF_SYNC_AP_NONE) {
-                       /*
-                        * The BSSID register has to be set to our own mac
-                        * address in AP mode.
-                        */
-                       memcpy(conf->bssid, conf->mac, sizeof(conf->mac));
-                       update_bssid = true;
-               }
-
-               if (!is_zero_ether_addr((const u8 *)conf->mac)) {
-                       reg = le32_to_cpu(conf->mac[1]);
-                       rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
-                       conf->mac[1] = cpu_to_le32(reg);
-               }
-
-               rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
-                                             conf->mac, sizeof(conf->mac));
-       }
-
-       if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {
-               if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
-                       reg = le32_to_cpu(conf->bssid[1]);
-                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
-                       rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
-                       conf->bssid[1] = cpu_to_le32(reg);
-               }
-
-               rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
-                                             conf->bssid, sizeof(conf->bssid));
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800_config_intf);
-
-static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_erp *erp)
-{
-       bool any_sta_nongf = !!(erp->ht_opmode &
-                               IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-       u8 protection = erp->ht_opmode & IEEE80211_HT_OP_MODE_PROTECTION;
-       u8 mm20_mode, mm40_mode, gf20_mode, gf40_mode;
-       u16 mm20_rate, mm40_rate, gf20_rate, gf40_rate;
-       u32 reg;
-
-       /* default protection rate for HT20: OFDM 24M */
-       mm20_rate = gf20_rate = 0x4004;
-
-       /* default protection rate for HT40: duplicate OFDM 24M */
-       mm40_rate = gf40_rate = 0x4084;
-
-       switch (protection) {
-       case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
-               /*
-                * All STAs in this BSS are HT20/40 but there might be
-                * STAs not supporting greenfield mode.
-                * => Disable protection for HT transmissions.
-                */
-               mm20_mode = mm40_mode = gf20_mode = gf40_mode = 0;
-
-               break;
-       case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
-               /*
-                * All STAs in this BSS are HT20 or HT20/40 but there
-                * might be STAs not supporting greenfield mode.
-                * => Protect all HT40 transmissions.
-                */
-               mm20_mode = gf20_mode = 0;
-               mm40_mode = gf40_mode = 2;
-
-               break;
-       case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
-               /*
-                * Nonmember protection:
-                * According to 802.11n we _should_ protect all
-                * HT transmissions (but we don't have to).
-                *
-                * But if cts_protection is enabled we _shall_ protect
-                * all HT transmissions using a CCK rate.
-                *
-                * And if any station is non GF we _shall_ protect
-                * GF transmissions.
-                *
-                * We decide to protect everything
-                * -> fall through to mixed mode.
-                */
-       case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
-               /*
-                * Legacy STAs are present
-                * => Protect all HT transmissions.
-                */
-               mm20_mode = mm40_mode = gf20_mode = gf40_mode = 2;
-
-               /*
-                * If erp protection is needed we have to protect HT
-                * transmissions with CCK 11M long preamble.
-                */
-               if (erp->cts_protection) {
-                       /* don't duplicate RTS/CTS in CCK mode */
-                       mm20_rate = mm40_rate = 0x0003;
-                       gf20_rate = gf40_rate = 0x0003;
-               }
-               break;
-       }
-
-       /* check for STAs not supporting greenfield mode */
-       if (any_sta_nongf)
-               gf20_mode = gf40_mode = 2;
-
-       /* Update HT protection config */
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, mm20_rate);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, mm20_mode);
-       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, mm40_rate);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, mm40_mode);
-       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, gf20_rate);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, gf20_mode);
-       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, gf40_rate);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, gf40_mode);
-       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-}
-
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
-                      u32 changed)
-{
-       u32 reg;
-
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
-               rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
-                                  !!erp->short_preamble);
-               rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
-                                  !!erp->short_preamble);
-               rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-       }
-
-       if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-               rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
-               rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
-                                  erp->cts_protection ? 2 : 0);
-               rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES) {
-               rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
-                                        erp->basic_rates);
-               rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-       }
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
-               rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME,
-                                  erp->slot_time);
-               rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
-
-               rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
-               rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
-       }
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
-                                  erp->beacon_int * 16);
-               rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-       }
-
-       if (changed & BSS_CHANGED_HT)
-               rt2800_config_ht_opmode(rt2x00dev, erp);
-}
-EXPORT_SYMBOL_GPL(rt2800_config_erp);
-
-static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 eeprom;
-       u8 led_ctrl, led_g_mode, led_r_mode;
-
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               rt2x00_set_field32(&reg, GPIO_SWITCH_0, 1);
-               rt2x00_set_field32(&reg, GPIO_SWITCH_1, 1);
-       } else {
-               rt2x00_set_field32(&reg, GPIO_SWITCH_0, 0);
-               rt2x00_set_field32(&reg, GPIO_SWITCH_1, 0);
-       }
-       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
-
-       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
-       led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0;
-       led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3;
-       if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) ||
-           led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-               led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE);
-               if (led_ctrl == 0 || led_ctrl > 0x40) {
-                       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, led_g_mode);
-                       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, led_r_mode);
-                       rt2800_register_write(rt2x00dev, LED_CFG, reg);
-               } else {
-                       rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff,
-                                          (led_g_mode << 2) | led_r_mode, 1);
-               }
-       }
-}
-
-static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
-                                    enum antenna ant)
-{
-       u32 reg;
-       u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0;
-       u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
-
-       if (rt2x00_is_pci(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
-               rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
-               rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
-       } else if (rt2x00_is_usb(rt2x00dev))
-               rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
-                                  eesk_pin, 0);
-
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-       rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
-       rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, gpio_bit3);
-       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
-}
-
-void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
-{
-       u8 r1;
-       u8 r3;
-       u16 eeprom;
-
-       rt2800_bbp_read(rt2x00dev, 1, &r1);
-       rt2800_bbp_read(rt2x00dev, 3, &r3);
-
-       if (rt2x00_rt(rt2x00dev, RT3572) &&
-           rt2x00_has_cap_bt_coexist(rt2x00dev))
-               rt2800_config_3572bt_ant(rt2x00dev);
-
-       /*
-        * Configure the TX antenna.
-        */
-       switch (ant->tx_chain_num) {
-       case 1:
-               rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
-               break;
-       case 2:
-               if (rt2x00_rt(rt2x00dev, RT3572) &&
-                   rt2x00_has_cap_bt_coexist(rt2x00dev))
-                       rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1);
-               else
-                       rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
-               break;
-       case 3:
-               rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
-               break;
-       }
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx_chain_num) {
-       case 1:
-               if (rt2x00_rt(rt2x00dev, RT3070) ||
-                   rt2x00_rt(rt2x00dev, RT3090) ||
-                   rt2x00_rt(rt2x00dev, RT3352) ||
-                   rt2x00_rt(rt2x00dev, RT3390)) {
-                       rt2800_eeprom_read(rt2x00dev,
-                                          EEPROM_NIC_CONF1, &eeprom);
-                       if (rt2x00_get_field16(eeprom,
-                                               EEPROM_NIC_CONF1_ANT_DIVERSITY))
-                               rt2800_set_ant_diversity(rt2x00dev,
-                                               rt2x00dev->default_ant.rx);
-               }
-               rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
-               break;
-       case 2:
-               if (rt2x00_rt(rt2x00dev, RT3572) &&
-                   rt2x00_has_cap_bt_coexist(rt2x00dev)) {
-                       rt2x00_set_field8(&r3, BBP3_RX_ADC, 1);
-                       rt2x00_set_field8(&r3, BBP3_RX_ANTENNA,
-                               rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-                       rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B);
-               } else {
-                       rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
-               }
-               break;
-       case 3:
-               rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
-               break;
-       }
-
-       rt2800_bbp_write(rt2x00dev, 3, r3);
-       rt2800_bbp_write(rt2x00dev, 1, r1);
-
-       if (rt2x00_rt(rt2x00dev, RT3593)) {
-               if (ant->rx_chain_num == 1)
-                       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-               else
-                       rt2800_bbp_write(rt2x00dev, 86, 0x46);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800_config_ant);
-
-static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
-                                  struct rt2x00lib_conf *libconf)
-{
-       u16 eeprom;
-       short lna_gain;
-
-       if (libconf->rf.channel <= 14) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
-               lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
-       } else if (libconf->rf.channel <= 64) {
-               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)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
-                       lna_gain = rt2x00_get_field16(eeprom,
-                                                     EEPROM_EXT_LNA2_A1);
-               } else {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
-                       lna_gain = rt2x00_get_field16(eeprom,
-                                                     EEPROM_RSSI_BG2_LNA_A1);
-               }
-       } else {
-               if (rt2x00_rt(rt2x00dev, RT3593)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
-                       lna_gain = rt2x00_get_field16(eeprom,
-                                                     EEPROM_EXT_LNA2_A2);
-               } else {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
-                       lna_gain = rt2x00_get_field16(eeprom,
-                                                     EEPROM_RSSI_A2_LNA_A2);
-               }
-       }
-
-       rt2x00dev->lna_gain = lna_gain;
-}
-
-#define FREQ_OFFSET_BOUND      0x5f
-
-static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
-{
-       u8 freq_offset, prev_freq_offset;
-       u8 rfcsr, prev_rfcsr;
-
-       freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
-       freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
-
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-       prev_rfcsr = rfcsr;
-
-       rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
-       if (rfcsr == prev_rfcsr)
-               return;
-
-       if (rt2x00_is_usb(rt2x00dev)) {
-               rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
-                                  freq_offset, prev_rfcsr);
-               return;
-       }
-
-       prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
-       while (prev_freq_offset != freq_offset) {
-               if (prev_freq_offset < freq_offset)
-                       prev_freq_offset++;
-               else
-                       prev_freq_offset--;
-
-               rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
-               rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
-
-               usleep_range(1000, 1500);
-       }
-}
-
-static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
-       if (rt2x00dev->default_ant.tx_chain_num == 1)
-               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
-
-       if (rt2x00dev->default_ant.rx_chain_num == 1) {
-               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
-               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
-       } else if (rt2x00dev->default_ant.rx_chain_num == 2)
-               rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
-
-       if (rf->channel > 14) {
-               /*
-                * When TX power is below 0, we should increase it by 7 to
-                * make it a positive value (Minimum value is -7).
-                * However this means that values between 0 and 7 have
-                * double meaning, and we should set a 7DBm boost flag.
-                */
-               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
-                                  (info->default_power1 >= 0));
-
-               if (info->default_power1 < 0)
-                       info->default_power1 += 7;
-
-               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
-
-               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
-                                  (info->default_power2 >= 0));
-
-               if (info->default_power2 < 0)
-                       info->default_power2 += 7;
-
-               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
-       } else {
-               rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
-               rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
-       }
-
-       rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
-
-       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
-
-       udelay(200);
-
-       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
-       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
-
-       udelay(200);
-
-       rt2800_rf_write(rt2x00dev, 1, rf->rf1);
-       rt2800_rf_write(rt2x00dev, 2, rf->rf2);
-       rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt2800_rf_write(rt2x00dev, 4, rf->rf4);
-}
-
-static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 rfcsr, calib_tx, calib_rx;
-
-       rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
-
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3);
-       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
-       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
-       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
-       rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
-                         rt2x00dev->default_ant.rx_chain_num <= 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD,
-                         rt2x00dev->default_ant.rx_chain_num <= 2);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,
-                         rt2x00dev->default_ant.tx_chain_num <= 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD,
-                         rt2x00dev->default_ant.tx_chain_num <= 2);
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
-       rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
-
-       if (rt2x00_rt(rt2x00dev, RT3390)) {
-               calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f;
-               calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f;
-       } else {
-               if (conf_is_ht40(conf)) {
-                       calib_tx = drv_data->calibration_bw40;
-                       calib_rx = drv_data->calibration_bw40;
-               } else {
-                       calib_tx = drv_data->calibration_bw20;
-                       calib_rx = drv_data->calibration_bw20;
-               }
-       }
-
-       rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx);
-       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx);
-       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
-       rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
-       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-       msleep(1);
-       rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
-       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-}
-
-static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 rfcsr;
-       u32 reg;
-
-       if (rf->channel <= 14) {
-               rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
-               rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
-       } else {
-               rt2800_bbp_write(rt2x00dev, 25, 0x09);
-               rt2800_bbp_write(rt2x00dev, 26, 0xff);
-       }
-
-       rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
-       rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
-
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2);
-       if (rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1);
-       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr);
-       if (rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2);
-       rt2800_rfcsr_write(rt2x00dev, 5, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
-       if (rf->channel <= 14) {
-               rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3);
-               rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
-                                 info->default_power1);
-       } else {
-               rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7);
-               rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
-                               (info->default_power1 & 0x3) |
-                               ((info->default_power1 & 0xC) << 1));
-       }
-       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
-       if (rf->channel <= 14) {
-               rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3);
-               rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
-                                 info->default_power2);
-       } else {
-               rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7);
-               rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
-                               (info->default_power2 & 0x3) |
-                               ((info->default_power2 & 0xC) << 1));
-       }
-       rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
-
-       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);
-       if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
-               if (rf->channel <= 14) {
-                       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
-                       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
-               }
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
-       } else {
-               switch (rt2x00dev->default_ant.tx_chain_num) {
-               case 1:
-                       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
-               case 2:
-                       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
-                       break;
-               }
-
-               switch (rt2x00dev->default_ant.rx_chain_num) {
-               case 1:
-                       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
-               case 2:
-                       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
-                       break;
-               }
-       }
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
-       rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
-
-       if (conf_is_ht40(conf)) {
-               rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40);
-               rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40);
-       } else {
-               rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20);
-               rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20);
-       }
-
-       if (rf->channel <= 14) {
-               rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
-               rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
-               rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
-               rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
-               rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
-               rfcsr = 0x4c;
-               rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,
-                                 drv_data->txmixer_gain_24g);
-               rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
-               rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
-               rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
-               rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
-               rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
-               rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
-       } else {
-               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0);
-               rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
-               rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
-               rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
-               rt2800_rfcsr_write(rt2x00dev, 11, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 15, 0x43);
-               rfcsr = 0x7a;
-               rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN,
-                                 drv_data->txmixer_gain_5g);
-               rt2800_rfcsr_write(rt2x00dev, 16, rfcsr);
-               rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
-               if (rf->channel <= 64) {
-                       rt2800_rfcsr_write(rt2x00dev, 19, 0xb7);
-                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf6);
-                       rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
-               } else if (rf->channel <= 128) {
-                       rt2800_rfcsr_write(rt2x00dev, 19, 0x74);
-                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf4);
-                       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
-               } else {
-                       rt2800_rfcsr_write(rt2x00dev, 19, 0x72);
-                       rt2800_rfcsr_write(rt2x00dev, 20, 0xf3);
-                       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
-               }
-               rt2800_rfcsr_write(rt2x00dev, 26, 0x87);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x01);
-               rt2800_rfcsr_write(rt2x00dev, 29, 0x9f);
-       }
-
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-       rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
-       if (rf->channel <= 14)
-               rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
-       else
-               rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 0);
-       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
-
-       rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
-       rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
-}
-
-static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 txrx_agc_fc;
-       u8 txrx_h20m;
-       u8 rfcsr;
-       u8 bbp;
-       const bool txbf_enabled = false; /* TODO */
-
-       /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */
-       rt2800_bbp_read(rt2x00dev, 109, &bbp);
-       rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0);
-       rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0);
-       rt2800_bbp_write(rt2x00dev, 109, bbp);
-
-       rt2800_bbp_read(rt2x00dev, 110, &bbp);
-       rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0);
-       rt2800_bbp_write(rt2x00dev, 110, bbp);
-
-       if (rf->channel <= 14) {
-               /* Restore BBP 25 & 26 for 2.4 GHz */
-               rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25);
-               rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);
-       } else {
-               /* Hard code BBP 25 & 26 for 5GHz */
-
-               /* Enable IQ Phase correction */
-               rt2800_bbp_write(rt2x00dev, 25, 0x09);
-               /* Setup IQ Phase correction value */
-               rt2800_bbp_write(rt2x00dev, 26, 0xff);
-       }
-
-       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf);
-
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3));
-       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1);
-       if (rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2);
-       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr);
-       if (rf->channel <= 14) {
-               rfcsr = 0;
-               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
-                                 info->default_power1 & 0x1f);
-       } else {
-               if (rt2x00_is_usb(rt2x00dev))
-                       rfcsr = 0x40;
-
-               rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER,
-                                 ((info->default_power1 & 0x18) << 1) |
-                                 (info->default_power1 & 7));
-       }
-       rt2800_rfcsr_write(rt2x00dev, 53, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr);
-       if (rf->channel <= 14) {
-               rfcsr = 0;
-               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
-                                 info->default_power2 & 0x1f);
-       } else {
-               if (rt2x00_is_usb(rt2x00dev))
-                       rfcsr = 0x40;
-
-               rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER,
-                                 ((info->default_power2 & 0x18) << 1) |
-                                 (info->default_power2 & 7));
-       }
-       rt2800_rfcsr_write(rt2x00dev, 55, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr);
-       if (rf->channel <= 14) {
-               rfcsr = 0;
-               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
-                                 info->default_power3 & 0x1f);
-       } else {
-               if (rt2x00_is_usb(rt2x00dev))
-                       rfcsr = 0x40;
-
-               rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER,
-                                 ((info->default_power3 & 0x18) << 1) |
-                                 (info->default_power3 & 7));
-       }
-       rt2800_rfcsr_write(rt2x00dev, 54, rfcsr);
-
-       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);
-
-       if (conf_is_ht40(conf)) {
-               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
-                                               RFCSR24_TX_AGC_FC);
-               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40,
-                                             RFCSR24_TX_H20M);
-       } else {
-               txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20,
-                                               RFCSR24_TX_AGC_FC);
-               txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20,
-                                             RFCSR24_TX_H20M);
-       }
-
-       /* NOTE: the reference driver does not writes the new value
-        * back to RFCSR 32
-        */
-       rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc);
-
-       if (rf->channel <= 14)
-               rfcsr = 0xa0;
-       else
-               rfcsr = 0x80;
-       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m);
-       rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m);
-       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-
-       /* Band selection */
-       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);
-
-       rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr);
-       if (rf->channel <= 14)
-               rfcsr = 0x3c;
-       else
-               rfcsr = 0x20;
-       rt2800_rfcsr_write(rt2x00dev, 34, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
-       if (rf->channel <= 14)
-               rfcsr = 0x1a;
-       else
-               rfcsr = 0x12;
-       rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-       if (rf->channel >= 1 && rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
-       else if (rf->channel >= 36 && rf->channel <= 64)
-               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
-       else if (rf->channel >= 100 && rf->channel <= 128)
-               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1);
-       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
-       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-
-       rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
-
-       if (rf->channel <= 14) {
-               rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
-               rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
-       } else {
-               rt2800_rfcsr_write(rt2x00dev, 10, 0xd8);
-               rt2800_rfcsr_write(rt2x00dev, 13, 0x23);
-       }
-
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1);
-       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
-       if (rf->channel <= 14) {
-               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5);
-               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3);
-       } else {
-               rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4);
-               rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2);
-       }
-       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
-       if (rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2);
-
-       if (txbf_enabled)
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1);
-
-       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
-       if (rf->channel <= 14)
-               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 57, rfcsr);
-
-       if (rf->channel <= 14) {
-               rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
-               rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
-       } else {
-               rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
-               rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
-       }
-
-       /* Initiate VCO calibration */
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-       if (rf->channel <= 14) {
-               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-       } else {
-               rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-       }
-       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-
-       if (rf->channel >= 1 && rf->channel <= 14) {
-               rfcsr = 0x23;
-               if (txbf_enabled)
-                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
-               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
-               rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
-       } else if (rf->channel >= 36 && rf->channel <= 64) {
-               rfcsr = 0x36;
-               if (txbf_enabled)
-                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
-               rt2800_rfcsr_write(rt2x00dev, 39, 0x36);
-
-               rt2800_rfcsr_write(rt2x00dev, 45, 0xeb);
-       } else if (rf->channel >= 100 && rf->channel <= 128) {
-               rfcsr = 0x32;
-               if (txbf_enabled)
-                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
-               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
-               rt2800_rfcsr_write(rt2x00dev, 45, 0xb3);
-       } else {
-               rfcsr = 0x30;
-               if (txbf_enabled)
-                       rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1);
-               rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
-               rt2800_rfcsr_write(rt2x00dev, 45, 0x9b);
-       }
-}
-
-#define POWER_BOUND            0x27
-#define POWER_BOUND_5G         0x2b
-
-static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       u8 rfcsr;
-
-       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
-       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
-       if (info->default_power1 > POWER_BOUND)
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
-       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
-
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       if (rf->channel <= 14) {
-               if (rf->channel == 6)
-                       rt2800_bbp_write(rt2x00dev, 68, 0x0c);
-               else
-                       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
-
-               if (rf->channel >= 1 && rf->channel <= 6)
-                       rt2800_bbp_write(rt2x00dev, 59, 0x0f);
-               else if (rf->channel >= 7 && rf->channel <= 11)
-                       rt2800_bbp_write(rt2x00dev, 59, 0x0e);
-               else if (rf->channel >= 12 && rf->channel <= 14)
-                       rt2800_bbp_write(rt2x00dev, 59, 0x0d);
-       }
-}
-
-static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       u8 rfcsr;
-
-       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
-
-       if (info->default_power1 > POWER_BOUND)
-               rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1);
-
-       if (info->default_power2 > POWER_BOUND)
-               rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2);
-
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
-
-       if ( rt2x00dev->default_ant.tx_chain_num == 2 )
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
-
-       if ( rt2x00dev->default_ant.rx_chain_num == 2 )
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
-
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-       rt2800_rfcsr_write(rt2x00dev, 31, 80);
-}
-
-static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       u8 rfcsr;
-
-       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
-       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
-       if (info->default_power1 > POWER_BOUND)
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
-       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
-
-       if (rt2x00_rt(rt2x00dev, RT5392)) {
-               rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
-               if (info->default_power2 > POWER_BOUND)
-                       rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND);
-               else
-                       rt2x00_set_field8(&rfcsr, RFCSR50_TX,
-                                         info->default_power2);
-               rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
-       }
-
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-       if (rt2x00_rt(rt2x00dev, RT5392)) {
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
-       }
-       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       if (rf->channel <= 14) {
-               int idx = rf->channel-1;
-
-               if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
-                       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
-                               /* r55/r59 value array of channel 1~14 */
-                               static const char r55_bt_rev[] = {0x83, 0x83,
-                                       0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
-                                       0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
-                               static const char r59_bt_rev[] = {0x0e, 0x0e,
-                                       0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
-                                       0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
-
-                               rt2800_rfcsr_write(rt2x00dev, 55,
-                                                  r55_bt_rev[idx]);
-                               rt2800_rfcsr_write(rt2x00dev, 59,
-                                                  r59_bt_rev[idx]);
-                       } else {
-                               static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
-                                       0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
-                                       0x88, 0x88, 0x86, 0x85, 0x84};
-
-                               rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
-                       }
-               } else {
-                       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
-                               static const char r55_nonbt_rev[] = {0x23, 0x23,
-                                       0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
-                                       0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
-                               static const char r59_nonbt_rev[] = {0x07, 0x07,
-                                       0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-                                       0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
-
-                               rt2800_rfcsr_write(rt2x00dev, 55,
-                                                  r55_nonbt_rev[idx]);
-                               rt2800_rfcsr_write(rt2x00dev, 59,
-                                                  r59_nonbt_rev[idx]);
-                       } else if (rt2x00_rt(rt2x00dev, RT5390) ||
-                                  rt2x00_rt(rt2x00dev, RT5392)) {
-                               static const char r59_non_bt[] = {0x8f, 0x8f,
-                                       0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
-                                       0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
-
-                               rt2800_rfcsr_write(rt2x00dev, 59,
-                                                  r59_non_bt[idx]);
-                       }
-               }
-       }
-}
-
-static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_conf *conf,
-                                        struct rf_channel *rf,
-                                        struct channel_info *info)
-{
-       u8 rfcsr, ep_reg;
-       u32 reg;
-       int power_bound;
-
-       /* TODO */
-       const bool is_11b = false;
-       const bool is_type_ep = false;
-
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL,
-                          (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0);
-       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
-       /* Order of values on rf_channel entry: N, K, mod, R */
-       rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff);
-
-       rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf);
-       rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8);
-       rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2);
-       rt2800_rfcsr_write(rt2x00dev, 9, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1);
-       rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3);
-       rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
-
-       if (rf->channel <= 14) {
-               rt2800_rfcsr_write(rt2x00dev, 10, 0x90);
-               /* FIXME: RF11 owerwrite ? */
-               rt2800_rfcsr_write(rt2x00dev, 11, 0x4A);
-               rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
-               rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
-               rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
-               rt2800_rfcsr_write(rt2x00dev, 24, 0x4A);
-               rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
-               rt2800_rfcsr_write(rt2x00dev, 36, 0x80);
-               rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
-               rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
-               rt2800_rfcsr_write(rt2x00dev, 39, 0x1B);
-               rt2800_rfcsr_write(rt2x00dev, 40, 0x0D);
-               rt2800_rfcsr_write(rt2x00dev, 41, 0x9B);
-               rt2800_rfcsr_write(rt2x00dev, 42, 0xD5);
-               rt2800_rfcsr_write(rt2x00dev, 43, 0x72);
-               rt2800_rfcsr_write(rt2x00dev, 44, 0x0E);
-               rt2800_rfcsr_write(rt2x00dev, 45, 0xA2);
-               rt2800_rfcsr_write(rt2x00dev, 46, 0x6B);
-               rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
-               rt2800_rfcsr_write(rt2x00dev, 51, 0x3E);
-               rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
-               rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
-               rt2800_rfcsr_write(rt2x00dev, 56, 0xA1);
-               rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
-               rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
-               rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
-               rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
-
-               /* TODO RF27 <- tssi */
-
-               rfcsr = rf->channel <= 10 ? 0x07 : 0x06;
-               rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
-               rt2800_rfcsr_write(rt2x00dev, 59, rfcsr);
-
-               if (is_11b) {
-                       /* CCK */
-                       rt2800_rfcsr_write(rt2x00dev, 31, 0xF8);
-                       rt2800_rfcsr_write(rt2x00dev, 32, 0xC0);
-                       if (is_type_ep)
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x06);
-                       else
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x47);
-               } else {
-                       /* OFDM */
-                       if (is_type_ep)
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x03);
-                       else
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
-               }
-
-               power_bound = POWER_BOUND;
-               ep_reg = 0x2;
-       } else {
-               rt2800_rfcsr_write(rt2x00dev, 10, 0x97);
-               /* FIMXE: RF11 overwrite */
-               rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
-               rt2800_rfcsr_write(rt2x00dev, 25, 0xBF);
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x42);
-               rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 37, 0x04);
-               rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
-               rt2800_rfcsr_write(rt2x00dev, 40, 0x42);
-               rt2800_rfcsr_write(rt2x00dev, 41, 0xBB);
-               rt2800_rfcsr_write(rt2x00dev, 42, 0xD7);
-               rt2800_rfcsr_write(rt2x00dev, 45, 0x41);
-               rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
-               rt2800_rfcsr_write(rt2x00dev, 57, 0x77);
-               rt2800_rfcsr_write(rt2x00dev, 60, 0x05);
-               rt2800_rfcsr_write(rt2x00dev, 61, 0x01);
-
-               /* TODO RF27 <- tssi */
-
-               if (rf->channel >= 36 && rf->channel <= 64) {
-
-                       rt2800_rfcsr_write(rt2x00dev, 12, 0x2E);
-                       rt2800_rfcsr_write(rt2x00dev, 13, 0x22);
-                       rt2800_rfcsr_write(rt2x00dev, 22, 0x60);
-                       rt2800_rfcsr_write(rt2x00dev, 23, 0x7F);
-                       if (rf->channel <= 50)
-                               rt2800_rfcsr_write(rt2x00dev, 24, 0x09);
-                       else if (rf->channel >= 52)
-                               rt2800_rfcsr_write(rt2x00dev, 24, 0x07);
-                       rt2800_rfcsr_write(rt2x00dev, 39, 0x1C);
-                       rt2800_rfcsr_write(rt2x00dev, 43, 0x5B);
-                       rt2800_rfcsr_write(rt2x00dev, 44, 0X40);
-                       rt2800_rfcsr_write(rt2x00dev, 46, 0X00);
-                       rt2800_rfcsr_write(rt2x00dev, 51, 0xFE);
-                       rt2800_rfcsr_write(rt2x00dev, 52, 0x0C);
-                       rt2800_rfcsr_write(rt2x00dev, 54, 0xF8);
-                       if (rf->channel <= 50) {
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x06),
-                               rt2800_rfcsr_write(rt2x00dev, 56, 0xD3);
-                       } else if (rf->channel >= 52) {
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x04);
-                               rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
-                       }
-
-                       rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
-                       rt2800_rfcsr_write(rt2x00dev, 59, 0x7F);
-                       rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
-
-               } else if (rf->channel >= 100 && rf->channel <= 165) {
-
-                       rt2800_rfcsr_write(rt2x00dev, 12, 0x0E);
-                       rt2800_rfcsr_write(rt2x00dev, 13, 0x42);
-                       rt2800_rfcsr_write(rt2x00dev, 22, 0x40);
-                       if (rf->channel <= 153) {
-                               rt2800_rfcsr_write(rt2x00dev, 23, 0x3C);
-                               rt2800_rfcsr_write(rt2x00dev, 24, 0x06);
-                       } else if (rf->channel >= 155) {
-                               rt2800_rfcsr_write(rt2x00dev, 23, 0x38);
-                               rt2800_rfcsr_write(rt2x00dev, 24, 0x05);
-                       }
-                       if (rf->channel <= 138) {
-                               rt2800_rfcsr_write(rt2x00dev, 39, 0x1A);
-                               rt2800_rfcsr_write(rt2x00dev, 43, 0x3B);
-                               rt2800_rfcsr_write(rt2x00dev, 44, 0x20);
-                               rt2800_rfcsr_write(rt2x00dev, 46, 0x18);
-                       } else if (rf->channel >= 140) {
-                               rt2800_rfcsr_write(rt2x00dev, 39, 0x18);
-                               rt2800_rfcsr_write(rt2x00dev, 43, 0x1B);
-                               rt2800_rfcsr_write(rt2x00dev, 44, 0x10);
-                               rt2800_rfcsr_write(rt2x00dev, 46, 0X08);
-                       }
-                       if (rf->channel <= 124)
-                               rt2800_rfcsr_write(rt2x00dev, 51, 0xFC);
-                       else if (rf->channel >= 126)
-                               rt2800_rfcsr_write(rt2x00dev, 51, 0xEC);
-                       if (rf->channel <= 138)
-                               rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
-                       else if (rf->channel >= 140)
-                               rt2800_rfcsr_write(rt2x00dev, 52, 0x06);
-                       rt2800_rfcsr_write(rt2x00dev, 54, 0xEB);
-                       if (rf->channel <= 138)
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x01);
-                       else if (rf->channel >= 140)
-                               rt2800_rfcsr_write(rt2x00dev, 55, 0x00);
-                       if (rf->channel <= 128)
-                               rt2800_rfcsr_write(rt2x00dev, 56, 0xBB);
-                       else if (rf->channel >= 130)
-                               rt2800_rfcsr_write(rt2x00dev, 56, 0xAB);
-                       if (rf->channel <= 116)
-                               rt2800_rfcsr_write(rt2x00dev, 58, 0x1D);
-                       else if (rf->channel >= 118)
-                               rt2800_rfcsr_write(rt2x00dev, 58, 0x15);
-                       if (rf->channel <= 138)
-                               rt2800_rfcsr_write(rt2x00dev, 59, 0x3F);
-                       else if (rf->channel >= 140)
-                               rt2800_rfcsr_write(rt2x00dev, 59, 0x7C);
-                       if (rf->channel <= 116)
-                               rt2800_rfcsr_write(rt2x00dev, 62, 0x1D);
-                       else if (rf->channel >= 118)
-                               rt2800_rfcsr_write(rt2x00dev, 62, 0x15);
-               }
-
-               power_bound = POWER_BOUND_5G;
-               ep_reg = 0x3;
-       }
-
-       rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
-       if (info->default_power1 > power_bound)
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
-       if (is_type_ep)
-               rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg);
-       rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
-       if (info->default_power2 > power_bound)
-               rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound);
-       else
-               rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2);
-       if (is_type_ep)
-               rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg);
-       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
-
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD,
-                         rt2x00dev->default_ant.tx_chain_num >= 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD,
-                         rt2x00dev->default_ant.tx_chain_num == 2);
-       rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
-
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD,
-                         rt2x00dev->default_ant.rx_chain_num >= 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD,
-                         rt2x00dev->default_ant.rx_chain_num == 2);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0xe4);
-
-       if (conf_is_ht40(conf))
-               rt2800_rfcsr_write(rt2x00dev, 30, 0x16);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
-
-       if (!is_11b) {
-               rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-               rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
-       }
-
-       /* TODO proper frequency adjustment */
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       /* TODO merge with others */
-       rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-       rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-
-       /* 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);
-
-       rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18);
-       rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08);
-       rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38);
-       rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92);
-
-       /* GLRT band configuration */
-       rt2800_bbp_write(rt2x00dev, 195, 128);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0);
-       rt2800_bbp_write(rt2x00dev, 195, 129);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E);
-       rt2800_bbp_write(rt2x00dev, 195, 130);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28);
-       rt2800_bbp_write(rt2x00dev, 195, 131);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20);
-       rt2800_bbp_write(rt2x00dev, 195, 133);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F);
-       rt2800_bbp_write(rt2x00dev, 195, 124);
-       rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F);
-}
-
-static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int word,
-                                          const u8 value)
-{
-       u8 chain, reg;
-
-       for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) {
-               rt2800_bbp_read(rt2x00dev, 27, &reg);
-               rt2x00_set_field8(&reg,  BBP27_RX_CHAIN_SEL, chain);
-               rt2800_bbp_write(rt2x00dev, 27, reg);
-
-               rt2800_bbp_write(rt2x00dev, word, value);
-       }
-}
-
-static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel)
-{
-       u8 cal;
-
-       /* TX0 IQ Gain */
-       rt2800_bbp_write(rt2x00dev, 158, 0x2c);
-       if (channel <= 14)
-               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G);
-       else if (channel >= 36 && channel <= 64)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G);
-       else if (channel >= 100 && channel <= 138)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G);
-       else if (channel >= 140 && channel <= 165)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G);
-       else
-               cal = 0;
-       rt2800_bbp_write(rt2x00dev, 159, cal);
-
-       /* TX0 IQ Phase */
-       rt2800_bbp_write(rt2x00dev, 158, 0x2d);
-       if (channel <= 14)
-               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G);
-       else if (channel >= 36 && channel <= 64)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G);
-       else if (channel >= 100 && channel <= 138)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G);
-       else if (channel >= 140 && channel <= 165)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G);
-       else
-               cal = 0;
-       rt2800_bbp_write(rt2x00dev, 159, cal);
-
-       /* TX1 IQ Gain */
-       rt2800_bbp_write(rt2x00dev, 158, 0x4a);
-       if (channel <= 14)
-               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G);
-       else if (channel >= 36 && channel <= 64)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G);
-       else if (channel >= 100 && channel <= 138)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G);
-       else if (channel >= 140 && channel <= 165)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G);
-       else
-               cal = 0;
-       rt2800_bbp_write(rt2x00dev, 159, cal);
-
-       /* TX1 IQ Phase */
-       rt2800_bbp_write(rt2x00dev, 158, 0x4b);
-       if (channel <= 14)
-               cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G);
-       else if (channel >= 36 && channel <= 64)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G);
-       else if (channel >= 100 && channel <= 138)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G);
-       else if (channel >= 140 && channel <= 165)
-               cal = rt2x00_eeprom_byte(rt2x00dev,
-                                        EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G);
-       else
-               cal = 0;
-       rt2800_bbp_write(rt2x00dev, 159, cal);
-
-       /* FIXME: possible RX0, RX1 callibration ? */
-
-       /* RF IQ compensation control */
-       rt2800_bbp_write(rt2x00dev, 158, 0x04);
-       cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL);
-       rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
-
-       /* RF IQ imbalance compensation control */
-       rt2800_bbp_write(rt2x00dev, 158, 0x03);
-       cal = rt2x00_eeprom_byte(rt2x00dev,
-                                EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL);
-       rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0);
-}
-
-static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev,
-                                 unsigned int channel,
-                                 char txpower)
-{
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               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))
-               return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
-                              MAX_A_TXPOWER_3593);
-       else
-               return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
-}
-
-static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
-                                 struct ieee80211_conf *conf,
-                                 struct rf_channel *rf,
-                                 struct channel_info *info)
-{
-       u32 reg;
-       unsigned int tx_pin;
-       u8 bbp, rfcsr;
-
-       info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
-                                                    info->default_power1);
-       info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel,
-                                                    info->default_power2);
-       if (rt2x00dev->default_ant.tx_chain_num > 2)
-               info->default_power3 =
-                       rt2800_txpower_to_dev(rt2x00dev, rf->channel,
-                                             info->default_power3);
-
-       switch (rt2x00dev->chip.rf) {
-       case RF2020:
-       case RF3020:
-       case RF3021:
-       case RF3022:
-       case RF3320:
-               rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
-               break;
-       case RF3052:
-               rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);
-               break;
-       case RF3053:
-               rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info);
-               break;
-       case RF3290:
-               rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
-               break;
-       case RF3322:
-               rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
-               break;
-       case RF3070:
-       case RF5360:
-       case RF5362:
-       case RF5370:
-       case RF5372:
-       case RF5390:
-       case RF5392:
-               rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
-               break;
-       case RF5592:
-               rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info);
-               break;
-       default:
-               rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
-       }
-
-       if (rt2x00_rf(rt2x00dev, RF3070) ||
-           rt2x00_rf(rt2x00dev, RF3290) ||
-           rt2x00_rf(rt2x00dev, RF3322) ||
-           rt2x00_rf(rt2x00dev, RF5360) ||
-           rt2x00_rf(rt2x00dev, RF5362) ||
-           rt2x00_rf(rt2x00dev, RF5370) ||
-           rt2x00_rf(rt2x00dev, RF5372) ||
-           rt2x00_rf(rt2x00dev, RF5390) ||
-           rt2x00_rf(rt2x00dev, RF5392)) {
-               rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
-               rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-
-               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-               rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-       }
-
-       /*
-        * Change BBP settings
-        */
-       if (rt2x00_rt(rt2x00dev, RT3352)) {
-               rt2800_bbp_write(rt2x00dev, 27, 0x0);
-               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
-               rt2800_bbp_write(rt2x00dev, 27, 0x20);
-               rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
-       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
-               if (rf->channel > 14) {
-                       /* Disable CCK Packet detection on 5GHz */
-                       rt2800_bbp_write(rt2x00dev, 70, 0x00);
-               } else {
-                       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-               }
-
-               if (conf_is_ht40(conf))
-                       rt2800_bbp_write(rt2x00dev, 105, 0x04);
-               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);
-       }
-
-       if (rf->channel <= 14) {
-               if (!rt2x00_rt(rt2x00dev, RT5390) &&
-                   !rt2x00_rt(rt2x00dev, RT5392)) {
-                       if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-                               rt2800_bbp_write(rt2x00dev, 82, 0x62);
-                               rt2800_bbp_write(rt2x00dev, 75, 0x46);
-                       } else {
-                               if (rt2x00_rt(rt2x00dev, RT3593))
-                                       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-                               else
-                                       rt2800_bbp_write(rt2x00dev, 82, 0x84);
-                               rt2800_bbp_write(rt2x00dev, 75, 0x50);
-                       }
-                       if (rt2x00_rt(rt2x00dev, RT3593))
-                               rt2800_bbp_write(rt2x00dev, 83, 0x8a);
-               }
-
-       } else {
-               if (rt2x00_rt(rt2x00dev, RT3572))
-                       rt2800_bbp_write(rt2x00dev, 82, 0x94);
-               else if (rt2x00_rt(rt2x00dev, RT3593))
-                       rt2800_bbp_write(rt2x00dev, 82, 0x82);
-               else
-                       rt2800_bbp_write(rt2x00dev, 82, 0xf2);
-
-               if (rt2x00_rt(rt2x00dev, RT3593))
-                       rt2800_bbp_write(rt2x00dev, 83, 0x9a);
-
-               if (rt2x00_has_cap_external_lna_a(rt2x00dev))
-                       rt2800_bbp_write(rt2x00dev, 75, 0x46);
-               else
-                       rt2800_bbp_write(rt2x00dev, 75, 0x50);
-       }
-
-       rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
-       rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
-       rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
-       rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
-
-       if (rt2x00_rt(rt2x00dev, RT3572))
-               rt2800_rfcsr_write(rt2x00dev, 8, 0);
-
-       tx_pin = 0;
-
-       switch (rt2x00dev->default_ant.tx_chain_num) {
-       case 3:
-               /* Turn on tertiary PAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN,
-                                  rf->channel > 14);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN,
-                                  rf->channel <= 14);
-               /* fall-through */
-       case 2:
-               /* Turn on secondary PAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
-                                  rf->channel > 14);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
-                                  rf->channel <= 14);
-               /* fall-through */
-       case 1:
-               /* Turn on primary PAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN,
-                                  rf->channel > 14);
-               if (rt2x00_has_cap_bt_coexist(rt2x00dev))
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
-               else
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN,
-                                          rf->channel <= 14);
-               break;
-       }
-
-       switch (rt2x00dev->default_ant.rx_chain_num) {
-       case 3:
-               /* Turn on tertiary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
-               /* fall-through */
-       case 2:
-               /* Turn on secondary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
-               /* fall-through */
-       case 1:
-               /* Turn on primary LNAs */
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
-               rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
-               break;
-       }
-
-       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
-       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
-
-       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
-
-       if (rt2x00_rt(rt2x00dev, RT3572)) {
-               rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
-
-               /* AGC init */
-               if (rf->channel <= 14)
-                       reg = 0x1c + (2 * rt2x00dev->lna_gain);
-               else
-                       reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3);
-
-               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
-       }
-
-       if (rt2x00_rt(rt2x00dev, RT3593)) {
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-
-               /* Band selection */
-               if (rt2x00_is_usb(rt2x00dev) ||
-                   rt2x00_is_pcie(rt2x00dev)) {
-                       /* GPIO #8 controls all paths */
-                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR8, 0);
-                       if (rf->channel <= 14)
-                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 1);
-                       else
-                               rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 0);
-               }
-
-               /* LNA PE control. */
-               if (rt2x00_is_usb(rt2x00dev)) {
-                       /* GPIO #4 controls PE0 and PE1,
-                        * GPIO #7 controls PE2
-                        */
-                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
-                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
-
-                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
-                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
-               } else if (rt2x00_is_pcie(rt2x00dev)) {
-                       /* GPIO #4 controls PE0, PE1 and PE2 */
-                       rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
-                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
-               }
-
-               rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
-
-               /* AGC init */
-               if (rf->channel <= 14)
-                       reg = 0x1c + 2 * rt2x00dev->lna_gain;
-               else
-                       reg = 0x22 + ((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);
-
-               /* AGC init */
-               reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain;
-               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
-
-               rt2800_iq_calibrate(rt2x00dev, rf->channel);
-       }
-
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
-       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
-       rt2800_bbp_write(rt2x00dev, 4, bbp);
-
-       rt2800_bbp_read(rt2x00dev, 3, &bbp);
-       rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
-       rt2800_bbp_write(rt2x00dev, 3, bbp);
-
-       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
-               if (conf_is_ht40(conf)) {
-                       rt2800_bbp_write(rt2x00dev, 69, 0x1a);
-                       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-                       rt2800_bbp_write(rt2x00dev, 73, 0x16);
-               } else {
-                       rt2800_bbp_write(rt2x00dev, 69, 0x16);
-                       rt2800_bbp_write(rt2x00dev, 70, 0x08);
-                       rt2800_bbp_write(rt2x00dev, 73, 0x11);
-               }
-       }
-
-       msleep(1);
-
-       /*
-        * Clear channel statistic counters
-        */
-       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
-
-       /*
-        * Clear update flag
-        */
-       if (rt2x00_rt(rt2x00dev, RT3352)) {
-               rt2800_bbp_read(rt2x00dev, 49, &bbp);
-               rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
-               rt2800_bbp_write(rt2x00dev, 49, bbp);
-       }
-}
-
-static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
-{
-       u8 tssi_bounds[9];
-       u8 current_tssi;
-       u16 eeprom;
-       u8 step;
-       int i;
-
-       /*
-        * First check if temperature compensation is supported.
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
-       if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC))
-               return 0;
-
-       /*
-        * Read TSSI boundaries for temperature compensation from
-        * the EEPROM.
-        *
-        * Array idx               0    1    2    3    4    5    6    7    8
-        * Matching Delta value   -4   -3   -2   -1    0   +1   +2   +3   +4
-        * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
-        */
-       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
-               tssi_bounds[0] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG1_MINUS4);
-               tssi_bounds[1] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG1_MINUS3);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
-               tssi_bounds[2] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG2_MINUS2);
-               tssi_bounds[3] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG2_MINUS1);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
-               tssi_bounds[4] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG3_REF);
-               tssi_bounds[5] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG3_PLUS1);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
-               tssi_bounds[6] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG4_PLUS2);
-               tssi_bounds[7] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG4_PLUS3);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
-               tssi_bounds[8] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_BG5_PLUS4);
-
-               step = rt2x00_get_field16(eeprom,
-                                         EEPROM_TSSI_BOUND_BG5_AGC_STEP);
-       } else {
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
-               tssi_bounds[0] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A1_MINUS4);
-               tssi_bounds[1] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A1_MINUS3);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
-               tssi_bounds[2] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A2_MINUS2);
-               tssi_bounds[3] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A2_MINUS1);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
-               tssi_bounds[4] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A3_REF);
-               tssi_bounds[5] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A3_PLUS1);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
-               tssi_bounds[6] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A4_PLUS2);
-               tssi_bounds[7] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A4_PLUS3);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
-               tssi_bounds[8] = rt2x00_get_field16(eeprom,
-                                       EEPROM_TSSI_BOUND_A5_PLUS4);
-
-               step = rt2x00_get_field16(eeprom,
-                                         EEPROM_TSSI_BOUND_A5_AGC_STEP);
-       }
-
-       /*
-        * Check if temperature compensation is supported.
-        */
-       if (tssi_bounds[4] == 0xff || step == 0xff)
-               return 0;
-
-       /*
-        * Read current TSSI (BBP 49).
-        */
-       rt2800_bbp_read(rt2x00dev, 49, &current_tssi);
-
-       /*
-        * Compare TSSI value (BBP49) with the compensation boundaries
-        * from the EEPROM and increase or decrease tx power.
-        */
-       for (i = 0; i <= 3; i++) {
-               if (current_tssi > tssi_bounds[i])
-                       break;
-       }
-
-       if (i == 4) {
-               for (i = 8; i >= 5; i--) {
-                       if (current_tssi < tssi_bounds[i])
-                               break;
-               }
-       }
-
-       return (i - 4) * step;
-}
-
-static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
-                                     enum ieee80211_band band)
-{
-       u16 eeprom;
-       u8 comp_en;
-       u8 comp_type;
-       int comp_value = 0;
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
-
-       /*
-        * HT40 compensation not required.
-        */
-       if (eeprom == 0xffff ||
-           !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
-               return 0;
-
-       if (band == IEEE80211_BAND_2GHZ) {
-               comp_en = rt2x00_get_field16(eeprom,
-                                EEPROM_TXPOWER_DELTA_ENABLE_2G);
-               if (comp_en) {
-                       comp_type = rt2x00_get_field16(eeprom,
-                                          EEPROM_TXPOWER_DELTA_TYPE_2G);
-                       comp_value = rt2x00_get_field16(eeprom,
-                                           EEPROM_TXPOWER_DELTA_VALUE_2G);
-                       if (!comp_type)
-                               comp_value = -comp_value;
-               }
-       } else {
-               comp_en = rt2x00_get_field16(eeprom,
-                                EEPROM_TXPOWER_DELTA_ENABLE_5G);
-               if (comp_en) {
-                       comp_type = rt2x00_get_field16(eeprom,
-                                          EEPROM_TXPOWER_DELTA_TYPE_5G);
-                       comp_value = rt2x00_get_field16(eeprom,
-                                           EEPROM_TXPOWER_DELTA_VALUE_5G);
-                       if (!comp_type)
-                               comp_value = -comp_value;
-               }
-       }
-
-       return comp_value;
-}
-
-static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
-                                       int power_level, int max_power)
-{
-       int delta;
-
-       if (rt2x00_has_cap_power_limit(rt2x00dev))
-               return 0;
-
-       /*
-        * XXX: We don't know the maximum transmit power of our hardware since
-        * the EEPROM doesn't expose it. We only know that we are calibrated
-        * to 100% tx power.
-        *
-        * Hence, we assume the regulatory limit that cfg80211 calulated for
-        * the current channel is our maximum and if we are requested to lower
-        * the value we just reduce our tx power accordingly.
-        */
-       delta = power_level - max_power;
-       return min(delta, 0);
-}
-
-static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
-                                  enum ieee80211_band band, int power_level,
-                                  u8 txpower, int delta)
-{
-       u16 eeprom;
-       u8 criterion;
-       u8 eirp_txpower;
-       u8 eirp_txpower_criterion;
-       u8 reg_limit;
-
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               return min_t(u8, txpower, 0xc);
-
-       if (rt2x00_has_cap_power_limit(rt2x00dev)) {
-               /*
-                * Check if eirp txpower exceed txpower_limit.
-                * We use OFDM 6M as criterion and its eirp txpower
-                * is stored at EEPROM_EIRP_MAX_TX_POWER.
-                * .11b data rate need add additional 4dbm
-                * when calculating eirp txpower.
-                */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             1, &eeprom);
-               criterion = rt2x00_get_field16(eeprom,
-                                              EEPROM_TXPOWER_BYRATE_RATE0);
-
-               rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
-                                  &eeprom);
-
-               if (band == IEEE80211_BAND_2GHZ)
-                       eirp_txpower_criterion = rt2x00_get_field16(eeprom,
-                                                EEPROM_EIRP_MAX_TX_POWER_2GHZ);
-               else
-                       eirp_txpower_criterion = rt2x00_get_field16(eeprom,
-                                                EEPROM_EIRP_MAX_TX_POWER_5GHZ);
-
-               eirp_txpower = eirp_txpower_criterion + (txpower - criterion) +
-                              (is_rate_b ? 4 : 0) + delta;
-
-               reg_limit = (eirp_txpower > power_level) ?
-                                       (eirp_txpower - power_level) : 0;
-       } else
-               reg_limit = 0;
-
-       txpower = max(0, txpower + delta - reg_limit);
-       return min_t(u8, txpower, 0xc);
-}
-
-
-enum {
-       TX_PWR_CFG_0_IDX,
-       TX_PWR_CFG_1_IDX,
-       TX_PWR_CFG_2_IDX,
-       TX_PWR_CFG_3_IDX,
-       TX_PWR_CFG_4_IDX,
-       TX_PWR_CFG_5_IDX,
-       TX_PWR_CFG_6_IDX,
-       TX_PWR_CFG_7_IDX,
-       TX_PWR_CFG_8_IDX,
-       TX_PWR_CFG_9_IDX,
-       TX_PWR_CFG_0_EXT_IDX,
-       TX_PWR_CFG_1_EXT_IDX,
-       TX_PWR_CFG_2_EXT_IDX,
-       TX_PWR_CFG_3_EXT_IDX,
-       TX_PWR_CFG_4_EXT_IDX,
-       TX_PWR_CFG_IDX_COUNT,
-};
-
-static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_channel *chan,
-                                        int power_level)
-{
-       u8 txpower;
-       u16 eeprom;
-       u32 regs[TX_PWR_CFG_IDX_COUNT];
-       unsigned int offset;
-       enum ieee80211_band band = chan->band;
-       int delta;
-       int i;
-
-       memset(regs, '\0', sizeof(regs));
-
-       /* TODO: adapt TX power reduction from the rt28xx code */
-
-       /* calculate temperature compensation delta */
-       delta = rt2800_get_gain_calibration_delta(rt2x00dev);
-
-       if (band == IEEE80211_BAND_5GHZ)
-               offset = 16;
-       else
-               offset = 0;
-
-       if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
-               offset += 8;
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset, &eeprom);
-
-       /* CCK 1MBS,2MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_CCK1_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_CCK1_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
-                          TX_PWR_CFG_0_EXT_CCK1_CH2, txpower);
-
-       /* CCK 5.5MBS,11MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_CCK5_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_CCK5_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
-                          TX_PWR_CFG_0_EXT_CCK5_CH2, txpower);
-
-       /* OFDM 6MBS,9MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_OFDM6_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_OFDM6_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
-                          TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower);
-
-       /* OFDM 12MBS,18MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_OFDM12_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_IDX],
-                          TX_PWR_CFG_0_OFDM12_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_0_EXT_IDX],
-                          TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 1, &eeprom);
-
-       /* OFDM 24MBS,36MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_OFDM24_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_OFDM24_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
-                          TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower);
-
-       /* OFDM 48MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_OFDM48_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_OFDM48_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
-                          TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower);
-
-       /* OFDM 54MBS */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_OFDM54_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_OFDM54_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_OFDM54_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 2, &eeprom);
-
-       /* MCS 0,1 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_MCS0_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_MCS0_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
-                          TX_PWR_CFG_1_EXT_MCS0_CH2, txpower);
-
-       /* MCS 2,3 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_MCS2_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_IDX],
-                          TX_PWR_CFG_1_MCS2_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_1_EXT_IDX],
-                          TX_PWR_CFG_1_EXT_MCS2_CH2, txpower);
-
-       /* MCS 4,5 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS4_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS4_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
-                          TX_PWR_CFG_2_EXT_MCS4_CH2, txpower);
-
-       /* MCS 6 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS6_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS6_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
-                          TX_PWR_CFG_2_EXT_MCS6_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 3, &eeprom);
-
-       /* MCS 7 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_MCS7_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_MCS7_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_7_IDX],
-                          TX_PWR_CFG_7_MCS7_CH2, txpower);
-
-       /* MCS 8,9 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS8_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS8_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
-                          TX_PWR_CFG_2_EXT_MCS8_CH2, txpower);
-
-       /* MCS 10,11 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS10_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_IDX],
-                          TX_PWR_CFG_2_MCS10_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_2_EXT_IDX],
-                          TX_PWR_CFG_2_EXT_MCS10_CH2, txpower);
-
-       /* MCS 12,13 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_MCS12_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_MCS12_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
-                          TX_PWR_CFG_3_EXT_MCS12_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 4, &eeprom);
-
-       /* MCS 14 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_MCS14_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_MCS14_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
-                          TX_PWR_CFG_3_EXT_MCS14_CH2, txpower);
-
-       /* MCS 15 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS15_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS15_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS15_CH2, txpower);
-
-       /* MCS 16,17 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS16_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS16_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS16_CH2, txpower);
-
-       /* MCS 18,19 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS18_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS18_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_5_IDX],
-                          TX_PWR_CFG_5_MCS18_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 5, &eeprom);
-
-       /* MCS 20,21 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS20_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS20_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS20_CH2, txpower);
-
-       /* MCS 22 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS22_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS22_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_6_IDX],
-                          TX_PWR_CFG_6_MCS22_CH2, txpower);
-
-       /* MCS 23 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS23_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS23_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_8_IDX],
-                          TX_PWR_CFG_8_MCS23_CH2, txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 6, &eeprom);
-
-       /* STBC, MCS 0,1 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_STBC0_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_STBC0_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
-                          TX_PWR_CFG_3_EXT_STBC0_CH2, txpower);
-
-       /* STBC, MCS 2,3 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_STBC2_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_IDX],
-                          TX_PWR_CFG_3_STBC2_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_3_EXT_IDX],
-                          TX_PWR_CFG_3_EXT_STBC2_CH2, txpower);
-
-       /* STBC, MCS 4,5 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0,
-                          txpower);
-
-       /* STBC, MCS 6 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2,
-                          txpower);
-
-       /* read the next four txpower values */
-       rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                     offset + 7, &eeprom);
-
-       /* STBC, MCS 7 */
-       txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0);
-       txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level,
-                                           txpower, delta);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
-                          TX_PWR_CFG_9_STBC7_CH0, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
-                          TX_PWR_CFG_9_STBC7_CH1, txpower);
-       rt2x00_set_field32(&regs[TX_PWR_CFG_9_IDX],
-                          TX_PWR_CFG_9_STBC7_CH2, txpower);
-
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]);
-
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT,
-                             regs[TX_PWR_CFG_0_EXT_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT,
-                             regs[TX_PWR_CFG_1_EXT_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT,
-                             regs[TX_PWR_CFG_2_EXT_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT,
-                             regs[TX_PWR_CFG_3_EXT_IDX]);
-       rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT,
-                             regs[TX_PWR_CFG_4_EXT_IDX]);
-
-       for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++)
-               rt2x00_dbg(rt2x00dev,
-                          "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n",
-                          (band == IEEE80211_BAND_5GHZ) ? '5' : '2',
-                          (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ?
-                                                               '4' : '2',
-                          (i > TX_PWR_CFG_9_IDX) ?
-                                       (i - TX_PWR_CFG_9_IDX - 1) : i,
-                          (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "",
-                          (unsigned long) regs[i]);
-}
-
-/*
- * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
- * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
- * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
- * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
- * Reference per rate transmit power values are located in the EEPROM at
- * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
- * current conditions (i.e. band, bandwidth, temperature, user settings).
- */
-static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev,
-                                        struct ieee80211_channel *chan,
-                                        int power_level)
-{
-       u8 txpower, r1;
-       u16 eeprom;
-       u32 reg, offset;
-       int i, is_rate_b, delta, power_ctrl;
-       enum ieee80211_band band = chan->band;
-
-       /*
-        * Calculate HT40 compensation. For 40MHz we need to add or subtract
-        * value read from EEPROM (different for 2GHz and for 5GHz).
-        */
-       delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
-
-       /*
-        * Calculate temperature compensation. Depends on measurement of current
-        * TSSI (Transmitter Signal Strength Indication) we know TX power (due
-        * to temperature or maybe other factors) is smaller or bigger than
-        * expected. We adjust it, based on TSSI reference and boundaries values
-        * provided in EEPROM.
-        */
-       switch (rt2x00dev->chip.rt) {
-       case RT2860:
-       case RT2872:
-       case RT2883:
-       case RT3070:
-       case RT3071:
-       case RT3090:
-       case RT3572:
-               delta += rt2800_get_gain_calibration_delta(rt2x00dev);
-               break;
-       default:
-               /* TODO: temperature compensation code for other chips. */
-               break;
-       }
-
-       /*
-        * Decrease power according to user settings, on devices with unknown
-        * maximum tx power. For other devices we take user power_level into
-        * consideration on rt2800_compensate_txpower().
-        */
-       delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
-                                             chan->max_power);
-
-       /*
-        * BBP_R1 controls TX power for all rates, it allow to set the following
-        * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
-        *
-        * TODO: we do not use +6 dBm option to do not increase power beyond
-        * regulatory limit, however this could be utilized for devices with
-        * CAPABILITY_POWER_LIMIT.
-        */
-       if (delta <= -12) {
-               power_ctrl = 2;
-               delta += 12;
-       } else if (delta <= -6) {
-               power_ctrl = 1;
-               delta += 6;
-       } else {
-               power_ctrl = 0;
-       }
-       rt2800_bbp_read(rt2x00dev, 1, &r1);
-       rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
-       rt2800_bbp_write(rt2x00dev, 1, r1);
-
-       offset = TX_PWR_CFG_0;
-
-       for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
-               /* just to be safe */
-               if (offset > TX_PWR_CFG_4)
-                       break;
-
-               rt2800_register_read(rt2x00dev, offset, &reg);
-
-               /* read the next four txpower values */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             i, &eeprom);
-
-               is_rate_b = i ? 0 : 1;
-               /*
-                * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
-                * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE0);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
-                * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE1);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,
-                * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE2);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
-                * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE3);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
-
-               /* read the next four txpower values */
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE,
-                                             i + 1, &eeprom);
-
-               is_rate_b = 0;
-               /*
-                * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
-                * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE0);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
-                * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE1);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
-                * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE2);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
-
-               /*
-                * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
-                * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown,
-                * TX_PWR_CFG_4: unknown
-                */
-               txpower = rt2x00_get_field16(eeprom,
-                                            EEPROM_TXPOWER_BYRATE_RATE3);
-               txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
-                                            power_level, txpower, delta);
-               rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
-
-               rt2800_register_write(rt2x00dev, offset, reg);
-
-               /* next TX_PWR_CFG register */
-               offset += 4;
-       }
-}
-
-static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                 struct ieee80211_channel *chan,
-                                 int power_level)
-{
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
-       else
-               rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
-}
-
-void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,
-                             rt2x00dev->tx_power);
-}
-EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
-
-void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
-{
-       u32     tx_pin;
-       u8      rfcsr;
-
-       /*
-        * A voltage-controlled oscillator(VCO) is an electronic oscillator
-        * designed to be controlled in oscillation frequency by a voltage
-        * input. Maybe the temperature will affect the frequency of
-        * oscillation to be shifted. The VCO calibration will be called
-        * periodically to adjust the frequency to be precision.
-       */
-
-       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
-       tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;
-       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
-
-       switch (rt2x00dev->chip.rf) {
-       case RF2020:
-       case RF3020:
-       case RF3021:
-       case RF3022:
-       case RF3320:
-       case RF3052:
-               rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
-               rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
-               break;
-       case RF3053:
-       case RF3070:
-       case RF3290:
-       case RF5360:
-       case RF5362:
-       case RF5370:
-       case RF5372:
-       case RF5390:
-       case RF5392:
-               rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-               rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-               break;
-       default:
-               return;
-       }
-
-       mdelay(1);
-
-       rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
-       if (rt2x00dev->rf_channel <= 14) {
-               switch (rt2x00dev->default_ant.tx_chain_num) {
-               case 3:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1);
-                       /* fall through */
-               case 2:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
-                       /* fall through */
-               case 1:
-               default:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
-                       break;
-               }
-       } else {
-               switch (rt2x00dev->default_ant.tx_chain_num) {
-               case 3:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1);
-                       /* fall through */
-               case 2:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
-                       /* fall through */
-               case 1:
-               default:
-                       rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);
-                       break;
-               }
-       }
-       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
-
-}
-EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
-
-static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
-                                     struct rt2x00lib_conf *libconf)
-{
-       u32 reg;
-
-       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
-                          libconf->conf->short_frame_max_tx_count);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
-                          libconf->conf->long_frame_max_tx_count);
-       rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
-}
-
-static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u32 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
-
-               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
-                                  libconf->conf->listen_interval - 1);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
-               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
-
-               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-       } else {
-               rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
-               rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
-               rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
-
-               rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-       }
-}
-
-void rt2800_config(struct rt2x00_dev *rt2x00dev,
-                  struct rt2x00lib_conf *libconf,
-                  const unsigned int flags)
-{
-       /* Always recalculate LNA gain before changing configuration */
-       rt2800_config_lna_gain(rt2x00dev, libconf);
-
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
-               rt2800_config_channel(rt2x00dev, libconf->conf,
-                                     &libconf->rf, &libconf->channel);
-               rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
-                                     libconf->conf->power_level);
-       }
-       if (flags & IEEE80211_CONF_CHANGE_POWER)
-               rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
-                                     libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
-               rt2800_config_retry_limit(rt2x00dev, libconf);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt2800_config_ps(rt2x00dev, libconf);
-}
-EXPORT_SYMBOL_GPL(rt2800_config);
-
-/*
- * Link tuning
- */
-void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
-{
-       u32 reg;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
-       qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
-}
-EXPORT_SYMBOL_GPL(rt2800_link_stats);
-
-static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
-{
-       u8 vgc;
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
-               if (rt2x00_rt(rt2x00dev, RT3070) ||
-                   rt2x00_rt(rt2x00dev, RT3071) ||
-                   rt2x00_rt(rt2x00dev, RT3090) ||
-                   rt2x00_rt(rt2x00dev, RT3290) ||
-                   rt2x00_rt(rt2x00dev, RT3390) ||
-                   rt2x00_rt(rt2x00dev, RT3572) ||
-                   rt2x00_rt(rt2x00dev, RT3593) ||
-                   rt2x00_rt(rt2x00dev, RT5390) ||
-                   rt2x00_rt(rt2x00dev, RT5392) ||
-                   rt2x00_rt(rt2x00dev, RT5592))
-                       vgc = 0x1c + (2 * rt2x00dev->lna_gain);
-               else
-                       vgc = 0x2e + rt2x00dev->lna_gain;
-       } else { /* 5GHZ band */
-               if (rt2x00_rt(rt2x00dev, RT3593))
-                       vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
-               else if (rt2x00_rt(rt2x00dev, RT5592))
-                       vgc = 0x24 + (2 * rt2x00dev->lna_gain);
-               else {
-                       if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
-                               vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3;
-                       else
-                               vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3;
-               }
-       }
-
-       return vgc;
-}
-
-static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,
-                                 struct link_qual *qual, u8 vgc_level)
-{
-       if (qual->vgc_level != vgc_level) {
-               if (rt2x00_rt(rt2x00dev, RT3572) ||
-                   rt2x00_rt(rt2x00dev, RT3593)) {
-                       rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
-                                                      vgc_level);
-               } else if (rt2x00_rt(rt2x00dev, RT5592)) {
-                       rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a);
-                       rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level);
-               } else {
-                       rt2800_bbp_write(rt2x00dev, 66, vgc_level);
-               }
-
-               qual->vgc_level = vgc_level;
-               qual->vgc_level_reg = vgc_level;
-       }
-}
-
-void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
-{
-       rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev));
-}
-EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
-
-void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
-                      const u32 count)
-{
-       u8 vgc;
-
-       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))
-               return;
-
-       /* When RSSI is better than a certain threshold, increase VGC
-        * with a chip specific value in order to improve the balance
-        * between sensibility and noise isolation.
-        */
-
-       vgc = rt2800_get_default_vgc(rt2x00dev);
-
-       switch (rt2x00dev->chip.rt) {
-       case RT3572:
-       case RT3593:
-               if (qual->rssi > -65) {
-                       if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)
-                               vgc += 0x20;
-                       else
-                               vgc += 0x10;
-               }
-               break;
-
-       case RT5592:
-               if (qual->rssi > -65)
-                       vgc += 0x20;
-               break;
-
-       default:
-               if (qual->rssi > -80)
-                       vgc += 0x10;
-               break;
-       }
-
-       rt2800_set_vgc(rt2x00dev, qual, vgc);
-}
-EXPORT_SYMBOL_GPL(rt2800_link_tuner);
-
-/*
- * Initialization functions.
- */
-static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 eeprom;
-       unsigned int i;
-       int ret;
-
-       rt2800_disable_wpdma(rt2x00dev);
-
-       ret = rt2800_drv_init_registers(rt2x00dev);
-       if (ret)
-               return ret;
-
-       rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
-       rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
-       rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1600);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-       rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
-       rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-       rt2800_config_filter(rt2x00dev, FIF_ALLMULTI);
-
-       rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
-       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, 9);
-       rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
-       rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
-
-       if (rt2x00_rt(rt2x00dev, RT3290)) {
-               rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
-               if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
-                       rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
-                       rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
-               }
-
-               rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
-               if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
-                       rt2x00_set_field32(&reg, LDO0_EN, 1);
-                       rt2x00_set_field32(&reg, LDO_BGSEL, 3);
-                       rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
-               }
-
-               rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
-               rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
-               rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
-               rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
-               rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
-
-               rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
-               rt2x00_set_field32(&reg, COEX_CFG_ANT, 0x5e);
-               rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
-
-               rt2800_register_read(rt2x00dev, COEX_CFG2, &reg);
-               rt2x00_set_field32(&reg, BT_COEX_CFG1, 0x00);
-               rt2x00_set_field32(&reg, BT_COEX_CFG0, 0x17);
-               rt2x00_set_field32(&reg, WL_COEX_CFG1, 0x93);
-               rt2x00_set_field32(&reg, WL_COEX_CFG0, 0x7f);
-               rt2800_register_write(rt2x00dev, COEX_CFG2, reg);
-
-               rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
-               rt2x00_set_field32(&reg, PLL_CONTROL, 1);
-               rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
-       }
-
-       if (rt2x00_rt(rt2x00dev, RT3071) ||
-           rt2x00_rt(rt2x00dev, RT3090) ||
-           rt2x00_rt(rt2x00dev, RT3290) ||
-           rt2x00_rt(rt2x00dev, RT3390)) {
-
-               if (rt2x00_rt(rt2x00dev, RT3290))
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
-                                             0x00000404);
-               else
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG0,
-                                             0x00000400);
-
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
-                   rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
-                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
-                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
-                                                     0x0000002c);
-                       else
-                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
-                                                     0x0000000f);
-               } else {
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
-               }
-       } else if (rt2x00_rt(rt2x00dev, RT3070)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
-
-               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c);
-               } else {
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
-               }
-       } else if (rt2800_is_305x_soc(rt2x00dev)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
-       } else if (rt2x00_rt(rt2x00dev, RT3352)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
-       } else if (rt2x00_rt(rt2x00dev, RT3572)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-               if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
-                       if (rt2x00_get_field16(eeprom,
-                                              EEPROM_NIC_CONF1_DAC_TEST))
-                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
-                                                     0x0000001f);
-                       else
-                               rt2800_register_write(rt2x00dev, TX_SW_CFG2,
-                                                     0x0000000f);
-               } else {
-                       rt2800_register_write(rt2x00dev, TX_SW_CFG2,
-                                             0x00000000);
-               }
-       } else if (rt2x00_rt(rt2x00dev, RT5390) ||
-                  rt2x00_rt(rt2x00dev, RT5392) ||
-                  rt2x00_rt(rt2x00dev, RT5592)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
-       } else {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-       }
-
-       rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
-       rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
-       rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
-       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
-       rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
-       rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
-       rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
-           rt2x00_rt(rt2x00dev, RT2883) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E))
-               rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
-       else
-               rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
-       rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
-       rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
-       rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, LED_CFG, &reg);
-       rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
-       rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
-       rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
-       rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
-       rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
-       rt2800_register_write(rt2x00dev, LED_CFG, reg);
-
-       rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
-
-       rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 31);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
-       rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
-       rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 1);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
-       rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
-       rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
-       rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
-       rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
-       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
-       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
-       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, 0);
-       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
-       if (rt2x00_is_usb(rt2x00dev)) {
-               rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
-
-               rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
-               rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
-               rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-       }
-
-       /*
-        * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
-        * although it is reserved.
-        */
-       rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
-       rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
-       rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
-
-       reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
-       rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
-
-       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
-       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
-                          IEEE80211_MAX_RTS_THRESHOLD);
-       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
-       rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
-       rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
-
-       /*
-        * Usually the CCK SIFS time should be set to 10 and the OFDM SIFS
-        * time should be set to 16. However, the original Ralink driver uses
-        * 16 for both and indeed using a value of 10 for CCK SIFS results in
-        * connection problems with 11g + CTS protection. Hence, use the same
-        * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
-        */
-       rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 314);
-       rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
-       rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
-
-       rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
-
-       /*
-        * ASIC will keep garbage value after boot, clear encryption keys.
-        */
-       for (i = 0; i < 4; i++)
-               rt2800_register_write(rt2x00dev,
-                                        SHARED_KEY_MODE_ENTRY(i), 0);
-
-       for (i = 0; i < 256; i++) {
-               rt2800_config_wcid(rt2x00dev, NULL, i);
-               rt2800_delete_wcid_attr(rt2x00dev, i);
-               rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
-       }
-
-       /*
-        * Clear all beacons
-        */
-       for (i = 0; i < 8; i++)
-               rt2800_clear_beacon_register(rt2x00dev, i);
-
-       if (rt2x00_is_usb(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
-               rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
-               rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
-       } else if (rt2x00_is_pcie(rt2x00dev)) {
-               rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
-               rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
-               rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
-       }
-
-       rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
-       rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
-       rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);
-
-       rt2800_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
-       rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
-       rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);
-
-       rt2800_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
-       rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);
-
-       rt2800_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
-       rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
-       rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);
-
-       /*
-        * Do not force the BA window size, we use the TXWI to set it
-        */
-       rt2800_register_read(rt2x00dev, AMPDU_BA_WINSIZE, &reg);
-       rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE_ENABLE, 0);
-       rt2x00_set_field32(&reg, AMPDU_BA_WINSIZE_FORCE_WINSIZE, 0);
-       rt2800_register_write(rt2x00dev, AMPDU_BA_WINSIZE, reg);
-
-       /*
-        * We must clear the error counters.
-        * These registers are cleared on read,
-        * so we may pass a useless variable to store the value.
-        */
-       rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
-       rt2800_register_read(rt2x00dev, RX_STA_CNT1, &reg);
-       rt2800_register_read(rt2x00dev, RX_STA_CNT2, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT0, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
-       rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
-
-       /*
-        * Setup leadtime for pre tbtt interrupt to 6ms
-        */
-       rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
-       rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
-       rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
-
-       /*
-        * Set up channel statistics timer
-        */
-       rt2800_register_read(rt2x00dev, CH_TIME_CFG, &reg);
-       rt2x00_set_field32(&reg, CH_TIME_CFG_EIFS_BUSY, 1);
-       rt2x00_set_field32(&reg, CH_TIME_CFG_NAV_BUSY, 1);
-       rt2x00_set_field32(&reg, CH_TIME_CFG_RX_BUSY, 1);
-       rt2x00_set_field32(&reg, CH_TIME_CFG_TX_BUSY, 1);
-       rt2x00_set_field32(&reg, CH_TIME_CFG_TMR_EN, 1);
-       rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg);
-
-       return 0;
-}
-
-static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u32 reg;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
-               if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
-                       return 0;
-
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       /*
-        * BBP was enabled after firmware was loaded,
-        * but we need to reactivate it now.
-        */
-       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-       msleep(1);
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2800_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev)
-{
-       u8 value;
-
-       rt2800_bbp_read(rt2x00dev, 4, &value);
-       rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
-       rt2800_bbp_write(rt2x00dev, 4, value);
-}
-
-static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 142, 1);
-       rt2800_bbp_write(rt2x00dev, 143, 57);
-}
-
-static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)
-{
-       const u8 glrt_table[] = {
-               0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */
-               0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */
-               0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */
-               0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */
-               0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */
-               0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */
-               0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */
-               0x2E, 0x36, 0x30, 0x6E,                                     /* 208 ~ 211 */
-       };
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(glrt_table); i++) {
-               rt2800_bbp_write(rt2x00dev, 195, 128 + i);
-               rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]);
-       }
-};
-
-static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 65, 0x2C);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-       rt2800_bbp_write(rt2x00dev, 68, 0x0B);
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-       rt2800_bbp_write(rt2x00dev, 81, 0x37);
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-       rt2800_bbp_write(rt2x00dev, 83, 0x6A);
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-       rt2800_bbp_write(rt2x00dev, 103, 0x00);
-       rt2800_bbp_write(rt2x00dev, 105, 0x05);
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-}
-
-static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)
-{
-       u16 eeprom;
-       u8 value;
-
-       rt2800_bbp_read(rt2x00dev, 138, &value);
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
-               value |= 0x20;
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
-               value &= ~0x02;
-       rt2800_bbp_write(rt2x00dev, 138, value);
-}
-
-static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 78, 0x0e);
-       rt2800_bbp_write(rt2x00dev, 80, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x01);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-}
-
-static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
-               rt2800_bbp_write(rt2x00dev, 69, 0x16);
-               rt2800_bbp_write(rt2x00dev, 73, 0x12);
-       } else {
-               rt2800_bbp_write(rt2x00dev, 69, 0x12);
-               rt2800_bbp_write(rt2x00dev, 73, 0x10);
-       }
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 81, 0x37);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
-               rt2800_bbp_write(rt2x00dev, 84, 0x19);
-       else
-               rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 103, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x05);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-}
-
-static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 79, 0x13);
-       rt2800_bbp_write(rt2x00dev, 80, 0x05);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
-           rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
-           rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E))
-               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-       else
-               rt2800_bbp_write(rt2x00dev, 103, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x05);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-
-       if (rt2x00_rt(rt2x00dev, RT3071) ||
-           rt2x00_rt(rt2x00dev, RT3090))
-               rt2800_disable_unused_dac_adc(rt2x00dev);
-}
-
-static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev)
-{
-       u8 value;
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x13);
-       rt2800_bbp_write(rt2x00dev, 75, 0x46);
-       rt2800_bbp_write(rt2x00dev, 76, 0x28);
-
-       rt2800_bbp_write(rt2x00dev, 77, 0x58);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 74, 0x0b);
-       rt2800_bbp_write(rt2x00dev, 79, 0x18);
-       rt2800_bbp_write(rt2x00dev, 80, 0x09);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x7a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x9a);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x02);
-
-       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_bbp_write(rt2x00dev, 104, 0x92);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x1c);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x03);
-
-       rt2800_bbp_write(rt2x00dev, 128, 0x12);
-
-       rt2800_bbp_write(rt2x00dev, 67, 0x24);
-       rt2800_bbp_write(rt2x00dev, 143, 0x04);
-       rt2800_bbp_write(rt2x00dev, 142, 0x99);
-       rt2800_bbp_write(rt2x00dev, 150, 0x30);
-       rt2800_bbp_write(rt2x00dev, 151, 0x2e);
-       rt2800_bbp_write(rt2x00dev, 152, 0x20);
-       rt2800_bbp_write(rt2x00dev, 153, 0x34);
-       rt2800_bbp_write(rt2x00dev, 154, 0x40);
-       rt2800_bbp_write(rt2x00dev, 155, 0x3b);
-       rt2800_bbp_write(rt2x00dev, 253, 0x04);
-
-       rt2800_bbp_read(rt2x00dev, 47, &value);
-       rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1);
-       rt2800_bbp_write(rt2x00dev, 47, value);
-
-       /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */
-       rt2800_bbp_read(rt2x00dev, 3, &value);
-       rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1);
-       rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1);
-       rt2800_bbp_write(rt2x00dev, 3, value);
-}
-
-static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 3, 0x00);
-       rt2800_bbp_write(rt2x00dev, 4, 0x50);
-
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 47, 0x48);
-
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x13);
-       rt2800_bbp_write(rt2x00dev, 75, 0x46);
-       rt2800_bbp_write(rt2x00dev, 76, 0x28);
-
-       rt2800_bbp_write(rt2x00dev, 77, 0x59);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 78, 0x0e);
-       rt2800_bbp_write(rt2x00dev, 80, 0x08);
-       rt2800_bbp_write(rt2x00dev, 81, 0x37);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 88, 0x90);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x02);
-
-       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_bbp_write(rt2x00dev, 104, 0x92);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x34);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x05);
-
-       rt2800_bbp_write(rt2x00dev, 120, 0x50);
-
-       rt2800_bbp_write(rt2x00dev, 137, 0x0f);
-
-       rt2800_bbp_write(rt2x00dev, 163, 0xbd);
-       /* 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_3390(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 79, 0x13);
-       rt2800_bbp_write(rt2x00dev, 80, 0x05);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))
-               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-       else
-               rt2800_bbp_write(rt2x00dev, 103, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x05);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-
-       rt2800_disable_unused_dac_adc(rt2x00dev);
-}
-
-static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x10);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 79, 0x13);
-       rt2800_bbp_write(rt2x00dev, 80, 0x05);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x6a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x99);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x00);
-
-       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x05);
-
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-
-       rt2800_disable_unused_dac_adc(rt2x00dev);
-}
-
-static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_init_bbp_early(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 79, 0x13);
-       rt2800_bbp_write(rt2x00dev, 80, 0x05);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-       rt2800_bbp_write(rt2x00dev, 137, 0x0f);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x19);
-
-       /* Enable DC filter */
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E))
-               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-}
-
-static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
-{
-       int ant, div_mode;
-       u16 eeprom;
-       u8 value;
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       rt2800_bbp_write(rt2x00dev, 65, 0x2c);
-       rt2800_bbp_write(rt2x00dev, 66, 0x38);
-
-       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
-
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
-       rt2800_bbp_write(rt2x00dev, 73, 0x13);
-       rt2800_bbp_write(rt2x00dev, 75, 0x46);
-       rt2800_bbp_write(rt2x00dev, 76, 0x28);
-
-       rt2800_bbp_write(rt2x00dev, 77, 0x59);
-
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
-       rt2800_bbp_write(rt2x00dev, 79, 0x13);
-       rt2800_bbp_write(rt2x00dev, 80, 0x05);
-       rt2800_bbp_write(rt2x00dev, 81, 0x33);
-
-       rt2800_bbp_write(rt2x00dev, 82, 0x62);
-
-       rt2800_bbp_write(rt2x00dev, 83, 0x7a);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x9a);
-
-       rt2800_bbp_write(rt2x00dev, 86, 0x38);
-
-       if (rt2x00_rt(rt2x00dev, RT5392))
-               rt2800_bbp_write(rt2x00dev, 88, 0x90);
-
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x02);
-
-       if (rt2x00_rt(rt2x00dev, RT5392)) {
-               rt2800_bbp_write(rt2x00dev, 95, 0x9a);
-               rt2800_bbp_write(rt2x00dev, 98, 0x12);
-       }
-
-       rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_bbp_write(rt2x00dev, 104, 0x92);
-
-       rt2800_bbp_write(rt2x00dev, 105, 0x3c);
-
-       if (rt2x00_rt(rt2x00dev, RT5390))
-               rt2800_bbp_write(rt2x00dev, 106, 0x03);
-       else if (rt2x00_rt(rt2x00dev, RT5392))
-               rt2800_bbp_write(rt2x00dev, 106, 0x12);
-       else
-               WARN_ON(1);
-
-       rt2800_bbp_write(rt2x00dev, 128, 0x12);
-
-       if (rt2x00_rt(rt2x00dev, RT5392)) {
-               rt2800_bbp_write(rt2x00dev, 134, 0xd0);
-               rt2800_bbp_write(rt2x00dev, 135, 0xf6);
-       }
-
-       rt2800_disable_unused_dac_adc(rt2x00dev);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
-       div_mode = rt2x00_get_field16(eeprom,
-                                     EEPROM_NIC_CONF1_ANT_DIVERSITY);
-       ant = (div_mode == 3) ? 1 : 0;
-
-       /* check if this is a Bluetooth combo card */
-       if (rt2x00_has_cap_bt_coexist(rt2x00dev)) {
-               u32 reg;
-
-               rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-               rt2x00_set_field32(&reg, GPIO_CTRL_DIR3, 0);
-               rt2x00_set_field32(&reg, GPIO_CTRL_DIR6, 0);
-               rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 0);
-               rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 0);
-               if (ant == 0)
-                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL3, 1);
-               else if (ant == 1)
-                       rt2x00_set_field32(&reg, GPIO_CTRL_VAL6, 1);
-               rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
-       }
-
-       /* This chip has hardware antenna diversity*/
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {
-               rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */
-               rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */
-               rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */
-       }
-
-       rt2800_bbp_read(rt2x00dev, 152, &value);
-       if (ant == 0)
-               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
-       else
-               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
-       rt2800_bbp_write(rt2x00dev, 152, value);
-
-       rt2800_init_freq_calibration(rt2x00dev);
-}
-
-static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
-{
-       int ant, div_mode;
-       u16 eeprom;
-       u8 value;
-
-       rt2800_init_bbp_early(rt2x00dev);
-
-       rt2800_bbp_read(rt2x00dev, 105, &value);
-       rt2x00_set_field8(&value, BBP105_MLD,
-                         rt2x00dev->default_ant.rx_chain_num == 2);
-       rt2800_bbp_write(rt2x00dev, 105, value);
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 20, 0x06);
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-       rt2800_bbp_write(rt2x00dev, 65, 0x2C);
-       rt2800_bbp_write(rt2x00dev, 68, 0xDD);
-       rt2800_bbp_write(rt2x00dev, 69, 0x1A);
-       rt2800_bbp_write(rt2x00dev, 70, 0x05);
-       rt2800_bbp_write(rt2x00dev, 73, 0x13);
-       rt2800_bbp_write(rt2x00dev, 74, 0x0F);
-       rt2800_bbp_write(rt2x00dev, 75, 0x4F);
-       rt2800_bbp_write(rt2x00dev, 76, 0x28);
-       rt2800_bbp_write(rt2x00dev, 77, 0x59);
-       rt2800_bbp_write(rt2x00dev, 84, 0x9A);
-       rt2800_bbp_write(rt2x00dev, 86, 0x38);
-       rt2800_bbp_write(rt2x00dev, 88, 0x90);
-       rt2800_bbp_write(rt2x00dev, 91, 0x04);
-       rt2800_bbp_write(rt2x00dev, 92, 0x02);
-       rt2800_bbp_write(rt2x00dev, 95, 0x9a);
-       rt2800_bbp_write(rt2x00dev, 98, 0x12);
-       rt2800_bbp_write(rt2x00dev, 103, 0xC0);
-       rt2800_bbp_write(rt2x00dev, 104, 0x92);
-       /* FIXME BBP105 owerwrite */
-       rt2800_bbp_write(rt2x00dev, 105, 0x3C);
-       rt2800_bbp_write(rt2x00dev, 106, 0x35);
-       rt2800_bbp_write(rt2x00dev, 128, 0x12);
-       rt2800_bbp_write(rt2x00dev, 134, 0xD0);
-       rt2800_bbp_write(rt2x00dev, 135, 0xF6);
-       rt2800_bbp_write(rt2x00dev, 137, 0x0F);
-
-       /* Initialize GLRT (Generalized Likehood Radio Test) */
-       rt2800_init_bbp_5592_glrt(rt2x00dev);
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
-       div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY);
-       ant = (div_mode == 3) ? 1 : 0;
-       rt2800_bbp_read(rt2x00dev, 152, &value);
-       if (ant == 0) {
-               /* Main antenna */
-               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
-       } else {
-               /* Auxiliary antenna */
-               rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
-       }
-       rt2800_bbp_write(rt2x00dev, 152, value);
-
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) {
-               rt2800_bbp_read(rt2x00dev, 254, &value);
-               rt2x00_set_field8(&value, BBP254_BIT7, 1);
-               rt2800_bbp_write(rt2x00dev, 254, value);
-       }
-
-       rt2800_init_freq_calibration(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 84, 0x19);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
-               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-}
-
-static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
-       u8 value;
-
-       if (rt2800_is_305x_soc(rt2x00dev))
-               rt2800_init_bbp_305x_soc(rt2x00dev);
-
-       switch (rt2x00dev->chip.rt) {
-       case RT2860:
-       case RT2872:
-       case RT2883:
-               rt2800_init_bbp_28xx(rt2x00dev);
-               break;
-       case RT3070:
-       case RT3071:
-       case RT3090:
-               rt2800_init_bbp_30xx(rt2x00dev);
-               break;
-       case RT3290:
-               rt2800_init_bbp_3290(rt2x00dev);
-               break;
-       case RT3352:
-               rt2800_init_bbp_3352(rt2x00dev);
-               break;
-       case RT3390:
-               rt2800_init_bbp_3390(rt2x00dev);
-               break;
-       case RT3572:
-               rt2800_init_bbp_3572(rt2x00dev);
-               break;
-       case RT3593:
-               rt2800_init_bbp_3593(rt2x00dev);
-               return;
-       case RT5390:
-       case RT5392:
-               rt2800_init_bbp_53xx(rt2x00dev);
-               break;
-       case RT5592:
-               rt2800_init_bbp_5592(rt2x00dev);
-               return;
-       }
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i,
-                                             &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt2800_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-}
-
-static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
-       rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
-       rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
-}
-
-static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
-                               u8 filter_target)
-{
-       unsigned int i;
-       u8 bbp;
-       u8 rfcsr;
-       u8 passband;
-       u8 stopband;
-       u8 overtuned = 0;
-       u8 rfcsr24 = (bw40) ? 0x27 : 0x07;
-
-       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
-
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
-       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
-       rt2800_bbp_write(rt2x00dev, 4, bbp);
-
-       rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
-       rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
-       rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
-
-       /*
-        * Set power & frequency of passband test tone
-        */
-       rt2800_bbp_write(rt2x00dev, 24, 0);
-
-       for (i = 0; i < 100; i++) {
-               rt2800_bbp_write(rt2x00dev, 25, 0x90);
-               msleep(1);
-
-               rt2800_bbp_read(rt2x00dev, 55, &passband);
-               if (passband)
-                       break;
-       }
-
-       /*
-        * Set power & frequency of stopband test tone
-        */
-       rt2800_bbp_write(rt2x00dev, 24, 0x06);
-
-       for (i = 0; i < 100; i++) {
-               rt2800_bbp_write(rt2x00dev, 25, 0x90);
-               msleep(1);
-
-               rt2800_bbp_read(rt2x00dev, 55, &stopband);
-
-               if ((passband - stopband) <= filter_target) {
-                       rfcsr24++;
-                       overtuned += ((passband - stopband) == filter_target);
-               } else
-                       break;
-
-               rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
-       }
-
-       rfcsr24 -= !!overtuned;
-
-       rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
-       return rfcsr24;
-}
-
-static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
-                                      const unsigned int rf_reg)
-{
-       u8 rfcsr;
-
-       rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
-       rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
-       rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
-       msleep(1);
-       rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0);
-       rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
-}
-
-static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 filter_tgt_bw20;
-       u8 filter_tgt_bw40;
-       u8 rfcsr, bbp;
-
-       /*
-        * TODO: sync filter_tgt values with vendor driver
-        */
-       if (rt2x00_rt(rt2x00dev, RT3070)) {
-               filter_tgt_bw20 = 0x16;
-               filter_tgt_bw40 = 0x19;
-       } else {
-               filter_tgt_bw20 = 0x13;
-               filter_tgt_bw40 = 0x15;
-       }
-
-       drv_data->calibration_bw20 =
-               rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20);
-       drv_data->calibration_bw40 =
-               rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);
-
-       /*
-        * Save BBP 25 & 26 values for later use in channel switching (for 3052)
-        */
-       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
-       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
-
-       /*
-        * Set back to initial state
-        */
-       rt2800_bbp_write(rt2x00dev, 24, 0);
-
-       rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
-       rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
-
-       /*
-        * Set BBP back to BW20
-        */
-       rt2800_bbp_read(rt2x00dev, 4, &bbp);
-       rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
-       rt2800_bbp_write(rt2x00dev, 4, bbp);
-}
-
-static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 min_gain, rfcsr, bbp;
-       u16 eeprom;
-
-       rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-
-       rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
-       if (rt2x00_rt(rt2x00dev, RT3070) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-               if (!rt2x00_has_cap_external_lna_bg(rt2x00dev))
-                       rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
-       }
-
-       min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;
-       if (drv_data->txmixer_gain_24g >= min_gain) {
-               rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
-                                 drv_data->txmixer_gain_24g);
-       }
-
-       rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
-
-       if (rt2x00_rt(rt2x00dev, RT3090)) {
-               /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
-               rt2800_bbp_read(rt2x00dev, 138, &bbp);
-               rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
-               if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
-                       rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
-               if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
-                       rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
-               rt2800_bbp_write(rt2x00dev, 138, bbp);
-       }
-
-       if (rt2x00_rt(rt2x00dev, RT3070)) {
-               rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
-               if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
-                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
-               else
-                       rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
-               rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
-       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
-                  rt2x00_rt(rt2x00dev, RT3090) ||
-                  rt2x00_rt(rt2x00dev, RT3390)) {
-               rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
-               rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
-               rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
-               rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-               rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
-               rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
-
-               rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
-               rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
-
-               rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
-               rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
-       }
-}
-
-static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u8 rfcsr;
-       u8 tx_gain;
-
-       rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 50, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
-       tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g,
-                                   RFCSR17_TXMIXER_GAIN);
-       rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain);
-       rt2800_rfcsr_write(rt2x00dev, 51, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-       rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
-       rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
-       rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
-       rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-
-       /* TODO: enable stream mode */
-}
-
-static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
-{
-       u8 reg;
-       u16 eeprom;
-
-       /*  Turn off unused DAC1 and ADC1 to reduce power consumption */
-       rt2800_bbp_read(rt2x00dev, 138, &reg);
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
-               rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
-               rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
-       rt2800_bbp_write(rt2x00dev, 138, reg);
-
-       rt2800_rfcsr_read(rt2x00dev, 38, &reg);
-       rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 38, reg);
-
-       rt2800_rfcsr_read(rt2x00dev, 39, &reg);
-       rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
-       rt2800_rfcsr_write(rt2x00dev, 39, reg);
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_rfcsr_read(rt2x00dev, 30, &reg);
-       rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
-       rt2800_rfcsr_write(rt2x00dev, 30, reg);
-}
-
-static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
-       rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
-       rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
-}
-
-static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
-{
-       u8 rfcsr;
-       u16 eeprom;
-       u32 reg;
-
-       /* XXX vendor driver do this only for 3070 */
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x60);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x41);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x7b);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
-       rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
-
-       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
-               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
-               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
-               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-       } else if (rt2x00_rt(rt2x00dev, RT3071) ||
-                  rt2x00_rt(rt2x00dev, RT3090)) {
-               rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
-
-               rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-               rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
-               rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
-               rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-               rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
-               if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-                   rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
-                       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1,
-                                          &eeprom);
-                       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
-                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
-                       else
-                               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
-               }
-               rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
-               rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
-               rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
-               rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
-       }
-
-       rt2800_rx_filter_calibration(rt2x00dev);
-
-       if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-           rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E))
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
-{
-       u8 rfcsr;
-
-       rt2800_rf_init_calibration(rt2x00dev, 2);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
-       rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
-       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, 0x05);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
-       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
-       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
-       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
-       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
-       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
-       rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
-       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
-       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
-       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
-       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
-       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
-       rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
-       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
-       rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
-       rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
-       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
-       rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
-
-       rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
-       rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x18);
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x33);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0xd2);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x42);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x1c);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x5a);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0x01);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x45);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x03);
-       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, 0x01);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 36, 0xbd);
-       rt2800_rfcsr_write(rt2x00dev, 37, 0x3c);
-       rt2800_rfcsr_write(rt2x00dev, 38, 0x5f);
-       rt2800_rfcsr_write(rt2x00dev, 39, 0xc5);
-       rt2800_rfcsr_write(rt2x00dev, 40, 0x33);
-       rt2800_rfcsr_write(rt2x00dev, 41, 0x5b);
-       rt2800_rfcsr_write(rt2x00dev, 42, 0x5b);
-       rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 46, 0xdd);
-       rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
-       rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
-       rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 50, 0x2d);
-       rt2800_rfcsr_write(rt2x00dev, 51, 0x7f);
-       rt2800_rfcsr_write(rt2x00dev, 52, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 53, 0x52);
-       rt2800_rfcsr_write(rt2x00dev, 54, 0x1b);
-       rt2800_rfcsr_write(rt2x00dev, 55, 0x7f);
-       rt2800_rfcsr_write(rt2x00dev, 56, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 57, 0x52);
-       rt2800_rfcsr_write(rt2x00dev, 58, 0x1b);
-       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);
-
-       rt2800_rx_filter_calibration(rt2x00dev);
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
-       rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x62);
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x8b);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x42);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x34);
-       rt2800_rfcsr_write(rt2x00dev, 8, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0xc0);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x61);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x3b);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0xe0);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0xe0);
-       rt2800_rfcsr_write(rt2x00dev, 17, 0x94);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x5c);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0xb2);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0xf6);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x14);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x3d);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x41);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
-
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
-       rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
-       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
-
-       rt2800_rx_filter_calibration(rt2x00dev);
-
-       if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
-{
-       u8 rfcsr;
-       u32 reg;
-
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 4, 0x4c);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x05);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0xd8);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0xc3);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0xf1);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0xb9);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x70);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x65);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0xa0);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x53);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0x4c);
-       rt2800_rfcsr_write(rt2x00dev, 17, 0x23);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0xac);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x93);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0xb3);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0xd0);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x3c);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x15);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x85);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
-
-       rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
-       rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
-       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
-       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-       msleep(1);
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
-       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
-       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
-       rt2800_rx_filter_calibration(rt2x00dev);
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
-}
-
-static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev)
-{
-       u8 bbp;
-       bool txbf_enabled = false; /* FIXME */
-
-       rt2800_bbp_read(rt2x00dev, 105, &bbp);
-       if (rt2x00dev->default_ant.rx_chain_num == 1)
-               rt2x00_set_field8(&bbp, BBP105_MLD, 0);
-       else
-               rt2x00_set_field8(&bbp, BBP105_MLD, 1);
-       rt2800_bbp_write(rt2x00dev, 105, bbp);
-
-       rt2800_bbp4_mac_if_ctrl(rt2x00dev);
-
-       rt2800_bbp_write(rt2x00dev, 92, 0x02);
-       rt2800_bbp_write(rt2x00dev, 82, 0x82);
-       rt2800_bbp_write(rt2x00dev, 106, 0x05);
-       rt2800_bbp_write(rt2x00dev, 104, 0x92);
-       rt2800_bbp_write(rt2x00dev, 88, 0x90);
-       rt2800_bbp_write(rt2x00dev, 148, 0xc8);
-       rt2800_bbp_write(rt2x00dev, 47, 0x48);
-       rt2800_bbp_write(rt2x00dev, 120, 0x50);
-
-       if (txbf_enabled)
-               rt2800_bbp_write(rt2x00dev, 163, 0xbd);
-       else
-               rt2800_bbp_write(rt2x00dev, 163, 0x9d);
-
-       /* SNR mapping */
-       rt2800_bbp_write(rt2x00dev, 142, 6);
-       rt2800_bbp_write(rt2x00dev, 143, 160);
-       rt2800_bbp_write(rt2x00dev, 142, 7);
-       rt2800_bbp_write(rt2x00dev, 143, 161);
-       rt2800_bbp_write(rt2x00dev, 142, 8);
-       rt2800_bbp_write(rt2x00dev, 143, 162);
-
-       /* ADC/DAC control */
-       rt2800_bbp_write(rt2x00dev, 31, 0x08);
-
-       /* RX AGC energy lower bound in log2 */
-       rt2800_bbp_write(rt2x00dev, 68, 0x0b);
-
-       /* FIXME: BBP 105 owerwrite? */
-       rt2800_bbp_write(rt2x00dev, 105, 0x04);
-
-}
-
-static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u32 reg;
-       u8 rfcsr;
-
-       /* Disable GPIO #4 and #7 function for LAN PE control */
-       rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
-       rt2x00_set_field32(&reg, GPIO_SWITCH_4, 0);
-       rt2x00_set_field32(&reg, GPIO_SWITCH_7, 0);
-       rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
-
-       /* Initialize default register values */
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 8, 0xf1);
-       rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x4e);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 32, 0x78);
-       rt2800_rfcsr_write(rt2x00dev, 33, 0x3b);
-       rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0xe0);
-       rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
-       rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
-       rt2800_rfcsr_write(rt2x00dev, 44, 0xd3);
-       rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
-       rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
-       rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
-       rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
-       rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
-       rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
-       rt2800_rfcsr_write(rt2x00dev, 53, 0x18);
-       rt2800_rfcsr_write(rt2x00dev, 54, 0x18);
-       rt2800_rfcsr_write(rt2x00dev, 55, 0x18);
-       rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
-       rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
-
-       /* Initiate calibration */
-       /* TODO: use rt2800_rf_init_calibration ? */
-       rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
-       rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
-
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr);
-       rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1);
-       rt2800_rfcsr_write(rt2x00dev, 18, rfcsr);
-
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
-       rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
-       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-       usleep_range(1000, 1500);
-       rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
-       rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
-       rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
-       /* Set initial values for RX filter calibration */
-       drv_data->calibration_bw20 = 0x1f;
-       drv_data->calibration_bw40 = 0x2f;
-
-       /* Save BBP 25 & 26 values for later use in channel switching */
-       rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
-       rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-       rt2800_normal_mode_setup_3593(rt2x00dev);
-
-       rt3593_post_bbp_init(rt2x00dev);
-
-       /* TODO: enable stream mode support */
-}
-
-static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_rf_init_calibration(rt2x00dev, 2);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
-
-       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
-       if (rt2x00_is_usb(rt2x00dev) &&
-           rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
-
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
-       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
-       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
-
-       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
-       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
-       rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);
-       rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);
-       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
-       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 46, 0x7b);
-       rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
-
-       rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 53, 0x84);
-       rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
-       rt2800_rfcsr_write(rt2x00dev, 55, 0x44);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 56, 0x42);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
-       rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
-       rt2800_rfcsr_write(rt2x00dev, 59, 0x8f);
-
-       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
-               if (rt2x00_is_usb(rt2x00dev))
-                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
-               else
-                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd5);
-       } else {
-               if (rt2x00_is_usb(rt2x00dev))
-                       rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
-               else
-                       rt2800_rfcsr_write(rt2x00dev, 61, 0xb5);
-       }
-       rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
-
-       rt2800_normal_mode_setup_5xxx(rt2x00dev);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_rf_init_calibration(rt2x00dev, 2);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
-       rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
-       rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x4d);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0x8d);
-       rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 23, 0x0b);
-       rt2800_rfcsr_write(rt2x00dev, 24, 0x44);
-       rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
-       rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-       rt2800_rfcsr_write(rt2x00dev, 32, 0x20);
-       rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
-       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
-       rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 38, 0x89);
-       rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
-       rt2800_rfcsr_write(rt2x00dev, 40, 0x0f);
-       rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
-       rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
-       rt2800_rfcsr_write(rt2x00dev, 43, 0x9b);
-       rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
-       rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
-       rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
-       rt2800_rfcsr_write(rt2x00dev, 47, 0x0c);
-       rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
-       rt2800_rfcsr_write(rt2x00dev, 50, 0x94);
-       rt2800_rfcsr_write(rt2x00dev, 51, 0x3a);
-       rt2800_rfcsr_write(rt2x00dev, 52, 0x48);
-       rt2800_rfcsr_write(rt2x00dev, 53, 0x44);
-       rt2800_rfcsr_write(rt2x00dev, 54, 0x38);
-       rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
-       rt2800_rfcsr_write(rt2x00dev, 56, 0xa1);
-       rt2800_rfcsr_write(rt2x00dev, 57, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 58, 0x39);
-       rt2800_rfcsr_write(rt2x00dev, 59, 0x07);
-       rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
-       rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
-       rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
-       rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
-
-       rt2800_normal_mode_setup_5xxx(rt2x00dev);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_rf_init_calibration(rt2x00dev, 30);
-
-       rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 6, 0xE4);
-       rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
-       rt2800_rfcsr_write(rt2x00dev, 19, 0x4D);
-       rt2800_rfcsr_write(rt2x00dev, 20, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 21, 0x8D);
-       rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
-       rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
-       rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
-       rt2800_rfcsr_write(rt2x00dev, 33, 0xC0);
-       rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
-       rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
-       rt2800_rfcsr_write(rt2x00dev, 47, 0x0C);
-       rt2800_rfcsr_write(rt2x00dev, 53, 0x22);
-       rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
-
-       rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
-       msleep(1);
-
-       rt2800_adjust_freq_offset(rt2x00dev);
-
-       /* Enable DC filter */
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
-               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-
-       rt2800_normal_mode_setup_5xxx(rt2x00dev);
-
-       if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
-               rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-
-       rt2800_led_open_drain_enable(rt2x00dev);
-}
-
-static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
-{
-       if (rt2800_is_305x_soc(rt2x00dev)) {
-               rt2800_init_rfcsr_305x_soc(rt2x00dev);
-               return;
-       }
-
-       switch (rt2x00dev->chip.rt) {
-       case RT3070:
-       case RT3071:
-       case RT3090:
-               rt2800_init_rfcsr_30xx(rt2x00dev);
-               break;
-       case RT3290:
-               rt2800_init_rfcsr_3290(rt2x00dev);
-               break;
-       case RT3352:
-               rt2800_init_rfcsr_3352(rt2x00dev);
-               break;
-       case RT3390:
-               rt2800_init_rfcsr_3390(rt2x00dev);
-               break;
-       case RT3572:
-               rt2800_init_rfcsr_3572(rt2x00dev);
-               break;
-       case RT3593:
-               rt2800_init_rfcsr_3593(rt2x00dev);
-               break;
-       case RT5390:
-               rt2800_init_rfcsr_5390(rt2x00dev);
-               break;
-       case RT5392:
-               rt2800_init_rfcsr_5392(rt2x00dev);
-               break;
-       case RT5592:
-               rt2800_init_rfcsr_5592(rt2x00dev);
-               break;
-       }
-}
-
-int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 word;
-
-       /*
-        * Initialize MAC registers.
-        */
-       if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
-                    rt2800_init_registers(rt2x00dev)))
-               return -EIO;
-
-       /*
-        * Wait BBP/RF to wake up.
-        */
-       if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
-               return -EIO;
-
-       /*
-        * Send signal during boot time to initialize firmware.
-        */
-       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-       if (rt2x00_is_usb(rt2x00dev))
-               rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
-       rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-       msleep(1);
-
-       /*
-        * Make sure BBP is up and running.
-        */
-       if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))
-               return -EIO;
-
-       /*
-        * Initialize BBP/RF registers.
-        */
-       rt2800_init_bbp(rt2x00dev);
-       rt2800_init_rfcsr(rt2x00dev);
-
-       if (rt2x00_is_usb(rt2x00dev) &&
-           (rt2x00_rt(rt2x00dev, RT3070) ||
-            rt2x00_rt(rt2x00dev, RT3071) ||
-            rt2x00_rt(rt2x00dev, RT3572))) {
-               udelay(200);
-               rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
-               udelay(10);
-       }
-
-       /*
-        * Enable RX.
-        */
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-       udelay(50);
-
-       rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
-       rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-       rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-       /*
-        * Initialize LED control
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
-       rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
-                          word & 0xff, (word >> 8) & 0xff);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
-       rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
-                          word & 0xff, (word >> 8) & 0xff);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
-       rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
-                          word & 0xff, (word >> 8) & 0xff);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_enable_radio);
-
-void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2800_disable_wpdma(rt2x00dev);
-
-       /* Wait for DMA, ignore error */
-       rt2800_wait_wpdma_ready(rt2x00dev);
-
-       rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-       rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-}
-EXPORT_SYMBOL_GPL(rt2800_disable_radio);
-
-int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 efuse_ctrl_reg;
-
-       if (rt2x00_rt(rt2x00dev, RT3290))
-               efuse_ctrl_reg = EFUSE_CTRL_3290;
-       else
-               efuse_ctrl_reg = EFUSE_CTRL;
-
-       rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
-       return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
-}
-EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
-
-static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
-{
-       u32 reg;
-       u16 efuse_ctrl_reg;
-       u16 efuse_data0_reg;
-       u16 efuse_data1_reg;
-       u16 efuse_data2_reg;
-       u16 efuse_data3_reg;
-
-       if (rt2x00_rt(rt2x00dev, RT3290)) {
-               efuse_ctrl_reg = EFUSE_CTRL_3290;
-               efuse_data0_reg = EFUSE_DATA0_3290;
-               efuse_data1_reg = EFUSE_DATA1_3290;
-               efuse_data2_reg = EFUSE_DATA2_3290;
-               efuse_data3_reg = EFUSE_DATA3_3290;
-       } else {
-               efuse_ctrl_reg = EFUSE_CTRL;
-               efuse_data0_reg = EFUSE_DATA0;
-               efuse_data1_reg = EFUSE_DATA1;
-               efuse_data2_reg = EFUSE_DATA2;
-               efuse_data3_reg = EFUSE_DATA3;
-       }
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
-       rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
-       rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
-       rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
-       rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
-
-       /* Wait until the EEPROM has been loaded */
-       rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
-       /* Apparently the data is read from end to start */
-       rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
-       /* The returned value is in CPU order, but eeprom is le */
-       *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
-       *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
-       *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
-       rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
-       *(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-
-       for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
-               rt2800_efuse_read(rt2x00dev, i);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
-
-static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)
-{
-       u16 word;
-
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               return 0;
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
-       if ((word & 0x00ff) != 0x00ff)
-               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL);
-
-       return 0;
-}
-
-static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev)
-{
-       u16 word;
-
-       if (rt2x00_rt(rt2x00dev, RT3593))
-               return 0;
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word);
-       if ((word & 0x00ff) != 0x00ff)
-               return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL);
-
-       return 0;
-}
-
-static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u16 word;
-       u8 *mac;
-       u8 default_lna_gain;
-       int retval;
-
-       /*
-        * Read the EEPROM.
-        */
-       retval = rt2800_read_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
-       } else if (rt2x00_rt(rt2x00dev, RT2860) ||
-                  rt2x00_rt(rt2x00dev, RT2872)) {
-               /*
-                * There is a max of 2 RX streams for RT28x0 series
-                */
-               if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2)
-                       rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
-       }
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
-       }
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
-       if ((word & 0x00ff) == 0x00ff) {
-               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
-       }
-       if ((word & 0xff00) == 0xff00) {
-               rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
-                                  LED_MODE_TXRX_ACTIVITY);
-               rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
-               rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);
-       }
-
-       /*
-        * During the LNA validation we are going to use
-        * lna0 as correct value. Note that EEPROM_LNA
-        * is never validated.
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
-       default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
-       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
-               rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
-       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
-               rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
-       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
-
-       drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev);
-
-       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_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,
-                                          default_lna_gain);
-       }
-       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
-
-       drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
-       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
-               rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
-       if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
-               rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
-       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
-
-       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_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,
-                                          default_lna_gain);
-       }
-       rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
-
-       if (rt2x00_rt(rt2x00dev, RT3593)) {
-               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)
-                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
-                                          default_lna_gain);
-               if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 ||
-                   rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff)
-                       rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1,
-                                          default_lna_gain);
-               rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word);
-       }
-
-       return 0;
-}
-
-static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u16 value;
-       u16 eeprom;
-       u16 rf;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
-
-       /*
-        * Identify RF chipset by EEPROM value
-        * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
-        * RT53xx: defined in "EEPROM_CHIP_ID" field
-        */
-       if (rt2x00_rt(rt2x00dev, RT3290) ||
-           rt2x00_rt(rt2x00dev, RT5390) ||
-           rt2x00_rt(rt2x00dev, RT5392))
-               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
-       else
-               rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
-
-       switch (rf) {
-       case RF2820:
-       case RF2850:
-       case RF2720:
-       case RF2750:
-       case RF3020:
-       case RF2020:
-       case RF3021:
-       case RF3022:
-       case RF3052:
-       case RF3053:
-       case RF3070:
-       case RF3290:
-       case RF3320:
-       case RF3322:
-       case RF5360:
-       case RF5362:
-       case RF5370:
-       case RF5372:
-       case RF5390:
-       case RF5392:
-       case RF5592:
-               break;
-       default:
-               rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
-                          rf);
-               return -ENODEV;
-       }
-
-       rt2x00_set_rf(rt2x00dev, rf);
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx_chain_num =
-           rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);
-       rt2x00dev->default_ant.rx_chain_num =
-           rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
-
-       rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
-
-       if (rt2x00_rt(rt2x00dev, RT3070) ||
-           rt2x00_rt(rt2x00dev, RT3090) ||
-           rt2x00_rt(rt2x00dev, RT3352) ||
-           rt2x00_rt(rt2x00dev, RT3390)) {
-               value = rt2x00_get_field16(eeprom,
-                               EEPROM_NIC_CONF1_ANT_DIVERSITY);
-               switch (value) {
-               case 0:
-               case 1:
-               case 2:
-                       rt2x00dev->default_ant.tx = ANTENNA_A;
-                       rt2x00dev->default_ant.rx = ANTENNA_A;
-                       break;
-               case 3:
-                       rt2x00dev->default_ant.tx = ANTENNA_A;
-                       rt2x00dev->default_ant.rx = ANTENNA_B;
-                       break;
-               }
-       } else {
-               rt2x00dev->default_ant.tx = ANTENNA_A;
-               rt2x00dev->default_ant.rx = ANTENNA_A;
-       }
-
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) {
-               rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */
-               rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */
-       }
-
-       /*
-        * Determine external LNA informations.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
-               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
-               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
-
-       /*
-        * Detect if this device has an hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-
-       /*
-        * Detect if this device has Bluetooth co-existence.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST))
-               __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
-
-       /*
-        * Read frequency offset and RF programming sequence.
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
-
-       /*
-        * Store led settings, for correct led behaviour.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
-       rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
-
-       rt2x00dev->led_mcu_reg = eeprom;
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       /*
-        * Check if support EIRP tx power limit feature.
-        */
-       rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
-
-       if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
-                                       EIRP_MAX_TX_POWER_LIMIT)
-               __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
-
-       return 0;
-}
-
-/*
- * RF value list for rt28xx
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
- */
-static const struct rf_channel rf_vals[] = {
-       { 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
-       { 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
-       { 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
-       { 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
-       { 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
-       { 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
-       { 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
-       { 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
-       { 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
-       { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
-       { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
-       { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
-       { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
-       { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
-       { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
-       { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
-       { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
-       { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
-       { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
-       { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
-       { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
-       { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
-       { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
-       { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
-       { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
-       { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
-       { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
-       { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
-       { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
-       { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
-       { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
-       { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
-       { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
-       { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
-       { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
-       { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
-       { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
-       { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
-       { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
-       { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
-
-       /* 802.11 UNII */
-       { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
-       { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
-       { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
-       { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
-       { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
-       { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
-       { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
-       { 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
-       { 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
-       { 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
-       { 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
-
-       /* 802.11 Japan */
-       { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
-       { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
-       { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
-       { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
-       { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
-       { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
-       { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
-};
-
-/*
- * RF value list for rt3xxx
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053)
- */
-static const struct rf_channel rf_vals_3x[] = {
-       {1,  241, 2, 2 },
-       {2,  241, 2, 7 },
-       {3,  242, 2, 2 },
-       {4,  242, 2, 7 },
-       {5,  243, 2, 2 },
-       {6,  243, 2, 7 },
-       {7,  244, 2, 2 },
-       {8,  244, 2, 7 },
-       {9,  245, 2, 2 },
-       {10, 245, 2, 7 },
-       {11, 246, 2, 2 },
-       {12, 246, 2, 7 },
-       {13, 247, 2, 2 },
-       {14, 248, 2, 4 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       {36, 0x56, 0, 4},
-       {38, 0x56, 0, 6},
-       {40, 0x56, 0, 8},
-       {44, 0x57, 0, 0},
-       {46, 0x57, 0, 2},
-       {48, 0x57, 0, 4},
-       {52, 0x57, 0, 8},
-       {54, 0x57, 0, 10},
-       {56, 0x58, 0, 0},
-       {60, 0x58, 0, 4},
-       {62, 0x58, 0, 6},
-       {64, 0x58, 0, 8},
-
-       /* 802.11 HyperLan 2 */
-       {100, 0x5b, 0, 8},
-       {102, 0x5b, 0, 10},
-       {104, 0x5c, 0, 0},
-       {108, 0x5c, 0, 4},
-       {110, 0x5c, 0, 6},
-       {112, 0x5c, 0, 8},
-       {116, 0x5d, 0, 0},
-       {118, 0x5d, 0, 2},
-       {120, 0x5d, 0, 4},
-       {124, 0x5d, 0, 8},
-       {126, 0x5d, 0, 10},
-       {128, 0x5e, 0, 0},
-       {132, 0x5e, 0, 4},
-       {134, 0x5e, 0, 6},
-       {136, 0x5e, 0, 8},
-       {140, 0x5f, 0, 0},
-
-       /* 802.11 UNII */
-       {149, 0x5f, 0, 9},
-       {151, 0x5f, 0, 11},
-       {153, 0x60, 0, 1},
-       {157, 0x60, 0, 5},
-       {159, 0x60, 0, 7},
-       {161, 0x60, 0, 9},
-       {165, 0x61, 0, 1},
-       {167, 0x61, 0, 3},
-       {169, 0x61, 0, 5},
-       {171, 0x61, 0, 7},
-       {173, 0x61, 0, 9},
-};
-
-static const struct rf_channel rf_vals_5592_xtal20[] = {
-       /* Channel, N, K, mod, R */
-       {1, 482, 4, 10, 3},
-       {2, 483, 4, 10, 3},
-       {3, 484, 4, 10, 3},
-       {4, 485, 4, 10, 3},
-       {5, 486, 4, 10, 3},
-       {6, 487, 4, 10, 3},
-       {7, 488, 4, 10, 3},
-       {8, 489, 4, 10, 3},
-       {9, 490, 4, 10, 3},
-       {10, 491, 4, 10, 3},
-       {11, 492, 4, 10, 3},
-       {12, 493, 4, 10, 3},
-       {13, 494, 4, 10, 3},
-       {14, 496, 8, 10, 3},
-       {36, 172, 8, 12, 1},
-       {38, 173, 0, 12, 1},
-       {40, 173, 4, 12, 1},
-       {42, 173, 8, 12, 1},
-       {44, 174, 0, 12, 1},
-       {46, 174, 4, 12, 1},
-       {48, 174, 8, 12, 1},
-       {50, 175, 0, 12, 1},
-       {52, 175, 4, 12, 1},
-       {54, 175, 8, 12, 1},
-       {56, 176, 0, 12, 1},
-       {58, 176, 4, 12, 1},
-       {60, 176, 8, 12, 1},
-       {62, 177, 0, 12, 1},
-       {64, 177, 4, 12, 1},
-       {100, 183, 4, 12, 1},
-       {102, 183, 8, 12, 1},
-       {104, 184, 0, 12, 1},
-       {106, 184, 4, 12, 1},
-       {108, 184, 8, 12, 1},
-       {110, 185, 0, 12, 1},
-       {112, 185, 4, 12, 1},
-       {114, 185, 8, 12, 1},
-       {116, 186, 0, 12, 1},
-       {118, 186, 4, 12, 1},
-       {120, 186, 8, 12, 1},
-       {122, 187, 0, 12, 1},
-       {124, 187, 4, 12, 1},
-       {126, 187, 8, 12, 1},
-       {128, 188, 0, 12, 1},
-       {130, 188, 4, 12, 1},
-       {132, 188, 8, 12, 1},
-       {134, 189, 0, 12, 1},
-       {136, 189, 4, 12, 1},
-       {138, 189, 8, 12, 1},
-       {140, 190, 0, 12, 1},
-       {149, 191, 6, 12, 1},
-       {151, 191, 10, 12, 1},
-       {153, 192, 2, 12, 1},
-       {155, 192, 6, 12, 1},
-       {157, 192, 10, 12, 1},
-       {159, 193, 2, 12, 1},
-       {161, 193, 6, 12, 1},
-       {165, 194, 2, 12, 1},
-       {184, 164, 0, 12, 1},
-       {188, 164, 4, 12, 1},
-       {192, 165, 8, 12, 1},
-       {196, 166, 0, 12, 1},
-};
-
-static const struct rf_channel rf_vals_5592_xtal40[] = {
-       /* Channel, N, K, mod, R */
-       {1, 241, 2, 10, 3},
-       {2, 241, 7, 10, 3},
-       {3, 242, 2, 10, 3},
-       {4, 242, 7, 10, 3},
-       {5, 243, 2, 10, 3},
-       {6, 243, 7, 10, 3},
-       {7, 244, 2, 10, 3},
-       {8, 244, 7, 10, 3},
-       {9, 245, 2, 10, 3},
-       {10, 245, 7, 10, 3},
-       {11, 246, 2, 10, 3},
-       {12, 246, 7, 10, 3},
-       {13, 247, 2, 10, 3},
-       {14, 248, 4, 10, 3},
-       {36, 86, 4, 12, 1},
-       {38, 86, 6, 12, 1},
-       {40, 86, 8, 12, 1},
-       {42, 86, 10, 12, 1},
-       {44, 87, 0, 12, 1},
-       {46, 87, 2, 12, 1},
-       {48, 87, 4, 12, 1},
-       {50, 87, 6, 12, 1},
-       {52, 87, 8, 12, 1},
-       {54, 87, 10, 12, 1},
-       {56, 88, 0, 12, 1},
-       {58, 88, 2, 12, 1},
-       {60, 88, 4, 12, 1},
-       {62, 88, 6, 12, 1},
-       {64, 88, 8, 12, 1},
-       {100, 91, 8, 12, 1},
-       {102, 91, 10, 12, 1},
-       {104, 92, 0, 12, 1},
-       {106, 92, 2, 12, 1},
-       {108, 92, 4, 12, 1},
-       {110, 92, 6, 12, 1},
-       {112, 92, 8, 12, 1},
-       {114, 92, 10, 12, 1},
-       {116, 93, 0, 12, 1},
-       {118, 93, 2, 12, 1},
-       {120, 93, 4, 12, 1},
-       {122, 93, 6, 12, 1},
-       {124, 93, 8, 12, 1},
-       {126, 93, 10, 12, 1},
-       {128, 94, 0, 12, 1},
-       {130, 94, 2, 12, 1},
-       {132, 94, 4, 12, 1},
-       {134, 94, 6, 12, 1},
-       {136, 94, 8, 12, 1},
-       {138, 94, 10, 12, 1},
-       {140, 95, 0, 12, 1},
-       {149, 95, 9, 12, 1},
-       {151, 95, 11, 12, 1},
-       {153, 96, 1, 12, 1},
-       {155, 96, 3, 12, 1},
-       {157, 96, 5, 12, 1},
-       {159, 96, 7, 12, 1},
-       {161, 96, 9, 12, 1},
-       {165, 97, 1, 12, 1},
-       {184, 82, 0, 12, 1},
-       {188, 82, 4, 12, 1},
-       {192, 82, 8, 12, 1},
-       {196, 83, 0, 12, 1},
-};
-
-static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *default_power1;
-       char *default_power2;
-       char *default_power3;
-       unsigned int i;
-       u32 reg;
-
-       /*
-        * Disable powersaving as default.
-        */
-       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       /*
-        * Initialize all hw fields.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_HT_CCK_RATES);
-       ieee80211_hw_set(rt2x00dev->hw, REPORTS_TX_ACK_STATUS);
-       ieee80211_hw_set(rt2x00dev->hw, AMPDU_AGGREGATION);
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-
-       /*
-        * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices
-        * unless we are capable of sending the buffered frames out after the
-        * DTIM transmission using rt2x00lib_beacondone. This will send out
-        * multicast and broadcast traffic immediately instead of buffering it
-        * infinitly and thus dropping it after some time.
-        */
-       if (!rt2x00_is_usb(rt2x00dev))
-               ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2800_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * As rt2800 has a global fallback table we cannot specify
-        * more then one tx rate per frame but since the hw will
-        * try several rates (based on the fallback table) we should
-        * initialize max_report_rates to the maximum number of rates
-        * we are going to try. Otherwise mac80211 will truncate our
-        * reported tx rates and the rc algortihm will end up with
-        * incorrect data.
-        */
-       rt2x00dev->hw->max_rates = 1;
-       rt2x00dev->hw->max_report_rates = 7;
-       rt2x00dev->hw->max_rate_tries = 1;
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-       switch (rt2x00dev->chip.rf) {
-       case RF2720:
-       case RF2820:
-               spec->num_channels = 14;
-               spec->channels = rf_vals;
-               break;
-
-       case RF2750:
-       case RF2850:
-               spec->num_channels = ARRAY_SIZE(rf_vals);
-               spec->channels = rf_vals;
-               break;
-
-       case RF2020:
-       case RF3020:
-       case RF3021:
-       case RF3022:
-       case RF3070:
-       case RF3290:
-       case RF3320:
-       case RF3322:
-       case RF5360:
-       case RF5362:
-       case RF5370:
-       case RF5372:
-       case RF5390:
-       case RF5392:
-               spec->num_channels = 14;
-               spec->channels = rf_vals_3x;
-               break;
-
-       case RF3052:
-       case RF3053:
-               spec->num_channels = ARRAY_SIZE(rf_vals_3x);
-               spec->channels = rf_vals_3x;
-               break;
-
-       case RF5592:
-               rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, &reg);
-               if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
-                       spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
-                       spec->channels = rf_vals_5592_xtal40;
-               } else {
-                       spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);
-                       spec->channels = rf_vals_5592_xtal20;
-               }
-               break;
-       }
-
-       if (WARN_ON_ONCE(!spec->channels))
-               return -ENODEV;
-
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       if (spec->num_channels > 14)
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-
-       /*
-        * Initialize HT information.
-        */
-       if (!rt2x00_rf(rt2x00dev, RF2020))
-               spec->ht.ht_supported = true;
-       else
-               spec->ht.ht_supported = false;
-
-       spec->ht.cap =
-           IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-           IEEE80211_HT_CAP_GRN_FLD |
-           IEEE80211_HT_CAP_SGI_20 |
-           IEEE80211_HT_CAP_SGI_40;
-
-       if (rt2x00dev->default_ant.tx_chain_num >= 2)
-               spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
-
-       spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num <<
-                       IEEE80211_HT_CAP_RX_STBC_SHIFT;
-
-       spec->ht.ampdu_factor = 3;
-       spec->ht.ampdu_density = 4;
-       spec->ht.mcs.tx_params =
-           IEEE80211_HT_MCS_TX_DEFINED |
-           IEEE80211_HT_MCS_TX_RX_DIFF |
-           ((rt2x00dev->default_ant.tx_chain_num - 1) <<
-            IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
-
-       switch (rt2x00dev->default_ant.rx_chain_num) {
-       case 3:
-               spec->ht.mcs.rx_mask[2] = 0xff;
-       case 2:
-               spec->ht.mcs.rx_mask[1] = 0xff;
-       case 1:
-               spec->ht.mcs.rx_mask[0] = 0xff;
-               spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
-               break;
-       }
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-       default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
-
-       if (rt2x00dev->default_ant.tx_chain_num > 2)
-               default_power3 = rt2800_eeprom_addr(rt2x00dev,
-                                                   EEPROM_EXT_TXPOWER_BG3);
-       else
-               default_power3 = NULL;
-
-       for (i = 0; i < 14; i++) {
-               info[i].default_power1 = default_power1[i];
-               info[i].default_power2 = default_power2[i];
-               if (default_power3)
-                       info[i].default_power3 = default_power3[i];
-       }
-
-       if (spec->num_channels > 14) {
-               default_power1 = rt2800_eeprom_addr(rt2x00dev,
-                                                   EEPROM_TXPOWER_A1);
-               default_power2 = rt2800_eeprom_addr(rt2x00dev,
-                                                   EEPROM_TXPOWER_A2);
-
-               if (rt2x00dev->default_ant.tx_chain_num > 2)
-                       default_power3 =
-                               rt2800_eeprom_addr(rt2x00dev,
-                                                  EEPROM_EXT_TXPOWER_A3);
-               else
-                       default_power3 = NULL;
-
-               for (i = 14; i < spec->num_channels; i++) {
-                       info[i].default_power1 = default_power1[i - 14];
-                       info[i].default_power2 = default_power2[i - 14];
-                       if (default_power3)
-                               info[i].default_power3 = default_power3[i - 14];
-               }
-       }
-
-       switch (rt2x00dev->chip.rf) {
-       case RF2020:
-       case RF3020:
-       case RF3021:
-       case RF3022:
-       case RF3320:
-       case RF3052:
-       case RF3053:
-       case RF3070:
-       case RF3290:
-       case RF5360:
-       case RF5362:
-       case RF5370:
-       case RF5372:
-       case RF5390:
-       case RF5392:
-               __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
-               break;
-       }
-
-       return 0;
-}
-
-static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u32 rt;
-       u32 rev;
-
-       if (rt2x00_rt(rt2x00dev, RT3290))
-               rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
-       else
-               rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-
-       rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET);
-       rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION);
-
-       switch (rt) {
-       case RT2860:
-       case RT2872:
-       case RT2883:
-       case RT3070:
-       case RT3071:
-       case RT3090:
-       case RT3290:
-       case RT3352:
-       case RT3390:
-       case RT3572:
-       case RT3593:
-       case RT5390:
-       case RT5392:
-       case RT5592:
-               break;
-       default:
-               rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n",
-                          rt, rev);
-               return -ENODEV;
-       }
-
-       rt2x00_set_rt(rt2x00dev, rt, rev);
-
-       return 0;
-}
-
-int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u32 reg;
-
-       retval = rt2800_probe_rt(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt2800_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt2800_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
-       rt2x00_set_field32(&reg, GPIO_CTRL_DIR2, 1);
-       rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt2800_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Set device capabilities.
-        */
-       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
-       __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
-       if (!rt2x00_is_usb(rt2x00dev))
-               __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
-
-       /*
-        * Set device requirements.
-        */
-       if (!rt2x00_is_soc(rt2x00dev))
-               __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
-       if (!rt2800_hwcrypt_disabled(rt2x00dev))
-               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
-       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
-       if (rt2x00_is_usb(rt2x00dev))
-               __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
-       else {
-               __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
-               __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
-       }
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_probe_hw);
-
-/*
- * IEEE80211 stack callback functions.
- */
-void rt2800_get_key_seq(struct ieee80211_hw *hw,
-                       struct ieee80211_key_conf *key,
-                       struct ieee80211_key_seq *seq)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct mac_iveiv_entry iveiv_entry;
-       u32 offset;
-
-       if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
-               return;
-
-       offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
-       rt2800_register_multiread(rt2x00dev, offset,
-                                     &iveiv_entry, sizeof(iveiv_entry));
-
-       memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2);
-       memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4);
-}
-EXPORT_SYMBOL_GPL(rt2800_get_key_seq);
-
-int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u32 reg;
-       bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
-
-       rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
-       rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
-       rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
-       rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
-       rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);
-
-int rt2800_conf_tx(struct ieee80211_hw *hw,
-                  struct ieee80211_vif *vif, u16 queue_idx,
-                  const struct ieee80211_tx_queue_params *params)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-       struct rt2x00_field32 field;
-       int retval;
-       u32 reg;
-       u32 offset;
-
-       /*
-        * First pass the configuration through rt2x00lib, that will
-        * update the queue settings and validate the input. After that
-        * we are free to update the registers based on the value
-        * in the queue parameter.
-        */
-       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
-       if (retval)
-               return retval;
-
-       /*
-        * We only need to perform additional register initialization
-        * for WMM queues/
-        */
-       if (queue_idx >= 4)
-               return 0;
-
-       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-
-       /* Update WMM TXOP register */
-       offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
-       field.bit_offset = (queue_idx & 1) * 16;
-       field.bit_mask = 0xffff << field.bit_offset;
-
-       rt2800_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, field, queue->txop);
-       rt2800_register_write(rt2x00dev, offset, reg);
-
-       /* Update WMM registers */
-       field.bit_offset = queue_idx * 4;
-       field.bit_mask = 0xf << field.bit_offset;
-
-       rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
-       rt2x00_set_field32(&reg, field, queue->aifs);
-       rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_min);
-       rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
-
-       rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_max);
-       rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
-
-       /* Update EDCA registers */
-       offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
-
-       rt2800_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
-       rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
-       rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
-       rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
-       rt2800_register_write(rt2x00dev, offset, reg);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800_conf_tx);
-
-u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u64 tsf;
-       u32 reg;
-
-       rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
-       tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
-       rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
-       tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
-
-       return tsf;
-}
-EXPORT_SYMBOL_GPL(rt2800_get_tsf);
-
-int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu)
-{
-       struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;
-       int ret = 0;
-
-       /*
-        * Don't allow aggregation for stations the hardware isn't aware
-        * of because tx status reports for frames to an unknown station
-        * always contain wcid=WCID_END+1 and thus we can't distinguish
-        * between multiple stations which leads to unwanted situations
-        * when the hw reorders frames due to aggregation.
-        */
-       if (sta_priv->wcid > WCID_END)
-               return 1;
-
-       switch (action) {
-       case IEEE80211_AMPDU_RX_START:
-       case IEEE80211_AMPDU_RX_STOP:
-               /*
-                * The hw itself takes care of setting up BlockAck mechanisms.
-                * So, we only have to allow mac80211 to nagotiate a BlockAck
-                * agreement. Once that is done, the hw will BlockAck incoming
-                * AMPDUs without further setup.
-                */
-               break;
-       case IEEE80211_AMPDU_TX_START:
-               ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-               break;
-       case IEEE80211_AMPDU_TX_STOP_CONT:
-       case IEEE80211_AMPDU_TX_STOP_FLUSH:
-       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-               break;
-       case IEEE80211_AMPDU_TX_OPERATIONAL:
-               break;
-       default:
-               rt2x00_warn((struct rt2x00_dev *)hw->priv,
-                           "Unknown AMPDU action\n");
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(rt2800_ampdu_action);
-
-int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
-                     struct survey_info *survey)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_conf *conf = &hw->conf;
-       u32 idle, busy, busy_ext;
-
-       if (idx != 0)
-               return -ENOENT;
-
-       survey->channel = conf->chandef.chan;
-
-       rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
-       rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
-
-       if (idle || busy) {
-               survey->filled = SURVEY_INFO_TIME |
-                                SURVEY_INFO_TIME_BUSY |
-                                SURVEY_INFO_TIME_EXT_BUSY;
-
-               survey->time = (idle + busy) / 1000;
-               survey->time_busy = busy / 1000;
-               survey->time_ext_busy = busy_ext / 1000;
-       }
-
-       if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
-               survey->filled |= SURVEY_INFO_IN_USE;
-
-       return 0;
-
-}
-EXPORT_SYMBOL_GPL(rt2800_get_survey);
-
-MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2800 library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
deleted file mode 100644 (file)
index 440790b..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Bartlomiej Zolnierkiewicz
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef RT2800LIB_H
-#define RT2800LIB_H
-
-struct rt2800_ops {
-       void (*register_read)(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int offset, u32 *value);
-       void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int offset, u32 *value);
-       void (*register_write)(struct rt2x00_dev *rt2x00dev,
-                              const unsigned int offset, u32 value);
-       void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int offset, u32 value);
-
-       void (*register_multiread)(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int offset,
-                                  void *value, const u32 length);
-       void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int offset,
-                                   const void *value, const u32 length);
-
-       int (*regbusy_read)(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int offset,
-                           const struct rt2x00_field32 field, u32 *reg);
-
-       int (*read_eeprom)(struct rt2x00_dev *rt2x00dev);
-       bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev);
-
-       int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
-                                 const u8 *data, const size_t len);
-       int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
-       __le32 *(*drv_get_txwi)(struct queue_entry *entry);
-};
-
-static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
-                                       const unsigned int offset,
-                                       u32 *value)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_read(rt2x00dev, offset, value);
-}
-
-static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                            const unsigned int offset,
-                                            u32 *value)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_read_lock(rt2x00dev, offset, value);
-}
-
-static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
-                                        const unsigned int offset,
-                                        u32 value)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_write(rt2x00dev, offset, value);
-}
-
-static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
-                                             const unsigned int offset,
-                                             u32 value)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_write_lock(rt2x00dev, offset, value);
-}
-
-static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                            const unsigned int offset,
-                                            void *value, const u32 length)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_multiread(rt2x00dev, offset, value, length);
-}
-
-static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                             const unsigned int offset,
-                                             const void *value,
-                                             const u32 length)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
-}
-
-static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                                     const unsigned int offset,
-                                     const struct rt2x00_field32 field,
-                                     u32 *reg)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
-}
-
-static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       return rt2800ops->read_eeprom(rt2x00dev);
-}
-
-static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       return rt2800ops->hwcrypt_disabled(rt2x00dev);
-}
-
-static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
-                                           const u8 *data, const size_t len)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
-}
-
-static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-       return rt2800ops->drv_init_registers(rt2x00dev);
-}
-
-static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry)
-{
-       const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv;
-
-       return rt2800ops->drv_get_txwi(entry);
-}
-
-void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
-                       const u8 command, const u8 token,
-                       const u8 arg0, const u8 arg1);
-
-int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev);
-int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev);
-
-int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
-                         const u8 *data, const size_t len);
-int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
-                        const u8 *data, const size_t len);
-
-void rt2800_write_tx_data(struct queue_entry *entry,
-                         struct txentry_desc *txdesc);
-void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
-
-void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);
-
-void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
-void rt2800_clear_beacon(struct queue_entry *entry);
-
-extern const struct rt2x00debug rt2800_rt2x00debug;
-
-int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
-int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00lib_crypto *crypto,
-                            struct ieee80211_key_conf *key);
-int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00lib_crypto *crypto,
-                              struct ieee80211_key_conf *key);
-int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
-                  struct ieee80211_sta *sta);
-int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);
-void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
-                         const unsigned int filter_flags);
-void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
-                       struct rt2x00intf_conf *conf, const unsigned int flags);
-void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
-                      u32 changed);
-void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
-void rt2800_config(struct rt2x00_dev *rt2x00dev,
-                  struct rt2x00lib_conf *libconf,
-                  const unsigned int flags);
-void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
-void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
-void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
-                      const u32 count);
-void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
-void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
-
-int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
-void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
-
-int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
-int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
-
-int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);
-
-void rt2800_get_key_seq(struct ieee80211_hw *hw,
-                       struct ieee80211_key_conf *key,
-                       struct ieee80211_key_seq *seq);
-int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-int rt2800_conf_tx(struct ieee80211_hw *hw,
-                  struct ieee80211_vif *vif, u16 queue_idx,
-                  const struct ieee80211_tx_queue_params *params);
-u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                       enum ieee80211_ampdu_mlme_action action,
-                       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                       u8 buf_size, bool amsdu);
-int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
-                     struct survey_info *survey);
-void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
-
-void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
-                              unsigned short *txwi_size,
-                              unsigned short *rxwi_size);
-
-#endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c
deleted file mode 100644 (file)
index de4790b..0000000
+++ /dev/null
@@ -1,871 +0,0 @@
-/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
- *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
- *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
- *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
- *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
- *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
- *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
- *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
- *     <http://rt2x00.serialmonkey.com>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*     Module: rt2800mmio
- *     Abstract: rt2800 MMIO device routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/export.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2800.h"
-#include "rt2800lib.h"
-#include "rt2800mmio.h"
-
-/*
- * TX descriptor initialization
- */
-__le32 *rt2800mmio_get_txwi(struct queue_entry *entry)
-{
-       return (__le32 *) entry->skb->data;
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi);
-
-void rt2800mmio_write_tx_desc(struct queue_entry *entry,
-                             struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       __le32 *txd = entry_priv->desc;
-       u32 word;
-       const unsigned int txwi_size = entry->queue->winfo_size;
-
-       /*
-        * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1
-        * must contains a TXWI structure + 802.11 header + padding + 802.11
-        * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and
-        * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11
-        * data. It means that LAST_SEC0 is always 0.
-        */
-
-       /*
-        * Initialize TX descriptor
-        */
-       word = 0;
-       rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma);
-       rt2x00_desc_write(txd, 0, word);
-
-       word = 0;
-       rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len);
-       rt2x00_set_field32(&word, TXD_W1_LAST_SEC1,
-                          !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W1_BURST,
-                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size);
-       rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
-       rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
-       rt2x00_desc_write(txd, 1, word);
-
-       word = 0;
-       rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
-                          skbdesc->skb_dma + txwi_size);
-       rt2x00_desc_write(txd, 2, word);
-
-       word = 0;
-       rt2x00_set_field32(&word, TXD_W3_WIV,
-                          !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
-       rt2x00_desc_write(txd, 3, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->desc = txd;
-       skbdesc->desc_len = TXD_DESC_SIZE;
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc);
-
-/*
- * RX control handlers
- */
-void rt2800mmio_fill_rxdone(struct queue_entry *entry,
-                           struct rxdone_entry_desc *rxdesc)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       __le32 *rxd = entry_priv->desc;
-       u32 word;
-
-       rt2x00_desc_read(rxd, 3, &word);
-
-       if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
-       /*
-        * Unfortunately we don't know the cipher type used during
-        * decryption. This prevents us from correct providing
-        * correct statistics through debugfs.
-        */
-       rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);
-
-       if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
-               /*
-                * Hardware has stripped IV/EIV data from 802.11 frame during
-                * decryption. Unfortunately the descriptor doesn't contain
-                * any fields with the EIV/IV data either, so they can't
-                * be restored by rt2x00lib.
-                */
-               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
-
-               /*
-                * The hardware has already checked the Michael Mic and has
-                * stripped it from the frame. Signal this to mac80211.
-                */
-               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-
-               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
-                       rxdesc->flags |= RX_FLAG_DECRYPTED;
-               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
-                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
-       }
-
-       if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-
-       if (rt2x00_get_field32(word, RXD_W3_L2PAD))
-               rxdesc->dev_flags |= RXDONE_L2PAD;
-
-       /*
-        * Process the RXWI structure that is at the start of the buffer.
-        */
-       rt2800_process_rxwi(entry, rxdesc);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone);
-
-/*
- * Interrupt functions.
- */
-static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev)
-{
-       struct ieee80211_conf conf = { .flags = 0 };
-       struct rt2x00lib_conf libconf = { .conf = &conf };
-
-       rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
-}
-
-static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
-{
-       __le32 *txwi;
-       u32 word;
-       int wcid, tx_wcid;
-
-       wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
-
-       txwi = rt2800_drv_get_txwi(entry);
-       rt2x00_desc_read(txwi, 1, &word);
-       tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-
-       return (tx_wcid == wcid);
-}
-
-static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
-{
-       u32 status = *(u32 *)data;
-
-       /*
-        * rt2800pci hardware might reorder frames when exchanging traffic
-        * with multiple BA enabled STAs.
-        *
-        * For example, a tx queue
-        *    [ STA1 | STA2 | STA1 | STA2 ]
-        * can result in tx status reports
-        *    [ STA1 | STA1 | STA2 | STA2 ]
-        * when the hw decides to aggregate the frames for STA1 into one AMPDU.
-        *
-        * To mitigate this effect, associate the tx status to the first frame
-        * in the tx queue with a matching wcid.
-        */
-       if (rt2800mmio_txdone_entry_check(entry, status) &&
-           !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-               /*
-                * Got a matching frame, associate the tx status with
-                * the frame
-                */
-               entry->status = status;
-               set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
-               return true;
-       }
-
-       /* Check the next frame */
-       return false;
-}
-
-static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
-{
-       u32 status = *(u32 *)data;
-
-       /*
-        * Find the first frame without tx status and assign this status to it
-        * regardless if it matches or not.
-        */
-       if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-               /*
-                * Got a matching frame, associate the tx status with
-                * the frame
-                */
-               entry->status = status;
-               set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
-               return true;
-       }
-
-       /* Check the next frame */
-       return false;
-}
-static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
-                                             void *data)
-{
-       if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-               rt2800_txdone_entry(entry, entry->status,
-                                   rt2800mmio_get_txwi(entry));
-               return false;
-       }
-
-       /* No more frames to release */
-       return true;
-}
-
-static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       u32 status;
-       u8 qid;
-       int max_tx_done = 16;
-
-       while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
-               qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
-               if (unlikely(qid >= QID_RX)) {
-                       /*
-                        * Unknown queue, this shouldn't happen. Just drop
-                        * this tx status.
-                        */
-                       rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
-                                   qid);
-                       break;
-               }
-
-               queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-               if (unlikely(queue == NULL)) {
-                       /*
-                        * The queue is NULL, this shouldn't happen. Stop
-                        * processing here and drop the tx status
-                        */
-                       rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
-                                   qid);
-                       break;
-               }
-
-               if (unlikely(rt2x00queue_empty(queue))) {
-                       /*
-                        * The queue is empty. Stop processing here
-                        * and drop the tx status.
-                        */
-                       rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
-                                   qid);
-                       break;
-               }
-
-               /*
-                * Let's associate this tx status with the first
-                * matching frame.
-                */
-               if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
-                                               Q_INDEX, &status,
-                                               rt2800mmio_txdone_find_entry)) {
-                       /*
-                        * We cannot match the tx status to any frame, so just
-                        * use the first one.
-                        */
-                       if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
-                                                       Q_INDEX, &status,
-                                                       rt2800mmio_txdone_match_first)) {
-                               rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
-                                           qid);
-                               break;
-                       }
-               }
-
-               /*
-                * Release all frames with a valid tx status.
-                */
-               rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
-                                          Q_INDEX, NULL,
-                                          rt2800mmio_txdone_release_entries);
-
-               if (--max_tx_done == 0)
-                       break;
-       }
-
-       return !max_tx_done;
-}
-
-static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                              struct rt2x00_field32 irq_field)
-{
-       u32 reg;
-
-       /*
-        * Enable a single interrupt. The interrupt mask register
-        * access needs locking.
-        */
-       spin_lock_irq(&rt2x00dev->irqmask_lock);
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, irq_field, 1);
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-       spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-void rt2800mmio_txstatus_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       if (rt2800mmio_txdone(rt2x00dev))
-               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-
-       /*
-        * No need to enable the tx status interrupt here as we always
-        * leave it enabled to minimize the possibility of a tx status
-        * register overflow. See comment in interrupt handler.
-        */
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
-
-void rt2800mmio_pretbtt_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt2x00lib_pretbtt(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet);
-
-void rt2800mmio_tbtt_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-       u32 reg;
-
-       rt2x00lib_beacondone(rt2x00dev);
-
-       if (rt2x00dev->intf_ap_count) {
-               /*
-                * The rt2800pci hardware tbtt timer is off by 1us per tbtt
-                * causing beacon skew and as a result causing problems with
-                * some powersaving clients over time. Shorten the beacon
-                * interval every 64 beacons by 64us to mitigate this effect.
-                */
-               if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
-                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-                       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
-                                          (rt2x00dev->beacon_int * 16) - 1);
-                       rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-               } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
-                       rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-                       rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
-                                          (rt2x00dev->beacon_int * 16));
-                       rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-               }
-               drv_data->tbtt_tick++;
-               drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
-       }
-
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet);
-
-void rt2800mmio_rxdone_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       if (rt2x00mmio_rxdone(rt2x00dev))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet);
-
-void rt2800mmio_autowake_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt2800mmio_wakeup(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2800mmio_enable_interrupt(rt2x00dev,
-                                           INT_MASK_CSR_AUTO_WAKEUP);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
-
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
-{
-       u32 status;
-       int i;
-
-       /*
-        * The TX_FIFO_STATUS interrupt needs special care. We should
-        * read TX_STA_FIFO but we should do it immediately as otherwise
-        * the register can overflow and we would lose status reports.
-        *
-        * Hence, read the TX_STA_FIFO register and copy all tx status
-        * reports into a kernel FIFO which is handled in the txstatus
-        * tasklet. We use a tasklet to process the tx status reports
-        * because we can schedule the tasklet multiple times (when the
-        * interrupt fires again during tx status processing).
-        *
-        * Furthermore we don't disable the TX_FIFO_STATUS
-        * interrupt here but leave it enabled so that the TX_STA_FIFO
-        * can also be read while the tx status tasklet gets executed.
-        *
-        * 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;
-
-               if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
-                       rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
-                       break;
-               }
-       }
-
-       /* Schedule the tasklet for processing the tx status. */
-       tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-}
-
-irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
-{
-       struct rt2x00_dev *rt2x00dev = dev_instance;
-       u32 reg, mask;
-
-       /* Read status and ACK all interrupts */
-       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-       rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-       if (!reg)
-               return IRQ_NONE;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return IRQ_HANDLED;
-
-       /*
-        * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
-        * for interrupts and interrupt masks we can just use the value of
-        * INT_SOURCE_CSR to create the interrupt mask.
-        */
-       mask = ~reg;
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
-               rt2800mmio_txstatus_interrupt(rt2x00dev);
-               /*
-                * Never disable the TX_FIFO_STATUS interrupt.
-                */
-               rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
-       }
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
-               tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
-               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
-               tasklet_schedule(&rt2x00dev->autowake_tasklet);
-
-       /*
-        * Disable all interrupts for which a tasklet was scheduled right now,
-        * the tasklet will reenable the appropriate interrupts.
-        */
-       spin_lock(&rt2x00dev->irqmask_lock);
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       reg &= mask;
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-       spin_unlock(&rt2x00dev->irqmask_lock);
-
-       return IRQ_HANDLED;
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_interrupt);
-
-void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
-                          enum dev_state state)
-{
-       u32 reg;
-       unsigned long flags;
-
-       /*
-        * When interrupts are being enabled, the interrupt registers
-        * should clear the register to assure a clean state.
-        */
-       if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-               rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-       }
-
-       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-       reg = 0;
-       if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
-               rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
-               rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
-               rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
-               rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
-       }
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
-
-       if (state == STATE_RADIO_IRQ_OFF) {
-               /*
-                * Wait for possibly running tasklets to finish.
-                */
-               tasklet_kill(&rt2x00dev->txstatus_tasklet);
-               tasklet_kill(&rt2x00dev->rxdone_tasklet);
-               tasklet_kill(&rt2x00dev->autowake_tasklet);
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-               tasklet_kill(&rt2x00dev->pretbtt_tasklet);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq);
-
-/*
- * Queue handlers.
- */
-void rt2800mmio_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-               rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-               rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
-               rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
-               rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
-               break;
-       default:
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
-
-void rt2800mmio_kick_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       struct queue_entry *entry;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
-                                         entry->entry_idx);
-               break;
-       case QID_MGMT:
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5),
-                                         entry->entry_idx);
-               break;
-       default:
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue);
-
-void rt2800mmio_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-               rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-               rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
-               rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
-               rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
-
-               /*
-                * Wait for current invocation to finish. The tasklet
-                * won't be scheduled anymore afterwards since we disabled
-                * the TBTT and PRE TBTT timer.
-                */
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-               tasklet_kill(&rt2x00dev->pretbtt_tasklet);
-
-               break;
-       default:
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_stop_queue);
-
-void rt2800mmio_queue_init(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       unsigned short txwi_size, rxwi_size;
-
-       rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
-
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 128;
-               queue->data_size = AGGREGATION_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->winfo_size = rxwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 64;
-               queue->data_size = AGGREGATION_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->winfo_size = txwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 8;
-               queue->data_size = 0; /* No DMA required for beacons */
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->winfo_size = txwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_ATIM:
-               /* fallthrough */
-       default:
-               BUG();
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_queue_init);
-
-/*
- * Initialization functions.
- */
-bool rt2800mmio_get_entry_state(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-
-               return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE));
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-
-               return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE));
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_get_entry_state);
-
-void rt2800mmio_clear_entry(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-               rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0);
-               rt2x00_desc_write(entry_priv->desc, 1, word);
-
-               /*
-                * Set RX IDX in register to inform hardware that we have
-                * handled this entry and it is available for reuse again.
-                */
-               rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
-                                         entry->entry_idx);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 1, &word);
-               rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
-               rt2x00_desc_write(entry_priv->desc, 1, word);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
-
-int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct queue_entry_priv_mmio *entry_priv;
-
-       /*
-        * Initialize registers.
-        */
-       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
-                                 entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
-                                 rt2x00dev->tx[0].limit);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
-
-       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
-                                 entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
-                                 rt2x00dev->tx[1].limit);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
-
-       entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
-                                 entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
-                                 rt2x00dev->tx[2].limit);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
-
-       entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
-                                 entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
-                                 rt2x00dev->tx[3].limit);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
-
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0);
-
-       rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0);
-
-       entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR,
-                                 entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT,
-                                 rt2x00dev->rx[0].limit);
-       rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
-                                 rt2x00dev->rx[0].limit - 1);
-       rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0);
-
-       rt2800_disable_wpdma(rt2x00dev);
-
-       rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_init_queues);
-
-int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       /*
-        * Reset DMA indexes
-        */
-       rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
-       rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-       rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
-
-       if (rt2x00_is_pcie(rt2x00dev) &&
-           (rt2x00_rt(rt2x00dev, RT3090) ||
-            rt2x00_rt(rt2x00dev, RT3390) ||
-            rt2x00_rt(rt2x00dev, RT3572) ||
-            rt2x00_rt(rt2x00dev, RT3593) ||
-            rt2x00_rt(rt2x00dev, RT5390) ||
-            rt2x00_rt(rt2x00dev, RT5392) ||
-            rt2x00_rt(rt2x00dev, RT5592))) {
-               rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
-               rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
-               rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
-               rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
-       }
-
-       rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
-
-       reg = 0;
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_init_registers);
-
-/*
- * Device state switch handlers.
- */
-int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /* Wait for DMA, ignore error until we initialize queues. */
-       rt2800_wait_wpdma_ready(rt2x00dev);
-
-       if (unlikely(rt2800mmio_init_queues(rt2x00dev)))
-               return -EIO;
-
-       return rt2800_enable_radio(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2800 MMIO library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h
deleted file mode 100644 (file)
index b63312c..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
- *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
- *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
- *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
- *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
- *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
- *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
- *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
- *     <http://rt2x00.serialmonkey.com>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*     Module: rt2800mmio
- *     Abstract: forward declarations for the rt2800mmio module.
- */
-
-#ifndef RT2800MMIO_H
-#define RT2800MMIO_H
-
-/*
- * Queue register offset macros
- */
-#define TX_QUEUE_REG_OFFSET    0x10
-#define TX_BASE_PTR(__x)       (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET))
-#define TX_MAX_CNT(__x)                (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET))
-#define TX_CTX_IDX(__x)                (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
-#define TX_DTX_IDX(__x)                (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  (4 * sizeof(__le32))
-#define RXD_DESC_SIZE                  (4 * sizeof(__le32))
-
-/*
- * TX descriptor format for TX, PRIO and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_SD_PTR0                 FIELD32(0xffffffff)
-
-/*
- * Word1
- */
-#define TXD_W1_SD_LEN1                 FIELD32(0x00003fff)
-#define TXD_W1_LAST_SEC1               FIELD32(0x00004000)
-#define TXD_W1_BURST                   FIELD32(0x00008000)
-#define TXD_W1_SD_LEN0                 FIELD32(0x3fff0000)
-#define TXD_W1_LAST_SEC0               FIELD32(0x40000000)
-#define TXD_W1_DMA_DONE                        FIELD32(0x80000000)
-
-/*
- * Word2
- */
-#define TXD_W2_SD_PTR1                 FIELD32(0xffffffff)
-
-/*
- * Word3
- * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
- * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
- *       0:MGMT, 1:HCCA 2:EDCA
- */
-#define TXD_W3_WIV                     FIELD32(0x01000000)
-#define TXD_W3_QSEL                    FIELD32(0x06000000)
-#define TXD_W3_TCO                     FIELD32(0x20000000)
-#define TXD_W3_UCO                     FIELD32(0x40000000)
-#define TXD_W3_ICO                     FIELD32(0x80000000)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- */
-#define RXD_W0_SDP0                    FIELD32(0xffffffff)
-
-/*
- * Word1
- */
-#define RXD_W1_SDL1                    FIELD32(0x00003fff)
-#define RXD_W1_SDL0                    FIELD32(0x3fff0000)
-#define RXD_W1_LS0                     FIELD32(0x40000000)
-#define RXD_W1_DMA_DONE                        FIELD32(0x80000000)
-
-/*
- * Word2
- */
-#define RXD_W2_SDP1                    FIELD32(0xffffffff)
-
-/*
- * Word3
- * AMSDU: RX with 802.3 header, not 802.11 header.
- * DECRYPTED: This frame is being decrypted.
- */
-#define RXD_W3_BA                      FIELD32(0x00000001)
-#define RXD_W3_DATA                    FIELD32(0x00000002)
-#define RXD_W3_NULLDATA                        FIELD32(0x00000004)
-#define RXD_W3_FRAG                    FIELD32(0x00000008)
-#define RXD_W3_UNICAST_TO_ME           FIELD32(0x00000010)
-#define RXD_W3_MULTICAST               FIELD32(0x00000020)
-#define RXD_W3_BROADCAST               FIELD32(0x00000040)
-#define RXD_W3_MY_BSS                  FIELD32(0x00000080)
-#define RXD_W3_CRC_ERROR               FIELD32(0x00000100)
-#define RXD_W3_CIPHER_ERROR            FIELD32(0x00000600)
-#define RXD_W3_AMSDU                   FIELD32(0x00000800)
-#define RXD_W3_HTC                     FIELD32(0x00001000)
-#define RXD_W3_RSSI                    FIELD32(0x00002000)
-#define RXD_W3_L2PAD                   FIELD32(0x00004000)
-#define RXD_W3_AMPDU                   FIELD32(0x00008000)
-#define RXD_W3_DECRYPTED               FIELD32(0x00010000)
-#define RXD_W3_PLCP_SIGNAL             FIELD32(0x00020000)
-#define RXD_W3_PLCP_RSSI               FIELD32(0x00040000)
-
-/* TX descriptor initialization */
-__le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
-void rt2800mmio_write_tx_desc(struct queue_entry *entry,
-                             struct txentry_desc *txdesc);
-
-/* RX control handlers */
-void rt2800mmio_fill_rxdone(struct queue_entry *entry,
-                           struct rxdone_entry_desc *rxdesc);
-
-/* Interrupt functions */
-void rt2800mmio_txstatus_tasklet(unsigned long data);
-void rt2800mmio_pretbtt_tasklet(unsigned long data);
-void rt2800mmio_tbtt_tasklet(unsigned long data);
-void rt2800mmio_rxdone_tasklet(unsigned long data);
-void rt2800mmio_autowake_tasklet(unsigned long data);
-irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance);
-void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev,
-                          enum dev_state state);
-
-/* Queue handlers */
-void rt2800mmio_start_queue(struct data_queue *queue);
-void rt2800mmio_kick_queue(struct data_queue *queue);
-void rt2800mmio_stop_queue(struct data_queue *queue);
-void rt2800mmio_queue_init(struct data_queue *queue);
-
-/* Initialization functions */
-bool rt2800mmio_get_entry_state(struct queue_entry *entry);
-void rt2800mmio_clear_entry(struct queue_entry *entry);
-int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
-int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev);
-
-/* Device state switch handlers. */
-int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev);
-
-#endif /* RT2800MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
deleted file mode 100644 (file)
index 0af2257..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
-       Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
-       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
-       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
-       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800pci
-       Abstract: rt2800pci device specific routines.
-       Supported chipsets: RT2800E & RT2800ED.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/eeprom_93cx6.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2x00pci.h"
-#include "rt2800lib.h"
-#include "rt2800mmio.h"
-#include "rt2800.h"
-#include "rt2800pci.h"
-
-/*
- * Allow hardware encryption to be disabled.
- */
-static bool modparam_nohwcrypt = false;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
-{
-       return modparam_nohwcrypt;
-}
-
-static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
-{
-       unsigned int i;
-       u32 reg;
-
-       /*
-        * SOC devices don't support MCU requests.
-        */
-       if (rt2x00_is_soc(rt2x00dev))
-               return;
-
-       for (i = 0; i < 200; i++) {
-               rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
-
-               if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
-                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
-                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) ||
-                   (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token))
-                       break;
-
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       if (i == 200)
-               rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
-
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-}
-
-static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
-
-       eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
-       eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
-       eeprom->reg_data_clock =
-           !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK);
-       eeprom->reg_chip_select =
-           !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT);
-}
-
-static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg = 0;
-
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in);
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out);
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK,
-                          !!eeprom->reg_data_clock);
-       rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
-                          !!eeprom->reg_chip_select);
-
-       rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
-}
-
-static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
-{
-       struct eeprom_93cx6 eeprom;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
-
-       eeprom.data = rt2x00dev;
-       eeprom.register_read = rt2800pci_eepromregister_read;
-       eeprom.register_write = rt2800pci_eepromregister_write;
-       switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
-       {
-       case 0:
-               eeprom.width = PCI_EEPROM_WIDTH_93C46;
-               break;
-       case 1:
-               eeprom.width = PCI_EEPROM_WIDTH_93C66;
-               break;
-       default:
-               eeprom.width = PCI_EEPROM_WIDTH_93C86;
-               break;
-       }
-       eeprom.reg_data_in = 0;
-       eeprom.reg_data_out = 0;
-       eeprom.reg_data_clock = 0;
-       eeprom.reg_chip_select = 0;
-
-       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
-                              EEPROM_SIZE / sizeof(u16));
-
-       return 0;
-}
-
-static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2800_efuse_detect(rt2x00dev);
-}
-
-static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2800_read_eeprom_efuse(rt2x00dev);
-}
-
-/*
- * Firmware functions
- */
-static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Chip rt3290 use specific 4KB firmware named rt3290.bin.
-        */
-       if (rt2x00_rt(rt2x00dev, RT3290))
-               return FIRMWARE_RT3290;
-       else
-               return FIRMWARE_RT2860;
-}
-
-static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
-                                   const u8 *data, const size_t len)
-{
-       u32 reg;
-
-       /*
-        * enable Host program ram write selection
-        */
-       reg = 0;
-       rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
-       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
-
-       /*
-        * Write firmware to device.
-        */
-       rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-                                      data, len);
-
-       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
-       rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
-
-       rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       retval = rt2800mmio_enable_radio(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /* After resume MCU_BOOT_SIGNAL will trash these. */
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-
-       rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
-       rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
-
-       rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0);
-       rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
-
-       return retval;
-}
-
-static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       if (state == STATE_AWAKE) {
-               rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP,
-                                  0, 0x02);
-               rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
-       } else if (state == STATE_SLEEP) {
-               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
-                                         0xffffffff);
-               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
-                                         0xffffffff);
-               rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
-                                  0xff, 0x01);
-       }
-
-       return 0;
-}
-
-static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt2800pci_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               /*
-                * After the radio has been disabled, the device should
-                * be put to sleep for powersaving.
-                */
-               rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               rt2800mmio_toggle_irq(rt2x00dev, state);
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt2800pci_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * Device probe functions.
- */
-static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       if (rt2800pci_efuse_detect(rt2x00dev))
-               retval = rt2800pci_read_eeprom_efuse(rt2x00dev);
-       else
-               retval = rt2800pci_read_eeprom_pci(rt2x00dev);
-
-       return retval;
-}
-
-static const struct ieee80211_ops rt2800pci_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .get_key_seq            = rt2800_get_key_seq,
-       .set_rts_threshold      = rt2800_set_rts_threshold,
-       .sta_add                = rt2x00mac_sta_add,
-       .sta_remove             = rt2x00mac_sta_remove,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2800_conf_tx,
-       .get_tsf                = rt2800_get_tsf,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .ampdu_action           = rt2800_ampdu_action,
-       .flush                  = rt2x00mac_flush,
-       .get_survey             = rt2800_get_survey,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2800_ops rt2800pci_rt2800_ops = {
-       .register_read          = rt2x00mmio_register_read,
-       .register_read_lock     = rt2x00mmio_register_read, /* same for PCI */
-       .register_write         = rt2x00mmio_register_write,
-       .register_write_lock    = rt2x00mmio_register_write, /* same for PCI */
-       .register_multiread     = rt2x00mmio_register_multiread,
-       .register_multiwrite    = rt2x00mmio_register_multiwrite,
-       .regbusy_read           = rt2x00mmio_regbusy_read,
-       .read_eeprom            = rt2800pci_read_eeprom,
-       .hwcrypt_disabled       = rt2800pci_hwcrypt_disabled,
-       .drv_write_firmware     = rt2800pci_write_firmware,
-       .drv_init_registers     = rt2800mmio_init_registers,
-       .drv_get_txwi           = rt2800mmio_get_txwi,
-};
-
-static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
-       .irq_handler            = rt2800mmio_interrupt,
-       .txstatus_tasklet       = rt2800mmio_txstatus_tasklet,
-       .pretbtt_tasklet        = rt2800mmio_pretbtt_tasklet,
-       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
-       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
-       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
-       .probe_hw               = rt2800_probe_hw,
-       .get_firmware_name      = rt2800pci_get_firmware_name,
-       .check_firmware         = rt2800_check_firmware,
-       .load_firmware          = rt2800_load_firmware,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt2800mmio_get_entry_state,
-       .clear_entry            = rt2800mmio_clear_entry,
-       .set_device_state       = rt2800pci_set_device_state,
-       .rfkill_poll            = rt2800_rfkill_poll,
-       .link_stats             = rt2800_link_stats,
-       .reset_tuner            = rt2800_reset_tuner,
-       .link_tuner             = rt2800_link_tuner,
-       .gain_calibration       = rt2800_gain_calibration,
-       .vco_calibration        = rt2800_vco_calibration,
-       .start_queue            = rt2800mmio_start_queue,
-       .kick_queue             = rt2800mmio_kick_queue,
-       .stop_queue             = rt2800mmio_stop_queue,
-       .flush_queue            = rt2x00mmio_flush_queue,
-       .write_tx_desc          = rt2800mmio_write_tx_desc,
-       .write_tx_data          = rt2800_write_tx_data,
-       .write_beacon           = rt2800_write_beacon,
-       .clear_beacon           = rt2800_clear_beacon,
-       .fill_rxdone            = rt2800mmio_fill_rxdone,
-       .config_shared_key      = rt2800_config_shared_key,
-       .config_pairwise_key    = rt2800_config_pairwise_key,
-       .config_filter          = rt2800_config_filter,
-       .config_intf            = rt2800_config_intf,
-       .config_erp             = rt2800_config_erp,
-       .config_ant             = rt2800_config_ant,
-       .config                 = rt2800_config,
-       .sta_add                = rt2800_sta_add,
-       .sta_remove             = rt2800_sta_remove,
-};
-
-static const struct rt2x00_ops rt2800pci_ops = {
-       .name                   = KBUILD_MODNAME,
-       .drv_data_size          = sizeof(struct rt2800_drv_data),
-       .max_ap_intf            = 8,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2800mmio_queue_init,
-       .lib                    = &rt2800pci_rt2x00_ops,
-       .drv                    = &rt2800pci_rt2800_ops,
-       .hw                     = &rt2800pci_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2800_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * RT2800pci module information.
- */
-static const struct pci_device_id rt2800pci_device_table[] = {
-       { PCI_DEVICE(0x1814, 0x0601) },
-       { PCI_DEVICE(0x1814, 0x0681) },
-       { PCI_DEVICE(0x1814, 0x0701) },
-       { PCI_DEVICE(0x1814, 0x0781) },
-       { PCI_DEVICE(0x1814, 0x3090) },
-       { PCI_DEVICE(0x1814, 0x3091) },
-       { PCI_DEVICE(0x1814, 0x3092) },
-       { PCI_DEVICE(0x1432, 0x7708) },
-       { PCI_DEVICE(0x1432, 0x7727) },
-       { PCI_DEVICE(0x1432, 0x7728) },
-       { PCI_DEVICE(0x1432, 0x7738) },
-       { PCI_DEVICE(0x1432, 0x7748) },
-       { PCI_DEVICE(0x1432, 0x7758) },
-       { PCI_DEVICE(0x1432, 0x7768) },
-       { PCI_DEVICE(0x1462, 0x891a) },
-       { PCI_DEVICE(0x1a3b, 0x1059) },
-#ifdef CONFIG_RT2800PCI_RT3290
-       { PCI_DEVICE(0x1814, 0x3290) },
-#endif
-#ifdef CONFIG_RT2800PCI_RT33XX
-       { PCI_DEVICE(0x1814, 0x3390) },
-#endif
-#ifdef CONFIG_RT2800PCI_RT35XX
-       { PCI_DEVICE(0x1432, 0x7711) },
-       { PCI_DEVICE(0x1432, 0x7722) },
-       { PCI_DEVICE(0x1814, 0x3060) },
-       { PCI_DEVICE(0x1814, 0x3062) },
-       { PCI_DEVICE(0x1814, 0x3562) },
-       { PCI_DEVICE(0x1814, 0x3592) },
-       { PCI_DEVICE(0x1814, 0x3593) },
-       { PCI_DEVICE(0x1814, 0x359f) },
-#endif
-#ifdef CONFIG_RT2800PCI_RT53XX
-       { PCI_DEVICE(0x1814, 0x5360) },
-       { PCI_DEVICE(0x1814, 0x5362) },
-       { PCI_DEVICE(0x1814, 0x5390) },
-       { PCI_DEVICE(0x1814, 0x5392) },
-       { PCI_DEVICE(0x1814, 0x539a) },
-       { PCI_DEVICE(0x1814, 0x539b) },
-       { PCI_DEVICE(0x1814, 0x539f) },
-#endif
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards");
-MODULE_FIRMWARE(FIRMWARE_RT2860);
-MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
-MODULE_LICENSE("GPL");
-
-static int rt2800pci_probe(struct pci_dev *pci_dev,
-                          const struct pci_device_id *id)
-{
-       return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
-}
-
-static struct pci_driver rt2800pci_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt2800pci_device_table,
-       .probe          = rt2800pci_probe,
-       .remove         = rt2x00pci_remove,
-       .suspend        = rt2x00pci_suspend,
-       .resume         = rt2x00pci_resume,
-};
-
-module_pci_driver(rt2800pci_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
deleted file mode 100644 (file)
index 9dfef46..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-       Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
-       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-       Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
-       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-       Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
-       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-       Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800pci
-       Abstract: Data structures and registers for the rt2800pci module.
-       Supported chipsets: RT2800E & RT2800ED.
- */
-
-#ifndef RT2800PCI_H
-#define RT2800PCI_H
-
-/*
- * 8051 firmware image.
- */
-#define FIRMWARE_RT2860                        "rt2860.bin"
-#define FIRMWARE_RT3290                        "rt3290.bin"
-#define FIRMWARE_IMAGE_BASE            0x2000
-
-#endif /* RT2800PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c
deleted file mode 100644 (file)
index a985a5a..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*     Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
- *     Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
- *     Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
- *     Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
- *     Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
- *     Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
- *     Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
- *     Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
- *     <http://rt2x00.serialmonkey.com>
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*     Module: rt2800soc
- *     Abstract: rt2800 WiSoC specific routines.
- */
-
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2x00soc.h"
-#include "rt2800.h"
-#include "rt2800lib.h"
-#include "rt2800mmio.h"
-
-/* Allow hardware encryption to be disabled. */
-static bool modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
-{
-       return modparam_nohwcrypt;
-}
-
-static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_disable_radio(rt2x00dev);
-       rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-       rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
-}
-
-static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt2800mmio_enable_radio(rt2x00dev);
-               break;
-
-       case STATE_RADIO_OFF:
-               rt2800soc_disable_radio(rt2x00dev);
-               break;
-
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               rt2800mmio_toggle_irq(rt2x00dev, state);
-               break;
-
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               /* These states are not supported, but don't report an error */
-               retval = 0;
-               break;
-
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
-
-       if (!base_addr)
-               return -ENOMEM;
-
-       memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
-
-       iounmap(base_addr);
-       return 0;
-}
-
-/* Firmware functions */
-static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
-       WARN_ON_ONCE(1);
-       return NULL;
-}
-
-static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev,
-                                  const u8 *data, const size_t len)
-{
-       WARN_ON_ONCE(1);
-       return 0;
-}
-
-static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev,
-                                   const u8 *data, const size_t len)
-{
-       WARN_ON_ONCE(1);
-       return 0;
-}
-
-static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev,
-                                   const u8 *data, const size_t len)
-{
-       WARN_ON_ONCE(1);
-       return 0;
-}
-
-static const struct ieee80211_ops rt2800soc_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .get_key_seq            = rt2800_get_key_seq,
-       .set_rts_threshold      = rt2800_set_rts_threshold,
-       .sta_add                = rt2x00mac_sta_add,
-       .sta_remove             = rt2x00mac_sta_remove,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2800_conf_tx,
-       .get_tsf                = rt2800_get_tsf,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .ampdu_action           = rt2800_ampdu_action,
-       .flush                  = rt2x00mac_flush,
-       .get_survey             = rt2800_get_survey,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2800_ops rt2800soc_rt2800_ops = {
-       .register_read          = rt2x00mmio_register_read,
-       .register_read_lock     = rt2x00mmio_register_read, /* same for SoCs */
-       .register_write         = rt2x00mmio_register_write,
-       .register_write_lock    = rt2x00mmio_register_write, /* same for SoCs */
-       .register_multiread     = rt2x00mmio_register_multiread,
-       .register_multiwrite    = rt2x00mmio_register_multiwrite,
-       .regbusy_read           = rt2x00mmio_regbusy_read,
-       .read_eeprom            = rt2800soc_read_eeprom,
-       .hwcrypt_disabled       = rt2800soc_hwcrypt_disabled,
-       .drv_write_firmware     = rt2800soc_write_firmware,
-       .drv_init_registers     = rt2800mmio_init_registers,
-       .drv_get_txwi           = rt2800mmio_get_txwi,
-};
-
-static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
-       .irq_handler            = rt2800mmio_interrupt,
-       .txstatus_tasklet       = rt2800mmio_txstatus_tasklet,
-       .pretbtt_tasklet        = rt2800mmio_pretbtt_tasklet,
-       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
-       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
-       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
-       .probe_hw               = rt2800_probe_hw,
-       .get_firmware_name      = rt2800soc_get_firmware_name,
-       .check_firmware         = rt2800soc_check_firmware,
-       .load_firmware          = rt2800soc_load_firmware,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt2800mmio_get_entry_state,
-       .clear_entry            = rt2800mmio_clear_entry,
-       .set_device_state       = rt2800soc_set_device_state,
-       .rfkill_poll            = rt2800_rfkill_poll,
-       .link_stats             = rt2800_link_stats,
-       .reset_tuner            = rt2800_reset_tuner,
-       .link_tuner             = rt2800_link_tuner,
-       .gain_calibration       = rt2800_gain_calibration,
-       .vco_calibration        = rt2800_vco_calibration,
-       .start_queue            = rt2800mmio_start_queue,
-       .kick_queue             = rt2800mmio_kick_queue,
-       .stop_queue             = rt2800mmio_stop_queue,
-       .flush_queue            = rt2x00mmio_flush_queue,
-       .write_tx_desc          = rt2800mmio_write_tx_desc,
-       .write_tx_data          = rt2800_write_tx_data,
-       .write_beacon           = rt2800_write_beacon,
-       .clear_beacon           = rt2800_clear_beacon,
-       .fill_rxdone            = rt2800mmio_fill_rxdone,
-       .config_shared_key      = rt2800_config_shared_key,
-       .config_pairwise_key    = rt2800_config_pairwise_key,
-       .config_filter          = rt2800_config_filter,
-       .config_intf            = rt2800_config_intf,
-       .config_erp             = rt2800_config_erp,
-       .config_ant             = rt2800_config_ant,
-       .config                 = rt2800_config,
-       .sta_add                = rt2800_sta_add,
-       .sta_remove             = rt2800_sta_remove,
-};
-
-static const struct rt2x00_ops rt2800soc_ops = {
-       .name                   = KBUILD_MODNAME,
-       .drv_data_size          = sizeof(struct rt2800_drv_data),
-       .max_ap_intf            = 8,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2800mmio_queue_init,
-       .lib                    = &rt2800soc_rt2x00_ops,
-       .drv                    = &rt2800soc_rt2800_ops,
-       .hw                     = &rt2800soc_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2800_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-static int rt2800soc_probe(struct platform_device *pdev)
-{
-       return rt2x00soc_probe(pdev, &rt2800soc_ops);
-}
-
-static struct platform_driver rt2800soc_driver = {
-       .driver         = {
-               .name           = "rt2800_wmac",
-               .mod_name       = KBUILD_MODNAME,
-       },
-       .probe          = rt2800soc_probe,
-       .remove         = rt2x00soc_remove,
-       .suspend        = rt2x00soc_suspend,
-       .resume         = rt2x00soc_resume,
-};
-
-module_platform_driver(rt2800soc_driver);
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver.");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
deleted file mode 100644 (file)
index bf9afbf..0000000
+++ /dev/null
@@ -1,1462 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-       Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800usb
-       Abstract: rt2800usb device specific routines.
-       Supported chipsets: RT2800U.
- */
-
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#include "rt2x00.h"
-#include "rt2x00usb.h"
-#include "rt2800lib.h"
-#include "rt2800.h"
-#include "rt2800usb.h"
-
-/*
- * Allow hardware encryption to be disabled.
- */
-static bool modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev)
-{
-       return modparam_nohwcrypt;
-}
-
-/*
- * Queue handlers.
- */
-static void rt2800usb_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-               break;
-       case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt2800usb_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
-               rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-               rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-               break;
-       case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
-               rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-               rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * test if there is an entry in any TX queue for which DMA is done
- * but the TX status has not been returned yet
- */
-static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
-                   rt2x00queue_get_entry(queue, Q_INDEX_DONE))
-                       return true;
-       }
-       return false;
-}
-
-static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
-{
-       bool tout;
-
-       if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-               return false;
-
-       tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
-       if (unlikely(tout))
-               rt2x00_dbg(entry->queue->rt2x00dev,
-                          "TX status timeout for entry %d in queue %d\n",
-                          entry->entry_idx, entry->queue->qid);
-       return tout;
-
-}
-
-static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       struct queue_entry *entry;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               if (rt2800usb_entry_txstatus_timeout(entry))
-                       return true;
-       }
-       return false;
-}
-
-#define TXSTATUS_READ_INTERVAL 1000000
-
-static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
-                                                int urb_status, u32 tx_status)
-{
-       bool valid;
-
-       if (urb_status) {
-               rt2x00_warn(rt2x00dev, "TX status read failed %d\n",
-                           urb_status);
-
-               goto stop_reading;
-       }
-
-       valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
-       if (valid) {
-               if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status))
-                       rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
-
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-
-               /* Reschedule urb to read TX status again instantly */
-               return true;
-       }
-
-       /* Check if there is any entry that timedout waiting on TX status */
-       if (rt2800usb_txstatus_timeout(rt2x00dev))
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-
-       if (rt2800usb_txstatus_pending(rt2x00dev)) {
-               /* Read register after 1 ms */
-               hrtimer_start(&rt2x00dev->txstatus_timer,
-                             ktime_set(0, TXSTATUS_READ_INTERVAL),
-                             HRTIMER_MODE_REL);
-               return false;
-       }
-
-stop_reading:
-       clear_bit(TX_STATUS_READING, &rt2x00dev->flags);
-       /*
-        * There is small race window above, between txstatus pending check and
-        * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
-        * here again if status reading is needed.
-        */
-       if (rt2800usb_txstatus_pending(rt2x00dev) &&
-           !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
-               return true;
-       else
-               return false;
-}
-
-static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev)
-{
-
-       if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
-               return;
-
-       /* Read TX_STA_FIFO register after 2 ms */
-       hrtimer_start(&rt2x00dev->txstatus_timer,
-                     ktime_set(0, 2*TXSTATUS_READ_INTERVAL),
-                     HRTIMER_MODE_REL);
-}
-
-static void rt2800usb_tx_dma_done(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-
-       rt2800usb_async_read_tx_status(rt2x00dev);
-}
-
-static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(timer, struct rt2x00_dev, txstatus_timer);
-
-       rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
-                                     rt2800usb_tx_sta_fifo_read_completed);
-
-       return HRTIMER_NORESTART;
-}
-
-/*
- * Firmware functions
- */
-static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
-{
-       __le32 *reg;
-       u32 fw_mode;
-       int ret;
-
-       reg = kmalloc(sizeof(*reg), GFP_KERNEL);
-       if (reg == NULL)
-               return -ENOMEM;
-       /* cannot use rt2x00usb_register_read here as it uses different
-        * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
-        * magic value USB_MODE_AUTORUN (0x11) to the device, thus the
-        * returned value would be invalid.
-        */
-       ret = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
-                                      USB_VENDOR_REQUEST_IN, 0,
-                                      USB_MODE_AUTORUN, reg, sizeof(*reg),
-                                      REGISTER_TIMEOUT_FIRMWARE);
-       fw_mode = le32_to_cpu(*reg);
-       kfree(reg);
-       if (ret < 0)
-               return ret;
-
-       if ((fw_mode & 0x00000003) == 2)
-               return 1;
-
-       return 0;
-}
-
-static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
-       return FIRMWARE_RT2870;
-}
-
-static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
-                                   const u8 *data, const size_t len)
-{
-       int status;
-       u32 offset;
-       u32 length;
-       int retval;
-
-       /*
-        * Check which section of the firmware we need.
-        */
-       if (rt2x00_rt(rt2x00dev, RT2860) ||
-           rt2x00_rt(rt2x00dev, RT2872) ||
-           rt2x00_rt(rt2x00dev, RT3070)) {
-               offset = 0;
-               length = 4096;
-       } else {
-               offset = 4096;
-               length = 4096;
-       }
-
-       /*
-        * Write firmware to device.
-        */
-       retval = rt2800usb_autorun_detect(rt2x00dev);
-       if (retval < 0)
-               return retval;
-       if (retval) {
-               rt2x00_info(rt2x00dev,
-                           "Firmware loading not required - NIC in AutoRun mode\n");
-               __clear_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
-       } else {
-               rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-                                             data + offset, length);
-       }
-
-       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-
-       /*
-        * Send firmware request to device to load firmware,
-        * we need to specify a long timeout time.
-        */
-       status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
-                                            0, USB_MODE_FIRMWARE,
-                                            REGISTER_TIMEOUT_FIRMWARE);
-       if (status < 0) {
-               rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
-               return status;
-       }
-
-       msleep(10);
-       rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       /*
-        * Wait until BBP and RF are ready.
-        */
-       if (rt2800_wait_csr_ready(rt2x00dev))
-               return -EBUSY;
-
-       rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-       rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
-
-       reg = 0;
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
-       rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
-
-       rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
-                                   USB_MODE_RESET, REGISTER_TIMEOUT);
-
-       rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
-       return 0;
-}
-
-static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
-               return -EIO;
-
-       rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
-       rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
-       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
-       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
-       /*
-        * Total room for RX frames in kilobytes, PBF might still exceed
-        * this limit so reduce the number to prevent errors.
-        */
-       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
-                          ((rt2x00dev->rx->limit * DATA_FRAME_SIZE)
-                           / 1024) - 3);
-       rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
-       rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
-       rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
-
-       return rt2800_enable_radio(rt2x00dev);
-}
-
-static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       rt2800_disable_radio(rt2x00dev);
-}
-
-static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       if (state == STATE_AWAKE)
-               rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
-       else
-               rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
-
-       return 0;
-}
-
-static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                     enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               /*
-                * Before the radio can be enabled, the device first has
-                * to be woken up. After that it needs a bit of time
-                * to be fully awake and then the radio can be enabled.
-                */
-               rt2800usb_set_state(rt2x00dev, STATE_AWAKE);
-               msleep(1);
-               retval = rt2800usb_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               /*
-                * After the radio has been disabled, the device should
-                * be put to sleep for powersaving.
-                */
-               rt2800usb_disable_radio(rt2x00dev);
-               rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               /* No support, but no error either */
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt2800usb_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * Watchdog handlers
- */
-static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
-       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
-               rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
-
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
-
-               for (i = 0; i < 10; i++) {
-                       udelay(10);
-                       if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q))
-                               break;
-               }
-
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
-       }
-
-       rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
-       if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
-               rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
-
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
-
-               for (i = 0; i < 10; i++) {
-                       udelay(10);
-                       if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q))
-                               break;
-               }
-
-               rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
-       }
-
-       rt2x00usb_watchdog(rt2x00dev);
-}
-
-/*
- * TX descriptor initialization
- */
-static __le32 *rt2800usb_get_txwi(struct queue_entry *entry)
-{
-       if (entry->queue->qid == QID_BEACON)
-               return (__le32 *) (entry->skb->data);
-       else
-               return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
-}
-
-static void rt2800usb_write_tx_desc(struct queue_entry *entry,
-                                   struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *txi = (__le32 *) entry->skb->data;
-       u32 word;
-
-       /*
-        * Initialize TXINFO descriptor
-        */
-       rt2x00_desc_read(txi, 0, &word);
-
-       /*
-        * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is
-        * TXWI + 802.11 header + L2 pad + payload + pad,
-        * so need to decrease size of TXINFO.
-        */
-       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
-                          roundup(entry->skb->len, 4) - TXINFO_DESC_SIZE);
-       rt2x00_set_field32(&word, TXINFO_W0_WIV,
-                          !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
-       rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
-       rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0);
-       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0);
-       rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
-                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_desc_write(txi, 0, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
-       skbdesc->desc = txi;
-       skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
-}
-
-/*
- * TX data initialization
- */
-static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
-{
-       /*
-        * pad(1~3 bytes) is needed after each 802.11 payload.
-        * USB end pad(4 bytes) is needed at each USB bulk out packet end.
-        * TX frame format is :
-        * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |
-        *                 |<------------- tx_pkt_len ------------->|
-        */
-
-       return roundup(entry->skb->len, 4) + 4;
-}
-
-/*
- * TX control handlers
- */
-static enum txdone_entry_desc_flags
-rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
-{
-       __le32 *txwi;
-       u32 word;
-       int wcid, ack, pid;
-       int tx_wcid, tx_ack, tx_pid, is_agg;
-
-       /*
-        * This frames has returned with an IO error,
-        * so the status report is not intended for this
-        * frame.
-        */
-       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
-               return TXDONE_FAILURE;
-
-       wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
-       ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
-       pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
-       is_agg  = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
-
-       /*
-        * Validate if this TX status report is intended for
-        * this entry by comparing the WCID/ACK/PID fields.
-        */
-       txwi = rt2800usb_get_txwi(entry);
-
-       rt2x00_desc_read(txwi, 1, &word);
-       tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-       tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
-       tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
-
-       if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
-               rt2x00_dbg(entry->queue->rt2x00dev,
-                          "TX status report missed for queue %d entry %d\n",
-                          entry->queue->qid, entry->entry_idx);
-               return TXDONE_UNKNOWN;
-       }
-
-       return TXDONE_SUCCESS;
-}
-
-static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       struct queue_entry *entry;
-       u32 reg;
-       u8 qid;
-       enum txdone_entry_desc_flags done_status;
-
-       while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-               /*
-                * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
-                * guaranteed to be one of the TX QIDs .
-                */
-               qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
-               queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-
-               if (unlikely(rt2x00queue_empty(queue))) {
-                       rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
-                                  qid);
-                       break;
-               }
-
-               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
-               if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                            !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
-                       rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
-                                   entry->entry_idx, qid);
-                       break;
-               }
-
-               done_status = rt2800usb_txdone_entry_check(entry, reg);
-               if (likely(done_status == TXDONE_SUCCESS))
-                       rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
-               else
-                       rt2x00lib_txdone_noinfo(entry, done_status);
-       }
-}
-
-static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       struct queue_entry *entry;
-
-       /*
-        * Process any trailing TX status reports for IO failures,
-        * we loop until we find the first non-IO error entry. This
-        * can either be a frame which is free, is being uploaded,
-        * or has completed the upload but didn't have an entry
-        * in the TX_STAT_FIFO register yet.
-        */
-       tx_queue_for_each(rt2x00dev, queue) {
-               while (!rt2x00queue_empty(queue)) {
-                       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-                               break;
-
-                       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
-                               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
-                       else if (rt2800usb_entry_txstatus_timeout(entry))
-                               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
-                       else
-                               break;
-               }
-       }
-}
-
-static void rt2800usb_work_txdone(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, txdone_work);
-
-       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
-              rt2800usb_txstatus_timeout(rt2x00dev)) {
-
-               rt2800usb_txdone(rt2x00dev);
-
-               rt2800usb_txdone_nostatus(rt2x00dev);
-
-               /*
-                * The hw may delay sending the packet after DMA complete
-                * if the medium is busy, thus the TX_STA_FIFO entry is
-                * also delayed -> use a timer to retrieve it.
-                */
-               if (rt2800usb_txstatus_pending(rt2x00dev))
-                       rt2800usb_async_read_tx_status(rt2x00dev);
-       }
-}
-
-/*
- * RX control handlers
- */
-static void rt2800usb_fill_rxdone(struct queue_entry *entry,
-                                 struct rxdone_entry_desc *rxdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *rxi = (__le32 *)entry->skb->data;
-       __le32 *rxd;
-       u32 word;
-       int rx_pkt_len;
-
-       /*
-        * Copy descriptor to the skbdesc->desc buffer, making it safe from
-        * moving of frame data in rt2x00usb.
-        */
-       memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
-
-       /*
-        * RX frame format is :
-        * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
-        *          |<------------ rx_pkt_len -------------->|
-        */
-       rt2x00_desc_read(rxi, 0, &word);
-       rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
-
-       /*
-        * Remove the RXINFO structure from the sbk.
-        */
-       skb_pull(entry->skb, RXINFO_DESC_SIZE);
-
-       /*
-        * Check for rx_pkt_len validity. Return if invalid, leaving
-        * rxdesc->size zeroed out by the upper level.
-        */
-       if (unlikely(rx_pkt_len == 0 ||
-                       rx_pkt_len > entry->queue->data_size)) {
-               rt2x00_err(entry->queue->rt2x00dev,
-                          "Bad frame size %d, forcing to 0\n", rx_pkt_len);
-               return;
-       }
-
-       rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
-
-       /*
-        * It is now safe to read the descriptor on all architectures.
-        */
-       rt2x00_desc_read(rxd, 0, &word);
-
-       if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
-       rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR);
-
-       if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) {
-               /*
-                * Hardware has stripped IV/EIV data from 802.11 frame during
-                * decryption. Unfortunately the descriptor doesn't contain
-                * any fields with the EIV/IV data either, so they can't
-                * be restored by rt2x00lib.
-                */
-               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
-
-               /*
-                * The hardware has already checked the Michael Mic and has
-                * stripped it from the frame. Signal this to mac80211.
-                */
-               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-
-               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
-                       rxdesc->flags |= RX_FLAG_DECRYPTED;
-               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
-                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
-       }
-
-       if (rt2x00_get_field32(word, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-
-       if (rt2x00_get_field32(word, RXD_W0_L2PAD))
-               rxdesc->dev_flags |= RXDONE_L2PAD;
-
-       /*
-        * Remove RXD descriptor from end of buffer.
-        */
-       skb_trim(entry->skb, rx_pkt_len);
-
-       /*
-        * Process the RXWI structure.
-        */
-       rt2800_process_rxwi(entry, rxdesc);
-}
-
-/*
- * Device probe functions.
- */
-static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       retval = rt2800usb_autorun_detect(rt2x00dev);
-       if (retval < 0)
-               return retval;
-       if (retval)
-               return 1;
-       return rt2800_efuse_detect(rt2x00dev);
-}
-
-static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       retval = rt2800usb_efuse_detect(rt2x00dev);
-       if (retval < 0)
-               return retval;
-       if (retval)
-               retval = rt2800_read_eeprom_efuse(rt2x00dev);
-       else
-               retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
-                                              EEPROM_SIZE);
-
-       return retval;
-}
-
-static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       retval = rt2800_probe_hw(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Set txstatus timer function.
-        */
-       rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;
-
-       /*
-        * Overwrite TX done handler
-        */
-       INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);
-
-       return 0;
-}
-
-static const struct ieee80211_ops rt2800usb_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_tim                = rt2x00mac_set_tim,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .get_key_seq            = rt2800_get_key_seq,
-       .set_rts_threshold      = rt2800_set_rts_threshold,
-       .sta_add                = rt2x00mac_sta_add,
-       .sta_remove             = rt2x00mac_sta_remove,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2800_conf_tx,
-       .get_tsf                = rt2800_get_tsf,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .ampdu_action           = rt2800_ampdu_action,
-       .flush                  = rt2x00mac_flush,
-       .get_survey             = rt2800_get_survey,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2800_ops rt2800usb_rt2800_ops = {
-       .register_read          = rt2x00usb_register_read,
-       .register_read_lock     = rt2x00usb_register_read_lock,
-       .register_write         = rt2x00usb_register_write,
-       .register_write_lock    = rt2x00usb_register_write_lock,
-       .register_multiread     = rt2x00usb_register_multiread,
-       .register_multiwrite    = rt2x00usb_register_multiwrite,
-       .regbusy_read           = rt2x00usb_regbusy_read,
-       .read_eeprom            = rt2800usb_read_eeprom,
-       .hwcrypt_disabled       = rt2800usb_hwcrypt_disabled,
-       .drv_write_firmware     = rt2800usb_write_firmware,
-       .drv_init_registers     = rt2800usb_init_registers,
-       .drv_get_txwi           = rt2800usb_get_txwi,
-};
-
-static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
-       .probe_hw               = rt2800usb_probe_hw,
-       .get_firmware_name      = rt2800usb_get_firmware_name,
-       .check_firmware         = rt2800_check_firmware,
-       .load_firmware          = rt2800_load_firmware,
-       .initialize             = rt2x00usb_initialize,
-       .uninitialize           = rt2x00usb_uninitialize,
-       .clear_entry            = rt2x00usb_clear_entry,
-       .set_device_state       = rt2800usb_set_device_state,
-       .rfkill_poll            = rt2800_rfkill_poll,
-       .link_stats             = rt2800_link_stats,
-       .reset_tuner            = rt2800_reset_tuner,
-       .link_tuner             = rt2800_link_tuner,
-       .gain_calibration       = rt2800_gain_calibration,
-       .vco_calibration        = rt2800_vco_calibration,
-       .watchdog               = rt2800usb_watchdog,
-       .start_queue            = rt2800usb_start_queue,
-       .kick_queue             = rt2x00usb_kick_queue,
-       .stop_queue             = rt2800usb_stop_queue,
-       .flush_queue            = rt2x00usb_flush_queue,
-       .tx_dma_done            = rt2800usb_tx_dma_done,
-       .write_tx_desc          = rt2800usb_write_tx_desc,
-       .write_tx_data          = rt2800_write_tx_data,
-       .write_beacon           = rt2800_write_beacon,
-       .clear_beacon           = rt2800_clear_beacon,
-       .get_tx_data_len        = rt2800usb_get_tx_data_len,
-       .fill_rxdone            = rt2800usb_fill_rxdone,
-       .config_shared_key      = rt2800_config_shared_key,
-       .config_pairwise_key    = rt2800_config_pairwise_key,
-       .config_filter          = rt2800_config_filter,
-       .config_intf            = rt2800_config_intf,
-       .config_erp             = rt2800_config_erp,
-       .config_ant             = rt2800_config_ant,
-       .config                 = rt2800_config,
-       .sta_add                = rt2800_sta_add,
-       .sta_remove             = rt2800_sta_remove,
-};
-
-static void rt2800usb_queue_init(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       unsigned short txwi_size, rxwi_size;
-
-       rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size);
-
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 128;
-               queue->data_size = AGGREGATION_SIZE;
-               queue->desc_size = RXINFO_DESC_SIZE;
-               queue->winfo_size = rxwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 16;
-               queue->data_size = AGGREGATION_SIZE;
-               queue->desc_size = TXINFO_DESC_SIZE;
-               queue->winfo_size = txwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 8;
-               queue->data_size = MGMT_FRAME_SIZE;
-               queue->desc_size = TXINFO_DESC_SIZE;
-               queue->winfo_size = txwi_size;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_ATIM:
-               /* fallthrough */
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt2800usb_ops = {
-       .name                   = KBUILD_MODNAME,
-       .drv_data_size          = sizeof(struct rt2800_drv_data),
-       .max_ap_intf            = 8,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt2800usb_queue_init,
-       .lib                    = &rt2800usb_rt2x00_ops,
-       .drv                    = &rt2800usb_rt2800_ops,
-       .hw                     = &rt2800usb_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt2800_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * rt2800usb module information.
- */
-static struct usb_device_id rt2800usb_device_table[] = {
-       /* Abocom */
-       { USB_DEVICE(0x07b8, 0x2870) },
-       { USB_DEVICE(0x07b8, 0x2770) },
-       { USB_DEVICE(0x07b8, 0x3070) },
-       { USB_DEVICE(0x07b8, 0x3071) },
-       { USB_DEVICE(0x07b8, 0x3072) },
-       { USB_DEVICE(0x1482, 0x3c09) },
-       /* AirTies */
-       { USB_DEVICE(0x1eda, 0x2012) },
-       { USB_DEVICE(0x1eda, 0x2210) },
-       { USB_DEVICE(0x1eda, 0x2310) },
-       /* Allwin */
-       { USB_DEVICE(0x8516, 0x2070) },
-       { USB_DEVICE(0x8516, 0x2770) },
-       { USB_DEVICE(0x8516, 0x2870) },
-       { USB_DEVICE(0x8516, 0x3070) },
-       { USB_DEVICE(0x8516, 0x3071) },
-       { USB_DEVICE(0x8516, 0x3072) },
-       /* Alpha Networks */
-       { USB_DEVICE(0x14b2, 0x3c06) },
-       { USB_DEVICE(0x14b2, 0x3c07) },
-       { USB_DEVICE(0x14b2, 0x3c09) },
-       { USB_DEVICE(0x14b2, 0x3c12) },
-       { USB_DEVICE(0x14b2, 0x3c23) },
-       { USB_DEVICE(0x14b2, 0x3c25) },
-       { USB_DEVICE(0x14b2, 0x3c27) },
-       { USB_DEVICE(0x14b2, 0x3c28) },
-       { USB_DEVICE(0x14b2, 0x3c2c) },
-       /* Amit */
-       { USB_DEVICE(0x15c5, 0x0008) },
-       /* Askey */
-       { USB_DEVICE(0x1690, 0x0740) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1731) },
-       { USB_DEVICE(0x0b05, 0x1732) },
-       { USB_DEVICE(0x0b05, 0x1742) },
-       { USB_DEVICE(0x0b05, 0x1784) },
-       { USB_DEVICE(0x1761, 0x0b05) },
-       /* AzureWave */
-       { USB_DEVICE(0x13d3, 0x3247) },
-       { USB_DEVICE(0x13d3, 0x3273) },
-       { USB_DEVICE(0x13d3, 0x3305) },
-       { USB_DEVICE(0x13d3, 0x3307) },
-       { USB_DEVICE(0x13d3, 0x3321) },
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x8053) },
-       { USB_DEVICE(0x050d, 0x805c) },
-       { USB_DEVICE(0x050d, 0x815c) },
-       { USB_DEVICE(0x050d, 0x825a) },
-       { USB_DEVICE(0x050d, 0x825b) },
-       { USB_DEVICE(0x050d, 0x935a) },
-       { USB_DEVICE(0x050d, 0x935b) },
-       /* Buffalo */
-       { USB_DEVICE(0x0411, 0x00e8) },
-       { USB_DEVICE(0x0411, 0x0158) },
-       { USB_DEVICE(0x0411, 0x015d) },
-       { USB_DEVICE(0x0411, 0x016f) },
-       { USB_DEVICE(0x0411, 0x01a2) },
-       { USB_DEVICE(0x0411, 0x01ee) },
-       { USB_DEVICE(0x0411, 0x01a8) },
-       /* Corega */
-       { USB_DEVICE(0x07aa, 0x002f) },
-       { USB_DEVICE(0x07aa, 0x003c) },
-       { USB_DEVICE(0x07aa, 0x003f) },
-       { USB_DEVICE(0x18c5, 0x0012) },
-       /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c09) },
-       { USB_DEVICE(0x07d1, 0x3c0a) },
-       { USB_DEVICE(0x07d1, 0x3c0d) },
-       { USB_DEVICE(0x07d1, 0x3c0e) },
-       { USB_DEVICE(0x07d1, 0x3c0f) },
-       { USB_DEVICE(0x07d1, 0x3c11) },
-       { USB_DEVICE(0x07d1, 0x3c13) },
-       { USB_DEVICE(0x07d1, 0x3c15) },
-       { USB_DEVICE(0x07d1, 0x3c16) },
-       { USB_DEVICE(0x07d1, 0x3c17) },
-       { USB_DEVICE(0x2001, 0x3317) },
-       { USB_DEVICE(0x2001, 0x3c1b) },
-       { USB_DEVICE(0x2001, 0x3c25) },
-       /* Draytek */
-       { USB_DEVICE(0x07fa, 0x7712) },
-       /* DVICO */
-       { USB_DEVICE(0x0fe9, 0xb307) },
-       /* Edimax */
-       { USB_DEVICE(0x7392, 0x4085) },
-       { USB_DEVICE(0x7392, 0x7711) },
-       { USB_DEVICE(0x7392, 0x7717) },
-       { USB_DEVICE(0x7392, 0x7718) },
-       { USB_DEVICE(0x7392, 0x7722) },
-       /* Encore */
-       { USB_DEVICE(0x203d, 0x1480) },
-       { USB_DEVICE(0x203d, 0x14a9) },
-       /* EnGenius */
-       { USB_DEVICE(0x1740, 0x9701) },
-       { USB_DEVICE(0x1740, 0x9702) },
-       { USB_DEVICE(0x1740, 0x9703) },
-       { USB_DEVICE(0x1740, 0x9705) },
-       { USB_DEVICE(0x1740, 0x9706) },
-       { USB_DEVICE(0x1740, 0x9707) },
-       { USB_DEVICE(0x1740, 0x9708) },
-       { USB_DEVICE(0x1740, 0x9709) },
-       /* Gemtek */
-       { USB_DEVICE(0x15a9, 0x0012) },
-       /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x800b) },
-       { USB_DEVICE(0x1044, 0x800d) },
-       /* Hawking */
-       { USB_DEVICE(0x0e66, 0x0001) },
-       { USB_DEVICE(0x0e66, 0x0003) },
-       { USB_DEVICE(0x0e66, 0x0009) },
-       { USB_DEVICE(0x0e66, 0x000b) },
-       { USB_DEVICE(0x0e66, 0x0013) },
-       { USB_DEVICE(0x0e66, 0x0017) },
-       { USB_DEVICE(0x0e66, 0x0018) },
-       /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x0945) },
-       { USB_DEVICE(0x04bb, 0x0947) },
-       { USB_DEVICE(0x04bb, 0x0948) },
-       /* Linksys */
-       { USB_DEVICE(0x13b1, 0x0031) },
-       { USB_DEVICE(0x1737, 0x0070) },
-       { USB_DEVICE(0x1737, 0x0071) },
-       { USB_DEVICE(0x1737, 0x0077) },
-       { USB_DEVICE(0x1737, 0x0078) },
-       /* Logitec */
-       { USB_DEVICE(0x0789, 0x0162) },
-       { USB_DEVICE(0x0789, 0x0163) },
-       { USB_DEVICE(0x0789, 0x0164) },
-       { USB_DEVICE(0x0789, 0x0166) },
-       /* Motorola */
-       { USB_DEVICE(0x100d, 0x9031) },
-       /* MSI */
-       { USB_DEVICE(0x0db0, 0x3820) },
-       { USB_DEVICE(0x0db0, 0x3821) },
-       { USB_DEVICE(0x0db0, 0x3822) },
-       { USB_DEVICE(0x0db0, 0x3870) },
-       { USB_DEVICE(0x0db0, 0x3871) },
-       { USB_DEVICE(0x0db0, 0x6899) },
-       { USB_DEVICE(0x0db0, 0x821a) },
-       { USB_DEVICE(0x0db0, 0x822a) },
-       { USB_DEVICE(0x0db0, 0x822b) },
-       { USB_DEVICE(0x0db0, 0x822c) },
-       { USB_DEVICE(0x0db0, 0x870a) },
-       { USB_DEVICE(0x0db0, 0x871a) },
-       { USB_DEVICE(0x0db0, 0x871b) },
-       { USB_DEVICE(0x0db0, 0x871c) },
-       { USB_DEVICE(0x0db0, 0x899a) },
-       /* Ovislink */
-       { USB_DEVICE(0x1b75, 0x3070) },
-       { USB_DEVICE(0x1b75, 0x3071) },
-       { USB_DEVICE(0x1b75, 0x3072) },
-       { USB_DEVICE(0x1b75, 0xa200) },
-       /* Para */
-       { USB_DEVICE(0x20b8, 0x8888) },
-       /* Pegatron */
-       { USB_DEVICE(0x1d4d, 0x0002) },
-       { USB_DEVICE(0x1d4d, 0x000c) },
-       { USB_DEVICE(0x1d4d, 0x000e) },
-       { USB_DEVICE(0x1d4d, 0x0011) },
-       /* Philips */
-       { USB_DEVICE(0x0471, 0x200f) },
-       /* Planex */
-       { USB_DEVICE(0x2019, 0x5201) },
-       { USB_DEVICE(0x2019, 0xab25) },
-       { USB_DEVICE(0x2019, 0xed06) },
-       /* Quanta */
-       { USB_DEVICE(0x1a32, 0x0304) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x2070) },
-       { USB_DEVICE(0x148f, 0x2770) },
-       { USB_DEVICE(0x148f, 0x2870) },
-       { USB_DEVICE(0x148f, 0x3070) },
-       { USB_DEVICE(0x148f, 0x3071) },
-       { USB_DEVICE(0x148f, 0x3072) },
-       /* Samsung */
-       { USB_DEVICE(0x04e8, 0x2018) },
-       /* Siemens */
-       { USB_DEVICE(0x129b, 0x1828) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0017) },
-       { USB_DEVICE(0x0df6, 0x002b) },
-       { USB_DEVICE(0x0df6, 0x002c) },
-       { USB_DEVICE(0x0df6, 0x002d) },
-       { USB_DEVICE(0x0df6, 0x0039) },
-       { USB_DEVICE(0x0df6, 0x003b) },
-       { USB_DEVICE(0x0df6, 0x003d) },
-       { USB_DEVICE(0x0df6, 0x003e) },
-       { USB_DEVICE(0x0df6, 0x003f) },
-       { USB_DEVICE(0x0df6, 0x0040) },
-       { USB_DEVICE(0x0df6, 0x0042) },
-       { USB_DEVICE(0x0df6, 0x0047) },
-       { USB_DEVICE(0x0df6, 0x0048) },
-       { USB_DEVICE(0x0df6, 0x0051) },
-       { USB_DEVICE(0x0df6, 0x005f) },
-       { USB_DEVICE(0x0df6, 0x0060) },
-       /* SMC */
-       { USB_DEVICE(0x083a, 0x6618) },
-       { USB_DEVICE(0x083a, 0x7511) },
-       { USB_DEVICE(0x083a, 0x7512) },
-       { USB_DEVICE(0x083a, 0x7522) },
-       { USB_DEVICE(0x083a, 0x8522) },
-       { USB_DEVICE(0x083a, 0xa618) },
-       { USB_DEVICE(0x083a, 0xa701) },
-       { USB_DEVICE(0x083a, 0xa702) },
-       { USB_DEVICE(0x083a, 0xa703) },
-       { USB_DEVICE(0x083a, 0xb522) },
-       /* Sparklan */
-       { USB_DEVICE(0x15a9, 0x0006) },
-       /* Sweex */
-       { USB_DEVICE(0x177f, 0x0153) },
-       { USB_DEVICE(0x177f, 0x0164) },
-       { USB_DEVICE(0x177f, 0x0302) },
-       { USB_DEVICE(0x177f, 0x0313) },
-       { USB_DEVICE(0x177f, 0x0323) },
-       { USB_DEVICE(0x177f, 0x0324) },
-       /* U-Media */
-       { USB_DEVICE(0x157e, 0x300e) },
-       { USB_DEVICE(0x157e, 0x3013) },
-       /* ZCOM */
-       { USB_DEVICE(0x0cde, 0x0022) },
-       { USB_DEVICE(0x0cde, 0x0025) },
-       /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0280) },
-       { USB_DEVICE(0x5a57, 0x0282) },
-       { USB_DEVICE(0x5a57, 0x0283) },
-       { USB_DEVICE(0x5a57, 0x5257) },
-       /* Zyxel */
-       { USB_DEVICE(0x0586, 0x3416) },
-       { USB_DEVICE(0x0586, 0x3418) },
-       { USB_DEVICE(0x0586, 0x341a) },
-       { USB_DEVICE(0x0586, 0x341e) },
-       { USB_DEVICE(0x0586, 0x343e) },
-#ifdef CONFIG_RT2800USB_RT33XX
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x945b) },
-       /* D-Link */
-       { USB_DEVICE(0x2001, 0x3c17) },
-       /* Panasonic */
-       { USB_DEVICE(0x083a, 0xb511) },
-       /* Philips */
-       { USB_DEVICE(0x0471, 0x20dd) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x3370) },
-       { USB_DEVICE(0x148f, 0x8070) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0050) },
-       /* Sweex */
-       { USB_DEVICE(0x177f, 0x0163) },
-       { USB_DEVICE(0x177f, 0x0165) },
-#endif
-#ifdef CONFIG_RT2800USB_RT35XX
-       /* Allwin */
-       { USB_DEVICE(0x8516, 0x3572) },
-       /* Askey */
-       { USB_DEVICE(0x1690, 0x0744) },
-       { USB_DEVICE(0x1690, 0x0761) },
-       { USB_DEVICE(0x1690, 0x0764) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x179d) },
-       /* Cisco */
-       { USB_DEVICE(0x167b, 0x4001) },
-       /* EnGenius */
-       { USB_DEVICE(0x1740, 0x9801) },
-       /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x0944) },
-       /* Linksys */
-       { USB_DEVICE(0x13b1, 0x002f) },
-       { USB_DEVICE(0x1737, 0x0079) },
-       /* Logitec */
-       { USB_DEVICE(0x0789, 0x0170) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x3572) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0041) },
-       { USB_DEVICE(0x0df6, 0x0062) },
-       { USB_DEVICE(0x0df6, 0x0065) },
-       { USB_DEVICE(0x0df6, 0x0066) },
-       { USB_DEVICE(0x0df6, 0x0068) },
-       /* Toshiba */
-       { USB_DEVICE(0x0930, 0x0a07) },
-       /* Zinwell */
-       { USB_DEVICE(0x5a57, 0x0284) },
-#endif
-#ifdef CONFIG_RT2800USB_RT3573
-       /* AirLive */
-       { USB_DEVICE(0x1b75, 0x7733) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x17bc) },
-       { USB_DEVICE(0x0b05, 0x17ad) },
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x1103) },
-       /* Cameo */
-       { USB_DEVICE(0x148f, 0xf301) },
-       /* D-Link */
-       { USB_DEVICE(0x2001, 0x3c1f) },
-       /* Edimax */
-       { USB_DEVICE(0x7392, 0x7733) },
-       /* Hawking */
-       { USB_DEVICE(0x0e66, 0x0020) },
-       { USB_DEVICE(0x0e66, 0x0021) },
-       /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x094e) },
-       /* Linksys */
-       { USB_DEVICE(0x13b1, 0x003b) },
-       /* Logitec */
-       { USB_DEVICE(0x0789, 0x016b) },
-       /* NETGEAR */
-       { USB_DEVICE(0x0846, 0x9012) },
-       { USB_DEVICE(0x0846, 0x9013) },
-       { USB_DEVICE(0x0846, 0x9019) },
-       /* Planex */
-       { USB_DEVICE(0x2019, 0xed19) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x3573) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0067) },
-       { USB_DEVICE(0x0df6, 0x006a) },
-       { USB_DEVICE(0x0df6, 0x006e) },
-       /* ZyXEL */
-       { USB_DEVICE(0x0586, 0x3421) },
-#endif
-#ifdef CONFIG_RT2800USB_RT53XX
-       /* Arcadyan */
-       { USB_DEVICE(0x043e, 0x7a12) },
-       { USB_DEVICE(0x043e, 0x7a32) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x17e8) },
-       /* Azurewave */
-       { USB_DEVICE(0x13d3, 0x3329) },
-       { USB_DEVICE(0x13d3, 0x3365) },
-       /* D-Link */
-       { USB_DEVICE(0x2001, 0x3c15) },
-       { USB_DEVICE(0x2001, 0x3c19) },
-       { USB_DEVICE(0x2001, 0x3c1c) },
-       { USB_DEVICE(0x2001, 0x3c1d) },
-       { USB_DEVICE(0x2001, 0x3c1e) },
-       { USB_DEVICE(0x2001, 0x3c20) },
-       { USB_DEVICE(0x2001, 0x3c22) },
-       { USB_DEVICE(0x2001, 0x3c23) },
-       /* LG innotek */
-       { USB_DEVICE(0x043e, 0x7a22) },
-       { USB_DEVICE(0x043e, 0x7a42) },
-       /* Panasonic */
-       { USB_DEVICE(0x04da, 0x1801) },
-       { USB_DEVICE(0x04da, 0x1800) },
-       { USB_DEVICE(0x04da, 0x23f6) },
-       /* Philips */
-       { USB_DEVICE(0x0471, 0x2104) },
-       { USB_DEVICE(0x0471, 0x2126) },
-       { USB_DEVICE(0x0471, 0x2180) },
-       { USB_DEVICE(0x0471, 0x2181) },
-       { USB_DEVICE(0x0471, 0x2182) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x5370) },
-       { USB_DEVICE(0x148f, 0x5372) },
-#endif
-#ifdef CONFIG_RT2800USB_RT55XX
-       /* Arcadyan */
-       { USB_DEVICE(0x043e, 0x7a32) },
-       /* AVM GmbH */
-       { USB_DEVICE(0x057c, 0x8501) },
-       /* Buffalo */
-       { USB_DEVICE(0x0411, 0x0241) },
-       { USB_DEVICE(0x0411, 0x0253) },
-       /* D-Link */
-       { USB_DEVICE(0x2001, 0x3c1a) },
-       { USB_DEVICE(0x2001, 0x3c21) },
-       /* Proware */
-       { USB_DEVICE(0x043e, 0x7a13) },
-       /* Ralink */
-       { USB_DEVICE(0x148f, 0x5572) },
-       /* TRENDnet */
-       { USB_DEVICE(0x20f4, 0x724a) },
-#endif
-#ifdef CONFIG_RT2800USB_UNKNOWN
-       /*
-        * Unclear what kind of devices these are (they aren't supported by the
-        * vendor linux driver).
-        */
-       /* Abocom */
-       { USB_DEVICE(0x07b8, 0x3073) },
-       { USB_DEVICE(0x07b8, 0x3074) },
-       /* Alpha Networks */
-       { USB_DEVICE(0x14b2, 0x3c08) },
-       { USB_DEVICE(0x14b2, 0x3c11) },
-       /* Amigo */
-       { USB_DEVICE(0x0e0b, 0x9031) },
-       { USB_DEVICE(0x0e0b, 0x9041) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x166a) },
-       { USB_DEVICE(0x0b05, 0x1760) },
-       { USB_DEVICE(0x0b05, 0x1761) },
-       { USB_DEVICE(0x0b05, 0x1790) },
-       { USB_DEVICE(0x0b05, 0x17a7) },
-       /* AzureWave */
-       { USB_DEVICE(0x13d3, 0x3262) },
-       { USB_DEVICE(0x13d3, 0x3284) },
-       { USB_DEVICE(0x13d3, 0x3322) },
-       { USB_DEVICE(0x13d3, 0x3340) },
-       { USB_DEVICE(0x13d3, 0x3399) },
-       { USB_DEVICE(0x13d3, 0x3400) },
-       { USB_DEVICE(0x13d3, 0x3401) },
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x1003) },
-       /* Buffalo */
-       { USB_DEVICE(0x0411, 0x012e) },
-       { USB_DEVICE(0x0411, 0x0148) },
-       { USB_DEVICE(0x0411, 0x0150) },
-       /* Corega */
-       { USB_DEVICE(0x07aa, 0x0041) },
-       { USB_DEVICE(0x07aa, 0x0042) },
-       { USB_DEVICE(0x18c5, 0x0008) },
-       /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c0b) },
-       /* Encore */
-       { USB_DEVICE(0x203d, 0x14a1) },
-       /* EnGenius */
-       { USB_DEVICE(0x1740, 0x0600) },
-       { USB_DEVICE(0x1740, 0x0602) },
-       /* Gemtek */
-       { USB_DEVICE(0x15a9, 0x0010) },
-       /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x800c) },
-       /* Hercules */
-       { USB_DEVICE(0x06f8, 0xe036) },
-       /* Huawei */
-       { USB_DEVICE(0x148f, 0xf101) },
-       /* I-O DATA */
-       { USB_DEVICE(0x04bb, 0x094b) },
-       /* LevelOne */
-       { USB_DEVICE(0x1740, 0x0605) },
-       { USB_DEVICE(0x1740, 0x0615) },
-       /* Logitec */
-       { USB_DEVICE(0x0789, 0x0168) },
-       { USB_DEVICE(0x0789, 0x0169) },
-       /* Motorola */
-       { USB_DEVICE(0x100d, 0x9032) },
-       /* Pegatron */
-       { USB_DEVICE(0x05a6, 0x0101) },
-       { USB_DEVICE(0x1d4d, 0x0010) },
-       /* Planex */
-       { USB_DEVICE(0x2019, 0xab24) },
-       { USB_DEVICE(0x2019, 0xab29) },
-       /* Qcom */
-       { USB_DEVICE(0x18e8, 0x6259) },
-       /* RadioShack */
-       { USB_DEVICE(0x08b9, 0x1197) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x003c) },
-       { USB_DEVICE(0x0df6, 0x004a) },
-       { USB_DEVICE(0x0df6, 0x004d) },
-       { USB_DEVICE(0x0df6, 0x0053) },
-       { USB_DEVICE(0x0df6, 0x0069) },
-       { USB_DEVICE(0x0df6, 0x006f) },
-       { USB_DEVICE(0x0df6, 0x0078) },
-       /* SMC */
-       { USB_DEVICE(0x083a, 0xa512) },
-       { USB_DEVICE(0x083a, 0xc522) },
-       { USB_DEVICE(0x083a, 0xd522) },
-       { USB_DEVICE(0x083a, 0xf511) },
-       /* Sweex */
-       { USB_DEVICE(0x177f, 0x0254) },
-       /* TP-LINK */
-       { USB_DEVICE(0xf201, 0x5370) },
-#endif
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards");
-MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
-MODULE_FIRMWARE(FIRMWARE_RT2870);
-MODULE_LICENSE("GPL");
-
-static int rt2800usb_probe(struct usb_interface *usb_intf,
-                          const struct usb_device_id *id)
-{
-       return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
-}
-
-static struct usb_driver rt2800usb_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt2800usb_device_table,
-       .probe          = rt2800usb_probe,
-       .disconnect     = rt2x00usb_disconnect,
-       .suspend        = rt2x00usb_suspend,
-       .resume         = rt2x00usb_resume,
-       .reset_resume   = rt2x00usb_resume,
-       .disable_hub_initiated_lpm = 1,
-};
-
-module_usb_driver(rt2800usb_driver);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h
deleted file mode 100644 (file)
index ea7cac0..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-       Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
-       Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-       Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
-       Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2800usb
-       Abstract: Data structures and registers for the rt2800usb module.
-       Supported chipsets: RT2800U.
- */
-
-#ifndef RT2800USB_H
-#define RT2800USB_H
-
-/*
- * 8051 firmware image.
- */
-#define FIRMWARE_RT2870                        "rt2870.bin"
-#define FIRMWARE_IMAGE_BASE            0x3000
-
-/*
- * DMA descriptor defines.
- */
-#define TXINFO_DESC_SIZE               (1 * sizeof(__le32))
-#define RXINFO_DESC_SIZE               (1 * sizeof(__le32))
-
-/*
- * TX Info structure
- */
-
-/*
- * Word0
- * WIV: Wireless Info Valid. 1: Driver filled WI,  0: DMA needs to copy WI
- * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
- *       0:MGMT, 1:HCCA 2:EDCA
- * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid
- * DMA_TX_BURST: used ONLY in USB bulk Aggregation.
- *               Force USB DMA transmit frame from current selected endpoint
- */
-#define TXINFO_W0_USB_DMA_TX_PKT_LEN   FIELD32(0x0000ffff)
-#define TXINFO_W0_WIV                  FIELD32(0x01000000)
-#define TXINFO_W0_QSEL                 FIELD32(0x06000000)
-#define TXINFO_W0_SW_USE_LAST_ROUND    FIELD32(0x08000000)
-#define TXINFO_W0_USB_DMA_NEXT_VALID   FIELD32(0x40000000)
-#define TXINFO_W0_USB_DMA_TX_BURST     FIELD32(0x80000000)
-
-/*
- * RX Info structure
- */
-
-/*
- * Word 0
- */
-
-#define RXINFO_W0_USB_DMA_RX_PKT_LEN   FIELD32(0x0000ffff)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- * UNICAST_TO_ME: This RX frame is unicast to me.
- * MULTICAST: This is a multicast frame.
- * BROADCAST: This is a broadcast frame.
- * MY_BSS: this frame belongs to the same BSSID.
- * CRC_ERROR: CRC error.
- * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid.
- * AMSDU: rx with 802.3 header, not 802.11 header.
- */
-
-#define RXD_W0_BA                      FIELD32(0x00000001)
-#define RXD_W0_DATA                    FIELD32(0x00000002)
-#define RXD_W0_NULLDATA                        FIELD32(0x00000004)
-#define RXD_W0_FRAG                    FIELD32(0x00000008)
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000010)
-#define RXD_W0_MULTICAST               FIELD32(0x00000020)
-#define RXD_W0_BROADCAST               FIELD32(0x00000040)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000080)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000100)
-#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000600)
-#define RXD_W0_AMSDU                   FIELD32(0x00000800)
-#define RXD_W0_HTC                     FIELD32(0x00001000)
-#define RXD_W0_RSSI                    FIELD32(0x00002000)
-#define RXD_W0_L2PAD                   FIELD32(0x00004000)
-#define RXD_W0_AMPDU                   FIELD32(0x00008000)
-#define RXD_W0_DECRYPTED               FIELD32(0x00010000)
-#define RXD_W0_PLCP_RSSI               FIELD32(0x00020000)
-#define RXD_W0_CIPHER_ALG              FIELD32(0x00040000)
-#define RXD_W0_LAST_AMSDU              FIELD32(0x00080000)
-#define RXD_W0_PLCP_SIGNAL             FIELD32(0xfff00000)
-
-#endif /* RT2800USB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
deleted file mode 100644 (file)
index 3282ddb..0000000
+++ /dev/null
@@ -1,1478 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00
-       Abstract: rt2x00 global information.
- */
-
-#ifndef RT2X00_H
-#define RT2X00_H
-
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/skbuff.h>
-#include <linux/workqueue.h>
-#include <linux/firmware.h>
-#include <linux/leds.h>
-#include <linux/mutex.h>
-#include <linux/etherdevice.h>
-#include <linux/input-polldev.h>
-#include <linux/kfifo.h>
-#include <linux/hrtimer.h>
-#include <linux/average.h>
-
-#include <net/mac80211.h>
-
-#include "rt2x00debug.h"
-#include "rt2x00dump.h"
-#include "rt2x00leds.h"
-#include "rt2x00reg.h"
-#include "rt2x00queue.h"
-
-/*
- * Module information.
- */
-#define DRV_VERSION    "2.3.0"
-#define DRV_PROJECT    "http://rt2x00.serialmonkey.com"
-
-/* Debug definitions.
- * Debug output has to be enabled during compile time.
- */
-#ifdef CONFIG_RT2X00_DEBUG
-#define DEBUG
-#endif /* CONFIG_RT2X00_DEBUG */
-
-/* Utility printing macros
- * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized
- */
-#define rt2x00_probe_err(fmt, ...)                                     \
-       printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt,            \
-              __func__, ##__VA_ARGS__)
-#define rt2x00_err(dev, fmt, ...)                                      \
-       wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt,                 \
-                 __func__, ##__VA_ARGS__)
-#define rt2x00_warn(dev, fmt, ...)                                     \
-       wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt,              \
-                  __func__, ##__VA_ARGS__)
-#define rt2x00_info(dev, fmt, ...)                                     \
-       wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt,                 \
-                  __func__, ##__VA_ARGS__)
-
-/* Various debug levels */
-#define rt2x00_dbg(dev, fmt, ...)                                      \
-       wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt,                 \
-                 __func__, ##__VA_ARGS__)
-#define rt2x00_eeprom_dbg(dev, fmt, ...)                               \
-       wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt,       \
-                 __func__, ##__VA_ARGS__)
-
-/*
- * Duration calculations
- * The rate variable passed is: 100kbs.
- * To convert from bytes to bits we multiply size with 8,
- * then the size is multiplied with 10 to make the
- * real rate -> rate argument correction.
- */
-#define GET_DURATION(__size, __rate)   (((__size) * 8 * 10) / (__rate))
-#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
-
-/*
- * Determine the number of L2 padding bytes required between the header and
- * the payload.
- */
-#define L2PAD_SIZE(__hdrlen)   (-(__hdrlen) & 3)
-
-/*
- * Determine the alignment requirement,
- * to make sure the 802.11 payload is padded to a 4-byte boundrary
- * we must determine the address of the payload and calculate the
- * amount of bytes needed to move the data.
- */
-#define ALIGN_SIZE(__skb, __header) \
-       (  ((unsigned long)((__skb)->data + (__header))) & 3 )
-
-/*
- * Constants for extra TX headroom for alignment purposes.
- */
-#define RT2X00_ALIGN_SIZE      4 /* Only whole frame needs alignment */
-#define RT2X00_L2PAD_SIZE      8 /* Both header & payload need alignment */
-
-/*
- * Standard timing and size defines.
- * These values should follow the ieee80211 specifications.
- */
-#define ACK_SIZE               14
-#define IEEE80211_HEADER       24
-#define PLCP                   48
-#define BEACON                 100
-#define PREAMBLE               144
-#define SHORT_PREAMBLE         72
-#define SLOT_TIME              20
-#define SHORT_SLOT_TIME                9
-#define SIFS                   10
-#define PIFS                   ( SIFS + SLOT_TIME )
-#define SHORT_PIFS             ( SIFS + SHORT_SLOT_TIME )
-#define DIFS                   ( PIFS + SLOT_TIME )
-#define SHORT_DIFS             ( SHORT_PIFS + SHORT_SLOT_TIME )
-#define EIFS                   ( SIFS + DIFS + \
-                                 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
-#define SHORT_EIFS             ( SIFS + SHORT_DIFS + \
-                                 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
-
-enum rt2x00_chip_intf {
-       RT2X00_CHIP_INTF_PCI,
-       RT2X00_CHIP_INTF_PCIE,
-       RT2X00_CHIP_INTF_USB,
-       RT2X00_CHIP_INTF_SOC,
-};
-
-/*
- * Chipset identification
- * The chipset on the device is composed of a RT and RF chip.
- * The chipset combination is important for determining device capabilities.
- */
-struct rt2x00_chip {
-       u16 rt;
-#define RT2460         0x2460
-#define RT2560         0x2560
-#define RT2570         0x2570
-#define RT2661         0x2661
-#define RT2573         0x2573
-#define RT2860         0x2860  /* 2.4GHz */
-#define RT2872         0x2872  /* WSOC */
-#define RT2883         0x2883  /* WSOC */
-#define RT3070         0x3070
-#define RT3071         0x3071
-#define RT3090         0x3090  /* 2.4GHz PCIe */
-#define RT3290         0x3290
-#define RT3352         0x3352  /* WSOC */
-#define RT3390         0x3390
-#define RT3572         0x3572
-#define RT3593         0x3593
-#define RT3883         0x3883  /* WSOC */
-#define RT5390         0x5390  /* 2.4GHz */
-#define RT5392         0x5392  /* 2.4GHz */
-#define RT5592         0x5592
-
-       u16 rf;
-       u16 rev;
-
-       enum rt2x00_chip_intf intf;
-};
-
-/*
- * RF register values that belong to a particular channel.
- */
-struct rf_channel {
-       int channel;
-       u32 rf1;
-       u32 rf2;
-       u32 rf3;
-       u32 rf4;
-};
-
-/*
- * Channel information structure
- */
-struct channel_info {
-       unsigned int flags;
-#define GEOGRAPHY_ALLOWED      0x00000001
-
-       short max_power;
-       short default_power1;
-       short default_power2;
-       short default_power3;
-};
-
-/*
- * Antenna setup values.
- */
-struct antenna_setup {
-       enum antenna rx;
-       enum antenna tx;
-       u8 rx_chain_num;
-       u8 tx_chain_num;
-};
-
-/*
- * Quality statistics about the currently active link.
- */
-struct link_qual {
-       /*
-        * Statistics required for Link tuning by driver
-        * The rssi value is provided by rt2x00lib during the
-        * link_tuner() callback function.
-        * The false_cca field is filled during the link_stats()
-        * callback function and could be used during the
-        * link_tuner() callback function.
-        */
-       int rssi;
-       int false_cca;
-
-       /*
-        * VGC levels
-        * Hardware driver will tune the VGC level during each call
-        * to the link_tuner() callback function. This vgc_level is
-        * is determined based on the link quality statistics like
-        * average RSSI and the false CCA count.
-        *
-        * In some cases the drivers need to differentiate between
-        * the currently "desired" VGC level and the level configured
-        * in the hardware. The latter is important to reduce the
-        * number of BBP register reads to reduce register access
-        * overhead. For this reason we store both values here.
-        */
-       u8 vgc_level;
-       u8 vgc_level_reg;
-
-       /*
-        * Statistics required for Signal quality calculation.
-        * These fields might be changed during the link_stats()
-        * callback function.
-        */
-       int rx_success;
-       int rx_failed;
-       int tx_success;
-       int tx_failed;
-};
-
-DECLARE_EWMA(rssi, 1024, 8)
-
-/*
- * Antenna settings about the currently active link.
- */
-struct link_ant {
-       /*
-        * Antenna flags
-        */
-       unsigned int flags;
-#define ANTENNA_RX_DIVERSITY   0x00000001
-#define ANTENNA_TX_DIVERSITY   0x00000002
-#define ANTENNA_MODE_SAMPLE    0x00000004
-
-       /*
-        * Currently active TX/RX antenna setup.
-        * When software diversity is used, this will indicate
-        * which antenna is actually used at this time.
-        */
-       struct antenna_setup active;
-
-       /*
-        * RSSI history information for the antenna.
-        * Used to determine when to switch antenna
-        * when using software diversity.
-        */
-       int rssi_history;
-
-       /*
-        * Current RSSI average of the currently active antenna.
-        * Similar to the avg_rssi in the link_qual structure
-        * this value is updated by using the walking average.
-        */
-       struct ewma_rssi rssi_ant;
-};
-
-/*
- * To optimize the quality of the link we need to store
- * the quality of received frames and periodically
- * optimize the link.
- */
-struct link {
-       /*
-        * Link tuner counter
-        * The number of times the link has been tuned
-        * since the radio has been switched on.
-        */
-       u32 count;
-
-       /*
-        * Quality measurement values.
-        */
-       struct link_qual qual;
-
-       /*
-        * TX/RX antenna setup.
-        */
-       struct link_ant ant;
-
-       /*
-        * Currently active average RSSI value
-        */
-       struct ewma_rssi avg_rssi;
-
-       /*
-        * Work structure for scheduling periodic link tuning.
-        */
-       struct delayed_work work;
-
-       /*
-        * Work structure for scheduling periodic watchdog monitoring.
-        * This work must be scheduled on the kernel workqueue, while
-        * all other work structures must be queued on the mac80211
-        * workqueue. This guarantees that the watchdog can schedule
-        * other work structures and wait for their completion in order
-        * to bring the device/driver back into the desired state.
-        */
-       struct delayed_work watchdog_work;
-
-       /*
-        * Work structure for scheduling periodic AGC adjustments.
-        */
-       struct delayed_work agc_work;
-
-       /*
-        * Work structure for scheduling periodic VCO calibration.
-        */
-       struct delayed_work vco_work;
-};
-
-enum rt2x00_delayed_flags {
-       DELAYED_UPDATE_BEACON,
-};
-
-/*
- * Interface structure
- * Per interface configuration details, this structure
- * is allocated as the private data for ieee80211_vif.
- */
-struct rt2x00_intf {
-       /*
-        * beacon->skb must be protected with the mutex.
-        */
-       struct mutex beacon_skb_mutex;
-
-       /*
-        * Entry in the beacon queue which belongs to
-        * this interface. Each interface has its own
-        * dedicated beacon entry.
-        */
-       struct queue_entry *beacon;
-       bool enable_beacon;
-
-       /*
-        * Actions that needed rescheduling.
-        */
-       unsigned long delayed_flags;
-
-       /*
-        * Software sequence counter, this is only required
-        * for hardware which doesn't support hardware
-        * sequence counting.
-        */
-       atomic_t seqno;
-};
-
-static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
-{
-       return (struct rt2x00_intf *)vif->drv_priv;
-}
-
-/**
- * struct hw_mode_spec: Hardware specifications structure
- *
- * Details about the supported modes, rates and channels
- * of a particular chipset. This is used by rt2x00lib
- * to build the ieee80211_hw_mode array for mac80211.
- *
- * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
- * @supported_rates: Rate types which are supported (CCK, OFDM).
- * @num_channels: Number of supported channels. This is used as array size
- *     for @tx_power_a, @tx_power_bg and @channels.
- * @channels: Device/chipset specific channel values (See &struct rf_channel).
- * @channels_info: Additional information for channels (See &struct channel_info).
- * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
- */
-struct hw_mode_spec {
-       unsigned int supported_bands;
-#define SUPPORT_BAND_2GHZ      0x00000001
-#define SUPPORT_BAND_5GHZ      0x00000002
-
-       unsigned int supported_rates;
-#define SUPPORT_RATE_CCK       0x00000001
-#define SUPPORT_RATE_OFDM      0x00000002
-
-       unsigned int num_channels;
-       const struct rf_channel *channels;
-       const struct channel_info *channels_info;
-
-       struct ieee80211_sta_ht_cap ht;
-};
-
-/*
- * Configuration structure wrapper around the
- * mac80211 configuration structure.
- * When mac80211 configures the driver, rt2x00lib
- * can precalculate values which are equal for all
- * rt2x00 drivers. Those values can be stored in here.
- */
-struct rt2x00lib_conf {
-       struct ieee80211_conf *conf;
-
-       struct rf_channel rf;
-       struct channel_info channel;
-};
-
-/*
- * Configuration structure for erp settings.
- */
-struct rt2x00lib_erp {
-       int short_preamble;
-       int cts_protection;
-
-       u32 basic_rates;
-
-       int slot_time;
-
-       short sifs;
-       short pifs;
-       short difs;
-       short eifs;
-
-       u16 beacon_int;
-       u16 ht_opmode;
-};
-
-/*
- * Configuration structure for hardware encryption.
- */
-struct rt2x00lib_crypto {
-       enum cipher cipher;
-
-       enum set_key_cmd cmd;
-       const u8 *address;
-
-       u32 bssidx;
-
-       u8 key[16];
-       u8 tx_mic[8];
-       u8 rx_mic[8];
-
-       int wcid;
-};
-
-/*
- * Configuration structure wrapper around the
- * rt2x00 interface configuration handler.
- */
-struct rt2x00intf_conf {
-       /*
-        * Interface type
-        */
-       enum nl80211_iftype type;
-
-       /*
-        * TSF sync value, this is dependent on the operation type.
-        */
-       enum tsf_sync sync;
-
-       /*
-        * The MAC and BSSID addresses are simple array of bytes,
-        * these arrays are little endian, so when sending the addresses
-        * to the drivers, copy the it into a endian-signed variable.
-        *
-        * Note that all devices (except rt2500usb) have 32 bits
-        * register word sizes. This means that whatever variable we
-        * pass _must_ be a multiple of 32 bits. Otherwise the device
-        * might not accept what we are sending to it.
-        * This will also make it easier for the driver to write
-        * the data to the device.
-        */
-       __le32 mac[2];
-       __le32 bssid[2];
-};
-
-/*
- * Private structure for storing STA details
- * wcid: Wireless Client ID
- */
-struct rt2x00_sta {
-       int wcid;
-};
-
-static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
-{
-       return (struct rt2x00_sta *)sta->drv_priv;
-}
-
-/*
- * rt2x00lib callback functions.
- */
-struct rt2x00lib_ops {
-       /*
-        * Interrupt handlers.
-        */
-       irq_handler_t irq_handler;
-
-       /*
-        * TX status tasklet handler.
-        */
-       void (*txstatus_tasklet) (unsigned long data);
-       void (*pretbtt_tasklet) (unsigned long data);
-       void (*tbtt_tasklet) (unsigned long data);
-       void (*rxdone_tasklet) (unsigned long data);
-       void (*autowake_tasklet) (unsigned long data);
-
-       /*
-        * Device init handlers.
-        */
-       int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
-       char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
-       int (*check_firmware) (struct rt2x00_dev *rt2x00dev,
-                              const u8 *data, const size_t len);
-       int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
-                             const u8 *data, const size_t len);
-
-       /*
-        * Device initialization/deinitialization handlers.
-        */
-       int (*initialize) (struct rt2x00_dev *rt2x00dev);
-       void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
-
-       /*
-        * queue initialization handlers
-        */
-       bool (*get_entry_state) (struct queue_entry *entry);
-       void (*clear_entry) (struct queue_entry *entry);
-
-       /*
-        * Radio control handlers.
-        */
-       int (*set_device_state) (struct rt2x00_dev *rt2x00dev,
-                                enum dev_state state);
-       int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev);
-       void (*link_stats) (struct rt2x00_dev *rt2x00dev,
-                           struct link_qual *qual);
-       void (*reset_tuner) (struct rt2x00_dev *rt2x00dev,
-                            struct link_qual *qual);
-       void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
-                           struct link_qual *qual, const u32 count);
-       void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
-       void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
-
-       /*
-        * Data queue handlers.
-        */
-       void (*watchdog) (struct rt2x00_dev *rt2x00dev);
-       void (*start_queue) (struct data_queue *queue);
-       void (*kick_queue) (struct data_queue *queue);
-       void (*stop_queue) (struct data_queue *queue);
-       void (*flush_queue) (struct data_queue *queue, bool drop);
-       void (*tx_dma_done) (struct queue_entry *entry);
-
-       /*
-        * TX control handlers
-        */
-       void (*write_tx_desc) (struct queue_entry *entry,
-                              struct txentry_desc *txdesc);
-       void (*write_tx_data) (struct queue_entry *entry,
-                              struct txentry_desc *txdesc);
-       void (*write_beacon) (struct queue_entry *entry,
-                             struct txentry_desc *txdesc);
-       void (*clear_beacon) (struct queue_entry *entry);
-       int (*get_tx_data_len) (struct queue_entry *entry);
-
-       /*
-        * RX control handlers
-        */
-       void (*fill_rxdone) (struct queue_entry *entry,
-                            struct rxdone_entry_desc *rxdesc);
-
-       /*
-        * Configuration handlers.
-        */
-       int (*config_shared_key) (struct rt2x00_dev *rt2x00dev,
-                                 struct rt2x00lib_crypto *crypto,
-                                 struct ieee80211_key_conf *key);
-       int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_crypto *crypto,
-                                   struct ieee80211_key_conf *key);
-       void (*config_filter) (struct rt2x00_dev *rt2x00dev,
-                              const unsigned int filter_flags);
-       void (*config_intf) (struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00_intf *intf,
-                            struct rt2x00intf_conf *conf,
-                            const unsigned int flags);
-#define CONFIG_UPDATE_TYPE             ( 1 << 1 )
-#define CONFIG_UPDATE_MAC              ( 1 << 2 )
-#define CONFIG_UPDATE_BSSID            ( 1 << 3 )
-
-       void (*config_erp) (struct rt2x00_dev *rt2x00dev,
-                           struct rt2x00lib_erp *erp,
-                           u32 changed);
-       void (*config_ant) (struct rt2x00_dev *rt2x00dev,
-                           struct antenna_setup *ant);
-       void (*config) (struct rt2x00_dev *rt2x00dev,
-                       struct rt2x00lib_conf *libconf,
-                       const unsigned int changed_flags);
-       int (*sta_add) (struct rt2x00_dev *rt2x00dev,
-                       struct ieee80211_vif *vif,
-                       struct ieee80211_sta *sta);
-       int (*sta_remove) (struct rt2x00_dev *rt2x00dev,
-                          int wcid);
-};
-
-/*
- * rt2x00 driver callback operation structure.
- */
-struct rt2x00_ops {
-       const char *name;
-       const unsigned int drv_data_size;
-       const unsigned int max_ap_intf;
-       const unsigned int eeprom_size;
-       const unsigned int rf_size;
-       const unsigned int tx_queues;
-       void (*queue_init)(struct data_queue *queue);
-       const struct rt2x00lib_ops *lib;
-       const void *drv;
-       const struct ieee80211_ops *hw;
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       const struct rt2x00debug *debugfs;
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * rt2x00 state flags
- */
-enum rt2x00_state_flags {
-       /*
-        * Device flags
-        */
-       DEVICE_STATE_PRESENT,
-       DEVICE_STATE_REGISTERED_HW,
-       DEVICE_STATE_INITIALIZED,
-       DEVICE_STATE_STARTED,
-       DEVICE_STATE_ENABLED_RADIO,
-       DEVICE_STATE_SCANNING,
-
-       /*
-        * Driver configuration
-        */
-       CONFIG_CHANNEL_HT40,
-       CONFIG_POWERSAVING,
-       CONFIG_HT_DISABLED,
-       CONFIG_QOS_DISABLED,
-
-       /*
-        * Mark we currently are sequentially reading TX_STA_FIFO register
-        * FIXME: this is for only rt2800usb, should go to private data
-        */
-       TX_STATUS_READING,
-};
-
-/*
- * rt2x00 capability flags
- */
-enum rt2x00_capability_flags {
-       /*
-        * Requirements
-        */
-       REQUIRE_FIRMWARE,
-       REQUIRE_BEACON_GUARD,
-       REQUIRE_ATIM_QUEUE,
-       REQUIRE_DMA,
-       REQUIRE_COPY_IV,
-       REQUIRE_L2PAD,
-       REQUIRE_TXSTATUS_FIFO,
-       REQUIRE_TASKLET_CONTEXT,
-       REQUIRE_SW_SEQNO,
-       REQUIRE_HT_TX_DESC,
-       REQUIRE_PS_AUTOWAKE,
-       REQUIRE_DELAYED_RFKILL,
-
-       /*
-        * Capabilities
-        */
-       CAPABILITY_HW_BUTTON,
-       CAPABILITY_HW_CRYPTO,
-       CAPABILITY_POWER_LIMIT,
-       CAPABILITY_CONTROL_FILTERS,
-       CAPABILITY_CONTROL_FILTER_PSPOLL,
-       CAPABILITY_PRE_TBTT_INTERRUPT,
-       CAPABILITY_LINK_TUNING,
-       CAPABILITY_FRAME_TYPE,
-       CAPABILITY_RF_SEQUENCE,
-       CAPABILITY_EXTERNAL_LNA_A,
-       CAPABILITY_EXTERNAL_LNA_BG,
-       CAPABILITY_DOUBLE_ANTENNA,
-       CAPABILITY_BT_COEXIST,
-       CAPABILITY_VCO_RECALIBRATION,
-};
-
-/*
- * Interface combinations
- */
-enum {
-       IF_COMB_AP = 0,
-       NUM_IF_COMB,
-};
-
-/*
- * rt2x00 device structure.
- */
-struct rt2x00_dev {
-       /*
-        * Device structure.
-        * The structure stored in here depends on the
-        * system bus (PCI or USB).
-        * When accessing this variable, the rt2x00dev_{pci,usb}
-        * macros should be used for correct typecasting.
-        */
-       struct device *dev;
-
-       /*
-        * Callback functions.
-        */
-       const struct rt2x00_ops *ops;
-
-       /*
-        * Driver data.
-        */
-       void *drv_data;
-
-       /*
-        * IEEE80211 control structure.
-        */
-       struct ieee80211_hw *hw;
-       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-       enum ieee80211_band curr_band;
-       int curr_freq;
-
-       /*
-        * If enabled, the debugfs interface structures
-        * required for deregistration of debugfs.
-        */
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       struct rt2x00debug_intf *debugfs_intf;
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-       /*
-        * LED structure for changing the LED status
-        * by mac8011 or the kernel.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       struct rt2x00_led led_radio;
-       struct rt2x00_led led_assoc;
-       struct rt2x00_led led_qual;
-       u16 led_mcu_reg;
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       /*
-        * Device state flags.
-        * In these flags the current status is stored.
-        * Access to these flags should occur atomically.
-        */
-       unsigned long flags;
-
-       /*
-        * Device capabiltiy flags.
-        * In these flags the device/driver capabilities are stored.
-        * Access to these flags should occur non-atomically.
-        */
-       unsigned long cap_flags;
-
-       /*
-        * Device information, Bus IRQ and name (PCI, SoC)
-        */
-       int irq;
-       const char *name;
-
-       /*
-        * Chipset identification.
-        */
-       struct rt2x00_chip chip;
-
-       /*
-        * hw capability specifications.
-        */
-       struct hw_mode_spec spec;
-
-       /*
-        * This is the default TX/RX antenna setup as indicated
-        * by the device's EEPROM.
-        */
-       struct antenna_setup default_ant;
-
-       /*
-        * Register pointers
-        * csr.base: CSR base register address. (PCI)
-        * csr.cache: CSR cache for usb_control_msg. (USB)
-        */
-       union csr {
-               void __iomem *base;
-               void *cache;
-       } csr;
-
-       /*
-        * Mutex to protect register accesses.
-        * For PCI and USB devices it protects against concurrent indirect
-        * register access (BBP, RF, MCU) since accessing those
-        * registers require multiple calls to the CSR registers.
-        * For USB devices it also protects the csr_cache since that
-        * field is used for normal CSR access and it cannot support
-        * multiple callers simultaneously.
-        */
-       struct mutex csr_mutex;
-
-       /*
-        * Current packet filter configuration for the device.
-        * This contains all currently active FIF_* flags send
-        * to us by mac80211 during configure_filter().
-        */
-       unsigned int packet_filter;
-
-       /*
-        * Interface details:
-        *  - Open ap interface count.
-        *  - Open sta interface count.
-        *  - Association count.
-        *  - Beaconing enabled count.
-        */
-       unsigned int intf_ap_count;
-       unsigned int intf_sta_count;
-       unsigned int intf_associated;
-       unsigned int intf_beaconing;
-
-       /*
-        * Interface combinations
-        */
-       struct ieee80211_iface_limit if_limits_ap;
-       struct ieee80211_iface_combination if_combinations[NUM_IF_COMB];
-
-       /*
-        * Link quality
-        */
-       struct link link;
-
-       /*
-        * EEPROM data.
-        */
-       __le16 *eeprom;
-
-       /*
-        * Active RF register values.
-        * These are stored here so we don't need
-        * to read the rf registers and can directly
-        * use this value instead.
-        * This field should be accessed by using
-        * rt2x00_rf_read() and rt2x00_rf_write().
-        */
-       u32 *rf;
-
-       /*
-        * LNA gain
-        */
-       short lna_gain;
-
-       /*
-        * Current TX power value.
-        */
-       u16 tx_power;
-
-       /*
-        * Current retry values.
-        */
-       u8 short_retry;
-       u8 long_retry;
-
-       /*
-        * Rssi <-> Dbm offset
-        */
-       u8 rssi_offset;
-
-       /*
-        * Frequency offset.
-        */
-       u8 freq_offset;
-
-       /*
-        * Association id.
-        */
-       u16 aid;
-
-       /*
-        * Beacon interval.
-        */
-       u16 beacon_int;
-
-       /**
-        * Timestamp of last received beacon
-        */
-       unsigned long last_beacon;
-
-       /*
-        * Low level statistics which will have
-        * to be kept up to date while device is running.
-        */
-       struct ieee80211_low_level_stats low_level_stats;
-
-       /**
-        * Work queue for all work which should not be placed
-        * on the mac80211 workqueue (because of dependencies
-        * between various work structures).
-        */
-       struct workqueue_struct *workqueue;
-
-       /*
-        * Scheduled work.
-        * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
-        * which means it cannot be placed on the hw->workqueue
-        * due to RTNL locking requirements.
-        */
-       struct work_struct intf_work;
-
-       /**
-        * Scheduled work for TX/RX done handling (USB devices)
-        */
-       struct work_struct rxdone_work;
-       struct work_struct txdone_work;
-
-       /*
-        * Powersaving work
-        */
-       struct delayed_work autowakeup_work;
-       struct work_struct sleep_work;
-
-       /*
-        * Data queue arrays for RX, TX, Beacon and ATIM.
-        */
-       unsigned int data_queues;
-       struct data_queue *rx;
-       struct data_queue *tx;
-       struct data_queue *bcn;
-       struct data_queue *atim;
-
-       /*
-        * Firmware image.
-        */
-       const struct firmware *fw;
-
-       /*
-        * FIFO for storing tx status reports between isr and tasklet.
-        */
-       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
-
-       /*
-        * Timer to ensure tx status reports are read (rt2800usb).
-        */
-       struct hrtimer txstatus_timer;
-
-       /*
-        * Tasklet for processing tx status reports (rt2800pci).
-        */
-       struct tasklet_struct txstatus_tasklet;
-       struct tasklet_struct pretbtt_tasklet;
-       struct tasklet_struct tbtt_tasklet;
-       struct tasklet_struct rxdone_tasklet;
-       struct tasklet_struct autowake_tasklet;
-
-       /*
-        * Used for VCO periodic calibration.
-        */
-       int rf_channel;
-
-       /*
-        * Protect the interrupt mask register.
-        */
-       spinlock_t irqmask_lock;
-
-       /*
-        * List of BlockAckReq TX entries that need driver BlockAck processing.
-        */
-       struct list_head bar_list;
-       spinlock_t bar_list_lock;
-
-       /* Extra TX headroom required for alignment purposes. */
-       unsigned int extra_tx_headroom;
-};
-
-struct rt2x00_bar_list_entry {
-       struct list_head list;
-       struct rcu_head head;
-
-       struct queue_entry *entry;
-       int block_acked;
-
-       /* Relevant parts of the IEEE80211 BAR header */
-       __u8 ra[6];
-       __u8 ta[6];
-       __le16 control;
-       __le16 start_seq_num;
-};
-
-/*
- * Register defines.
- * Some registers require multiple attempts before success,
- * in those cases REGISTER_BUSY_COUNT attempts should be
- * taken with a REGISTER_BUSY_DELAY interval. Due to USB
- * bus delays, we do not have to loop so many times to wait
- * for valid register value on that bus.
- */
-#define REGISTER_BUSY_COUNT    100
-#define REGISTER_USB_BUSY_COUNT 20
-#define REGISTER_BUSY_DELAY    100
-
-/*
- * Generic RF access.
- * The RF is being accessed by word index.
- */
-static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int word, u32 *data)
-{
-       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
-       *data = rt2x00dev->rf[word - 1];
-}
-
-static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int word, u32 data)
-{
-       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
-       rt2x00dev->rf[word - 1] = data;
-}
-
-/*
- * Generic EEPROM access. The EEPROM is being accessed by word or byte index.
- */
-static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
-                                      const unsigned int word)
-{
-       return (void *)&rt2x00dev->eeprom[word];
-}
-
-static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
-                                     const unsigned int word, u16 *data)
-{
-       *data = le16_to_cpu(rt2x00dev->eeprom[word]);
-}
-
-static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
-                                      const unsigned int word, u16 data)
-{
-       rt2x00dev->eeprom[word] = cpu_to_le16(data);
-}
-
-static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev,
-                                   const unsigned int byte)
-{
-       return *(((u8 *)rt2x00dev->eeprom) + byte);
-}
-
-/*
- * Chipset handlers
- */
-static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
-                                  const u16 rt, const u16 rf, const u16 rev)
-{
-       rt2x00dev->chip.rt = rt;
-       rt2x00dev->chip.rf = rf;
-       rt2x00dev->chip.rev = rev;
-
-       rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n",
-                   rt2x00dev->chip.rt, rt2x00dev->chip.rf,
-                   rt2x00dev->chip.rev);
-}
-
-static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
-                                const u16 rt, const u16 rev)
-{
-       rt2x00dev->chip.rt = rt;
-       rt2x00dev->chip.rev = rev;
-
-       rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
-                   rt2x00dev->chip.rt, rt2x00dev->chip.rev);
-}
-
-static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
-{
-       rt2x00dev->chip.rf = rf;
-
-       rt2x00_info(rt2x00dev, "RF chipset %04x detected\n",
-                   rt2x00dev->chip.rf);
-}
-
-static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
-{
-       return (rt2x00dev->chip.rt == rt);
-}
-
-static inline bool rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
-{
-       return (rt2x00dev->chip.rf == rf);
-}
-
-static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00dev->chip.rev;
-}
-
-static inline bool rt2x00_rt_rev(struct rt2x00_dev *rt2x00dev,
-                                const u16 rt, const u16 rev)
-{
-       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) == rev);
-}
-
-static inline bool rt2x00_rt_rev_lt(struct rt2x00_dev *rt2x00dev,
-                                   const u16 rt, const u16 rev)
-{
-       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) < rev);
-}
-
-static inline bool rt2x00_rt_rev_gte(struct rt2x00_dev *rt2x00dev,
-                                    const u16 rt, const u16 rev)
-{
-       return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) >= rev);
-}
-
-static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
-                                       enum rt2x00_chip_intf intf)
-{
-       rt2x00dev->chip.intf = intf;
-}
-
-static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev,
-                              enum rt2x00_chip_intf intf)
-{
-       return (rt2x00dev->chip.intf == intf);
-}
-
-static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI) ||
-              rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
-}
-
-static inline bool rt2x00_is_pcie(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
-}
-
-static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
-}
-
-static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
-}
-
-/* Helpers for capability flags */
-
-static inline bool
-rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev,
-                   enum rt2x00_capability_flags cap_flag)
-{
-       return test_bit(cap_flag, &rt2x00dev->cap_flags);
-}
-
-static inline bool
-rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO);
-}
-
-static inline bool
-rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT);
-}
-
-static inline bool
-rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS);
-}
-
-static inline bool
-rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL);
-}
-
-static inline bool
-rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT);
-}
-
-static inline bool
-rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING);
-}
-
-static inline bool
-rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE);
-}
-
-static inline bool
-rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE);
-}
-
-static inline bool
-rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A);
-}
-
-static inline bool
-rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG);
-}
-
-static inline bool
-rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA);
-}
-
-static inline bool
-rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST);
-}
-
-static inline bool
-rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev)
-{
-       return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION);
-}
-
-/**
- * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
- * @entry: Pointer to &struct queue_entry
- *
- * Returns -ENOMEM if mapping fail, 0 otherwise.
- */
-int rt2x00queue_map_txskb(struct queue_entry *entry);
-
-/**
- * rt2x00queue_unmap_skb - Unmap a skb from DMA.
- * @entry: Pointer to &struct queue_entry
- */
-void rt2x00queue_unmap_skb(struct queue_entry *entry);
-
-/**
- * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @queue: rt2x00 queue index (see &enum data_queue_qid).
- *
- * Returns NULL for non tx queues.
- */
-static inline struct data_queue *
-rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev,
-                        const enum data_queue_qid queue)
-{
-       if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
-               return &rt2x00dev->tx[queue];
-
-       if (queue == QID_ATIM)
-               return rt2x00dev->atim;
-
-       return NULL;
-}
-
-/**
- * rt2x00queue_get_entry - Get queue entry where the given index points to.
- * @queue: Pointer to &struct data_queue from where we obtain the entry.
- * @index: Index identifier for obtaining the correct index.
- */
-struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
-                                         enum queue_index index);
-
-/**
- * rt2x00queue_pause_queue - Pause a data queue
- * @queue: Pointer to &struct data_queue.
- *
- * This function will pause the data queue locally, preventing
- * new frames to be added to the queue (while the hardware is
- * still allowed to run).
- */
-void rt2x00queue_pause_queue(struct data_queue *queue);
-
-/**
- * rt2x00queue_unpause_queue - unpause a data queue
- * @queue: Pointer to &struct data_queue.
- *
- * This function will unpause the data queue locally, allowing
- * new frames to be added to the queue again.
- */
-void rt2x00queue_unpause_queue(struct data_queue *queue);
-
-/**
- * rt2x00queue_start_queue - Start a data queue
- * @queue: Pointer to &struct data_queue.
- *
- * This function will start handling all pending frames in the queue.
- */
-void rt2x00queue_start_queue(struct data_queue *queue);
-
-/**
- * rt2x00queue_stop_queue - Halt a data queue
- * @queue: Pointer to &struct data_queue.
- *
- * This function will stop all pending frames in the queue.
- */
-void rt2x00queue_stop_queue(struct data_queue *queue);
-
-/**
- * rt2x00queue_flush_queue - Flush a data queue
- * @queue: Pointer to &struct data_queue.
- * @drop: True to drop all pending frames.
- *
- * This function will flush the queue. After this call
- * the queue is guaranteed to be empty.
- */
-void rt2x00queue_flush_queue(struct data_queue *queue, bool drop);
-
-/**
- * rt2x00queue_start_queues - Start all data queues
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * This function will loop through all available queues to start them
- */
-void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00queue_stop_queues - Halt all data queues
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * This function will loop through all available queues to stop
- * any pending frames.
- */
-void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00queue_flush_queues - Flush all data queues
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @drop: True to drop all pending frames.
- *
- * This function will loop through all available queues to flush
- * any pending frames.
- */
-void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop);
-
-/*
- * Debugfs handlers.
- */
-/**
- * rt2x00debug_dump_frame - Dump a frame to userspace through debugfs.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @type: The type of frame that is being dumped.
- * @skb: The skb containing the frame to be dumped.
- */
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
-                           enum rt2x00_dump_type type, struct sk_buff *skb);
-#else
-static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
-                                         enum rt2x00_dump_type type,
-                                         struct sk_buff *skb)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-/*
- * Utility functions.
- */
-u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
-                        struct ieee80211_vif *vif);
-
-/*
- * Interrupt context handlers.
- */
-void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_dmastart(struct queue_entry *entry);
-void rt2x00lib_dmadone(struct queue_entry *entry);
-void rt2x00lib_txdone(struct queue_entry *entry,
-                     struct txdone_entry_desc *txdesc);
-void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
-void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp);
-
-/*
- * mac80211 handlers.
- */
-void rt2x00mac_tx(struct ieee80211_hw *hw,
-                 struct ieee80211_tx_control *control,
-                 struct sk_buff *skb);
-int rt2x00mac_start(struct ieee80211_hw *hw);
-void rt2x00mac_stop(struct ieee80211_hw *hw);
-int rt2x00mac_add_interface(struct ieee80211_hw *hw,
-                           struct ieee80211_vif *vif);
-void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif);
-int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
-void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
-                               unsigned int changed_flags,
-                               unsigned int *total_flags,
-                               u64 multicast);
-int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-                     bool set);
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-                     struct ieee80211_key_conf *key);
-#else
-#define rt2x00mac_set_key      NULL
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
-int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                     struct ieee80211_sta *sta);
-int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                        struct ieee80211_sta *sta);
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif,
-                            const u8 *mac_addr);
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif);
-int rt2x00mac_get_stats(struct ieee80211_hw *hw,
-                       struct ieee80211_low_level_stats *stats);
-void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_bss_conf *bss_conf,
-                               u32 changes);
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
-                     struct ieee80211_vif *vif, u16 queue,
-                     const struct ieee80211_tx_queue_params *params);
-void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
-void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                    u32 queues, bool drop);
-int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
-int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
-void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
-                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
-bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
-
-/*
- * Driver allocation handlers.
- */
-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev);
-#ifdef CONFIG_PM
-int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state);
-int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev);
-#endif /* CONFIG_PM */
-
-#endif /* RT2X00_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
deleted file mode 100644 (file)
index 7e8bb11..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 generic configuration routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
-                          struct rt2x00_intf *intf,
-                          enum nl80211_iftype type,
-                          const u8 *mac, const u8 *bssid)
-{
-       struct rt2x00intf_conf conf;
-       unsigned int flags = 0;
-
-       conf.type = type;
-
-       switch (type) {
-       case NL80211_IFTYPE_ADHOC:
-               conf.sync = TSF_SYNC_ADHOC;
-               break;
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_MESH_POINT:
-       case NL80211_IFTYPE_WDS:
-               conf.sync = TSF_SYNC_AP_NONE;
-               break;
-       case NL80211_IFTYPE_STATION:
-               conf.sync = TSF_SYNC_INFRA;
-               break;
-       default:
-               conf.sync = TSF_SYNC_NONE;
-               break;
-       }
-
-       /*
-        * Note that when NULL is passed as address we will send
-        * 00:00:00:00:00 to the device to clear the address.
-        * This will prevent the device being confused when it wants
-        * to ACK frames or considers itself associated.
-        */
-       memset(conf.mac, 0, sizeof(conf.mac));
-       if (mac)
-               memcpy(conf.mac, mac, ETH_ALEN);
-
-       memset(conf.bssid, 0, sizeof(conf.bssid));
-       if (bssid)
-               memcpy(conf.bssid, bssid, ETH_ALEN);
-
-       flags |= CONFIG_UPDATE_TYPE;
-       if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
-               flags |= CONFIG_UPDATE_MAC;
-       if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
-               flags |= CONFIG_UPDATE_BSSID;
-
-       rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
-}
-
-void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
-                         struct rt2x00_intf *intf,
-                         struct ieee80211_bss_conf *bss_conf,
-                         u32 changed)
-{
-       struct rt2x00lib_erp erp;
-
-       memset(&erp, 0, sizeof(erp));
-
-       erp.short_preamble = bss_conf->use_short_preamble;
-       erp.cts_protection = bss_conf->use_cts_prot;
-
-       erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
-       erp.sifs = SIFS;
-       erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
-       erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
-       erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
-
-       erp.basic_rates = bss_conf->basic_rates;
-       erp.beacon_int = bss_conf->beacon_int;
-
-       /* Update the AID, this is needed for dynamic PS support */
-       rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
-       rt2x00dev->last_beacon = bss_conf->sync_tsf;
-
-       /* Update global beacon interval time, this is needed for PS support */
-       rt2x00dev->beacon_int = bss_conf->beacon_int;
-
-       if (changed & BSS_CHANGED_HT)
-               erp.ht_opmode = bss_conf->ht_operation_mode;
-
-       rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
-}
-
-void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
-                             struct antenna_setup config)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct antenna_setup *def = &rt2x00dev->default_ant;
-       struct antenna_setup *active = &rt2x00dev->link.ant.active;
-
-       /*
-        * When the caller tries to send the SW diversity,
-        * we must update the ANTENNA_RX_DIVERSITY flag to
-        * enable the antenna diversity in the link tuner.
-        *
-        * Secondly, we must guarentee we never send the
-        * software antenna diversity command to the driver.
-        */
-       if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
-               if (config.rx == ANTENNA_SW_DIVERSITY) {
-                       ant->flags |= ANTENNA_RX_DIVERSITY;
-
-                       if (def->rx == ANTENNA_SW_DIVERSITY)
-                               config.rx = ANTENNA_B;
-                       else
-                               config.rx = def->rx;
-               }
-       } else if (config.rx == ANTENNA_SW_DIVERSITY)
-               config.rx = active->rx;
-
-       if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
-               if (config.tx == ANTENNA_SW_DIVERSITY) {
-                       ant->flags |= ANTENNA_TX_DIVERSITY;
-
-                       if (def->tx == ANTENNA_SW_DIVERSITY)
-                               config.tx = ANTENNA_B;
-                       else
-                               config.tx = def->tx;
-               }
-       } else if (config.tx == ANTENNA_SW_DIVERSITY)
-               config.tx = active->tx;
-
-       /*
-        * Antenna setup changes require the RX to be disabled,
-        * else the changes will be ignored by the device.
-        */
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2x00queue_stop_queue(rt2x00dev->rx);
-
-       /*
-        * Write new antenna setup to device and reset the link tuner.
-        * The latter is required since we need to recalibrate the
-        * noise-sensitivity ratio for the new setup.
-        */
-       rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
-
-       rt2x00link_reset_tuner(rt2x00dev, true);
-
-       memcpy(active, &config, sizeof(config));
-
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2x00queue_start_queue(rt2x00dev->rx);
-}
-
-static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-                                  struct ieee80211_conf *conf)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       int center_channel;
-       u16 i;
-
-       /*
-        * Initialize center channel to current channel.
-        */
-       center_channel = spec->channels[conf->chandef.chan->hw_value].channel;
-
-       /*
-        * Adjust center channel to HT40+ and HT40- operation.
-        */
-       if (conf_is_ht40_plus(conf))
-               center_channel += 2;
-       else if (conf_is_ht40_minus(conf))
-               center_channel -= (center_channel == 14) ? 1 : 2;
-
-       for (i = 0; i < spec->num_channels; i++)
-               if (spec->channels[i].channel == center_channel)
-                       return i;
-
-       WARN_ON(1);
-       return conf->chandef.chan->hw_value;
-}
-
-void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
-                     struct ieee80211_conf *conf,
-                     unsigned int ieee80211_flags)
-{
-       struct rt2x00lib_conf libconf;
-       u16 hw_value;
-       u16 autowake_timeout;
-       u16 beacon_int;
-       u16 beacon_diff;
-
-       memset(&libconf, 0, sizeof(libconf));
-
-       libconf.conf = conf;
-
-       if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
-               if (!conf_is_ht(conf))
-                       set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
-               else
-                       clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags);
-
-               if (conf_is_ht40(conf)) {
-                       set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
-                       hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
-               } else {
-                       clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
-                       hw_value = conf->chandef.chan->hw_value;
-               }
-
-               memcpy(&libconf.rf,
-                      &rt2x00dev->spec.channels[hw_value],
-                      sizeof(libconf.rf));
-
-               memcpy(&libconf.channel,
-                      &rt2x00dev->spec.channels_info[hw_value],
-                      sizeof(libconf.channel));
-
-               /* Used for VCO periodic calibration */
-               rt2x00dev->rf_channel = libconf.rf.channel;
-       }
-
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
-           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS))
-               cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
-
-       /*
-        * Start configuration.
-        */
-       rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
-
-       /*
-        * Some configuration changes affect the link quality
-        * which means we need to reset the link tuner.
-        */
-       if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt2x00link_reset_tuner(rt2x00dev, false);
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_PS_AUTOWAKE) &&
-           (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) &&
-           (conf->flags & IEEE80211_CONF_PS)) {
-               beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon;
-               beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int);
-
-               if (beacon_diff > beacon_int)
-                       beacon_diff = 0;
-
-               autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff;
-               queue_delayed_work(rt2x00dev->workqueue,
-                                  &rt2x00dev->autowakeup_work,
-                                  autowake_timeout - 15);
-       }
-
-       if (conf->flags & IEEE80211_CONF_PS)
-               set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
-       else
-               clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
-
-       rt2x00dev->curr_band = conf->chandef.chan->band;
-       rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
-       rt2x00dev->tx_power = conf->power_level;
-       rt2x00dev->short_retry = conf->short_frame_max_tx_count;
-       rt2x00dev->long_retry = conf->long_frame_max_tx_count;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
deleted file mode 100644 (file)
index a2fd05b..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 crypto specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
-{
-       switch (key->cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-               return CIPHER_WEP64;
-       case WLAN_CIPHER_SUITE_WEP104:
-               return CIPHER_WEP128;
-       case WLAN_CIPHER_SUITE_TKIP:
-               return CIPHER_TKIP;
-       case WLAN_CIPHER_SUITE_CCMP:
-               return CIPHER_AES;
-       default:
-               return CIPHER_NONE;
-       }
-}
-
-void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
-                                      struct sk_buff *skb,
-                                      struct txentry_desc *txdesc)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
-
-       if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key)
-               return;
-
-       __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
-
-       txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
-
-       if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
-               __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
-
-       txdesc->key_idx = hw_key->hw_key_idx;
-       txdesc->iv_offset = txdesc->header_length;
-       txdesc->iv_len = hw_key->iv_len;
-
-       if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
-               __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
-
-       if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
-               __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
-}
-
-unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
-                                     struct sk_buff *skb)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_key_conf *key = tx_info->control.hw_key;
-       unsigned int overhead = 0;
-
-       if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key)
-               return overhead;
-
-       /*
-        * Extend frame length to include IV/EIV/ICV/MMIC,
-        * note that these lengths should only be added when
-        * mac80211 does not generate it.
-        */
-       overhead += key->icv_len;
-
-       if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
-               overhead += key->iv_len;
-
-       if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
-               if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
-                       overhead += 8;
-       }
-
-       return overhead;
-}
-
-void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-
-       if (unlikely(!txdesc->iv_len))
-               return;
-
-       /* Copy IV/EIV data */
-       memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
-}
-
-void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-
-       if (unlikely(!txdesc->iv_len))
-               return;
-
-       /* Copy IV/EIV data */
-       memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
-
-       /* Move ieee80211 header */
-       memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);
-
-       /* Pull buffer to correct size */
-       skb_pull(skb, txdesc->iv_len);
-       txdesc->length -= txdesc->iv_len;
-
-       /* IV/EIV data has officially been stripped */
-       skbdesc->flags |= SKBDESC_IV_STRIPPED;
-}
-
-void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       const unsigned int iv_len =
-           ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
-
-       if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
-               return;
-
-       skb_push(skb, iv_len);
-
-       /* Move ieee80211 header */
-       memmove(skb->data, skb->data + iv_len, header_length);
-
-       /* Copy IV/EIV data */
-       memcpy(skb->data + header_length, skbdesc->iv, iv_len);
-
-       /* IV/EIV data has returned into the frame */
-       skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
-}
-
-void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
-                              unsigned int header_length,
-                              struct rxdone_entry_desc *rxdesc)
-{
-       unsigned int payload_len = rxdesc->size - header_length;
-       unsigned int align = ALIGN_SIZE(skb, header_length);
-       unsigned int iv_len;
-       unsigned int icv_len;
-       unsigned int transfer = 0;
-
-       /*
-        * WEP64/WEP128: Provides IV & ICV
-        * TKIP: Provides IV/EIV & ICV
-        * AES: Provies IV/EIV & ICV
-        */
-       switch (rxdesc->cipher) {
-       case CIPHER_WEP64:
-       case CIPHER_WEP128:
-               iv_len = 4;
-               icv_len = 4;
-               break;
-       case CIPHER_TKIP:
-               iv_len = 8;
-               icv_len = 4;
-               break;
-       case CIPHER_AES:
-               iv_len = 8;
-               icv_len = 8;
-               break;
-       default:
-               /* Unsupport type */
-               return;
-       }
-
-       /*
-        * Make room for new data. There are 2 possibilities
-        * either the alignment is already present between
-        * the 802.11 header and payload. In that case we
-        * we have to move the header less then the iv_len
-        * since we can use the already available l2pad bytes
-        * for the iv data.
-        * When the alignment must be added manually we must
-        * move the header more then iv_len since we must
-        * make room for the payload move as well.
-        */
-       if (rxdesc->dev_flags & RXDONE_L2PAD) {
-               skb_push(skb, iv_len - align);
-               skb_put(skb, icv_len);
-
-               /* Move ieee80211 header */
-               memmove(skb->data + transfer,
-                       skb->data + transfer + (iv_len - align),
-                       header_length);
-               transfer += header_length;
-       } else {
-               skb_push(skb, iv_len + align);
-               if (align < icv_len)
-                       skb_put(skb, icv_len - align);
-               else if (align > icv_len)
-                       skb_trim(skb, rxdesc->size + iv_len + icv_len);
-
-               /* Move ieee80211 header */
-               memmove(skb->data + transfer,
-                       skb->data + transfer + iv_len + align,
-                       header_length);
-               transfer += header_length;
-       }
-
-       /* Copy IV/EIV data */
-       memcpy(skb->data + transfer, rxdesc->iv, iv_len);
-       transfer += iv_len;
-
-       /*
-        * Move payload for alignment purposes. Note that
-        * this is only needed when no l2 padding is present.
-        */
-       if (!(rxdesc->dev_flags & RXDONE_L2PAD)) {
-               memmove(skb->data + transfer,
-                       skb->data + transfer + align,
-                       payload_len);
-       }
-
-       /*
-        * NOTE: Always count the payload as transferred,
-        * even when alignment was set to zero. This is required
-        * for determining the correct offset for the ICV data.
-        */
-       transfer += payload_len;
-
-       /*
-        * Copy ICV data
-        * AES appends 8 bytes, we can't fill the upper
-        * 4 bytes, but mac80211 doesn't care about what
-        * we provide here anyway and strips it immediately.
-        */
-       memcpy(skb->data + transfer, &rxdesc->icv, 4);
-       transfer += icv_len;
-
-       /* IV/EIV/ICV has been inserted into frame */
-       rxdesc->size = transfer;
-       rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
deleted file mode 100644 (file)
index 90fdb02..0000000
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 debugfs specific routines.
- */
-
-#include <linux/debugfs.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-#include "rt2x00dump.h"
-
-#define MAX_LINE_LENGTH 64
-
-struct rt2x00debug_crypto {
-       unsigned long success;
-       unsigned long icv_error;
-       unsigned long mic_error;
-       unsigned long key_error;
-};
-
-struct rt2x00debug_intf {
-       /*
-        * Pointer to driver structure where
-        * this debugfs entry belongs to.
-        */
-       struct rt2x00_dev *rt2x00dev;
-
-       /*
-        * Reference to the rt2x00debug structure
-        * which can be used to communicate with
-        * the registers.
-        */
-       const struct rt2x00debug *debug;
-
-       /*
-        * Debugfs entries for:
-        * - driver folder
-        *   - driver file
-        *   - chipset file
-        *   - device state flags file
-        *   - device capability flags file
-        *   - register folder
-        *     - csr offset/value files
-        *     - eeprom offset/value files
-        *     - bbp offset/value files
-        *     - rf offset/value files
-        *     - rfcsr offset/value files
-        *   - queue folder
-        *     - frame dump file
-        *     - queue stats file
-        *     - crypto stats file
-        */
-       struct dentry *driver_folder;
-       struct dentry *driver_entry;
-       struct dentry *chipset_entry;
-       struct dentry *dev_flags;
-       struct dentry *cap_flags;
-       struct dentry *register_folder;
-       struct dentry *csr_off_entry;
-       struct dentry *csr_val_entry;
-       struct dentry *eeprom_off_entry;
-       struct dentry *eeprom_val_entry;
-       struct dentry *bbp_off_entry;
-       struct dentry *bbp_val_entry;
-       struct dentry *rf_off_entry;
-       struct dentry *rf_val_entry;
-       struct dentry *rfcsr_off_entry;
-       struct dentry *rfcsr_val_entry;
-       struct dentry *queue_folder;
-       struct dentry *queue_frame_dump_entry;
-       struct dentry *queue_stats_entry;
-       struct dentry *crypto_stats_entry;
-
-       /*
-        * The frame dump file only allows a single reader,
-        * so we need to store the current state here.
-        */
-       unsigned long frame_dump_flags;
-#define FRAME_DUMP_FILE_OPEN   1
-
-       /*
-        * We queue each frame before dumping it to the user,
-        * per read command we will pass a single skb structure
-        * so we should be prepared to queue multiple sk buffers
-        * before sending it to userspace.
-        */
-       struct sk_buff_head frame_dump_skbqueue;
-       wait_queue_head_t frame_dump_waitqueue;
-
-       /*
-        * HW crypto statistics.
-        * All statistics are stored separately per cipher type.
-        */
-       struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
-
-       /*
-        * Driver and chipset files will use a data buffer
-        * that has been created in advance. This will simplify
-        * the code since we can use the debugfs functions.
-        */
-       struct debugfs_blob_wrapper driver_blob;
-       struct debugfs_blob_wrapper chipset_blob;
-
-       /*
-        * Requested offset for each register type.
-        */
-       unsigned int offset_csr;
-       unsigned int offset_eeprom;
-       unsigned int offset_bbp;
-       unsigned int offset_rf;
-       unsigned int offset_rfcsr;
-};
-
-void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                              struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
-       enum cipher cipher = rxdesc->cipher;
-       enum rx_crypto status = rxdesc->cipher_status;
-
-       if (cipher == CIPHER_TKIP_NO_MIC)
-               cipher = CIPHER_TKIP;
-       if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX)
-               return;
-
-       /* Remove CIPHER_NONE index */
-       cipher--;
-
-       intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS);
-       intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV);
-       intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC);
-       intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY);
-}
-
-void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
-                           enum rt2x00_dump_type type, struct sk_buff *skb)
-{
-       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-       struct sk_buff *skbcopy;
-       struct rt2x00dump_hdr *dump_hdr;
-       struct timeval timestamp;
-       u32 data_len;
-
-       if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
-               return;
-
-       do_gettimeofday(&timestamp);
-
-       if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
-               rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
-               return;
-       }
-
-       data_len = skb->len;
-       if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
-               data_len -= skbdesc->desc_len;
-
-       skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
-                           GFP_ATOMIC);
-       if (!skbcopy) {
-               rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
-               return;
-       }
-
-       dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
-       dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
-       dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
-       dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
-       dump_hdr->data_length = cpu_to_le32(data_len);
-       dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
-       dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
-       dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
-       dump_hdr->type = cpu_to_le16(type);
-       dump_hdr->queue_index = skbdesc->entry->queue->qid;
-       dump_hdr->entry_index = skbdesc->entry->entry_idx;
-       dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
-       dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
-
-       if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
-               memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
-                      skbdesc->desc_len);
-       memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
-
-       skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
-       wake_up_interruptible(&intf->frame_dump_waitqueue);
-
-       /*
-        * Verify that the file has not been closed while we were working.
-        */
-       if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
-               skb_queue_purge(&intf->frame_dump_skbqueue);
-}
-EXPORT_SYMBOL_GPL(rt2x00debug_dump_frame);
-
-static int rt2x00debug_file_open(struct inode *inode, struct file *file)
-{
-       struct rt2x00debug_intf *intf = inode->i_private;
-
-       file->private_data = inode->i_private;
-
-       if (!try_module_get(intf->debug->owner))
-               return -EBUSY;
-
-       return 0;
-}
-
-static int rt2x00debug_file_release(struct inode *inode, struct file *file)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-
-       module_put(intf->debug->owner);
-
-       return 0;
-}
-
-static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
-{
-       struct rt2x00debug_intf *intf = inode->i_private;
-       int retval;
-
-       retval = rt2x00debug_file_open(inode, file);
-       if (retval)
-               return retval;
-
-       if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
-               rt2x00debug_file_release(inode, file);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
-{
-       struct rt2x00debug_intf *intf = inode->i_private;
-
-       skb_queue_purge(&intf->frame_dump_skbqueue);
-
-       clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
-
-       return rt2x00debug_file_release(inode, file);
-}
-
-static ssize_t rt2x00debug_read_queue_dump(struct file *file,
-                                          char __user *buf,
-                                          size_t length,
-                                          loff_t *offset)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-       struct sk_buff *skb;
-       size_t status;
-       int retval;
-
-       if (file->f_flags & O_NONBLOCK)
-               return -EAGAIN;
-
-       retval =
-           wait_event_interruptible(intf->frame_dump_waitqueue,
-                                    (skb =
-                                    skb_dequeue(&intf->frame_dump_skbqueue)));
-       if (retval)
-               return retval;
-
-       status = min_t(size_t, skb->len, length);
-       if (copy_to_user(buf, skb->data, status)) {
-               status = -EFAULT;
-               goto exit;
-       }
-
-       *offset += status;
-
-exit:
-       kfree_skb(skb);
-
-       return status;
-}
-
-static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
-                                               poll_table *wait)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-
-       poll_wait(file, &intf->frame_dump_waitqueue, wait);
-
-       if (!skb_queue_empty(&intf->frame_dump_skbqueue))
-               return POLLOUT | POLLWRNORM;
-
-       return 0;
-}
-
-static const struct file_operations rt2x00debug_fop_queue_dump = {
-       .owner          = THIS_MODULE,
-       .read           = rt2x00debug_read_queue_dump,
-       .poll           = rt2x00debug_poll_queue_dump,
-       .open           = rt2x00debug_open_queue_dump,
-       .release        = rt2x00debug_release_queue_dump,
-       .llseek         = default_llseek,
-};
-
-static ssize_t rt2x00debug_read_queue_stats(struct file *file,
-                                           char __user *buf,
-                                           size_t length,
-                                           loff_t *offset)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-       struct data_queue *queue;
-       unsigned long irqflags;
-       unsigned int lines = 1 + intf->rt2x00dev->data_queues;
-       size_t size;
-       char *data;
-       char *temp;
-
-       if (*offset)
-               return 0;
-
-       data = kcalloc(lines, MAX_LINE_LENGTH, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       temp = data +
-           sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
-
-       queue_for_each(intf->rt2x00dev, queue) {
-               spin_lock_irqsave(&queue->index_lock, irqflags);
-
-               temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
-                               queue->qid, (unsigned int)queue->flags,
-                               queue->count, queue->limit, queue->length,
-                               queue->index[Q_INDEX],
-                               queue->index[Q_INDEX_DMA_DONE],
-                               queue->index[Q_INDEX_DONE]);
-
-               spin_unlock_irqrestore(&queue->index_lock, irqflags);
-       }
-
-       size = strlen(data);
-       size = min(size, length);
-
-       if (copy_to_user(buf, data, size)) {
-               kfree(data);
-               return -EFAULT;
-       }
-
-       kfree(data);
-
-       *offset += size;
-       return size;
-}
-
-static const struct file_operations rt2x00debug_fop_queue_stats = {
-       .owner          = THIS_MODULE,
-       .read           = rt2x00debug_read_queue_stats,
-       .open           = rt2x00debug_file_open,
-       .release        = rt2x00debug_file_release,
-       .llseek         = default_llseek,
-};
-
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
-                                            char __user *buf,
-                                            size_t length,
-                                            loff_t *offset)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-       static const char * const name[] = { "WEP64", "WEP128", "TKIP", "AES" };
-       char *data;
-       char *temp;
-       size_t size;
-       unsigned int i;
-
-       if (*offset)
-               return 0;
-
-       data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       temp = data;
-       temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n");
-
-       for (i = 0; i < CIPHER_MAX; i++) {
-               temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i],
-                               intf->crypto_stats[i].success,
-                               intf->crypto_stats[i].icv_error,
-                               intf->crypto_stats[i].mic_error,
-                               intf->crypto_stats[i].key_error);
-       }
-
-       size = strlen(data);
-       size = min(size, length);
-
-       if (copy_to_user(buf, data, size)) {
-               kfree(data);
-               return -EFAULT;
-       }
-
-       kfree(data);
-
-       *offset += size;
-       return size;
-}
-
-static const struct file_operations rt2x00debug_fop_crypto_stats = {
-       .owner          = THIS_MODULE,
-       .read           = rt2x00debug_read_crypto_stats,
-       .open           = rt2x00debug_file_open,
-       .release        = rt2x00debug_file_release,
-       .llseek         = default_llseek,
-};
-#endif
-
-#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)       \
-static ssize_t rt2x00debug_read_##__name(struct file *file,    \
-                                        char __user *buf,      \
-                                        size_t length,         \
-                                        loff_t *offset)        \
-{                                                              \
-       struct rt2x00debug_intf *intf = file->private_data;     \
-       const struct rt2x00debug *debug = intf->debug;          \
-       char line[16];                                          \
-       size_t size;                                            \
-       unsigned int index = intf->offset_##__name;             \
-       __type value;                                           \
-                                                               \
-       if (*offset)                                            \
-               return 0;                                       \
-                                                               \
-       if (index >= debug->__name.word_count)                  \
-               return -EINVAL;                                 \
-                                                               \
-       index += (debug->__name.word_base /                     \
-                 debug->__name.word_size);                     \
-                                                               \
-       if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
-               index *= debug->__name.word_size;               \
-                                                               \
-       debug->__name.read(intf->rt2x00dev, index, &value);     \
-                                                               \
-       size = sprintf(line, __format, value);                  \
-                                                               \
-       if (copy_to_user(buf, line, size))                      \
-               return -EFAULT;                                 \
-                                                               \
-       *offset += size;                                        \
-       return size;                                            \
-}
-
-#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                        \
-static ssize_t rt2x00debug_write_##__name(struct file *file,   \
-                                         const char __user *buf,\
-                                         size_t length,        \
-                                         loff_t *offset)       \
-{                                                              \
-       struct rt2x00debug_intf *intf = file->private_data;     \
-       const struct rt2x00debug *debug = intf->debug;          \
-       char line[16];                                          \
-       size_t size;                                            \
-       unsigned int index = intf->offset_##__name;             \
-       __type value;                                           \
-                                                               \
-       if (*offset)                                            \
-               return 0;                                       \
-                                                               \
-       if (index >= debug->__name.word_count)                  \
-               return -EINVAL;                                 \
-                                                               \
-       if (length > sizeof(line))                              \
-               return -EINVAL;                                 \
-                                                               \
-       if (copy_from_user(line, buf, length))                  \
-               return -EFAULT;                                 \
-                                                               \
-       size = strlen(line);                                    \
-       value = simple_strtoul(line, NULL, 0);                  \
-                                                               \
-       index += (debug->__name.word_base /                     \
-                 debug->__name.word_size);                     \
-                                                               \
-       if (debug->__name.flags & RT2X00DEBUGFS_OFFSET)         \
-               index *= debug->__name.word_size;               \
-                                                               \
-       debug->__name.write(intf->rt2x00dev, index, value);     \
-                                                               \
-       *offset += size;                                        \
-       return size;                                            \
-}
-
-#define RT2X00DEBUGFS_OPS(__name, __format, __type)            \
-RT2X00DEBUGFS_OPS_READ(__name, __format, __type);              \
-RT2X00DEBUGFS_OPS_WRITE(__name, __type);                       \
-                                                               \
-static const struct file_operations rt2x00debug_fop_##__name = {\
-       .owner          = THIS_MODULE,                          \
-       .read           = rt2x00debug_read_##__name,            \
-       .write          = rt2x00debug_write_##__name,           \
-       .open           = rt2x00debug_file_open,                \
-       .release        = rt2x00debug_file_release,             \
-       .llseek         = generic_file_llseek,                  \
-};
-
-RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
-RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
-RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
-RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
-RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);
-
-static ssize_t rt2x00debug_read_dev_flags(struct file *file,
-                                         char __user *buf,
-                                         size_t length,
-                                         loff_t *offset)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-       char line[16];
-       size_t size;
-
-       if (*offset)
-               return 0;
-
-       size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
-
-       if (copy_to_user(buf, line, size))
-               return -EFAULT;
-
-       *offset += size;
-       return size;
-}
-
-static const struct file_operations rt2x00debug_fop_dev_flags = {
-       .owner          = THIS_MODULE,
-       .read           = rt2x00debug_read_dev_flags,
-       .open           = rt2x00debug_file_open,
-       .release        = rt2x00debug_file_release,
-       .llseek         = default_llseek,
-};
-
-static ssize_t rt2x00debug_read_cap_flags(struct file *file,
-                                         char __user *buf,
-                                         size_t length,
-                                         loff_t *offset)
-{
-       struct rt2x00debug_intf *intf = file->private_data;
-       char line[16];
-       size_t size;
-
-       if (*offset)
-               return 0;
-
-       size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
-
-       if (copy_to_user(buf, line, size))
-               return -EFAULT;
-
-       *offset += size;
-       return size;
-}
-
-static const struct file_operations rt2x00debug_fop_cap_flags = {
-       .owner          = THIS_MODULE,
-       .read           = rt2x00debug_read_cap_flags,
-       .open           = rt2x00debug_file_open,
-       .release        = rt2x00debug_file_release,
-       .llseek         = default_llseek,
-};
-
-static struct dentry *rt2x00debug_create_file_driver(const char *name,
-                                                    struct rt2x00debug_intf
-                                                    *intf,
-                                                    struct debugfs_blob_wrapper
-                                                    *blob)
-{
-       char *data;
-
-       data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
-       if (!data)
-               return NULL;
-
-       blob->data = data;
-       data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
-       data += sprintf(data, "version:\t%s\n", DRV_VERSION);
-       blob->size = strlen(blob->data);
-
-       return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
-}
-
-static struct dentry *rt2x00debug_create_file_chipset(const char *name,
-                                                     struct rt2x00debug_intf
-                                                     *intf,
-                                                     struct
-                                                     debugfs_blob_wrapper
-                                                     *blob)
-{
-       const struct rt2x00debug *debug = intf->debug;
-       char *data;
-
-       data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);
-       if (!data)
-               return NULL;
-
-       blob->data = data;
-       data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
-       data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
-       data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
-       data += sprintf(data, "\n");
-       data += sprintf(data, "register\tbase\twords\twordsize\n");
-#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name)                 \
-{                                                              \
-       if(debug->__name.read)                                  \
-               data += sprintf(data, __stringify(__name)       \
-                               "\t%d\t%d\t%d\n",               \
-                               debug->__name.word_base,        \
-                               debug->__name.word_count,       \
-                               debug->__name.word_size);       \
-}
-       RT2X00DEBUGFS_SPRINTF_REGISTER(csr);
-       RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom);
-       RT2X00DEBUGFS_SPRINTF_REGISTER(bbp);
-       RT2X00DEBUGFS_SPRINTF_REGISTER(rf);
-       RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr);
-#undef RT2X00DEBUGFS_SPRINTF_REGISTER
-
-       blob->size = strlen(blob->data);
-
-       return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
-}
-
-void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
-{
-       const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
-       struct rt2x00debug_intf *intf;
-
-       intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
-       if (!intf) {
-               rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
-               return;
-       }
-
-       intf->debug = debug;
-       intf->rt2x00dev = rt2x00dev;
-       rt2x00dev->debugfs_intf = intf;
-
-       intf->driver_folder =
-           debugfs_create_dir(intf->rt2x00dev->ops->name,
-                              rt2x00dev->hw->wiphy->debugfsdir);
-       if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
-               goto exit;
-
-       intf->driver_entry =
-           rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
-       if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
-               goto exit;
-
-       intf->chipset_entry =
-           rt2x00debug_create_file_chipset("chipset",
-                                           intf, &intf->chipset_blob);
-       if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
-               goto exit;
-
-       intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
-                                             intf->driver_folder, intf,
-                                             &rt2x00debug_fop_dev_flags);
-       if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
-               goto exit;
-
-       intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
-                                             intf->driver_folder, intf,
-                                             &rt2x00debug_fop_cap_flags);
-       if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
-               goto exit;
-
-       intf->register_folder =
-           debugfs_create_dir("register", intf->driver_folder);
-       if (IS_ERR(intf->register_folder) || !intf->register_folder)
-               goto exit;
-
-#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)                    \
-({                                                                             \
-       if(debug->__name.read) {                                                \
-               (__intf)->__name##_off_entry =                                  \
-               debugfs_create_u32(__stringify(__name) "_offset",               \
-                                      S_IRUSR | S_IWUSR,                       \
-                                      (__intf)->register_folder,               \
-                                      &(__intf)->offset_##__name);             \
-               if (IS_ERR((__intf)->__name##_off_entry)                        \
-                               || !(__intf)->__name##_off_entry)               \
-                       goto exit;                                              \
-                                                                               \
-               (__intf)->__name##_val_entry =                                  \
-               debugfs_create_file(__stringify(__name) "_value",               \
-                                       S_IRUSR | S_IWUSR,                      \
-                                       (__intf)->register_folder,              \
-                                       (__intf), &rt2x00debug_fop_##__name);   \
-               if (IS_ERR((__intf)->__name##_val_entry)                        \
-                               || !(__intf)->__name##_val_entry)               \
-                       goto exit;                                              \
-       }                                                                       \
-})
-
-       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
-       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
-       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
-       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
-       RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);
-
-#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
-
-       intf->queue_folder =
-           debugfs_create_dir("queue", intf->driver_folder);
-       if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
-               goto exit;
-
-       intf->queue_frame_dump_entry =
-           debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
-                               intf, &rt2x00debug_fop_queue_dump);
-       if (IS_ERR(intf->queue_frame_dump_entry)
-               || !intf->queue_frame_dump_entry)
-               goto exit;
-
-       skb_queue_head_init(&intf->frame_dump_skbqueue);
-       init_waitqueue_head(&intf->frame_dump_waitqueue);
-
-       intf->queue_stats_entry =
-           debugfs_create_file("queue", S_IRUSR, intf->queue_folder,
-                               intf, &rt2x00debug_fop_queue_stats);
-
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-       if (rt2x00_has_cap_hw_crypto(rt2x00dev))
-               intf->crypto_stats_entry =
-                   debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
-                                       intf, &rt2x00debug_fop_crypto_stats);
-#endif
-
-       return;
-
-exit:
-       rt2x00debug_deregister(rt2x00dev);
-       rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
-}
-
-void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
-
-       if (unlikely(!intf))
-               return;
-
-       skb_queue_purge(&intf->frame_dump_skbqueue);
-
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-       debugfs_remove(intf->crypto_stats_entry);
-#endif
-       debugfs_remove(intf->queue_stats_entry);
-       debugfs_remove(intf->queue_frame_dump_entry);
-       debugfs_remove(intf->queue_folder);
-       debugfs_remove(intf->rfcsr_val_entry);
-       debugfs_remove(intf->rfcsr_off_entry);
-       debugfs_remove(intf->rf_val_entry);
-       debugfs_remove(intf->rf_off_entry);
-       debugfs_remove(intf->bbp_val_entry);
-       debugfs_remove(intf->bbp_off_entry);
-       debugfs_remove(intf->eeprom_val_entry);
-       debugfs_remove(intf->eeprom_off_entry);
-       debugfs_remove(intf->csr_val_entry);
-       debugfs_remove(intf->csr_off_entry);
-       debugfs_remove(intf->register_folder);
-       debugfs_remove(intf->dev_flags);
-       debugfs_remove(intf->cap_flags);
-       debugfs_remove(intf->chipset_entry);
-       debugfs_remove(intf->driver_entry);
-       debugfs_remove(intf->driver_folder);
-       kfree(intf->chipset_blob.data);
-       kfree(intf->driver_blob.data);
-       kfree(intf);
-
-       rt2x00dev->debugfs_intf = NULL;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
deleted file mode 100644 (file)
index e65712c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00debug
-       Abstract: Data structures for the rt2x00debug.
- */
-
-#ifndef RT2X00DEBUG_H
-#define RT2X00DEBUG_H
-
-struct rt2x00_dev;
-
-/**
- * enum rt2x00debugfs_entry_flags: Flags for debugfs registry entry
- *
- * @RT2X00DEBUGFS_OFFSET: rt2x00lib should pass the register offset
- *     as argument when using the callback function read()/write()
- */
-enum rt2x00debugfs_entry_flags {
-       RT2X00DEBUGFS_OFFSET    = (1 << 0),
-};
-
-#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type)           \
-struct reg##__name {                                           \
-       void (*read)(struct rt2x00_dev *rt2x00dev,              \
-                    const unsigned int word, __type *data);    \
-       void (*write)(struct rt2x00_dev *rt2x00dev,             \
-                     const unsigned int word, __type data);    \
-                                                               \
-       unsigned int flags;                                     \
-                                                               \
-       unsigned int word_base;                                 \
-       unsigned int word_size;                                 \
-       unsigned int word_count;                                \
-} __name
-
-struct rt2x00debug {
-       /*
-        * Reference to the modules structure.
-        */
-       struct module *owner;
-
-       /*
-        * Register access entries.
-        */
-       RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32);
-       RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
-       RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
-       RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
-       RT2X00DEBUGFS_REGISTER_ENTRY(rfcsr, u8);
-};
-
-#endif /* RT2X00DEBUG_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
deleted file mode 100644 (file)
index 5639ed8..0000000
+++ /dev/null
@@ -1,1549 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 generic device routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/log2.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-/*
- * Utility functions.
- */
-u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
-                        struct ieee80211_vif *vif)
-{
-       /*
-        * When in STA mode, bssidx is always 0 otherwise local_address[5]
-        * contains the bss number, see BSS_ID_MASK comments for details.
-        */
-       if (rt2x00dev->intf_sta_count)
-               return 0;
-       return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx);
-
-/*
- * Radio control handlers.
- */
-int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       int status;
-
-       /*
-        * Don't enable the radio twice.
-        * And check if the hardware button has been disabled.
-        */
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Initialize all data queues.
-        */
-       rt2x00queue_init_queues(rt2x00dev);
-
-       /*
-        * Enable radio.
-        */
-       status =
-           rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
-       if (status)
-               return status;
-
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON);
-
-       rt2x00leds_led_radio(rt2x00dev, true);
-       rt2x00led_led_activity(rt2x00dev, true);
-
-       set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
-
-       /*
-        * Enable queues.
-        */
-       rt2x00queue_start_queues(rt2x00dev);
-       rt2x00link_start_tuner(rt2x00dev);
-       rt2x00link_start_agc(rt2x00dev);
-       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
-               rt2x00link_start_vcocal(rt2x00dev);
-
-       /*
-        * Start watchdog monitoring.
-        */
-       rt2x00link_start_watchdog(rt2x00dev);
-
-       return 0;
-}
-
-void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Stop watchdog monitoring.
-        */
-       rt2x00link_stop_watchdog(rt2x00dev);
-
-       /*
-        * Stop all queues
-        */
-       rt2x00link_stop_agc(rt2x00dev);
-       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
-               rt2x00link_stop_vcocal(rt2x00dev);
-       rt2x00link_stop_tuner(rt2x00dev);
-       rt2x00queue_stop_queues(rt2x00dev);
-       rt2x00queue_flush_queues(rt2x00dev, true);
-
-       /*
-        * Disable radio.
-        */
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
-       rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF);
-       rt2x00led_led_activity(rt2x00dev, false);
-       rt2x00leds_led_radio(rt2x00dev, false);
-}
-
-static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
-                                         struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = data;
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       /*
-        * It is possible the radio was disabled while the work had been
-        * scheduled. If that happens we should return here immediately,
-        * note that in the spinlock protected area above the delayed_flags
-        * have been cleared correctly.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
-               mutex_lock(&intf->beacon_skb_mutex);
-               rt2x00queue_update_beacon(rt2x00dev, vif);
-               mutex_unlock(&intf->beacon_skb_mutex);
-       }
-}
-
-static void rt2x00lib_intf_scheduled(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, intf_work);
-
-       /*
-        * Iterate over each interface and perform the
-        * requested configurations.
-        */
-       ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-                                           IEEE80211_IFACE_ITER_RESUME_ALL,
-                                           rt2x00lib_intf_scheduled_iter,
-                                           rt2x00dev);
-}
-
-static void rt2x00lib_autowakeup(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, autowakeup_work.work);
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return;
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               rt2x00_err(rt2x00dev, "Device failed to wakeup\n");
-       clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
-}
-
-/*
- * Interrupt context handlers.
- */
-static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
-                                    struct ieee80211_vif *vif)
-{
-       struct ieee80211_tx_control control = {};
-       struct rt2x00_dev *rt2x00dev = data;
-       struct sk_buff *skb;
-
-       /*
-        * Only AP mode interfaces do broad- and multicast buffering
-        */
-       if (vif->type != NL80211_IFTYPE_AP)
-               return;
-
-       /*
-        * Send out buffered broad- and multicast frames
-        */
-       skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
-       while (skb) {
-               rt2x00mac_tx(rt2x00dev->hw, &control, skb);
-               skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
-       }
-}
-
-static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
-                                       struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = data;
-
-       if (vif->type != NL80211_IFTYPE_AP &&
-           vif->type != NL80211_IFTYPE_ADHOC &&
-           vif->type != NL80211_IFTYPE_MESH_POINT &&
-           vif->type != NL80211_IFTYPE_WDS)
-               return;
-
-       /*
-        * Update the beacon without locking. This is safe on PCI devices
-        * as they only update the beacon periodically here. This should
-        * never be called for USB devices.
-        */
-       WARN_ON(rt2x00_is_usb(rt2x00dev));
-       rt2x00queue_update_beacon(rt2x00dev, vif);
-}
-
-void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /* send buffered bc/mc frames out for every bssid */
-       ieee80211_iterate_active_interfaces_atomic(
-               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-               rt2x00lib_bc_buffer_iter, rt2x00dev);
-       /*
-        * Devices with pre tbtt interrupt don't need to update the beacon
-        * here as they will fetch the next beacon directly prior to
-        * transmission.
-        */
-       if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev))
-               return;
-
-       /* fetch next beacon */
-       ieee80211_iterate_active_interfaces_atomic(
-               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-               rt2x00lib_beaconupdate_iter, rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
-
-void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /* fetch next beacon */
-       ieee80211_iterate_active_interfaces_atomic(
-               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-               rt2x00lib_beaconupdate_iter, rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
-
-void rt2x00lib_dmastart(struct queue_entry *entry)
-{
-       set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-       rt2x00queue_index_inc(entry, Q_INDEX);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
-
-void rt2x00lib_dmadone(struct queue_entry *entry)
-{
-       set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
-       clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-       rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
-
-static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct ieee80211_bar *bar = (void *) entry->skb->data;
-       struct rt2x00_bar_list_entry *bar_entry;
-       int ret;
-
-       if (likely(!ieee80211_is_back_req(bar->frame_control)))
-               return 0;
-
-       /*
-        * Unlike all other frames, the status report for BARs does
-        * not directly come from the hardware as it is incapable of
-        * matching a BA to a previously send BAR. The hardware will
-        * report all BARs as if they weren't acked at all.
-        *
-        * Instead the RX-path will scan for incoming BAs and set the
-        * block_acked flag if it sees one that was likely caused by
-        * a BAR from us.
-        *
-        * Remove remaining BARs here and return their status for
-        * TX done processing.
-        */
-       ret = 0;
-       rcu_read_lock();
-       list_for_each_entry_rcu(bar_entry, &rt2x00dev->bar_list, list) {
-               if (bar_entry->entry != entry)
-                       continue;
-
-               spin_lock_bh(&rt2x00dev->bar_list_lock);
-               /* Return whether this BAR was blockacked or not */
-               ret = bar_entry->block_acked;
-               /* Remove the BAR from our checklist */
-               list_del_rcu(&bar_entry->list);
-               spin_unlock_bh(&rt2x00dev->bar_list_lock);
-               kfree_rcu(bar_entry, head);
-
-               break;
-       }
-       rcu_read_unlock();
-
-       return ret;
-}
-
-void rt2x00lib_txdone(struct queue_entry *entry,
-                     struct txdone_entry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       unsigned int header_length, i;
-       u8 rate_idx, rate_flags, retry_rates;
-       u8 skbdesc_flags = skbdesc->flags;
-       bool success;
-
-       /*
-        * Unmap the skb.
-        */
-       rt2x00queue_unmap_skb(entry);
-
-       /*
-        * Remove the extra tx headroom from the skb.
-        */
-       skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
-
-       /*
-        * Signal that the TX descriptor is no longer in the skb.
-        */
-       skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
-
-       /*
-        * Determine the length of 802.11 header.
-        */
-       header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-
-       /*
-        * Remove L2 padding which was added during
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
-               rt2x00queue_remove_l2pad(entry->skb, header_length);
-
-       /*
-        * If the IV/EIV data was stripped from the frame before it was
-        * passed to the hardware, we should now reinsert it again because
-        * mac80211 will expect the same data to be present it the
-        * frame as it was passed to us.
-        */
-       if (rt2x00_has_cap_hw_crypto(rt2x00dev))
-               rt2x00crypto_tx_insert_iv(entry->skb, header_length);
-
-       /*
-        * Send frame to debugfs immediately, after this call is completed
-        * we are going to overwrite the skb->cb array.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
-
-       /*
-        * Determine if the frame has been successfully transmitted and
-        * remove BARs from our check list while checking for their
-        * TX status.
-        */
-       success =
-           rt2x00lib_txdone_bar_status(entry) ||
-           test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
-           test_bit(TXDONE_UNKNOWN, &txdesc->flags);
-
-       /*
-        * Update TX statistics.
-        */
-       rt2x00dev->link.qual.tx_success += success;
-       rt2x00dev->link.qual.tx_failed += !success;
-
-       rate_idx = skbdesc->tx_rate_idx;
-       rate_flags = skbdesc->tx_rate_flags;
-       retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ?
-           (txdesc->retry + 1) : 1;
-
-       /*
-        * Initialize TX status
-        */
-       memset(&tx_info->status, 0, sizeof(tx_info->status));
-       tx_info->status.ack_signal = 0;
-
-       /*
-        * Frame was send with retries, hardware tried
-        * different rates to send out the frame, at each
-        * retry it lowered the rate 1 step except when the
-        * lowest rate was used.
-        */
-       for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) {
-               tx_info->status.rates[i].idx = rate_idx - i;
-               tx_info->status.rates[i].flags = rate_flags;
-
-               if (rate_idx - i == 0) {
-                       /*
-                        * The lowest rate (index 0) was used until the
-                        * number of max retries was reached.
-                        */
-                       tx_info->status.rates[i].count = retry_rates - i;
-                       i++;
-                       break;
-               }
-               tx_info->status.rates[i].count = 1;
-       }
-       if (i < (IEEE80211_TX_MAX_RATES - 1))
-               tx_info->status.rates[i].idx = -1; /* terminate */
-
-       if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-               if (success)
-                       tx_info->flags |= IEEE80211_TX_STAT_ACK;
-               else
-                       rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-       }
-
-       /*
-        * Every single frame has it's own tx status, hence report
-        * every frame as ampdu of size 1.
-        *
-        * TODO: if we can find out how many frames were aggregated
-        * by the hw we could provide the real ampdu_len to mac80211
-        * which would allow the rc algorithm to better decide on
-        * which rates are suitable.
-        */
-       if (test_bit(TXDONE_AMPDU, &txdesc->flags) ||
-           tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-               tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
-               tx_info->status.ampdu_len = 1;
-               tx_info->status.ampdu_ack_len = success ? 1 : 0;
-
-               if (!success)
-                       tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-       }
-
-       if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-               if (success)
-                       rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
-               else
-                       rt2x00dev->low_level_stats.dot11RTSFailureCount++;
-       }
-
-       /*
-        * Only send the status report to mac80211 when it's a frame
-        * that originated in mac80211. If this was a extra frame coming
-        * through a mac80211 library call (RTS/CTS) then we should not
-        * send the status report back.
-        */
-       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
-               if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TASKLET_CONTEXT))
-                       ieee80211_tx_status(rt2x00dev->hw, entry->skb);
-               else
-                       ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
-       } else
-               dev_kfree_skb_any(entry->skb);
-
-       /*
-        * Make this entry available for reuse.
-        */
-       entry->skb = NULL;
-       entry->flags = 0;
-
-       rt2x00dev->ops->lib->clear_entry(entry);
-
-       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
-
-       /*
-        * If the data queue was below the threshold before the txdone
-        * handler we must make sure the packet queue in the mac80211 stack
-        * is reenabled when the txdone handler has finished. This has to be
-        * serialized with rt2x00mac_tx(), otherwise we can wake up queue
-        * before it was stopped.
-        */
-       spin_lock_bh(&entry->queue->tx_lock);
-       if (!rt2x00queue_threshold(entry->queue))
-               rt2x00queue_unpause_queue(entry->queue);
-       spin_unlock_bh(&entry->queue->tx_lock);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
-
-void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
-{
-       struct txdone_entry_desc txdesc;
-
-       txdesc.flags = 0;
-       __set_bit(status, &txdesc.flags);
-       txdesc.retry = 0;
-
-       rt2x00lib_txdone(entry, &txdesc);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo);
-
-static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
-{
-       struct ieee80211_mgmt *mgmt = (void *)data;
-       u8 *pos, *end;
-
-       pos = (u8 *)mgmt->u.beacon.variable;
-       end = data + len;
-       while (pos < end) {
-               if (pos + 2 + pos[1] > end)
-                       return NULL;
-
-               if (pos[0] == ie)
-                       return pos;
-
-               pos += 2 + pos[1];
-       }
-
-       return NULL;
-}
-
-static void rt2x00lib_sleep(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, sleep_work);
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Check again is powersaving is enabled, to prevent races from delayed
-        * work execution.
-        */
-       if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
-               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
-                                IEEE80211_CONF_CHANGE_PS);
-}
-
-static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev,
-                                     struct sk_buff *skb,
-                                     struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00_bar_list_entry *entry;
-       struct ieee80211_bar *ba = (void *)skb->data;
-
-       if (likely(!ieee80211_is_back(ba->frame_control)))
-               return;
-
-       if (rxdesc->size < sizeof(*ba) + FCS_LEN)
-               return;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(entry, &rt2x00dev->bar_list, list) {
-
-               if (ba->start_seq_num != entry->start_seq_num)
-                       continue;
-
-#define TID_CHECK(a, b) (                                              \
-       ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) ==        \
-       ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)))          \
-
-               if (!TID_CHECK(ba->control, entry->control))
-                       continue;
-
-#undef TID_CHECK
-
-               if (!ether_addr_equal_64bits(ba->ra, entry->ta))
-                       continue;
-
-               if (!ether_addr_equal_64bits(ba->ta, entry->ra))
-                       continue;
-
-               /* Mark BAR since we received the according BA */
-               spin_lock_bh(&rt2x00dev->bar_list_lock);
-               entry->block_acked = 1;
-               spin_unlock_bh(&rt2x00dev->bar_list_lock);
-               break;
-       }
-       rcu_read_unlock();
-
-}
-
-static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
-                                     struct sk_buff *skb,
-                                     struct rxdone_entry_desc *rxdesc)
-{
-       struct ieee80211_hdr *hdr = (void *) skb->data;
-       struct ieee80211_tim_ie *tim_ie;
-       u8 *tim;
-       u8 tim_len;
-       bool cam;
-
-       /* If this is not a beacon, or if mac80211 has no powersaving
-        * configured, or if the device is already in powersaving mode
-        * we can exit now. */
-       if (likely(!ieee80211_is_beacon(hdr->frame_control) ||
-                  !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS)))
-               return;
-
-       /* min. beacon length + FCS_LEN */
-       if (skb->len <= 40 + FCS_LEN)
-               return;
-
-       /* and only beacons from the associated BSSID, please */
-       if (!(rxdesc->dev_flags & RXDONE_MY_BSS) ||
-           !rt2x00dev->aid)
-               return;
-
-       rt2x00dev->last_beacon = jiffies;
-
-       tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM);
-       if (!tim)
-               return;
-
-       if (tim[1] < sizeof(*tim_ie))
-               return;
-
-       tim_len = tim[1];
-       tim_ie = (struct ieee80211_tim_ie *) &tim[2];
-
-       /* Check whenever the PHY can be turned off again. */
-
-       /* 1. What about buffered unicast traffic for our AID? */
-       cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid);
-
-       /* 2. Maybe the AP wants to send multicast/broadcast data? */
-       cam |= (tim_ie->bitmap_ctrl & 0x01);
-
-       if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
-}
-
-static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
-                                       struct rxdone_entry_desc *rxdesc)
-{
-       struct ieee80211_supported_band *sband;
-       const struct rt2x00_rate *rate;
-       unsigned int i;
-       int signal = rxdesc->signal;
-       int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK);
-
-       switch (rxdesc->rate_mode) {
-       case RATE_MODE_CCK:
-       case RATE_MODE_OFDM:
-               /*
-                * For non-HT rates the MCS value needs to contain the
-                * actually used rate modulation (CCK or OFDM).
-                */
-               if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS)
-                       signal = RATE_MCS(rxdesc->rate_mode, signal);
-
-               sband = &rt2x00dev->bands[rt2x00dev->curr_band];
-               for (i = 0; i < sband->n_bitrates; i++) {
-                       rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
-                       if (((type == RXDONE_SIGNAL_PLCP) &&
-                            (rate->plcp == signal)) ||
-                           ((type == RXDONE_SIGNAL_BITRATE) &&
-                             (rate->bitrate == signal)) ||
-                           ((type == RXDONE_SIGNAL_MCS) &&
-                             (rate->mcs == signal))) {
-                               return i;
-                       }
-               }
-               break;
-       case RATE_MODE_HT_MIX:
-       case RATE_MODE_HT_GREENFIELD:
-               if (signal >= 0 && signal <= 76)
-                       return signal;
-               break;
-       default:
-               break;
-       }
-
-       rt2x00_warn(rt2x00dev, "Frame received with unrecognized signal, mode=0x%.4x, signal=0x%.4x, type=%d\n",
-                   rxdesc->rate_mode, signal, type);
-       return 0;
-}
-
-void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct rxdone_entry_desc rxdesc;
-       struct sk_buff *skb;
-       struct ieee80211_rx_status *rx_status;
-       unsigned int header_length;
-       int rate_idx;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
-           !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               goto submit_entry;
-
-       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
-               goto submit_entry;
-
-       /*
-        * Allocate a new sk_buffer. If no new buffer available, drop the
-        * received frame and reuse the existing buffer.
-        */
-       skb = rt2x00queue_alloc_rxskb(entry, gfp);
-       if (!skb)
-               goto submit_entry;
-
-       /*
-        * Unmap the skb.
-        */
-       rt2x00queue_unmap_skb(entry);
-
-       /*
-        * Extract the RXD details.
-        */
-       memset(&rxdesc, 0, sizeof(rxdesc));
-       rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
-
-       /*
-        * Check for valid size in case we get corrupted descriptor from
-        * hardware.
-        */
-       if (unlikely(rxdesc.size == 0 ||
-                    rxdesc.size > entry->queue->data_size)) {
-               rt2x00_err(rt2x00dev, "Wrong frame size %d max %d\n",
-                          rxdesc.size, entry->queue->data_size);
-               dev_kfree_skb(entry->skb);
-               goto renew_skb;
-       }
-
-       /*
-        * The data behind the ieee80211 header must be
-        * aligned on a 4 byte boundary.
-        */
-       header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-
-       /*
-        * Hardware might have stripped the IV/EIV/ICV data,
-        * in that case it is possible that the data was
-        * provided separately (through hardware descriptor)
-        * in which case we should reinsert the data into the frame.
-        */
-       if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
-           (rxdesc.flags & RX_FLAG_IV_STRIPPED))
-               rt2x00crypto_rx_insert_iv(entry->skb, header_length,
-                                         &rxdesc);
-       else if (header_length &&
-                (rxdesc.size > header_length) &&
-                (rxdesc.dev_flags & RXDONE_L2PAD))
-               rt2x00queue_remove_l2pad(entry->skb, header_length);
-
-       /* Trim buffer to correct size */
-       skb_trim(entry->skb, rxdesc.size);
-
-       /*
-        * Translate the signal to the correct bitrate index.
-        */
-       rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
-       if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
-           rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
-               rxdesc.flags |= RX_FLAG_HT;
-
-       /*
-        * Check if this is a beacon, and more frames have been
-        * buffered while we were in powersaving mode.
-        */
-       rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc);
-
-       /*
-        * Check for incoming BlockAcks to match to the BlockAckReqs
-        * we've send out.
-        */
-       rt2x00lib_rxdone_check_ba(rt2x00dev, entry->skb, &rxdesc);
-
-       /*
-        * Update extra components
-        */
-       rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
-       rt2x00debug_update_crypto(rt2x00dev, &rxdesc);
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
-
-       /*
-        * Initialize RX status information, and send frame
-        * to mac80211.
-        */
-       rx_status = IEEE80211_SKB_RXCB(entry->skb);
-
-       /* Ensure that all fields of rx_status are initialized
-        * properly. The skb->cb array was used for driver
-        * specific informations, so rx_status might contain
-        * garbage.
-        */
-       memset(rx_status, 0, sizeof(*rx_status));
-
-       rx_status->mactime = rxdesc.timestamp;
-       rx_status->band = rt2x00dev->curr_band;
-       rx_status->freq = rt2x00dev->curr_freq;
-       rx_status->rate_idx = rate_idx;
-       rx_status->signal = rxdesc.rssi;
-       rx_status->flag = rxdesc.flags;
-       rx_status->antenna = rt2x00dev->link.ant.active.rx;
-
-       ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
-
-renew_skb:
-       /*
-        * Replace the skb with the freshly allocated one.
-        */
-       entry->skb = skb;
-
-submit_entry:
-       entry->flags = 0;
-       rt2x00queue_index_inc(entry, Q_INDEX_DONE);
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-           test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2x00dev->ops->lib->clear_entry(entry);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
-
-/*
- * Driver initialization handlers.
- */
-const struct rt2x00_rate rt2x00_supported_rates[12] = {
-       {
-               .flags = DEV_RATE_CCK,
-               .bitrate = 10,
-               .ratemask = BIT(0),
-               .plcp = 0x00,
-               .mcs = RATE_MCS(RATE_MODE_CCK, 0),
-       },
-       {
-               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
-               .bitrate = 20,
-               .ratemask = BIT(1),
-               .plcp = 0x01,
-               .mcs = RATE_MCS(RATE_MODE_CCK, 1),
-       },
-       {
-               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
-               .bitrate = 55,
-               .ratemask = BIT(2),
-               .plcp = 0x02,
-               .mcs = RATE_MCS(RATE_MODE_CCK, 2),
-       },
-       {
-               .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
-               .bitrate = 110,
-               .ratemask = BIT(3),
-               .plcp = 0x03,
-               .mcs = RATE_MCS(RATE_MODE_CCK, 3),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 60,
-               .ratemask = BIT(4),
-               .plcp = 0x0b,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 0),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 90,
-               .ratemask = BIT(5),
-               .plcp = 0x0f,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 1),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 120,
-               .ratemask = BIT(6),
-               .plcp = 0x0a,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 2),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 180,
-               .ratemask = BIT(7),
-               .plcp = 0x0e,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 3),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 240,
-               .ratemask = BIT(8),
-               .plcp = 0x09,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 4),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 360,
-               .ratemask = BIT(9),
-               .plcp = 0x0d,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 5),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 480,
-               .ratemask = BIT(10),
-               .plcp = 0x08,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 6),
-       },
-       {
-               .flags = DEV_RATE_OFDM,
-               .bitrate = 540,
-               .ratemask = BIT(11),
-               .plcp = 0x0c,
-               .mcs = RATE_MCS(RATE_MODE_OFDM, 7),
-       },
-};
-
-static void rt2x00lib_channel(struct ieee80211_channel *entry,
-                             const int channel, const int tx_power,
-                             const int value)
-{
-       /* XXX: this assumption about the band is wrong for 802.11j */
-       entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-       entry->center_freq = ieee80211_channel_to_frequency(channel,
-                                                           entry->band);
-       entry->hw_value = value;
-       entry->max_power = tx_power;
-       entry->max_antenna_gain = 0xff;
-}
-
-static void rt2x00lib_rate(struct ieee80211_rate *entry,
-                          const u16 index, const struct rt2x00_rate *rate)
-{
-       entry->flags = 0;
-       entry->bitrate = rate->bitrate;
-       entry->hw_value = index;
-       entry->hw_value_short = index;
-
-       if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
-               entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
-}
-
-static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
-                                   struct hw_mode_spec *spec)
-{
-       struct ieee80211_hw *hw = rt2x00dev->hw;
-       struct ieee80211_channel *channels;
-       struct ieee80211_rate *rates;
-       unsigned int num_rates;
-       unsigned int i;
-
-       num_rates = 0;
-       if (spec->supported_rates & SUPPORT_RATE_CCK)
-               num_rates += 4;
-       if (spec->supported_rates & SUPPORT_RATE_OFDM)
-               num_rates += 8;
-
-       channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL);
-       if (!channels)
-               return -ENOMEM;
-
-       rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL);
-       if (!rates)
-               goto exit_free_channels;
-
-       /*
-        * Initialize Rate list.
-        */
-       for (i = 0; i < num_rates; i++)
-               rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
-
-       /*
-        * Initialize Channel list.
-        */
-       for (i = 0; i < spec->num_channels; i++) {
-               rt2x00lib_channel(&channels[i],
-                                 spec->channels[i].channel,
-                                 spec->channels_info[i].max_power, i);
-       }
-
-       /*
-        * Intitialize 802.11b, 802.11g
-        * Rates: CCK, OFDM.
-        * Channels: 2.4 GHz
-        */
-       if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
-               rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
-               rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
-               rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
-               rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
-               hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-                   &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
-               memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap,
-                      &spec->ht, sizeof(spec->ht));
-       }
-
-       /*
-        * Intitialize 802.11a
-        * Rates: OFDM.
-        * Channels: OFDM, UNII, HiperLAN2.
-        */
-       if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
-               rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
-                   spec->num_channels - 14;
-               rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
-                   num_rates - 4;
-               rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
-               rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
-               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-                   &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
-               memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap,
-                      &spec->ht, sizeof(spec->ht));
-       }
-
-       return 0;
-
- exit_free_channels:
-       kfree(channels);
-       rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");
-       return -ENOMEM;
-}
-
-static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
-{
-       if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
-               ieee80211_unregister_hw(rt2x00dev->hw);
-
-       if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
-               kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
-               kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
-               rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
-               rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-       }
-
-       kfree(rt2x00dev->spec.channels_info);
-}
-
-static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       int status;
-
-       if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Initialize HW modes.
-        */
-       status = rt2x00lib_probe_hw_modes(rt2x00dev, spec);
-       if (status)
-               return status;
-
-       /*
-        * Initialize HW fields.
-        */
-       rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues;
-
-       /*
-        * Initialize extra TX headroom required.
-        */
-       rt2x00dev->hw->extra_tx_headroom =
-               max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM,
-                     rt2x00dev->extra_tx_headroom);
-
-       /*
-        * Take TX headroom required for alignment into account.
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
-               rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
-       else if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA))
-               rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
-
-       /*
-        * Tell mac80211 about the size of our private STA structure.
-        */
-       rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta);
-
-       /*
-        * Allocate tx status FIFO for driver use.
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TXSTATUS_FIFO)) {
-               /*
-                * Allocate the txstatus fifo. In the worst case the tx
-                * status fifo has to hold the tx status of all entries
-                * in all tx queues. Hence, calculate the kfifo size as
-                * tx_queues * entry_num and round up to the nearest
-                * power of 2.
-                */
-               int kfifo_size =
-                       roundup_pow_of_two(rt2x00dev->ops->tx_queues *
-                                          rt2x00dev->tx->limit *
-                                          sizeof(u32));
-
-               status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size,
-                                    GFP_KERNEL);
-               if (status)
-                       return status;
-       }
-
-       /*
-        * Initialize tasklets if used by the driver. Tasklets are
-        * disabled until the interrupts are turned on. The driver
-        * has to handle that.
-        */
-#define RT2X00_TASKLET_INIT(taskletname) \
-       if (rt2x00dev->ops->lib->taskletname) { \
-               tasklet_init(&rt2x00dev->taskletname, \
-                            rt2x00dev->ops->lib->taskletname, \
-                            (unsigned long)rt2x00dev); \
-       }
-
-       RT2X00_TASKLET_INIT(txstatus_tasklet);
-       RT2X00_TASKLET_INIT(pretbtt_tasklet);
-       RT2X00_TASKLET_INIT(tbtt_tasklet);
-       RT2X00_TASKLET_INIT(rxdone_tasklet);
-       RT2X00_TASKLET_INIT(autowake_tasklet);
-
-#undef RT2X00_TASKLET_INIT
-
-       /*
-        * Register HW.
-        */
-       status = ieee80211_register_hw(rt2x00dev->hw);
-       if (status)
-               return status;
-
-       set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags);
-
-       return 0;
-}
-
-/*
- * Initialization/uninitialization handlers.
- */
-static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Stop rfkill polling.
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
-               rt2x00rfkill_unregister(rt2x00dev);
-
-       /*
-        * Allow the HW to uninitialize.
-        */
-       rt2x00dev->ops->lib->uninitialize(rt2x00dev);
-
-       /*
-        * Free allocated queue entries.
-        */
-       rt2x00queue_uninitialize(rt2x00dev);
-}
-
-static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
-{
-       int status;
-
-       if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Allocate all queue entries.
-        */
-       status = rt2x00queue_initialize(rt2x00dev);
-       if (status)
-               return status;
-
-       /*
-        * Initialize the device.
-        */
-       status = rt2x00dev->ops->lib->initialize(rt2x00dev);
-       if (status) {
-               rt2x00queue_uninitialize(rt2x00dev);
-               return status;
-       }
-
-       set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
-
-       /*
-        * Start rfkill polling.
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
-               rt2x00rfkill_register(rt2x00dev);
-
-       return 0;
-}
-
-int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * If this is the first interface which is added,
-        * we should load the firmware now.
-        */
-       retval = rt2x00lib_load_firmware(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Initialize the device.
-        */
-       retval = rt2x00lib_initialize(rt2x00dev);
-       if (retval)
-               return retval;
-
-       rt2x00dev->intf_ap_count = 0;
-       rt2x00dev->intf_sta_count = 0;
-       rt2x00dev->intf_associated = 0;
-
-       /* Enable the radio */
-       retval = rt2x00lib_enable_radio(rt2x00dev);
-       if (retval)
-               return retval;
-
-       set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
-
-       return 0;
-}
-
-void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
-{
-       if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Perhaps we can add something smarter here,
-        * but for now just disabling the radio should do.
-        */
-       rt2x00lib_disable_radio(rt2x00dev);
-
-       rt2x00dev->intf_ap_count = 0;
-       rt2x00dev->intf_sta_count = 0;
-       rt2x00dev->intf_associated = 0;
-}
-
-static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
-{
-       struct ieee80211_iface_limit *if_limit;
-       struct ieee80211_iface_combination *if_combination;
-
-       if (rt2x00dev->ops->max_ap_intf < 2)
-               return;
-
-       /*
-        * Build up AP interface limits structure.
-        */
-       if_limit = &rt2x00dev->if_limits_ap;
-       if_limit->max = rt2x00dev->ops->max_ap_intf;
-       if_limit->types = BIT(NL80211_IFTYPE_AP);
-#ifdef CONFIG_MAC80211_MESH
-       if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
-#endif
-
-       /*
-        * Build up AP interface combinations structure.
-        */
-       if_combination = &rt2x00dev->if_combinations[IF_COMB_AP];
-       if_combination->limits = if_limit;
-       if_combination->n_limits = 1;
-       if_combination->max_interfaces = if_limit->max;
-       if_combination->num_different_channels = 1;
-
-       /*
-        * Finally, specify the possible combinations to mac80211.
-        */
-       rt2x00dev->hw->wiphy->iface_combinations = rt2x00dev->if_combinations;
-       rt2x00dev->hw->wiphy->n_iface_combinations = 1;
-}
-
-static unsigned int rt2x00dev_extra_tx_headroom(struct rt2x00_dev *rt2x00dev)
-{
-       if (WARN_ON(!rt2x00dev->tx))
-               return 0;
-
-       if (rt2x00_is_usb(rt2x00dev))
-               return rt2x00dev->tx[0].winfo_size + rt2x00dev->tx[0].desc_size;
-
-       return rt2x00dev->tx[0].winfo_size;
-}
-
-/*
- * driver allocation handlers.
- */
-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
-{
-       int retval = -ENOMEM;
-
-       /*
-        * Set possible interface combinations.
-        */
-       rt2x00lib_set_if_combinations(rt2x00dev);
-
-       /*
-        * Allocate the driver data memory, if necessary.
-        */
-       if (rt2x00dev->ops->drv_data_size > 0) {
-               rt2x00dev->drv_data = kzalloc(rt2x00dev->ops->drv_data_size,
-                                             GFP_KERNEL);
-               if (!rt2x00dev->drv_data) {
-                       retval = -ENOMEM;
-                       goto exit;
-               }
-       }
-
-       spin_lock_init(&rt2x00dev->irqmask_lock);
-       mutex_init(&rt2x00dev->csr_mutex);
-       INIT_LIST_HEAD(&rt2x00dev->bar_list);
-       spin_lock_init(&rt2x00dev->bar_list_lock);
-
-       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-
-       /*
-        * Make room for rt2x00_intf inside the per-interface
-        * structure ieee80211_vif.
-        */
-       rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
-
-       /*
-        * rt2x00 devices can only use the last n bits of the MAC address
-        * for virtual interfaces.
-        */
-       rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] =
-               (rt2x00dev->ops->max_ap_intf - 1);
-
-       /*
-        * Initialize work.
-        */
-       rt2x00dev->workqueue =
-           alloc_ordered_workqueue("%s", 0, wiphy_name(rt2x00dev->hw->wiphy));
-       if (!rt2x00dev->workqueue) {
-               retval = -ENOMEM;
-               goto exit;
-       }
-
-       INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
-       INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
-       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
-
-       /*
-        * Let the driver probe the device to detect the capabilities.
-        */
-       retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
-       if (retval) {
-               rt2x00_err(rt2x00dev, "Failed to allocate device\n");
-               goto exit;
-       }
-
-       /*
-        * Allocate queue array.
-        */
-       retval = rt2x00queue_allocate(rt2x00dev);
-       if (retval)
-               goto exit;
-
-       /* Cache TX headroom value */
-       rt2x00dev->extra_tx_headroom = rt2x00dev_extra_tx_headroom(rt2x00dev);
-
-       /*
-        * Determine which operating modes are supported, all modes
-        * which require beaconing, depend on the availability of
-        * beacon entries.
-        */
-       rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-       if (rt2x00dev->bcn->limit > 0)
-               rt2x00dev->hw->wiphy->interface_modes |=
-                   BIT(NL80211_IFTYPE_ADHOC) |
-                   BIT(NL80211_IFTYPE_AP) |
-#ifdef CONFIG_MAC80211_MESH
-                   BIT(NL80211_IFTYPE_MESH_POINT) |
-#endif
-                   BIT(NL80211_IFTYPE_WDS);
-
-       rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
-
-       /*
-        * Initialize ieee80211 structure.
-        */
-       retval = rt2x00lib_probe_hw(rt2x00dev);
-       if (retval) {
-               rt2x00_err(rt2x00dev, "Failed to initialize hw\n");
-               goto exit;
-       }
-
-       /*
-        * Register extra components.
-        */
-       rt2x00link_register(rt2x00dev);
-       rt2x00leds_register(rt2x00dev);
-       rt2x00debug_register(rt2x00dev);
-
-       /*
-        * Start rfkill polling.
-        */
-       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
-               rt2x00rfkill_register(rt2x00dev);
-
-       return 0;
-
-exit:
-       rt2x00lib_remove_dev(rt2x00dev);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);
-
-void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
-{
-       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-
-       /*
-        * Stop rfkill polling.
-        */
-       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DELAYED_RFKILL))
-               rt2x00rfkill_unregister(rt2x00dev);
-
-       /*
-        * Disable radio.
-        */
-       rt2x00lib_disable_radio(rt2x00dev);
-
-       /*
-        * Stop all work.
-        */
-       cancel_work_sync(&rt2x00dev->intf_work);
-       cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
-       cancel_work_sync(&rt2x00dev->sleep_work);
-       if (rt2x00_is_usb(rt2x00dev)) {
-               hrtimer_cancel(&rt2x00dev->txstatus_timer);
-               cancel_work_sync(&rt2x00dev->rxdone_work);
-               cancel_work_sync(&rt2x00dev->txdone_work);
-       }
-       if (rt2x00dev->workqueue)
-               destroy_workqueue(rt2x00dev->workqueue);
-
-       /*
-        * Free the tx status fifo.
-        */
-       kfifo_free(&rt2x00dev->txstatus_fifo);
-
-       /*
-        * Kill the tx status tasklet.
-        */
-       tasklet_kill(&rt2x00dev->txstatus_tasklet);
-       tasklet_kill(&rt2x00dev->pretbtt_tasklet);
-       tasklet_kill(&rt2x00dev->tbtt_tasklet);
-       tasklet_kill(&rt2x00dev->rxdone_tasklet);
-       tasklet_kill(&rt2x00dev->autowake_tasklet);
-
-       /*
-        * Uninitialize device.
-        */
-       rt2x00lib_uninitialize(rt2x00dev);
-
-       /*
-        * Free extra components
-        */
-       rt2x00debug_deregister(rt2x00dev);
-       rt2x00leds_unregister(rt2x00dev);
-
-       /*
-        * Free ieee80211_hw memory.
-        */
-       rt2x00lib_remove_hw(rt2x00dev);
-
-       /*
-        * Free firmware image.
-        */
-       rt2x00lib_free_firmware(rt2x00dev);
-
-       /*
-        * Free queue structures.
-        */
-       rt2x00queue_free(rt2x00dev);
-
-       /*
-        * Free the driver data.
-        */
-       kfree(rt2x00dev->drv_data);
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
-
-/*
- * Device state handlers
- */
-#ifdef CONFIG_PM
-int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
-{
-       rt2x00_dbg(rt2x00dev, "Going to sleep\n");
-
-       /*
-        * Prevent mac80211 from accessing driver while suspended.
-        */
-       if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Cleanup as much as possible.
-        */
-       rt2x00lib_uninitialize(rt2x00dev);
-
-       /*
-        * Suspend/disable extra components.
-        */
-       rt2x00leds_suspend(rt2x00dev);
-       rt2x00debug_deregister(rt2x00dev);
-
-       /*
-        * Set device mode to sleep for power management,
-        * on some hardware this call seems to consistently fail.
-        * From the specifications it is hard to tell why it fails,
-        * and if this is a "bad thing".
-        * Overall it is safe to just ignore the failure and
-        * continue suspending. The only downside is that the
-        * device will not be in optimal power save mode, but with
-        * the radio and the other components already disabled the
-        * device is as good as disabled.
-        */
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP))
-               rt2x00_warn(rt2x00dev, "Device failed to enter sleep state, continue suspending\n");
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
-
-int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
-{
-       rt2x00_dbg(rt2x00dev, "Waking up\n");
-
-       /*
-        * Restore/enable extra components.
-        */
-       rt2x00debug_register(rt2x00dev);
-       rt2x00leds_resume(rt2x00dev);
-
-       /*
-        * We are ready again to receive requests from mac80211.
-        */
-       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_resume);
-#endif /* CONFIG_PM */
-
-/*
- * rt2x00lib module information.
- */
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2x00 library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h
deleted file mode 100644 (file)
index 4c0e01b..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00dump
-       Abstract:
-               Data structures for the rt2x00debug & userspace.
-
-               The declarations in this file can be used by both rt2x00
-               and userspace and therefore should be kept together in
-               this file.
- */
-
-#ifndef RT2X00DUMP_H
-#define RT2X00DUMP_H
-
-/**
- * DOC: Introduction
- *
- * This header is intended to be exported to userspace,
- * to make the structures and enumerations available to userspace
- * applications. This means that all data types should be exportable.
- *
- * When rt2x00 is compiled with debugfs support enabled,
- * it is possible to capture all data coming in and out of the device
- * by reading the frame dump file. This file can have only a single reader.
- * The following frames will be reported:
- *   - All incoming frames (rx)
- *   - All outgoing frames (tx, including beacon and atim)
- *   - All completed frames (txdone including atim)
- *
- * The data is send to the file using the following format:
- *
- *   [rt2x00dump header][hardware descriptor][ieee802.11 frame]
- *
- * rt2x00dump header: The description of the dumped frame, as well as
- *     additional information useful for debugging. See &rt2x00dump_hdr.
- * hardware descriptor: Descriptor that was used to receive or transmit
- *     the frame.
- * ieee802.11 frame: The actual frame that was received or transmitted.
- */
-
-/**
- * enum rt2x00_dump_type - Frame type
- *
- * These values are used for the @type member of &rt2x00dump_hdr.
- * @DUMP_FRAME_RXDONE: This frame has been received by the hardware.
- * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware.
- * @DUMP_FRAME_TXDONE: This frame indicates the device has handled
- *     the tx event which has either succeeded or failed. A frame
- *     with this type should also have been reported with as a
- *     %DUMP_FRAME_TX frame.
- * @DUMP_FRAME_BEACON: This beacon frame is queued for transmission to the
- *     hardware.
- */
-enum rt2x00_dump_type {
-       DUMP_FRAME_RXDONE = 1,
-       DUMP_FRAME_TX = 2,
-       DUMP_FRAME_TXDONE = 3,
-       DUMP_FRAME_BEACON = 4,
-};
-
-/**
- * struct rt2x00dump_hdr - Dump frame header
- *
- * Each frame dumped to the debugfs file starts with this header
- * attached. This header contains the description of the actual
- * frame which was dumped.
- *
- * New fields inside the structure must be appended to the end of
- * the structure. This way userspace tools compiled for earlier
- * header versions can still correctly handle the frame dump
- * (although they will not handle all data passed to them in the dump).
- *
- * @version: Header version should always be set to %DUMP_HEADER_VERSION.
- *     This field must be checked by userspace to determine if it can
- *     handle this frame.
- * @header_length: The length of the &rt2x00dump_hdr structure. This is
- *     used for compatibility reasons so userspace can easily determine
- *     the location of the next field in the dump.
- * @desc_length: The length of the device descriptor.
- * @data_length: The length of the frame data (including the ieee802.11 header.
- * @chip_rt: RT chipset
- * @chip_rf: RF chipset
- * @chip_rev: Chipset revision
- * @type: The frame type (&rt2x00_dump_type)
- * @queue_index: The index number of the data queue.
- * @entry_index: The index number of the entry inside the data queue.
- * @timestamp_sec: Timestamp - seconds
- * @timestamp_usec: Timestamp - microseconds
- */
-struct rt2x00dump_hdr {
-       __le32 version;
-#define DUMP_HEADER_VERSION    2
-
-       __le32 header_length;
-       __le32 desc_length;
-       __le32 data_length;
-
-       __le16 chip_rt;
-       __le16 chip_rf;
-       __le16 chip_rev;
-
-       __le16 type;
-       __u8 queue_index;
-       __u8 entry_index;
-
-       __le32 timestamp_sec;
-       __le32 timestamp_usec;
-};
-
-#endif /* RT2X00DUMP_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
deleted file mode 100644 (file)
index 5813300..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 firmware loading routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
-{
-       struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
-       const struct firmware *fw;
-       char *fw_name;
-       int retval;
-
-       /*
-        * Read correct firmware from harddisk.
-        */
-       fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
-       if (!fw_name) {
-               rt2x00_err(rt2x00dev,
-                          "Invalid firmware filename\n"
-                          "Please file bug report to %s\n", DRV_PROJECT);
-               return -EINVAL;
-       }
-
-       rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
-
-       retval = request_firmware(&fw, fw_name, device);
-       if (retval) {
-               rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
-               return retval;
-       }
-
-       if (!fw || !fw->size || !fw->data) {
-               rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
-               release_firmware(fw);
-               return -ENOENT;
-       }
-
-       rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
-                   fw->data[fw->size - 4], fw->data[fw->size - 3]);
-       snprintf(rt2x00dev->hw->wiphy->fw_version,
-                       sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
-                       fw->data[fw->size - 4], fw->data[fw->size - 3]);
-
-       retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size);
-       switch (retval) {
-       case FW_OK:
-               break;
-       case FW_BAD_CRC:
-               rt2x00_err(rt2x00dev, "Firmware checksum error\n");
-               goto exit;
-       case FW_BAD_LENGTH:
-               rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
-                          fw->size);
-               goto exit;
-       case FW_BAD_VERSION:
-               rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
-               goto exit;
-       }
-
-       rt2x00dev->fw = fw;
-
-       return 0;
-
-exit:
-       release_firmware(fw);
-
-       return -ENOENT;
-}
-
-int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-
-       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_FIRMWARE))
-               return 0;
-
-       if (!rt2x00dev->fw) {
-               retval = rt2x00lib_request_firmware(rt2x00dev);
-               if (retval)
-                       return retval;
-       }
-
-       /*
-        * Send firmware to the device.
-        */
-       retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
-                                                   rt2x00dev->fw->data,
-                                                   rt2x00dev->fw->size);
-
-       /*
-        * When the firmware is uploaded to the hardware the LED
-        * association status might have been triggered, for correct
-        * LED handling it should now be reset.
-        */
-       rt2x00leds_led_assoc(rt2x00dev, false);
-
-       return retval;
-}
-
-void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
-{
-       release_firmware(rt2x00dev->fw);
-       rt2x00dev->fw = NULL;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
deleted file mode 100644 (file)
index c681d04..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 led specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
-{
-       struct rt2x00_led *led = &rt2x00dev->led_qual;
-       unsigned int brightness;
-
-       if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED))
-               return;
-
-       /*
-        * Led handling requires a positive value for the rssi,
-        * to do that correctly we need to add the correction.
-        */
-       rssi += rt2x00dev->rssi_offset;
-
-       /*
-        * Get the rssi level, this is used to convert the rssi
-        * to a LED value inside the range LED_OFF - LED_FULL.
-        */
-       if (rssi <= 30)
-               rssi = 0;
-       else if (rssi <= 39)
-               rssi = 1;
-       else if (rssi <= 49)
-               rssi = 2;
-       else if (rssi <= 53)
-               rssi = 3;
-       else if (rssi <= 63)
-               rssi = 4;
-       else
-               rssi = 5;
-
-       /*
-        * Note that we must _not_ send LED_OFF since the driver
-        * is going to calculate the value and might use it in a
-        * division.
-        */
-       brightness = ((LED_FULL / 6) * rssi) + 1;
-       if (brightness != led->led_dev.brightness) {
-               led->led_dev.brightness_set(&led->led_dev, brightness);
-               led->led_dev.brightness = brightness;
-       }
-}
-
-static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled)
-{
-       unsigned int brightness = enabled ? LED_FULL : LED_OFF;
-
-       if (!(led->flags & LED_REGISTERED))
-               return;
-
-       led->led_dev.brightness_set(&led->led_dev, brightness);
-       led->led_dev.brightness = brightness;
-}
-
-void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
-{
-       if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY)
-               rt2x00led_led_simple(&rt2x00dev->led_qual, enabled);
-}
-
-void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
-{
-       if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC)
-               rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled);
-}
-
-void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
-{
-       if (rt2x00dev->led_radio.type == LED_TYPE_RADIO)
-               rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
-}
-
-static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
-                                  struct rt2x00_led *led,
-                                  const char *name)
-{
-       struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
-       int retval;
-
-       led->led_dev.name = name;
-       led->led_dev.brightness = LED_OFF;
-
-       retval = led_classdev_register(device, &led->led_dev);
-       if (retval) {
-               rt2x00_err(rt2x00dev, "Failed to register led handler\n");
-               return retval;
-       }
-
-       led->flags |= LED_REGISTERED;
-
-       return 0;
-}
-
-void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
-{
-       char name[36];
-       int retval;
-       unsigned long on_period;
-       unsigned long off_period;
-       const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy);
-
-       if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
-               snprintf(name, sizeof(name), "%s-%s::radio",
-                        rt2x00dev->ops->name, phy_name);
-
-               retval = rt2x00leds_register_led(rt2x00dev,
-                                                &rt2x00dev->led_radio,
-                                                name);
-               if (retval)
-                       goto exit_fail;
-       }
-
-       if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
-               snprintf(name, sizeof(name), "%s-%s::assoc",
-                        rt2x00dev->ops->name, phy_name);
-
-               retval = rt2x00leds_register_led(rt2x00dev,
-                                                &rt2x00dev->led_assoc,
-                                                name);
-               if (retval)
-                       goto exit_fail;
-       }
-
-       if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
-               snprintf(name, sizeof(name), "%s-%s::quality",
-                        rt2x00dev->ops->name, phy_name);
-
-               retval = rt2x00leds_register_led(rt2x00dev,
-                                                &rt2x00dev->led_qual,
-                                                name);
-               if (retval)
-                       goto exit_fail;
-       }
-
-       /*
-        * Initialize blink time to default value:
-        * On period: 70ms
-        * Off period: 30ms
-        */
-       if (rt2x00dev->led_radio.led_dev.blink_set) {
-               on_period = 70;
-               off_period = 30;
-               rt2x00dev->led_radio.led_dev.blink_set(
-                   &rt2x00dev->led_radio.led_dev, &on_period, &off_period);
-       }
-
-       return;
-
-exit_fail:
-       rt2x00leds_unregister(rt2x00dev);
-}
-
-static void rt2x00leds_unregister_led(struct rt2x00_led *led)
-{
-       led_classdev_unregister(&led->led_dev);
-
-       /*
-        * This might look weird, but when we are unregistering while
-        * suspended the led is already off, and since we haven't
-        * fully resumed yet, access to the device might not be
-        * possible yet.
-        */
-       if (!(led->led_dev.flags & LED_SUSPENDED))
-               led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-
-       led->flags &= ~LED_REGISTERED;
-}
-
-void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
-{
-       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-               rt2x00leds_unregister_led(&rt2x00dev->led_qual);
-       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-               rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
-       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-               rt2x00leds_unregister_led(&rt2x00dev->led_radio);
-}
-
-static inline void rt2x00leds_suspend_led(struct rt2x00_led *led)
-{
-       led_classdev_suspend(&led->led_dev);
-
-       /* This shouldn't be needed, but just to be safe */
-       led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-       led->led_dev.brightness = LED_OFF;
-}
-
-void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
-{
-       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-               rt2x00leds_suspend_led(&rt2x00dev->led_qual);
-       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-               rt2x00leds_suspend_led(&rt2x00dev->led_assoc);
-       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-               rt2x00leds_suspend_led(&rt2x00dev->led_radio);
-}
-
-static inline void rt2x00leds_resume_led(struct rt2x00_led *led)
-{
-       led_classdev_resume(&led->led_dev);
-
-       /* Device might have enabled the LEDS during resume */
-       led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-       led->led_dev.brightness = LED_OFF;
-}
-
-void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
-{
-       if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-               rt2x00leds_resume_led(&rt2x00dev->led_radio);
-       if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-               rt2x00leds_resume_led(&rt2x00dev->led_assoc);
-       if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-               rt2x00leds_resume_led(&rt2x00dev->led_qual);
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h
deleted file mode 100644 (file)
index b2c5269..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 led datastructures and routines
- */
-
-#ifndef RT2X00LEDS_H
-#define RT2X00LEDS_H
-
-enum led_type {
-       LED_TYPE_RADIO,
-       LED_TYPE_ASSOC,
-       LED_TYPE_ACTIVITY,
-       LED_TYPE_QUALITY,
-};
-
-struct rt2x00_led {
-       struct rt2x00_dev *rt2x00dev;
-       struct led_classdev led_dev;
-
-       enum led_type type;
-       unsigned int flags;
-#define LED_INITIALIZED                ( 1 << 0 )
-#define LED_REGISTERED         ( 1 << 1 )
-};
-
-#endif /* RT2X00LEDS_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
deleted file mode 100644 (file)
index fb7c349..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: Data structures and definitions for the rt2x00lib module.
- */
-
-#ifndef RT2X00LIB_H
-#define RT2X00LIB_H
-
-/*
- * Interval defines
- */
-#define WATCHDOG_INTERVAL      round_jiffies_relative(HZ)
-#define LINK_TUNE_INTERVAL     round_jiffies_relative(HZ)
-#define AGC_INTERVAL           round_jiffies_relative(4 * HZ)
-#define VCO_INTERVAL           round_jiffies_relative(10 * HZ) /* 10 sec */
-
-/*
- * rt2x00_rate: Per rate device information
- */
-struct rt2x00_rate {
-       unsigned short flags;
-#define DEV_RATE_CCK                   0x0001
-#define DEV_RATE_OFDM                  0x0002
-#define DEV_RATE_SHORT_PREAMBLE                0x0004
-
-       unsigned short bitrate; /* In 100kbit/s */
-       unsigned short ratemask;
-
-       unsigned short plcp;
-       unsigned short mcs;
-};
-
-extern const struct rt2x00_rate rt2x00_supported_rates[12];
-
-static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
-{
-       return &rt2x00_supported_rates[hw_value & 0xff];
-}
-
-#define RATE_MCS(__mode, __mcs) \
-       ((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
-
-static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
-{
-       return (mcs_value & 0x00ff);
-}
-
-/*
- * Radio control handlers.
- */
-int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
-
-/*
- * Initialization handlers.
- */
-int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
-
-/*
- * Configuration handlers.
- */
-void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
-                          struct rt2x00_intf *intf,
-                          enum nl80211_iftype type,
-                          const u8 *mac, const u8 *bssid);
-void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
-                         struct rt2x00_intf *intf,
-                         struct ieee80211_bss_conf *conf,
-                         u32 changed);
-void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
-                             struct antenna_setup ant);
-void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
-                     struct ieee80211_conf *conf,
-                     const unsigned int changed_flags);
-
-/**
- * DOC: Queue handlers
- */
-
-/**
- * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
- * @entry: The entry for which the skb will be applicable.
- */
-struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp);
-
-/**
- * rt2x00queue_free_skb - free a skb
- * @entry: The entry for which the skb will be applicable.
- */
-void rt2x00queue_free_skb(struct queue_entry *entry);
-
-/**
- * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary
- * @skb: The skb to align
- *
- * Align the start of the 802.11 frame to a 4-byte boundary, this could
- * mean the payload is not aligned properly though.
- */
-void rt2x00queue_align_frame(struct sk_buff *skb);
-
-/**
- * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary
- * @skb: The skb to align
- * @header_length: Length of 802.11 header
- *
- * Apply L2 padding to align both header and payload to 4-byte boundary
- */
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length);
-
-/**
- * rt2x00queue_insert_l2pad - Remove L2 padding from 802.11 frame
- * @skb: The skb to align
- * @header_length: Length of 802.11 header
- *
- * Remove L2 padding used to align both header and payload to 4-byte boundary,
- * by removing the L2 padding the header will no longer be 4-byte aligned.
- */
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length);
-
-/**
- * rt2x00queue_write_tx_frame - Write TX frame to hardware
- * @queue: Queue over which the frame should be send
- * @skb: The skb to send
- * @local: frame is not from mac80211
- */
-int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
-                              struct ieee80211_sta *sta, bool local);
-
-/**
- * rt2x00queue_update_beacon - Send new beacon from mac80211
- *     to hardware. Handles locking by itself (mutex).
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @vif: Interface for which the beacon should be updated.
- */
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-                             struct ieee80211_vif *vif);
-
-/**
- * rt2x00queue_update_beacon_locked - Send new beacon from mac80211
- *     to hardware. Caller needs to ensure locking.
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @vif: Interface for which the beacon should be updated.
- */
-int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
-                                    struct ieee80211_vif *vif);
-
-/**
- * rt2x00queue_clear_beacon - Clear beacon in hardware
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @vif: Interface for which the beacon should be updated.
- */
-int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
-                            struct ieee80211_vif *vif);
-
-/**
- * rt2x00queue_index_inc - Index incrementation function
- * @entry: Queue entry (&struct queue_entry) to perform the action on.
- * @index: Index type (&enum queue_index) to perform the action on.
- *
- * This function will increase the requested index on the entry's queue,
- * it will grab the appropriate locks and handle queue overflow events by
- * resetting the index to the start of the queue.
- */
-void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);
-
-/**
- * rt2x00queue_init_queues - Initialize all data queues
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * This function will loop through all available queues to clear all
- * index numbers and set the queue entry to the correct initialization
- * state.
- */
-void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev);
-
-int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
-int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
-void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_update_stats - Update link statistics from RX frame
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @skb: Received frame
- * @rxdesc: Received frame descriptor
- *
- * Update link statistics based on the information from the
- * received frame descriptor.
- */
-void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
-                            struct sk_buff *skb,
-                            struct rxdone_entry_desc *rxdesc);
-
-/**
- * rt2x00link_start_tuner - Start periodic link tuner work
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * This start the link tuner periodic work, this work will
- * be executed periodically until &rt2x00link_stop_tuner has
- * been called.
- */
-void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_stop_tuner - Stop periodic link tuner work
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * After this function completed the link tuner will not
- * be running until &rt2x00link_start_tuner is called.
- */
-void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_reset_tuner - Reset periodic link tuner work
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @antenna: Should the antenna tuning also be reset
- *
- * The VGC limit configured in the hardware will be reset to 0
- * which forces the driver to rediscover the correct value for
- * the current association. This is needed when configuration
- * options have changed which could drastically change the
- * SNR level or link quality (i.e. changing the antenna setting).
- *
- * Resetting the link tuner will also cause the periodic work counter
- * to be reset. Any driver which has a fixed limit on the number
- * of rounds the link tuner is supposed to work will accept the
- * tuner actions again if this limit was previously reached.
- *
- * If @antenna is set to true a the software antenna diversity
- * tuning will also be reset.
- */
-void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
-
-/**
- * rt2x00link_start_watchdog - Start periodic watchdog monitoring
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * This start the watchdog periodic work, this work will
- *be executed periodically until &rt2x00link_stop_watchdog has
- * been called.
- */
-void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * After this function completed the watchdog monitoring will not
- * be running until &rt2x00link_start_watchdog is called.
- */
-void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_start_agc - Start periodic gain calibration
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- */
-void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_start_vcocal - Start periodic VCO calibration
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- */
-void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_stop_agc - Stop periodic gain calibration
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- */
-void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_stop_vcocal - Stop periodic VCO calibration
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- */
-void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00link_register - Initialize link tuning & watchdog functionality
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- *
- * Initialize work structure and all link tuning and watchdog related
- * parameters. This will not start the periodic work itself.
- */
-void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
-
-/*
- * Firmware handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_FIRMWARE
-int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev);
-#else
-static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
-{
-       return 0;
-}
-static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_FIRMWARE */
-
-/*
- * Debugfs handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
-void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
-void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                              struct rxdone_entry_desc *rxdesc);
-#else
-static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
-                                            struct rxdone_entry_desc *rxdesc)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-/*
- * Crypto handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
-void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
-                                      struct sk_buff *skb,
-                                      struct txentry_desc *txdesc);
-unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
-                                     struct sk_buff *skb);
-void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
-                            struct txentry_desc *txdesc);
-void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
-                              struct txentry_desc *txdesc);
-void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length);
-void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
-                              unsigned int header_length,
-                              struct rxdone_entry_desc *rxdesc);
-#else
-static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
-{
-       return CIPHER_NONE;
-}
-
-static inline void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
-                                                    struct sk_buff *skb,
-                                                    struct txentry_desc *txdesc)
-{
-}
-
-static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
-                                                   struct sk_buff *skb)
-{
-       return 0;
-}
-
-static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
-                                          struct txentry_desc *txdesc)
-{
-}
-
-static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
-                                            struct txentry_desc *txdesc)
-{
-}
-
-static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
-                                            unsigned int header_length)
-{
-}
-
-static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
-                                            unsigned int header_length,
-                                            struct rxdone_entry_desc *rxdesc)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
-
-/*
- * RFkill handlers.
- */
-static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
-{
-       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
-               wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
-}
-
-static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
-{
-       if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
-               wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
-}
-
-/*
- * LED handlers
- */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
-void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled);
-void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
-void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
-void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
-void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
-void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
-void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
-#else
-static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
-                                         int rssi)
-{
-}
-
-static inline void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev,
-                                         bool enabled)
-{
-}
-
-static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
-                                       bool enabled)
-{
-}
-
-static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev,
-                                       bool enabled)
-{
-}
-
-static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
-{
-}
-
-static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
-{
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-#endif /* RT2X00LIB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
deleted file mode 100644 (file)
index 017188e..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 generic link tuning routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-/*
- * When we lack RSSI information return something less then -80 to
- * tell the driver to tune the device to maximum sensitivity.
- */
-#define DEFAULT_RSSI           -128
-
-static inline int rt2x00link_get_avg_rssi(struct ewma_rssi *ewma)
-{
-       unsigned long avg;
-
-       avg = ewma_rssi_read(ewma);
-       if (avg)
-               return -avg;
-
-       return DEFAULT_RSSI;
-}
-
-static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-
-       if (rt2x00dev->link.qual.rx_success)
-               return rt2x00link_get_avg_rssi(&ant->rssi_ant);
-
-       return DEFAULT_RSSI;
-}
-
-static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-
-       if (ant->rssi_history)
-               return ant->rssi_history;
-       return DEFAULT_RSSI;
-}
-
-static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
-                                                  int rssi)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       ant->rssi_history = rssi;
-}
-
-static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
-{
-       ewma_rssi_init(&rt2x00dev->link.ant.rssi_ant);
-}
-
-static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct antenna_setup new_ant;
-       int other_antenna;
-
-       int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
-       int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
-
-       memcpy(&new_ant, &ant->active, sizeof(new_ant));
-
-       /*
-        * We are done sampling. Now we should evaluate the results.
-        */
-       ant->flags &= ~ANTENNA_MODE_SAMPLE;
-
-       /*
-        * During the last period we have sampled the RSSI
-        * from both antennas. It now is time to determine
-        * which antenna demonstrated the best performance.
-        * When we are already on the antenna with the best
-        * performance, just create a good starting point
-        * for the history and we are done.
-        */
-       if (sample_current >= sample_other) {
-               rt2x00link_antenna_update_rssi_history(rt2x00dev,
-                       sample_current);
-               return;
-       }
-
-       other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
-
-       if (ant->flags & ANTENNA_RX_DIVERSITY)
-               new_ant.rx = other_antenna;
-
-       if (ant->flags & ANTENNA_TX_DIVERSITY)
-               new_ant.tx = other_antenna;
-
-       rt2x00lib_config_antenna(rt2x00dev, new_ant);
-}
-
-static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct antenna_setup new_ant;
-       int rssi_curr;
-       int rssi_old;
-
-       memcpy(&new_ant, &ant->active, sizeof(new_ant));
-
-       /*
-        * Get current RSSI value along with the historical value,
-        * after that update the history with the current value.
-        */
-       rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
-       rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
-       rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
-
-       /*
-        * Legacy driver indicates that we should swap antenna's
-        * when the difference in RSSI is greater that 5. This
-        * also should be done when the RSSI was actually better
-        * then the previous sample.
-        * When the difference exceeds the threshold we should
-        * sample the rssi from the other antenna to make a valid
-        * comparison between the 2 antennas.
-        */
-       if (abs(rssi_curr - rssi_old) < 5)
-               return;
-
-       ant->flags |= ANTENNA_MODE_SAMPLE;
-
-       if (ant->flags & ANTENNA_RX_DIVERSITY)
-               new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
-
-       if (ant->flags & ANTENNA_TX_DIVERSITY)
-               new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
-
-       rt2x00lib_config_antenna(rt2x00dev, new_ant);
-}
-
-static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_ant *ant = &rt2x00dev->link.ant;
-
-       /*
-        * Determine if software diversity is enabled for
-        * either the TX or RX antenna (or both).
-        */
-       if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
-           !(ant->flags & ANTENNA_TX_DIVERSITY)) {
-               ant->flags = 0;
-               return true;
-       }
-
-       /*
-        * If we have only sampled the data over the last period
-        * we should now harvest the data. Otherwise just evaluate
-        * the data. The latter should only be performed once
-        * every 2 seconds.
-        */
-       if (ant->flags & ANTENNA_MODE_SAMPLE) {
-               rt2x00lib_antenna_diversity_sample(rt2x00dev);
-               return true;
-       } else if (rt2x00dev->link.count & 1) {
-               rt2x00lib_antenna_diversity_eval(rt2x00dev);
-               return true;
-       }
-
-       return false;
-}
-
-void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
-                            struct sk_buff *skb,
-                            struct rxdone_entry_desc *rxdesc)
-{
-       struct link *link = &rt2x00dev->link;
-       struct link_qual *qual = &rt2x00dev->link.qual;
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-
-       /*
-        * No need to update the stats for !=STA interfaces
-        */
-       if (!rt2x00dev->intf_sta_count)
-               return;
-
-       /*
-        * Frame was received successfully since non-succesfull
-        * frames would have been dropped by the hardware.
-        */
-       qual->rx_success++;
-
-       /*
-        * We are only interested in quality statistics from
-        * beacons which came from the BSS which we are
-        * associated with.
-        */
-       if (!ieee80211_is_beacon(hdr->frame_control) ||
-           !(rxdesc->dev_flags & RXDONE_MY_BSS))
-               return;
-
-       /*
-        * Update global RSSI
-        */
-       ewma_rssi_add(&link->avg_rssi, -rxdesc->rssi);
-
-       /*
-        * Update antenna RSSI
-        */
-       ewma_rssi_add(&ant->rssi_ant, -rxdesc->rssi);
-}
-
-void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
-{
-       struct link *link = &rt2x00dev->link;
-
-       /*
-        * Link tuning should only be performed when
-        * an active sta interface exists. AP interfaces
-        * don't need link tuning and monitor mode interfaces
-        * should never have to work with link tuners.
-        */
-       if (!rt2x00dev->intf_sta_count)
-               return;
-
-       /**
-        * While scanning, link tuning is disabled. By default
-        * the most sensitive settings will be used to make sure
-        * that all beacons and probe responses will be received
-        * during the scan.
-        */
-       if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
-               return;
-
-       rt2x00link_reset_tuner(rt2x00dev, false);
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->work, LINK_TUNE_INTERVAL);
-}
-
-void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
-{
-       cancel_delayed_work_sync(&rt2x00dev->link.work);
-}
-
-void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
-{
-       struct link_qual *qual = &rt2x00dev->link.qual;
-       u8 vgc_level = qual->vgc_level_reg;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Reset link information.
-        * Both the currently active vgc level as well as
-        * the link tuner counter should be reset. Resetting
-        * the counter is important for devices where the
-        * device should only perform link tuning during the
-        * first minute after being enabled.
-        */
-       rt2x00dev->link.count = 0;
-       memset(qual, 0, sizeof(*qual));
-       ewma_rssi_init(&rt2x00dev->link.avg_rssi);
-
-       /*
-        * Restore the VGC level as stored in the registers,
-        * the driver can use this to determine if the register
-        * must be updated during reset or not.
-        */
-       qual->vgc_level_reg = vgc_level;
-
-       /*
-        * Reset the link tuner.
-        */
-       rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
-
-       if (antenna)
-               rt2x00link_antenna_reset(rt2x00dev);
-}
-
-static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
-{
-       struct link_qual *qual = &rt2x00dev->link.qual;
-
-       qual->rx_success = 0;
-       qual->rx_failed = 0;
-       qual->tx_success = 0;
-       qual->tx_failed = 0;
-}
-
-static void rt2x00link_tuner(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, link.work.work);
-       struct link *link = &rt2x00dev->link;
-       struct link_qual *qual = &rt2x00dev->link.qual;
-
-       /*
-        * When the radio is shutting down we should
-        * immediately cease all link tuning.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
-           test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Update statistics.
-        */
-       rt2x00dev->ops->lib->link_stats(rt2x00dev, qual);
-       rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed;
-
-       /*
-        * Update quality RSSI for link tuning,
-        * when we have received some frames and we managed to
-        * collect the RSSI data we could use this. Otherwise we
-        * must fallback to the default RSSI value.
-        */
-       if (!qual->rx_success)
-               qual->rssi = DEFAULT_RSSI;
-       else
-               qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi);
-
-       /*
-        * Check if link tuning is supported by the hardware, some hardware
-        * do not support link tuning at all, while other devices can disable
-        * the feature from the EEPROM.
-        */
-       if (rt2x00_has_cap_link_tuning(rt2x00dev))
-               rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
-
-       /*
-        * Send a signal to the led to update the led signal strength.
-        */
-       rt2x00leds_led_quality(rt2x00dev, qual->rssi);
-
-       /*
-        * Evaluate antenna setup, make this the last step when
-        * rt2x00lib_antenna_diversity made changes the quality
-        * statistics will be reset.
-        */
-       if (rt2x00lib_antenna_diversity(rt2x00dev))
-               rt2x00link_reset_qual(rt2x00dev);
-
-       /*
-        * Increase tuner counter, and reschedule the next link tuner run.
-        */
-       link->count++;
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->work, LINK_TUNE_INTERVAL);
-}
-
-void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
-{
-       struct link *link = &rt2x00dev->link;
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-           rt2x00dev->ops->lib->watchdog)
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->watchdog_work,
-                                            WATCHDOG_INTERVAL);
-}
-
-void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
-{
-       cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
-}
-
-static void rt2x00link_watchdog(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, link.watchdog_work.work);
-       struct link *link = &rt2x00dev->link;
-
-       /*
-        * When the radio is shutting down we should
-        * immediately cease the watchdog monitoring.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       rt2x00dev->ops->lib->watchdog(rt2x00dev);
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->watchdog_work,
-                                            WATCHDOG_INTERVAL);
-}
-
-void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
-{
-       struct link *link = &rt2x00dev->link;
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-           rt2x00dev->ops->lib->gain_calibration)
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->agc_work,
-                                            AGC_INTERVAL);
-}
-
-void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
-{
-       struct link *link = &rt2x00dev->link;
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-           rt2x00dev->ops->lib->vco_calibration)
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->vco_work,
-                                            VCO_INTERVAL);
-}
-
-void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
-{
-       cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
-}
-
-void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
-{
-       cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
-}
-
-static void rt2x00link_agc(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, link.agc_work.work);
-       struct link *link = &rt2x00dev->link;
-
-       /*
-        * When the radio is shutting down we should
-        * immediately cease the watchdog monitoring.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->agc_work,
-                                            AGC_INTERVAL);
-}
-
-static void rt2x00link_vcocal(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, link.vco_work.work);
-       struct link *link = &rt2x00dev->link;
-
-       /*
-        * When the radio is shutting down we should
-        * immediately cease the VCO calibration.
-        */
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return;
-
-       rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
-
-       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               ieee80211_queue_delayed_work(rt2x00dev->hw,
-                                            &link->vco_work,
-                                            VCO_INTERVAL);
-}
-
-void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
-{
-       INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
-       if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
-               INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
-       INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
-       INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
deleted file mode 100644 (file)
index 3c26ee6..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00mac
-       Abstract: rt2x00 generic mac80211 routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
-                               struct data_queue *queue,
-                               struct sk_buff *frag_skb)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
-       struct ieee80211_tx_info *rts_info;
-       struct sk_buff *skb;
-       unsigned int data_length;
-       int retval = 0;
-
-       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-               data_length = sizeof(struct ieee80211_cts);
-       else
-               data_length = sizeof(struct ieee80211_rts);
-
-       skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
-       if (unlikely(!skb)) {
-               rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n");
-               return -ENOMEM;
-       }
-
-       skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
-       skb_put(skb, data_length);
-
-       /*
-        * Copy TX information over from original frame to
-        * RTS/CTS frame. Note that we set the no encryption flag
-        * since we don't want this frame to be encrypted.
-        * RTS frames should be acked, while CTS-to-self frames
-        * should not. The ready for TX flag is cleared to prevent
-        * it being automatically send when the descriptor is
-        * written to the hardware.
-        */
-       memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
-       rts_info = IEEE80211_SKB_CB(skb);
-       rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
-       rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
-
-       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-               rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
-       else
-               rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
-
-       /* Disable hardware encryption */
-       rts_info->control.hw_key = NULL;
-
-       /*
-        * RTS/CTS frame should use the length of the frame plus any
-        * encryption overhead that will be added by the hardware.
-        */
-       data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
-
-       if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-               ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
-                                       frag_skb->data, data_length, tx_info,
-                                       (struct ieee80211_cts *)(skb->data));
-       else
-               ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
-                                 frag_skb->data, data_length, tx_info,
-                                 (struct ieee80211_rts *)(skb->data));
-
-       retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true);
-       if (retval) {
-               dev_kfree_skb_any(skb);
-               rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n");
-       }
-
-       return retval;
-}
-
-void rt2x00mac_tx(struct ieee80211_hw *hw,
-                 struct ieee80211_tx_control *control,
-                 struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       enum data_queue_qid qid = skb_get_queue_mapping(skb);
-       struct data_queue *queue = NULL;
-
-       /*
-        * Mac80211 might be calling this function while we are trying
-        * to remove the device or perhaps suspending it.
-        * Note that we can only stop the TX queues inside the TX path
-        * due to possible race conditions in mac80211.
-        */
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               goto exit_free_skb;
-
-       /*
-        * Use the ATIM queue if appropriate and present.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
-           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE))
-               qid = QID_ATIM;
-
-       queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-       if (unlikely(!queue)) {
-               rt2x00_err(rt2x00dev,
-                          "Attempt to send packet over invalid queue %d\n"
-                          "Please file bug report to %s\n", qid, DRV_PROJECT);
-               goto exit_free_skb;
-       }
-
-       /*
-        * If CTS/RTS is required. create and queue that frame first.
-        * Make sure we have at least enough entries available to send
-        * this CTS/RTS frame as well as the data frame.
-        * Note that when the driver has set the set_rts_threshold()
-        * callback function it doesn't need software generation of
-        * either RTS or CTS-to-self frame and handles everything
-        * inside the hardware.
-        */
-       if (!rt2x00dev->ops->hw->set_rts_threshold &&
-           (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
-                                               IEEE80211_TX_RC_USE_CTS_PROTECT))) {
-               if (rt2x00queue_available(queue) <= 1)
-                       goto exit_fail;
-
-               if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
-                       goto exit_fail;
-       }
-
-       if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false)))
-               goto exit_fail;
-
-       /*
-        * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
-        * we should not use spin_lock_bh variant as bottom halve was already
-        * disabled before ieee80211_xmit() call.
-        */
-       spin_lock(&queue->tx_lock);
-       if (rt2x00queue_threshold(queue))
-               rt2x00queue_pause_queue(queue);
-       spin_unlock(&queue->tx_lock);
-
-       return;
-
- exit_fail:
-       spin_lock(&queue->tx_lock);
-       rt2x00queue_pause_queue(queue);
-       spin_unlock(&queue->tx_lock);
- exit_free_skb:
-       ieee80211_free_txskb(hw, skb);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_tx);
-
-int rt2x00mac_start(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       return rt2x00lib_start(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_start);
-
-void rt2x00mac_stop(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return;
-
-       rt2x00lib_stop(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_stop);
-
-int rt2x00mac_add_interface(struct ieee80211_hw *hw,
-                           struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-       struct data_queue *queue = rt2x00dev->bcn;
-       struct queue_entry *entry = NULL;
-       unsigned int i;
-
-       /*
-        * Don't allow interfaces to be added
-        * the device has disappeared.
-        */
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
-           !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
-               return -ENODEV;
-
-       /*
-        * Loop through all beacon queues to find a free
-        * entry. Since there are as much beacon entries
-        * as the maximum interfaces, this search shouldn't
-        * fail.
-        */
-       for (i = 0; i < queue->limit; i++) {
-               entry = &queue->entries[i];
-               if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
-                       break;
-       }
-
-       if (unlikely(i == queue->limit))
-               return -ENOBUFS;
-
-       /*
-        * We are now absolutely sure the interface can be created,
-        * increase interface count and start initialization.
-        */
-
-       if (vif->type == NL80211_IFTYPE_AP)
-               rt2x00dev->intf_ap_count++;
-       else
-               rt2x00dev->intf_sta_count++;
-
-       mutex_init(&intf->beacon_skb_mutex);
-       intf->beacon = entry;
-
-       /*
-        * The MAC address must be configured after the device
-        * has been initialized. Otherwise the device can reset
-        * the MAC registers.
-        * The BSSID address must only be configured in AP mode,
-        * however we should not send an empty BSSID address for
-        * STA interfaces at this time, since this can cause
-        * invalid behavior in the device.
-        */
-       rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
-                             vif->addr, NULL);
-
-       /*
-        * Some filters depend on the current working mode. We can force
-        * an update during the next configure_filter() run by mac80211 by
-        * resetting the current packet_filter state.
-        */
-       rt2x00dev->packet_filter = 0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
-
-void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       /*
-        * Don't allow interfaces to be remove while
-        * either the device has disappeared or when
-        * no interface is present.
-        */
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
-           (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
-           (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
-               return;
-
-       if (vif->type == NL80211_IFTYPE_AP)
-               rt2x00dev->intf_ap_count--;
-       else
-               rt2x00dev->intf_sta_count--;
-
-       /*
-        * Release beacon entry so it is available for
-        * new interfaces again.
-        */
-       clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
-
-       /*
-        * Make sure the bssid and mac address registers
-        * are cleared to prevent false ACKing of frames.
-        */
-       rt2x00lib_config_intf(rt2x00dev, intf,
-                             NL80211_IFTYPE_UNSPECIFIED, NULL, NULL);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
-
-int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_conf *conf = &hw->conf;
-
-       /*
-        * mac80211 might be calling this function while we are trying
-        * to remove the device or perhaps suspending it.
-        */
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       /*
-        * Some configuration parameters (e.g. channel and antenna values) can
-        * only be set when the radio is enabled, but do require the RX to
-        * be off. During this period we should keep link tuning enabled,
-        * if for any reason the link tuner must be reset, this will be
-        * handled by rt2x00lib_config().
-        */
-       rt2x00queue_stop_queue(rt2x00dev->rx);
-
-       /*
-        * When we've just turned on the radio, we want to reprogram
-        * everything to ensure a consistent state
-        */
-       rt2x00lib_config(rt2x00dev, conf, changed);
-
-       /*
-        * After the radio has been enabled we need to configure
-        * the antenna to the default settings. rt2x00lib_config_antenna()
-        * should determine if any action should be taken based on
-        * checking if diversity has been enabled or no antenna changes
-        * have been made since the last configuration change.
-        */
-       rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);
-
-       /* Turn RX back on */
-       rt2x00queue_start_queue(rt2x00dev->rx);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_config);
-
-void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
-                               unsigned int changed_flags,
-                               unsigned int *total_flags,
-                               u64 multicast)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * Mask off any flags we are going to ignore
-        * from the total_flags field.
-        */
-       *total_flags &=
-           FIF_ALLMULTI |
-           FIF_FCSFAIL |
-           FIF_PLCPFAIL |
-           FIF_CONTROL |
-           FIF_PSPOLL |
-           FIF_OTHER_BSS;
-
-       /*
-        * Apply some rules to the filters:
-        * - Some filters imply different filters to be set.
-        * - Some things we can't filter out at all.
-        * - Multicast filter seems to kill broadcast traffic so never use it.
-        */
-       *total_flags |= FIF_ALLMULTI;
-
-       /*
-        * If the device has a single filter for all control frames,
-        * FIF_CONTROL and FIF_PSPOLL flags imply each other.
-        * And if the device has more than one filter for control frames
-        * of different types, but has no a separate filter for PS Poll frames,
-        * FIF_CONTROL flag implies FIF_PSPOLL.
-        */
-       if (!rt2x00_has_cap_control_filters(rt2x00dev)) {
-               if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
-                       *total_flags |= FIF_CONTROL | FIF_PSPOLL;
-       }
-       if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) {
-               if (*total_flags & FIF_CONTROL)
-                       *total_flags |= FIF_PSPOLL;
-       }
-
-       /*
-        * Check if there is any work left for us.
-        */
-       if (rt2x00dev->packet_filter == *total_flags)
-               return;
-       rt2x00dev->packet_filter = *total_flags;
-
-       rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
-
-static void rt2x00mac_set_tim_iter(void *data, u8 *mac,
-                                  struct ieee80211_vif *vif)
-{
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       if (vif->type != NL80211_IFTYPE_AP &&
-           vif->type != NL80211_IFTYPE_ADHOC &&
-           vif->type != NL80211_IFTYPE_MESH_POINT &&
-           vif->type != NL80211_IFTYPE_WDS)
-               return;
-
-       set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags);
-}
-
-int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-                     bool set)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return 0;
-
-       ieee80211_iterate_active_interfaces_atomic(
-               rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
-               rt2x00mac_set_tim_iter, rt2x00dev);
-
-       /* queue work to upodate the beacon template */
-       ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
-
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
-static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
-{
-       if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
-               memcpy(crypto->key,
-                      &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
-                      sizeof(crypto->key));
-
-       if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
-               memcpy(crypto->tx_mic,
-                      &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
-                      sizeof(crypto->tx_mic));
-
-       if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
-               memcpy(crypto->rx_mic,
-                      &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
-                      sizeof(crypto->rx_mic));
-}
-
-int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-                     struct ieee80211_vif *vif, struct ieee80211_sta *sta,
-                     struct ieee80211_key_conf *key)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       int (*set_key) (struct rt2x00_dev *rt2x00dev,
-                       struct rt2x00lib_crypto *crypto,
-                       struct ieee80211_key_conf *key);
-       struct rt2x00lib_crypto crypto;
-       static const u8 bcast_addr[ETH_ALEN] =
-               { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
-       struct rt2x00_sta *sta_priv = NULL;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       if (!rt2x00_has_cap_hw_crypto(rt2x00dev))
-               return -EOPNOTSUPP;
-
-       /*
-        * To support IBSS RSN, don't program group keys in IBSS, the
-        * hardware will then not attempt to decrypt the frames.
-        */
-       if (vif->type == NL80211_IFTYPE_ADHOC &&
-           !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
-               return -EOPNOTSUPP;
-
-       if (key->keylen > 32)
-               return -ENOSPC;
-
-       memset(&crypto, 0, sizeof(crypto));
-
-       crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);
-       crypto.cipher = rt2x00crypto_key_to_cipher(key);
-       if (crypto.cipher == CIPHER_NONE)
-               return -EOPNOTSUPP;
-       if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev))
-               return -EOPNOTSUPP;
-
-       crypto.cmd = cmd;
-
-       if (sta) {
-               crypto.address = sta->addr;
-               sta_priv = sta_to_rt2x00_sta(sta);
-               crypto.wcid = sta_priv->wcid;
-       } else
-               crypto.address = bcast_addr;
-
-       if (crypto.cipher == CIPHER_TKIP)
-               memcpy_tkip(&crypto, &key->key[0], key->keylen);
-       else
-               memcpy(crypto.key, &key->key[0], key->keylen);
-       /*
-        * Each BSS has a maximum of 4 shared keys.
-        * Shared key index values:
-        *      0) BSS0 key0
-        *      1) BSS0 key1
-        *      ...
-        *      4) BSS1 key0
-        *      ...
-        *      8) BSS2 key0
-        *      ...
-        * Both pairwise as shared key indeces are determined by
-        * driver. This is required because the hardware requires
-        * keys to be assigned in correct order (When key 1 is
-        * provided but key 0 is not, then the key is not found
-        * by the hardware during RX).
-        */
-       if (cmd == SET_KEY)
-               key->hw_key_idx = 0;
-
-       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
-               set_key = rt2x00dev->ops->lib->config_pairwise_key;
-       else
-               set_key = rt2x00dev->ops->lib->config_shared_key;
-
-       if (!set_key)
-               return -EOPNOTSUPP;
-
-       return set_key(rt2x00dev, &crypto, key);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
-
-int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                     struct ieee80211_sta *sta)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
-
-int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                        struct ieee80211_sta *sta)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
-
-       return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
-
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
-                            struct ieee80211_vif *vif,
-                            const u8 *mac_addr)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
-       rt2x00link_stop_tuner(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
-
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
-       rt2x00link_start_tuner(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
-
-int rt2x00mac_get_stats(struct ieee80211_hw *hw,
-                       struct ieee80211_low_level_stats *stats)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * The dot11ACKFailureCount, dot11RTSFailureCount and
-        * dot11RTSSuccessCount are updated in interrupt time.
-        * dot11FCSErrorCount is updated in the link tuner.
-        */
-       memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
-
-void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif,
-                               struct ieee80211_bss_conf *bss_conf,
-                               u32 changes)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       /*
-        * mac80211 might be calling this function while we are trying
-        * to remove the device or perhaps suspending it.
-        */
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return;
-
-       /*
-        * Update the BSSID.
-        */
-       if (changes & BSS_CHANGED_BSSID)
-               rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
-                                     bss_conf->bssid);
-
-       /*
-        * Start/stop beaconing.
-        */
-       if (changes & BSS_CHANGED_BEACON_ENABLED) {
-               mutex_lock(&intf->beacon_skb_mutex);
-               if (!bss_conf->enable_beacon && intf->enable_beacon) {
-                       rt2x00dev->intf_beaconing--;
-                       intf->enable_beacon = false;
-
-                       if (rt2x00dev->intf_beaconing == 0) {
-                               /*
-                                * Last beaconing interface disabled
-                                * -> stop beacon queue.
-                                */
-                               rt2x00queue_stop_queue(rt2x00dev->bcn);
-                       }
-                       /*
-                        * Clear beacon in the H/W for this vif. This is needed
-                        * to disable beaconing on this particular interface
-                        * and keep it running on other interfaces.
-                        */
-                       rt2x00queue_clear_beacon(rt2x00dev, vif);
-               } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
-                       rt2x00dev->intf_beaconing++;
-                       intf->enable_beacon = true;
-                       /*
-                        * Upload beacon to the H/W. This is only required on
-                        * USB devices. PCI devices fetch beacons periodically.
-                        */
-                       if (rt2x00_is_usb(rt2x00dev))
-                               rt2x00queue_update_beacon(rt2x00dev, vif);
-
-                       if (rt2x00dev->intf_beaconing == 1) {
-                               /*
-                                * First beaconing interface enabled
-                                * -> start beacon queue.
-                                */
-                               rt2x00queue_start_queue(rt2x00dev->bcn);
-                       }
-               }
-               mutex_unlock(&intf->beacon_skb_mutex);
-       }
-
-       /*
-        * When the association status has changed we must reset the link
-        * tuner counter. This is because some drivers determine if they
-        * should perform link tuning based on the number of seconds
-        * while associated or not associated.
-        */
-       if (changes & BSS_CHANGED_ASSOC) {
-               rt2x00dev->link.count = 0;
-
-               if (bss_conf->assoc)
-                       rt2x00dev->intf_associated++;
-               else
-                       rt2x00dev->intf_associated--;
-
-               rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
-
-               clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
-       }
-
-       /*
-        * Check for access point which do not support 802.11e . We have to
-        * generate data frames sequence number in S/W for such AP, because
-        * of H/W bug.
-        */
-       if (changes & BSS_CHANGED_QOS && !bss_conf->qos)
-               set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
-
-       /*
-        * When the erp information has changed, we should perform
-        * additional configuration steps. For all other changes we are done.
-        */
-       if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE |
-                      BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BASIC_RATES |
-                      BSS_CHANGED_BEACON_INT | BSS_CHANGED_HT))
-               rt2x00lib_config_erp(rt2x00dev, intf, bss_conf, changes);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
-
-int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
-                     struct ieee80211_vif *vif, u16 queue_idx,
-                     const struct ieee80211_tx_queue_params *params)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-
-       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-       if (unlikely(!queue))
-               return -EINVAL;
-
-       /*
-        * The passed variables are stored as real value ((2^n)-1).
-        * Ralink registers require to know the bit number 'n'.
-        */
-       if (params->cw_min > 0)
-               queue->cw_min = fls(params->cw_min);
-       else
-               queue->cw_min = 5; /* cw_min: 2^5 = 32. */
-
-       if (params->cw_max > 0)
-               queue->cw_max = fls(params->cw_max);
-       else
-               queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
-
-       queue->aifs = params->aifs;
-       queue->txop = params->txop;
-
-       rt2x00_dbg(rt2x00dev,
-                  "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d\n",
-                  queue_idx, queue->cw_min, queue->cw_max, queue->aifs,
-                  queue->txop);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);
-
-void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
-
-       wiphy_rfkill_set_hw_state(hw->wiphy, !active);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
-
-void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-                    u32 queues, bool drop)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return;
-
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_flush_queue(queue, drop);
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_flush);
-
-int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct antenna_setup *def = &rt2x00dev->default_ant;
-       struct antenna_setup setup;
-
-       // The antenna value is not supposed to be 0,
-       // or exceed the maximum number of antenna's.
-       if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
-               return -EINVAL;
-
-       // When the client tried to configure the antenna to or from
-       // diversity mode, we must reset the default antenna as well
-       // as that controls the diversity switch.
-       if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
-               ant->flags &= ~ANTENNA_TX_DIVERSITY;
-       if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
-               ant->flags &= ~ANTENNA_RX_DIVERSITY;
-
-       // If diversity is being enabled, check if we need hardware
-       // or software diversity. In the latter case, reset the value,
-       // and make sure we update the antenna flags to have the
-       // link tuner pick up the diversity tuning.
-       if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
-               tx_ant = ANTENNA_SW_DIVERSITY;
-               ant->flags |= ANTENNA_TX_DIVERSITY;
-       }
-
-       if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
-               rx_ant = ANTENNA_SW_DIVERSITY;
-               ant->flags |= ANTENNA_RX_DIVERSITY;
-       }
-
-       setup.tx = tx_ant;
-       setup.rx = rx_ant;
-       setup.rx_chain_num = 0;
-       setup.tx_chain_num = 0;
-
-       rt2x00lib_config_antenna(rt2x00dev, setup);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
-
-int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct link_ant *ant = &rt2x00dev->link.ant;
-       struct antenna_setup *active = &rt2x00dev->link.ant.active;
-
-       // When software diversity is active, we must report this to the
-       // client and not the current active antenna state.
-       if (ant->flags & ANTENNA_TX_DIVERSITY)
-               *tx_ant = ANTENNA_HW_DIVERSITY;
-       else
-               *tx_ant = active->tx;
-
-       if (ant->flags & ANTENNA_RX_DIVERSITY)
-               *rx_ant = ANTENNA_HW_DIVERSITY;
-       else
-               *rx_ant = active->rx;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
-
-void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
-                            u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               *tx += queue->length;
-               *tx_max += queue->limit;
-       }
-
-       *rx = rt2x00dev->rx->length;
-       *rx_max = rt2x00dev->rx->limit;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
-
-bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               if (!rt2x00queue_empty(queue))
-                       return true;
-       }
-
-       return false;
-}
-EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
deleted file mode 100644 (file)
index f0178fd..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00mmio
-       Abstract: rt2x00 generic mmio device routines.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-
-/*
- * Register access.
- */
-int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int offset,
-                           const struct rt2x00_field32 field,
-                           u32 *reg)
-{
-       unsigned int i;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return 0;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, offset, reg);
-               if (!rt2x00_get_field32(*reg, field))
-                       return 1;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       printk_once(KERN_ERR "%s() Indirect register access failed: "
-             "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
-       *reg = ~0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read);
-
-bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue = rt2x00dev->rx;
-       struct queue_entry *entry;
-       struct queue_entry_priv_mmio *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       int max_rx = 16;
-
-       while (--max_rx) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               entry_priv = entry->priv_data;
-
-               if (rt2x00dev->ops->lib->get_entry_state(entry))
-                       break;
-
-               /*
-                * Fill in desc fields of the skb descriptor
-                */
-               skbdesc = get_skb_frame_desc(entry->skb);
-               skbdesc->desc = entry_priv->desc;
-               skbdesc->desc_len = entry->queue->desc_size;
-
-               /*
-                * DMA is already done, notify rt2x00lib that
-                * it finished successfully.
-                */
-               rt2x00lib_dmastart(entry);
-               rt2x00lib_dmadone(entry);
-
-               /*
-                * Send the frame to rt2x00lib for further processing.
-                */
-               rt2x00lib_rxdone(entry, GFP_ATOMIC);
-       }
-
-       return !max_rx;
-}
-EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone);
-
-void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop)
-{
-       unsigned int i;
-
-       for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
-               msleep(10);
-}
-EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue);
-
-/*
- * Device initialization handlers.
- */
-static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
-                                     struct data_queue *queue)
-{
-       struct queue_entry_priv_mmio *entry_priv;
-       void *addr;
-       dma_addr_t dma;
-       unsigned int i;
-
-       /*
-        * Allocate DMA memory for descriptor and buffer.
-        */
-       addr = dma_zalloc_coherent(rt2x00dev->dev,
-                                  queue->limit * queue->desc_size, &dma,
-                                  GFP_KERNEL);
-       if (!addr)
-               return -ENOMEM;
-
-       /*
-        * Initialize all queue entries to contain valid addresses.
-        */
-       for (i = 0; i < queue->limit; i++) {
-               entry_priv = queue->entries[i].priv_data;
-               entry_priv->desc = addr + i * queue->desc_size;
-               entry_priv->desc_dma = dma + i * queue->desc_size;
-       }
-
-       return 0;
-}
-
-static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev,
-                                     struct data_queue *queue)
-{
-       struct queue_entry_priv_mmio *entry_priv =
-           queue->entries[0].priv_data;
-
-       if (entry_priv->desc)
-               dma_free_coherent(rt2x00dev->dev,
-                                 queue->limit * queue->desc_size,
-                                 entry_priv->desc, entry_priv->desc_dma);
-       entry_priv->desc = NULL;
-}
-
-int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       int status;
-
-       /*
-        * Allocate DMA
-        */
-       queue_for_each(rt2x00dev, queue) {
-               status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue);
-               if (status)
-                       goto exit;
-       }
-
-       /*
-        * Register interrupt handler.
-        */
-       status = request_irq(rt2x00dev->irq,
-                            rt2x00dev->ops->lib->irq_handler,
-                            IRQF_SHARED, rt2x00dev->name, rt2x00dev);
-       if (status) {
-               rt2x00_err(rt2x00dev, "IRQ %d allocation failed (error %d)\n",
-                          rt2x00dev->irq, status);
-               goto exit;
-       }
-
-       return 0;
-
-exit:
-       queue_for_each(rt2x00dev, queue)
-               rt2x00mmio_free_queue_dma(rt2x00dev, queue);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00mmio_initialize);
-
-void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       /*
-        * Free irq line.
-        */
-       free_irq(rt2x00dev->irq, rt2x00dev);
-
-       /*
-        * Free DMA
-        */
-       queue_for_each(rt2x00dev, queue)
-               rt2x00mmio_free_queue_dma(rt2x00dev, queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize);
-
-/*
- * rt2x00mmio module information.
- */
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2x00 mmio library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
deleted file mode 100644 (file)
index 701c312..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00mmio
-       Abstract: Data structures for the rt2x00mmio module.
- */
-
-#ifndef RT2X00MMIO_H
-#define RT2X00MMIO_H
-
-#include <linux/io.h>
-
-/*
- * Register access.
- */
-static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
-                                           const unsigned int offset,
-                                           u32 *value)
-{
-       *value = readl(rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                void *value, const u32 length)
-{
-       memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
-}
-
-static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev,
-                                            const unsigned int offset,
-                                            u32 value)
-{
-       writel(value, rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                                 const unsigned int offset,
-                                                 const void *value,
-                                                 const u32 length)
-{
-       __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
-}
-
-/**
- * rt2x00mmio_regbusy_read - Read from register with busy check
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @field: Field to check if register is busy
- * @reg: Pointer to where register contents should be stored
- *
- * This function will read the given register, and checks if the
- * register is busy. If it is, it will sleep for a couple of
- * microseconds before reading the register again. If the register
- * is not read after a certain timeout, this function will return
- * FALSE.
- */
-int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                           const unsigned int offset,
-                           const struct rt2x00_field32 field,
-                           u32 *reg);
-
-/**
- * struct queue_entry_priv_mmio: Per entry PCI specific information
- *
- * @desc: Pointer to device descriptor
- * @desc_dma: DMA pointer to &desc.
- * @data: Pointer to device's entry memory.
- * @data_dma: DMA pointer to &data.
- */
-struct queue_entry_priv_mmio {
-       __le32 *desc;
-       dma_addr_t desc_dma;
-};
-
-/**
- * rt2x00mmio_rxdone - Handle RX done events
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- *
- * Returns true if there are still rx frames pending and false if all
- * pending rx frames were processed.
- */
-bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00mmio_flush_queue - Flush data queue
- * @queue: Data queue to stop
- * @drop: True to drop all pending frames.
- *
- * This will wait for a maximum of 100ms, waiting for the queues
- * to become empty.
- */
-void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop);
-
-/*
- * Device initialization handlers.
- */
-int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev);
-
-#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
deleted file mode 100644 (file)
index d93db4b..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00pci
-       Abstract: rt2x00 generic pci device routines.
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2x00pci.h"
-
-/*
- * PCI driver handlers.
- */
-static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
-{
-       kfree(rt2x00dev->rf);
-       rt2x00dev->rf = NULL;
-
-       kfree(rt2x00dev->eeprom);
-       rt2x00dev->eeprom = NULL;
-
-       if (rt2x00dev->csr.base) {
-               iounmap(rt2x00dev->csr.base);
-               rt2x00dev->csr.base = NULL;
-       }
-}
-
-static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
-{
-       struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev);
-
-       rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0);
-       if (!rt2x00dev->csr.base)
-               goto exit;
-
-       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
-       if (!rt2x00dev->eeprom)
-               goto exit;
-
-       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
-       if (!rt2x00dev->rf)
-               goto exit;
-
-       return 0;
-
-exit:
-       rt2x00_probe_err("Failed to allocate registers\n");
-
-       rt2x00pci_free_reg(rt2x00dev);
-
-       return -ENOMEM;
-}
-
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
-{
-       struct ieee80211_hw *hw;
-       struct rt2x00_dev *rt2x00dev;
-       int retval;
-       u16 chip;
-
-       retval = pci_enable_device(pci_dev);
-       if (retval) {
-               rt2x00_probe_err("Enable device failed\n");
-               return retval;
-       }
-
-       retval = pci_request_regions(pci_dev, pci_name(pci_dev));
-       if (retval) {
-               rt2x00_probe_err("PCI request regions failed\n");
-               goto exit_disable_device;
-       }
-
-       pci_set_master(pci_dev);
-
-       if (pci_set_mwi(pci_dev))
-               rt2x00_probe_err("MWI not available\n");
-
-       if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
-               rt2x00_probe_err("PCI DMA not supported\n");
-               retval = -EIO;
-               goto exit_release_regions;
-       }
-
-       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
-       if (!hw) {
-               rt2x00_probe_err("Failed to allocate hardware\n");
-               retval = -ENOMEM;
-               goto exit_release_regions;
-       }
-
-       pci_set_drvdata(pci_dev, hw);
-
-       rt2x00dev = hw->priv;
-       rt2x00dev->dev = &pci_dev->dev;
-       rt2x00dev->ops = ops;
-       rt2x00dev->hw = hw;
-       rt2x00dev->irq = pci_dev->irq;
-       rt2x00dev->name = ops->name;
-
-       if (pci_is_pcie(pci_dev))
-               rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
-       else
-               rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
-
-       retval = rt2x00pci_alloc_reg(rt2x00dev);
-       if (retval)
-               goto exit_free_device;
-
-       /*
-        * Because rt3290 chip use different efuse offset to read efuse data.
-        * So before read efuse it need to indicate it is the
-        * rt3290 or not.
-        */
-       pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
-       rt2x00dev->chip.rt = chip;
-
-       retval = rt2x00lib_probe_dev(rt2x00dev);
-       if (retval)
-               goto exit_free_reg;
-
-       return 0;
-
-exit_free_reg:
-       rt2x00pci_free_reg(rt2x00dev);
-
-exit_free_device:
-       ieee80211_free_hw(hw);
-
-exit_release_regions:
-       pci_release_regions(pci_dev);
-
-exit_disable_device:
-       pci_disable_device(pci_dev);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_probe);
-
-void rt2x00pci_remove(struct pci_dev *pci_dev)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * Free all allocated data.
-        */
-       rt2x00lib_remove_dev(rt2x00dev);
-       rt2x00pci_free_reg(rt2x00dev);
-       ieee80211_free_hw(hw);
-
-       /*
-        * Free the PCI device data.
-        */
-       pci_disable_device(pci_dev);
-       pci_release_regions(pci_dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_remove);
-
-#ifdef CONFIG_PM
-int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       int retval;
-
-       retval = rt2x00lib_suspend(rt2x00dev, state);
-       if (retval)
-               return retval;
-
-       pci_save_state(pci_dev);
-       pci_disable_device(pci_dev);
-       return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_suspend);
-
-int rt2x00pci_resume(struct pci_dev *pci_dev)
-{
-       struct ieee80211_hw *hw = pci_get_drvdata(pci_dev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       if (pci_set_power_state(pci_dev, PCI_D0) ||
-           pci_enable_device(pci_dev)) {
-               rt2x00_err(rt2x00dev, "Failed to resume device\n");
-               return -EIO;
-       }
-
-       pci_restore_state(pci_dev);
-       return rt2x00lib_resume(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_resume);
-#endif /* CONFIG_PM */
-
-/*
- * rt2x00pci module information.
- */
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2x00 pci library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
deleted file mode 100644 (file)
index bc0ca5f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00pci
-       Abstract: Data structures for the rt2x00pci module.
- */
-
-#ifndef RT2X00PCI_H
-#define RT2X00PCI_H
-
-#include <linux/io.h>
-#include <linux/pci.h>
-
-/*
- * This variable should be used with the
- * pci_driver structure initialization.
- */
-#define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops)
-
-/*
- * PCI driver handlers.
- */
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
-void rt2x00pci_remove(struct pci_dev *pci_dev);
-#ifdef CONFIG_PM
-int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
-int rt2x00pci_resume(struct pci_dev *pci_dev);
-#else
-#define rt2x00pci_suspend      NULL
-#define rt2x00pci_resume       NULL
-#endif /* CONFIG_PM */
-
-#endif /* RT2X00PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
deleted file mode 100644 (file)
index 68b620b..0000000
+++ /dev/null
@@ -1,1290 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00lib
-       Abstract: rt2x00 queue specific routines.
- */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
-{
-       struct data_queue *queue = entry->queue;
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       struct sk_buff *skb;
-       struct skb_frame_desc *skbdesc;
-       unsigned int frame_size;
-       unsigned int head_size = 0;
-       unsigned int tail_size = 0;
-
-       /*
-        * The frame size includes descriptor size, because the
-        * hardware directly receive the frame into the skbuffer.
-        */
-       frame_size = queue->data_size + queue->desc_size + queue->winfo_size;
-
-       /*
-        * The payload should be aligned to a 4-byte boundary,
-        * this means we need at least 3 bytes for moving the frame
-        * into the correct offset.
-        */
-       head_size = 4;
-
-       /*
-        * For IV/EIV/ICV assembly we must make sure there is
-        * at least 8 bytes bytes available in headroom for IV/EIV
-        * and 8 bytes for ICV data as tailroon.
-        */
-       if (rt2x00_has_cap_hw_crypto(rt2x00dev)) {
-               head_size += 8;
-               tail_size += 8;
-       }
-
-       /*
-        * Allocate skbuffer.
-        */
-       skb = __dev_alloc_skb(frame_size + head_size + tail_size, gfp);
-       if (!skb)
-               return NULL;
-
-       /*
-        * Make sure we not have a frame with the requested bytes
-        * available in the head and tail.
-        */
-       skb_reserve(skb, head_size);
-       skb_put(skb, frame_size);
-
-       /*
-        * Populate skbdesc.
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->entry = entry;
-
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA)) {
-               dma_addr_t skb_dma;
-
-               skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len,
-                                        DMA_FROM_DEVICE);
-               if (unlikely(dma_mapping_error(rt2x00dev->dev, skb_dma))) {
-                       dev_kfree_skb_any(skb);
-                       return NULL;
-               }
-
-               skbdesc->skb_dma = skb_dma;
-               skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;
-       }
-
-       return skb;
-}
-
-int rt2x00queue_map_txskb(struct queue_entry *entry)
-{
-       struct device *dev = entry->queue->rt2x00dev->dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-
-       skbdesc->skb_dma =
-           dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE);
-
-       if (unlikely(dma_mapping_error(dev, skbdesc->skb_dma)))
-               return -ENOMEM;
-
-       skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
-
-void rt2x00queue_unmap_skb(struct queue_entry *entry)
-{
-       struct device *dev = entry->queue->rt2x00dev->dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-
-       if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) {
-               dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
-                                DMA_FROM_DEVICE);
-               skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX;
-       } else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) {
-               dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len,
-                                DMA_TO_DEVICE);
-               skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb);
-
-void rt2x00queue_free_skb(struct queue_entry *entry)
-{
-       if (!entry->skb)
-               return;
-
-       rt2x00queue_unmap_skb(entry);
-       dev_kfree_skb_any(entry->skb);
-       entry->skb = NULL;
-}
-
-void rt2x00queue_align_frame(struct sk_buff *skb)
-{
-       unsigned int frame_length = skb->len;
-       unsigned int align = ALIGN_SIZE(skb, 0);
-
-       if (!align)
-               return;
-
-       skb_push(skb, align);
-       memmove(skb->data, skb->data + align, frame_length);
-       skb_trim(skb, frame_length);
-}
-
-/*
- * H/W needs L2 padding between the header and the paylod if header size
- * is not 4 bytes aligned.
- */
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
-{
-       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
-
-       if (!l2pad)
-               return;
-
-       skb_push(skb, l2pad);
-       memmove(skb->data, skb->data + l2pad, hdr_len);
-}
-
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
-{
-       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
-
-       if (!l2pad)
-               return;
-
-       memmove(skb->data + l2pad, skb->data, hdr_len);
-       skb_pull(skb, l2pad);
-}
-
-static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
-                                                struct sk_buff *skb,
-                                                struct txentry_desc *txdesc)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       u16 seqno;
-
-       if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
-               return;
-
-       __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
-
-       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_SW_SEQNO)) {
-               /*
-                * rt2800 has a H/W (or F/W) bug, device incorrectly increase
-                * seqno on retransmited data (non-QOS) frames. To workaround
-                * the problem let's generate seqno in software if QOS is
-                * disabled.
-                */
-               if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags))
-                       __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
-               else
-                       /* H/W will generate sequence number */
-                       return;
-       }
-
-       /*
-        * The hardware is not able to insert a sequence number. Assign a
-        * software generated one here.
-        *
-        * This is wrong because beacons are not getting sequence
-        * numbers assigned properly.
-        *
-        * A secondary problem exists for drivers that cannot toggle
-        * sequence counting per-frame, since those will override the
-        * sequence counter given by mac80211.
-        */
-       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
-               seqno = atomic_add_return(0x10, &intf->seqno);
-       else
-               seqno = atomic_read(&intf->seqno);
-
-       hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-       hdr->seq_ctrl |= cpu_to_le16(seqno);
-}
-
-static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
-                                                 struct sk_buff *skb,
-                                                 struct txentry_desc *txdesc,
-                                                 const struct rt2x00_rate *hwrate)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-       unsigned int data_length;
-       unsigned int duration;
-       unsigned int residual;
-
-       /*
-        * Determine with what IFS priority this frame should be send.
-        * Set ifs to IFS_SIFS when the this is not the first fragment,
-        * or this fragment came after RTS/CTS.
-        */
-       if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
-               txdesc->u.plcp.ifs = IFS_BACKOFF;
-       else
-               txdesc->u.plcp.ifs = IFS_SIFS;
-
-       /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
-       data_length = skb->len + 4;
-       data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
-
-       /*
-        * PLCP setup
-        * Length calculation depends on OFDM/CCK rate.
-        */
-       txdesc->u.plcp.signal = hwrate->plcp;
-       txdesc->u.plcp.service = 0x04;
-
-       if (hwrate->flags & DEV_RATE_OFDM) {
-               txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f;
-               txdesc->u.plcp.length_low = data_length & 0x3f;
-       } else {
-               /*
-                * Convert length to microseconds.
-                */
-               residual = GET_DURATION_RES(data_length, hwrate->bitrate);
-               duration = GET_DURATION(data_length, hwrate->bitrate);
-
-               if (residual != 0) {
-                       duration++;
-
-                       /*
-                        * Check if we need to set the Length Extension
-                        */
-                       if (hwrate->bitrate == 110 && residual <= 30)
-                               txdesc->u.plcp.service |= 0x80;
-               }
-
-               txdesc->u.plcp.length_high = (duration >> 8) & 0xff;
-               txdesc->u.plcp.length_low = duration & 0xff;
-
-               /*
-                * When preamble is enabled we should set the
-                * preamble bit for the signal.
-                */
-               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->u.plcp.signal |= 0x08;
-       }
-}
-
-static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
-                                               struct sk_buff *skb,
-                                               struct txentry_desc *txdesc,
-                                               struct ieee80211_sta *sta,
-                                               const struct rt2x00_rate *hwrate)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct rt2x00_sta *sta_priv = NULL;
-
-       if (sta) {
-               txdesc->u.ht.mpdu_density =
-                   sta->ht_cap.ampdu_density;
-
-               sta_priv = sta_to_rt2x00_sta(sta);
-               txdesc->u.ht.wcid = sta_priv->wcid;
-       }
-
-       /*
-        * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
-        * mcs rate to be used
-        */
-       if (txrate->flags & IEEE80211_TX_RC_MCS) {
-               txdesc->u.ht.mcs = txrate->idx;
-
-               /*
-                * MIMO PS should be set to 1 for STA's using dynamic SM PS
-                * when using more then one tx stream (>MCS7).
-                */
-               if (sta && txdesc->u.ht.mcs > 7 &&
-                   sta->smps_mode == IEEE80211_SMPS_DYNAMIC)
-                       __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
-       } else {
-               txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
-               if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       txdesc->u.ht.mcs |= 0x08;
-       }
-
-       if (test_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags)) {
-               if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-                       txdesc->u.ht.txop = TXOP_SIFS;
-               else
-                       txdesc->u.ht.txop = TXOP_BACKOFF;
-
-               /* Left zero on all other settings. */
-               return;
-       }
-
-       txdesc->u.ht.ba_size = 7;       /* FIXME: What value is needed? */
-
-       /*
-        * Only one STBC stream is supported for now.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_STBC)
-               txdesc->u.ht.stbc = 1;
-
-       /*
-        * This frame is eligible for an AMPDU, however, don't aggregate
-        * frames that are intended to probe a specific tx rate.
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
-           !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
-               __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
-
-       /*
-        * Set 40Mhz mode if necessary (for legacy rates this will
-        * duplicate the frame to both channels).
-        */
-       if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
-           txrate->flags & IEEE80211_TX_RC_DUP_DATA)
-               __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
-       if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
-               __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
-
-       /*
-        * Determine IFS values
-        * - Use TXOP_BACKOFF for management frames except beacons
-        * - Use TXOP_SIFS for fragment bursts
-        * - Use TXOP_HTTXOP for everything else
-        *
-        * Note: rt2800 devices won't use CTS protection (if used)
-        * for frames not transmitted with TXOP_HTTXOP
-        */
-       if (ieee80211_is_mgmt(hdr->frame_control) &&
-           !ieee80211_is_beacon(hdr->frame_control))
-               txdesc->u.ht.txop = TXOP_BACKOFF;
-       else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-               txdesc->u.ht.txop = TXOP_SIFS;
-       else
-               txdesc->u.ht.txop = TXOP_HTTXOP;
-}
-
-static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
-                                            struct sk_buff *skb,
-                                            struct txentry_desc *txdesc,
-                                            struct ieee80211_sta *sta)
-{
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-       struct ieee80211_rate *rate;
-       const struct rt2x00_rate *hwrate = NULL;
-
-       memset(txdesc, 0, sizeof(*txdesc));
-
-       /*
-        * Header and frame information.
-        */
-       txdesc->length = skb->len;
-       txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
-
-       /*
-        * Check whether this frame is to be acked.
-        */
-       if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
-               __set_bit(ENTRY_TXD_ACK, &txdesc->flags);
-
-       /*
-        * Check if this is a RTS/CTS frame
-        */
-       if (ieee80211_is_rts(hdr->frame_control) ||
-           ieee80211_is_cts(hdr->frame_control)) {
-               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
-               if (ieee80211_is_rts(hdr->frame_control))
-                       __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags);
-               else
-                       __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags);
-               if (tx_info->control.rts_cts_rate_idx >= 0)
-                       rate =
-                           ieee80211_get_rts_cts_rate(rt2x00dev->hw, tx_info);
-       }
-
-       /*
-        * Determine retry information.
-        */
-       txdesc->retry_limit = tx_info->control.rates[0].count - 1;
-       if (txdesc->retry_limit >= rt2x00dev->long_retry)
-               __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
-
-       /*
-        * Check if more fragments are pending
-        */
-       if (ieee80211_has_morefrags(hdr->frame_control)) {
-               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
-               __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags);
-       }
-
-       /*
-        * Check if more frames (!= fragments) are pending
-        */
-       if (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)
-               __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
-
-       /*
-        * Beacons and probe responses require the tsf timestamp
-        * to be inserted into the frame.
-        */
-       if (ieee80211_is_beacon(hdr->frame_control) ||
-           ieee80211_is_probe_resp(hdr->frame_control))
-               __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
-
-       if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) &&
-           !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags))
-               __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
-
-       /*
-        * Determine rate modulation.
-        */
-       if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
-               txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
-       else if (txrate->flags & IEEE80211_TX_RC_MCS)
-               txdesc->rate_mode = RATE_MODE_HT_MIX;
-       else {
-               rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
-               hwrate = rt2x00_get_rate(rate->hw_value);
-               if (hwrate->flags & DEV_RATE_OFDM)
-                       txdesc->rate_mode = RATE_MODE_OFDM;
-               else
-                       txdesc->rate_mode = RATE_MODE_CCK;
-       }
-
-       /*
-        * Apply TX descriptor handling by components
-        */
-       rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
-       rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
-
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_HT_TX_DESC))
-               rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
-                                                  sta, hwrate);
-       else
-               rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
-                                                     hwrate);
-}
-
-static int rt2x00queue_write_tx_data(struct queue_entry *entry,
-                                    struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-
-       /*
-        * This should not happen, we already checked the entry
-        * was ours. When the hardware disagrees there has been
-        * a queue corruption!
-        */
-       if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
-                    rt2x00dev->ops->lib->get_entry_state(entry))) {
-               rt2x00_err(rt2x00dev,
-                          "Corrupt queue %d, accessing entry which is not ours\n"
-                          "Please file bug report to %s\n",
-                          entry->queue->qid, DRV_PROJECT);
-               return -EINVAL;
-       }
-
-       /*
-        * Add the requested extra tx headroom in front of the skb.
-        */
-       skb_push(entry->skb, rt2x00dev->extra_tx_headroom);
-       memset(entry->skb->data, 0, rt2x00dev->extra_tx_headroom);
-
-       /*
-        * Call the driver's write_tx_data function, if it exists.
-        */
-       if (rt2x00dev->ops->lib->write_tx_data)
-               rt2x00dev->ops->lib->write_tx_data(entry, txdesc);
-
-       /*
-        * Map the skb to DMA.
-        */
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_DMA) &&
-           rt2x00queue_map_txskb(entry))
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
-                                           struct txentry_desc *txdesc)
-{
-       struct data_queue *queue = entry->queue;
-
-       queue->rt2x00dev->ops->lib->write_tx_desc(entry, txdesc);
-
-       /*
-        * All processing on the frame has been completed, this means
-        * it is now ready to be dumped to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb);
-}
-
-static void rt2x00queue_kick_tx_queue(struct data_queue *queue,
-                                     struct txentry_desc *txdesc)
-{
-       /*
-        * Check if we need to kick the queue, there are however a few rules
-        *      1) Don't kick unless this is the last in frame in a burst.
-        *         When the burst flag is set, this frame is always followed
-        *         by another frame which in some way are related to eachother.
-        *         This is true for fragments, RTS or CTS-to-self frames.
-        *      2) Rule 1 can be broken when the available entries
-        *         in the queue are less then a certain threshold.
-        */
-       if (rt2x00queue_threshold(queue) ||
-           !test_bit(ENTRY_TXD_BURST, &txdesc->flags))
-               queue->rt2x00dev->ops->lib->kick_queue(queue);
-}
-
-static void rt2x00queue_bar_check(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct ieee80211_bar *bar = (void *) (entry->skb->data +
-                                   rt2x00dev->extra_tx_headroom);
-       struct rt2x00_bar_list_entry *bar_entry;
-
-       if (likely(!ieee80211_is_back_req(bar->frame_control)))
-               return;
-
-       bar_entry = kmalloc(sizeof(*bar_entry), GFP_ATOMIC);
-
-       /*
-        * If the alloc fails we still send the BAR out but just don't track
-        * it in our bar list. And as a result we will report it to mac80211
-        * back as failed.
-        */
-       if (!bar_entry)
-               return;
-
-       bar_entry->entry = entry;
-       bar_entry->block_acked = 0;
-
-       /*
-        * Copy the relevant parts of the 802.11 BAR into out check list
-        * such that we can use RCU for less-overhead in the RX path since
-        * sending BARs and processing the according BlockAck should be
-        * the exception.
-        */
-       memcpy(bar_entry->ra, bar->ra, sizeof(bar->ra));
-       memcpy(bar_entry->ta, bar->ta, sizeof(bar->ta));
-       bar_entry->control = bar->control;
-       bar_entry->start_seq_num = bar->start_seq_num;
-
-       /*
-        * Insert BAR into our BAR check list.
-        */
-       spin_lock_bh(&rt2x00dev->bar_list_lock);
-       list_add_tail_rcu(&bar_entry->list, &rt2x00dev->bar_list);
-       spin_unlock_bh(&rt2x00dev->bar_list_lock);
-}
-
-int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
-                              struct ieee80211_sta *sta, bool local)
-{
-       struct ieee80211_tx_info *tx_info;
-       struct queue_entry *entry;
-       struct txentry_desc txdesc;
-       struct skb_frame_desc *skbdesc;
-       u8 rate_idx, rate_flags;
-       int ret = 0;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, sta);
-
-       /*
-        * All information is retrieved from the skb->cb array,
-        * now we should claim ownership of the driver part of that
-        * array, preserving the bitrate index and flags.
-        */
-       tx_info = IEEE80211_SKB_CB(skb);
-       rate_idx = tx_info->control.rates[0].idx;
-       rate_flags = tx_info->control.rates[0].flags;
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->tx_rate_idx = rate_idx;
-       skbdesc->tx_rate_flags = rate_flags;
-
-       if (local)
-               skbdesc->flags |= SKBDESC_NOT_MAC80211;
-
-       /*
-        * When hardware encryption is supported, and this frame
-        * is to be encrypted, we should strip the IV/EIV data from
-        * the frame so we can provide it to the driver separately.
-        */
-       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
-           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
-               if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_COPY_IV))
-                       rt2x00crypto_tx_copy_iv(skb, &txdesc);
-               else
-                       rt2x00crypto_tx_remove_iv(skb, &txdesc);
-       }
-
-       /*
-        * When DMA allocation is required we should guarantee to the
-        * driver that the DMA is aligned to a 4-byte boundary.
-        * However some drivers require L2 padding to pad the payload
-        * rather then the header. This could be a requirement for
-        * PCI and USB devices, while header alignment only is valid
-        * for PCI devices.
-        */
-       if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_L2PAD))
-               rt2x00queue_insert_l2pad(skb, txdesc.header_length);
-       else if (rt2x00_has_cap_flag(queue->rt2x00dev, REQUIRE_DMA))
-               rt2x00queue_align_frame(skb);
-
-       /*
-        * That function must be called with bh disabled.
-        */
-       spin_lock(&queue->tx_lock);
-
-       if (unlikely(rt2x00queue_full(queue))) {
-               rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
-                          queue->qid);
-               ret = -ENOBUFS;
-               goto out;
-       }
-
-       entry = rt2x00queue_get_entry(queue, Q_INDEX);
-
-       if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
-                                     &entry->flags))) {
-               rt2x00_err(queue->rt2x00dev,
-                          "Arrived at non-free entry in the non-full queue %d\n"
-                          "Please file bug report to %s\n",
-                          queue->qid, DRV_PROJECT);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       skbdesc->entry = entry;
-       entry->skb = skb;
-
-       /*
-        * It could be possible that the queue was corrupted and this
-        * call failed. Since we always return NETDEV_TX_OK to mac80211,
-        * this frame will simply be dropped.
-        */
-       if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
-               clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-               entry->skb = NULL;
-               ret = -EIO;
-               goto out;
-       }
-
-       /*
-        * Put BlockAckReqs into our check list for driver BA processing.
-        */
-       rt2x00queue_bar_check(entry);
-
-       set_bit(ENTRY_DATA_PENDING, &entry->flags);
-
-       rt2x00queue_index_inc(entry, Q_INDEX);
-       rt2x00queue_write_tx_descriptor(entry, &txdesc);
-       rt2x00queue_kick_tx_queue(queue, &txdesc);
-
-out:
-       spin_unlock(&queue->tx_lock);
-       return ret;
-}
-
-int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
-                            struct ieee80211_vif *vif)
-{
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Clean up the beacon skb.
-        */
-       rt2x00queue_free_skb(intf->beacon);
-
-       /*
-        * Clear beacon (single bssid devices don't need to clear the beacon
-        * since the beacon queue will get stopped anyway).
-        */
-       if (rt2x00dev->ops->lib->clear_beacon)
-               rt2x00dev->ops->lib->clear_beacon(intf->beacon);
-
-       return 0;
-}
-
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-                             struct ieee80211_vif *vif)
-{
-       struct rt2x00_intf *intf = vif_to_intf(vif);
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Clean up the beacon skb.
-        */
-       rt2x00queue_free_skb(intf->beacon);
-
-       intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
-       if (!intf->beacon->skb)
-               return -ENOMEM;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc, NULL);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(intf->beacon->skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Send beacon to hardware.
-        */
-       rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);
-
-       return 0;
-
-}
-
-bool rt2x00queue_for_each_entry(struct data_queue *queue,
-                               enum queue_index start,
-                               enum queue_index end,
-                               void *data,
-                               bool (*fn)(struct queue_entry *entry,
-                                          void *data))
-{
-       unsigned long irqflags;
-       unsigned int index_start;
-       unsigned int index_end;
-       unsigned int i;
-
-       if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
-               rt2x00_err(queue->rt2x00dev,
-                          "Entry requested from invalid index range (%d - %d)\n",
-                          start, end);
-               return true;
-       }
-
-       /*
-        * Only protect the range we are going to loop over,
-        * if during our loop a extra entry is set to pending
-        * it should not be kicked during this run, since it
-        * is part of another TX operation.
-        */
-       spin_lock_irqsave(&queue->index_lock, irqflags);
-       index_start = queue->index[start];
-       index_end = queue->index[end];
-       spin_unlock_irqrestore(&queue->index_lock, irqflags);
-
-       /*
-        * Start from the TX done pointer, this guarantees that we will
-        * send out all frames in the correct order.
-        */
-       if (index_start < index_end) {
-               for (i = index_start; i < index_end; i++) {
-                       if (fn(&queue->entries[i], data))
-                               return true;
-               }
-       } else {
-               for (i = index_start; i < queue->limit; i++) {
-                       if (fn(&queue->entries[i], data))
-                               return true;
-               }
-
-               for (i = 0; i < index_end; i++) {
-                       if (fn(&queue->entries[i], data))
-                               return true;
-               }
-       }
-
-       return false;
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
-
-struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
-                                         enum queue_index index)
-{
-       struct queue_entry *entry;
-       unsigned long irqflags;
-
-       if (unlikely(index >= Q_INDEX_MAX)) {
-               rt2x00_err(queue->rt2x00dev, "Entry requested from invalid index type (%d)\n",
-                          index);
-               return NULL;
-       }
-
-       spin_lock_irqsave(&queue->index_lock, irqflags);
-
-       entry = &queue->entries[queue->index[index]];
-
-       spin_unlock_irqrestore(&queue->index_lock, irqflags);
-
-       return entry;
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
-
-void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
-{
-       struct data_queue *queue = entry->queue;
-       unsigned long irqflags;
-
-       if (unlikely(index >= Q_INDEX_MAX)) {
-               rt2x00_err(queue->rt2x00dev,
-                          "Index change on invalid index type (%d)\n", index);
-               return;
-       }
-
-       spin_lock_irqsave(&queue->index_lock, irqflags);
-
-       queue->index[index]++;
-       if (queue->index[index] >= queue->limit)
-               queue->index[index] = 0;
-
-       entry->last_action = jiffies;
-
-       if (index == Q_INDEX) {
-               queue->length++;
-       } else if (index == Q_INDEX_DONE) {
-               queue->length--;
-               queue->count++;
-       }
-
-       spin_unlock_irqrestore(&queue->index_lock, irqflags);
-}
-
-static void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               /*
-                * For TX queues, we have to disable the queue
-                * inside mac80211.
-                */
-               ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
-               break;
-       default:
-               break;
-       }
-}
-void rt2x00queue_pause_queue(struct data_queue *queue)
-{
-       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
-           !test_bit(QUEUE_STARTED, &queue->flags) ||
-           test_and_set_bit(QUEUE_PAUSED, &queue->flags))
-               return;
-
-       rt2x00queue_pause_queue_nocheck(queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
-
-void rt2x00queue_unpause_queue(struct data_queue *queue)
-{
-       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
-           !test_bit(QUEUE_STARTED, &queue->flags) ||
-           !test_and_clear_bit(QUEUE_PAUSED, &queue->flags))
-               return;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               /*
-                * For TX queues, we have to enable the queue
-                * inside mac80211.
-                */
-               ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
-               break;
-       case QID_RX:
-               /*
-                * For RX we need to kick the queue now in order to
-                * receive frames.
-                */
-               queue->rt2x00dev->ops->lib->kick_queue(queue);
-       default:
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue);
-
-void rt2x00queue_start_queue(struct data_queue *queue)
-{
-       mutex_lock(&queue->status_lock);
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
-           test_and_set_bit(QUEUE_STARTED, &queue->flags)) {
-               mutex_unlock(&queue->status_lock);
-               return;
-       }
-
-       set_bit(QUEUE_PAUSED, &queue->flags);
-
-       queue->rt2x00dev->ops->lib->start_queue(queue);
-
-       rt2x00queue_unpause_queue(queue);
-
-       mutex_unlock(&queue->status_lock);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_start_queue);
-
-void rt2x00queue_stop_queue(struct data_queue *queue)
-{
-       mutex_lock(&queue->status_lock);
-
-       if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) {
-               mutex_unlock(&queue->status_lock);
-               return;
-       }
-
-       rt2x00queue_pause_queue_nocheck(queue);
-
-       queue->rt2x00dev->ops->lib->stop_queue(queue);
-
-       mutex_unlock(&queue->status_lock);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
-
-void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
-{
-       bool tx_queue =
-               (queue->qid == QID_AC_VO) ||
-               (queue->qid == QID_AC_VI) ||
-               (queue->qid == QID_AC_BE) ||
-               (queue->qid == QID_AC_BK);
-
-
-       /*
-        * If we are not supposed to drop any pending
-        * frames, this means we must force a start (=kick)
-        * to the queue to make sure the hardware will
-        * start transmitting.
-        */
-       if (!drop && tx_queue)
-               queue->rt2x00dev->ops->lib->kick_queue(queue);
-
-       /*
-        * Check if driver supports flushing, if that is the case we can
-        * defer the flushing to the driver. Otherwise we must use the
-        * alternative which just waits for the queue to become empty.
-        */
-       if (likely(queue->rt2x00dev->ops->lib->flush_queue))
-               queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
-
-       /*
-        * The queue flush has failed...
-        */
-       if (unlikely(!rt2x00queue_empty(queue)))
-               rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n",
-                           queue->qid);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue);
-
-void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       /*
-        * rt2x00queue_start_queue will call ieee80211_wake_queue
-        * for each queue after is has been properly initialized.
-        */
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_start_queue(queue);
-
-       rt2x00queue_start_queue(rt2x00dev->rx);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_start_queues);
-
-void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       /*
-        * rt2x00queue_stop_queue will call ieee80211_stop_queue
-        * as well, but we are completely shutting doing everything
-        * now, so it is much safer to stop all TX queues at once,
-        * and use rt2x00queue_stop_queue for cleaning up.
-        */
-       ieee80211_stop_queues(rt2x00dev->hw);
-
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_stop_queue(queue);
-
-       rt2x00queue_stop_queue(rt2x00dev->rx);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues);
-
-void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop)
-{
-       struct data_queue *queue;
-
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_flush_queue(queue, drop);
-
-       rt2x00queue_flush_queue(rt2x00dev->rx, drop);
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues);
-
-static void rt2x00queue_reset(struct data_queue *queue)
-{
-       unsigned long irqflags;
-       unsigned int i;
-
-       spin_lock_irqsave(&queue->index_lock, irqflags);
-
-       queue->count = 0;
-       queue->length = 0;
-
-       for (i = 0; i < Q_INDEX_MAX; i++)
-               queue->index[i] = 0;
-
-       spin_unlock_irqrestore(&queue->index_lock, irqflags);
-}
-
-void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       unsigned int i;
-
-       queue_for_each(rt2x00dev, queue) {
-               rt2x00queue_reset(queue);
-
-               for (i = 0; i < queue->limit; i++)
-                       rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
-       }
-}
-
-static int rt2x00queue_alloc_entries(struct data_queue *queue)
-{
-       struct queue_entry *entries;
-       unsigned int entry_size;
-       unsigned int i;
-
-       rt2x00queue_reset(queue);
-
-       /*
-        * Allocate all queue entries.
-        */
-       entry_size = sizeof(*entries) + queue->priv_size;
-       entries = kcalloc(queue->limit, entry_size, GFP_KERNEL);
-       if (!entries)
-               return -ENOMEM;
-
-#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
-       (((char *)(__base)) + ((__limit) * (__esize)) + \
-           ((__index) * (__psize)))
-
-       for (i = 0; i < queue->limit; i++) {
-               entries[i].flags = 0;
-               entries[i].queue = queue;
-               entries[i].skb = NULL;
-               entries[i].entry_idx = i;
-               entries[i].priv_data =
-                   QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
-                                           sizeof(*entries), queue->priv_size);
-       }
-
-#undef QUEUE_ENTRY_PRIV_OFFSET
-
-       queue->entries = entries;
-
-       return 0;
-}
-
-static void rt2x00queue_free_skbs(struct data_queue *queue)
-{
-       unsigned int i;
-
-       if (!queue->entries)
-               return;
-
-       for (i = 0; i < queue->limit; i++) {
-               rt2x00queue_free_skb(&queue->entries[i]);
-       }
-}
-
-static int rt2x00queue_alloc_rxskbs(struct data_queue *queue)
-{
-       unsigned int i;
-       struct sk_buff *skb;
-
-       for (i = 0; i < queue->limit; i++) {
-               skb = rt2x00queue_alloc_rxskb(&queue->entries[i], GFP_KERNEL);
-               if (!skb)
-                       return -ENOMEM;
-               queue->entries[i].skb = skb;
-       }
-
-       return 0;
-}
-
-int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       int status;
-
-       status = rt2x00queue_alloc_entries(rt2x00dev->rx);
-       if (status)
-               goto exit;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               status = rt2x00queue_alloc_entries(queue);
-               if (status)
-                       goto exit;
-       }
-
-       status = rt2x00queue_alloc_entries(rt2x00dev->bcn);
-       if (status)
-               goto exit;
-
-       if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE)) {
-               status = rt2x00queue_alloc_entries(rt2x00dev->atim);
-               if (status)
-                       goto exit;
-       }
-
-       status = rt2x00queue_alloc_rxskbs(rt2x00dev->rx);
-       if (status)
-               goto exit;
-
-       return 0;
-
-exit:
-       rt2x00_err(rt2x00dev, "Queue entries allocation failed\n");
-
-       rt2x00queue_uninitialize(rt2x00dev);
-
-       return status;
-}
-
-void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       rt2x00queue_free_skbs(rt2x00dev->rx);
-
-       queue_for_each(rt2x00dev, queue) {
-               kfree(queue->entries);
-               queue->entries = NULL;
-       }
-}
-
-static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
-                            struct data_queue *queue, enum data_queue_qid qid)
-{
-       mutex_init(&queue->status_lock);
-       spin_lock_init(&queue->tx_lock);
-       spin_lock_init(&queue->index_lock);
-
-       queue->rt2x00dev = rt2x00dev;
-       queue->qid = qid;
-       queue->txop = 0;
-       queue->aifs = 2;
-       queue->cw_min = 5;
-       queue->cw_max = 10;
-
-       rt2x00dev->ops->queue_init(queue);
-
-       queue->threshold = DIV_ROUND_UP(queue->limit, 10);
-}
-
-int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       enum data_queue_qid qid;
-       unsigned int req_atim =
-           rt2x00_has_cap_flag(rt2x00dev, REQUIRE_ATIM_QUEUE);
-
-       /*
-        * We need the following queues:
-        * RX: 1
-        * TX: ops->tx_queues
-        * Beacon: 1
-        * Atim: 1 (if required)
-        */
-       rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim;
-
-       queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
-       if (!queue) {
-               rt2x00_err(rt2x00dev, "Queue allocation failed\n");
-               return -ENOMEM;
-       }
-
-       /*
-        * Initialize pointers
-        */
-       rt2x00dev->rx = queue;
-       rt2x00dev->tx = &queue[1];
-       rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues];
-       rt2x00dev->atim = req_atim ? &queue[2 + rt2x00dev->ops->tx_queues] : NULL;
-
-       /*
-        * Initialize queue parameters.
-        * RX: qid = QID_RX
-        * TX: qid = QID_AC_VO + index
-        * TX: cw_min: 2^5 = 32.
-        * TX: cw_max: 2^10 = 1024.
-        * BCN: qid = QID_BEACON
-        * ATIM: qid = QID_ATIM
-        */
-       rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
-
-       qid = QID_AC_VO;
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_init(rt2x00dev, queue, qid++);
-
-       rt2x00queue_init(rt2x00dev, rt2x00dev->bcn, QID_BEACON);
-       if (req_atim)
-               rt2x00queue_init(rt2x00dev, rt2x00dev->atim, QID_ATIM);
-
-       return 0;
-}
-
-void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
-{
-       kfree(rt2x00dev->rx);
-       rt2x00dev->rx = NULL;
-       rt2x00dev->tx = NULL;
-       rt2x00dev->bcn = NULL;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
deleted file mode 100644 (file)
index 2233b91..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00
-       Abstract: rt2x00 queue datastructures and routines
- */
-
-#ifndef RT2X00QUEUE_H
-#define RT2X00QUEUE_H
-
-#include <linux/prefetch.h>
-
-/**
- * DOC: Entry frame size
- *
- * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
- * for USB devices this restriction does not apply, but the value of
- * 2432 makes sense since it is big enough to contain the maximum fragment
- * size according to the ieee802.11 specs.
- * The aggregation size depends on support from the driver, but should
- * be something around 3840 bytes.
- */
-#define DATA_FRAME_SIZE                2432
-#define MGMT_FRAME_SIZE                256
-#define AGGREGATION_SIZE       3840
-
-/**
- * enum data_queue_qid: Queue identification
- *
- * @QID_AC_VO: AC VO queue
- * @QID_AC_VI: AC VI queue
- * @QID_AC_BE: AC BE queue
- * @QID_AC_BK: AC BK queue
- * @QID_HCCA: HCCA queue
- * @QID_MGMT: MGMT queue (prio queue)
- * @QID_RX: RX queue
- * @QID_OTHER: None of the above (don't use, only present for completeness)
- * @QID_BEACON: Beacon queue (value unspecified, don't send it to device)
- * @QID_ATIM: Atim queue (value unspecified, don't send it to device)
- */
-enum data_queue_qid {
-       QID_AC_VO = 0,
-       QID_AC_VI = 1,
-       QID_AC_BE = 2,
-       QID_AC_BK = 3,
-       QID_HCCA = 4,
-       QID_MGMT = 13,
-       QID_RX = 14,
-       QID_OTHER = 15,
-       QID_BEACON,
-       QID_ATIM,
-};
-
-/**
- * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
- *
- * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX
- * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX
- * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by
- *     mac80211 but was stripped for processing by the driver.
- * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211,
- *     don't try to pass it back.
- * @SKBDESC_DESC_IN_SKB: The descriptor is at the start of the
- *     skb, instead of in the desc field.
- */
-enum skb_frame_desc_flags {
-       SKBDESC_DMA_MAPPED_RX = 1 << 0,
-       SKBDESC_DMA_MAPPED_TX = 1 << 1,
-       SKBDESC_IV_STRIPPED = 1 << 2,
-       SKBDESC_NOT_MAC80211 = 1 << 3,
-       SKBDESC_DESC_IN_SKB = 1 << 4,
-};
-
-/**
- * struct skb_frame_desc: Descriptor information for the skb buffer
- *
- * This structure is placed over the driver_data array, this means that
- * this structure should not exceed the size of that array (40 bytes).
- *
- * @flags: Frame flags, see &enum skb_frame_desc_flags.
- * @desc_len: Length of the frame descriptor.
- * @tx_rate_idx: the index of the TX rate, used for TX status reporting
- * @tx_rate_flags: the TX rate flags, used for TX status reporting
- * @desc: Pointer to descriptor part of the frame.
- *     Note that this pointer could point to something outside
- *     of the scope of the skb->data pointer.
- * @iv: IV/EIV data used during encryption/decryption.
- * @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
- * @entry: The entry to which this sk buffer belongs.
- */
-struct skb_frame_desc {
-       u8 flags;
-
-       u8 desc_len;
-       u8 tx_rate_idx;
-       u8 tx_rate_flags;
-
-       void *desc;
-
-       __le32 iv[2];
-
-       dma_addr_t skb_dma;
-
-       struct queue_entry *entry;
-};
-
-/**
- * get_skb_frame_desc - Obtain the rt2x00 frame descriptor from a sk_buff.
- * @skb: &struct sk_buff from where we obtain the &struct skb_frame_desc
- */
-static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
-{
-       BUILD_BUG_ON(sizeof(struct skb_frame_desc) >
-                    IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
-       return (struct skb_frame_desc *)&IEEE80211_SKB_CB(skb)->driver_data;
-}
-
-/**
- * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
- *
- * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
- * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
- * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value.
- * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
- * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
- * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
- * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary.
- */
-enum rxdone_entry_desc_flags {
-       RXDONE_SIGNAL_PLCP = BIT(0),
-       RXDONE_SIGNAL_BITRATE = BIT(1),
-       RXDONE_SIGNAL_MCS = BIT(2),
-       RXDONE_MY_BSS = BIT(3),
-       RXDONE_CRYPTO_IV = BIT(4),
-       RXDONE_CRYPTO_ICV = BIT(5),
-       RXDONE_L2PAD = BIT(6),
-};
-
-/**
- * RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags
- * except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags
- * from &rxdone_entry_desc to a signal value type.
- */
-#define RXDONE_SIGNAL_MASK \
-       ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS )
-
-/**
- * struct rxdone_entry_desc: RX Entry descriptor
- *
- * Summary of information that has been read from the RX frame descriptor.
- *
- * @timestamp: RX Timestamp
- * @signal: Signal of the received frame.
- * @rssi: RSSI of the received frame.
- * @size: Data size of the received frame.
- * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
- * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
- * @rate_mode: Rate mode (See @enum rate_modulation).
- * @cipher: Cipher type used during decryption.
- * @cipher_status: Decryption status.
- * @iv: IV/EIV data used during decryption.
- * @icv: ICV data used during decryption.
- */
-struct rxdone_entry_desc {
-       u64 timestamp;
-       int signal;
-       int rssi;
-       int size;
-       int flags;
-       int dev_flags;
-       u16 rate_mode;
-       u8 cipher;
-       u8 cipher_status;
-
-       __le32 iv[2];
-       __le32 icv;
-};
-
-/**
- * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc
- *
- * Every txdone report has to contain the basic result of the
- * transmission, either &TXDONE_UNKNOWN, &TXDONE_SUCCESS or
- * &TXDONE_FAILURE. The flag &TXDONE_FALLBACK can be used in
- * conjunction with all of these flags but should only be set
- * if retires > 0. The flag &TXDONE_EXCESSIVE_RETRY can only be used
- * in conjunction with &TXDONE_FAILURE.
- *
- * @TXDONE_UNKNOWN: Hardware could not determine success of transmission.
- * @TXDONE_SUCCESS: Frame was successfully send
- * @TXDONE_FALLBACK: Hardware used fallback rates for retries
- * @TXDONE_FAILURE: Frame was not successfully send
- * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
- *     frame transmission failed due to excessive retries.
- */
-enum txdone_entry_desc_flags {
-       TXDONE_UNKNOWN,
-       TXDONE_SUCCESS,
-       TXDONE_FALLBACK,
-       TXDONE_FAILURE,
-       TXDONE_EXCESSIVE_RETRY,
-       TXDONE_AMPDU,
-};
-
-/**
- * struct txdone_entry_desc: TX done entry descriptor
- *
- * Summary of information that has been read from the TX frame descriptor
- * after the device is done with transmission.
- *
- * @flags: TX done flags (See &enum txdone_entry_desc_flags).
- * @retry: Retry count.
- */
-struct txdone_entry_desc {
-       unsigned long flags;
-       int retry;
-};
-
-/**
- * enum txentry_desc_flags: Status flags for TX entry descriptor
- *
- * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
- * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame.
- * @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter.
- * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame.
- * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
- * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
- * @ENTRY_TXD_BURST: This frame belongs to the same burst event.
- * @ENTRY_TXD_ACK: An ACK is required for this frame.
- * @ENTRY_TXD_RETRY_MODE: When set, the long retry count is used.
- * @ENTRY_TXD_ENCRYPT: This frame should be encrypted.
- * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared).
- * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware.
- * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware.
- * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU.
- * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth.
- * @ENTRY_TXD_HT_SHORT_GI: Use short GI.
- * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode.
- */
-enum txentry_desc_flags {
-       ENTRY_TXD_RTS_FRAME,
-       ENTRY_TXD_CTS_FRAME,
-       ENTRY_TXD_GENERATE_SEQ,
-       ENTRY_TXD_FIRST_FRAGMENT,
-       ENTRY_TXD_MORE_FRAG,
-       ENTRY_TXD_REQ_TIMESTAMP,
-       ENTRY_TXD_BURST,
-       ENTRY_TXD_ACK,
-       ENTRY_TXD_RETRY_MODE,
-       ENTRY_TXD_ENCRYPT,
-       ENTRY_TXD_ENCRYPT_PAIRWISE,
-       ENTRY_TXD_ENCRYPT_IV,
-       ENTRY_TXD_ENCRYPT_MMIC,
-       ENTRY_TXD_HT_AMPDU,
-       ENTRY_TXD_HT_BW_40,
-       ENTRY_TXD_HT_SHORT_GI,
-       ENTRY_TXD_HT_MIMO_PS,
-};
-
-/**
- * struct txentry_desc: TX Entry descriptor
- *
- * Summary of information for the frame descriptor before sending a TX frame.
- *
- * @flags: Descriptor flags (See &enum queue_entry_flags).
- * @length: Length of the entire frame.
- * @header_length: Length of 802.11 header.
- * @length_high: PLCP length high word.
- * @length_low: PLCP length low word.
- * @signal: PLCP signal.
- * @service: PLCP service.
- * @msc: MCS.
- * @stbc: Use Space Time Block Coding (only available for MCS rates < 8).
- * @ba_size: Size of the recepients RX reorder buffer - 1.
- * @rate_mode: Rate mode (See @enum rate_modulation).
- * @mpdu_density: MDPU density.
- * @retry_limit: Max number of retries.
- * @ifs: IFS value.
- * @txop: IFS value for 11n capable chips.
- * @cipher: Cipher type used for encryption.
- * @key_idx: Key index used for encryption.
- * @iv_offset: Position where IV should be inserted by hardware.
- * @iv_len: Length of IV data.
- */
-struct txentry_desc {
-       unsigned long flags;
-
-       u16 length;
-       u16 header_length;
-
-       union {
-               struct {
-                       u16 length_high;
-                       u16 length_low;
-                       u16 signal;
-                       u16 service;
-                       enum ifs ifs;
-               } plcp;
-
-               struct {
-                       u16 mcs;
-                       u8 stbc;
-                       u8 ba_size;
-                       u8 mpdu_density;
-                       enum txop txop;
-                       int wcid;
-               } ht;
-       } u;
-
-       enum rate_modulation rate_mode;
-
-       short retry_limit;
-
-       enum cipher cipher;
-       u16 key_idx;
-       u16 iv_offset;
-       u16 iv_len;
-};
-
-/**
- * enum queue_entry_flags: Status flags for queue entry
- *
- * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
- *     As long as this bit is set, this entry may only be touched
- *     through the interface structure.
- * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
- *     transfer (either TX or RX depending on the queue). The entry should
- *     only be touched after the device has signaled it is done with it.
- * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting
- *     for the signal to start sending.
- * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occurred
- *     while transferring the data to the hardware. No TX status report will
- *     be expected from the hardware.
- * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
- *     returned. It is now waiting for the status reporting before the
- *     entry can be reused again.
- */
-enum queue_entry_flags {
-       ENTRY_BCN_ASSIGNED,
-       ENTRY_BCN_ENABLED,
-       ENTRY_OWNER_DEVICE_DATA,
-       ENTRY_DATA_PENDING,
-       ENTRY_DATA_IO_FAILED,
-       ENTRY_DATA_STATUS_PENDING,
-       ENTRY_DATA_STATUS_SET,
-};
-
-/**
- * struct queue_entry: Entry inside the &struct data_queue
- *
- * @flags: Entry flags, see &enum queue_entry_flags.
- * @last_action: Timestamp of last change.
- * @queue: The data queue (&struct data_queue) to which this entry belongs.
- * @skb: The buffer which is currently being transmitted (for TX queue),
- *     or used to directly receive data in (for RX queue).
- * @entry_idx: The entry index number.
- * @priv_data: Private data belonging to this queue entry. The pointer
- *     points to data specific to a particular driver and queue type.
- * @status: Device specific status
- */
-struct queue_entry {
-       unsigned long flags;
-       unsigned long last_action;
-
-       struct data_queue *queue;
-
-       struct sk_buff *skb;
-
-       unsigned int entry_idx;
-
-       u32 status;
-
-       void *priv_data;
-};
-
-/**
- * enum queue_index: Queue index type
- *
- * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
- *     owned by the hardware then the queue is considered to be full.
- * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
- *     transferred to the hardware.
- * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
- *     the hardware and for which we need to run the txdone handler. If this
- *     entry is not owned by the hardware the queue is considered to be empty.
- * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
- *     of the index array.
- */
-enum queue_index {
-       Q_INDEX,
-       Q_INDEX_DMA_DONE,
-       Q_INDEX_DONE,
-       Q_INDEX_MAX,
-};
-
-/**
- * enum data_queue_flags: Status flags for data queues
- *
- * @QUEUE_STARTED: The queue has been started. Fox RX queues this means the
- *     device might be DMA'ing skbuffers. TX queues will accept skbuffers to
- *     be transmitted and beacon queues will start beaconing the configured
- *     beacons.
- * @QUEUE_PAUSED: The queue has been started but is currently paused.
- *     When this bit is set, the queue has been stopped in mac80211,
- *     preventing new frames to be enqueued. However, a few frames
- *     might still appear shortly after the pausing...
- */
-enum data_queue_flags {
-       QUEUE_STARTED,
-       QUEUE_PAUSED,
-};
-
-/**
- * struct data_queue: Data queue
- *
- * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
- * @entries: Base address of the &struct queue_entry which are
- *     part of this queue.
- * @qid: The queue identification, see &enum data_queue_qid.
- * @flags: Entry flags, see &enum queue_entry_flags.
- * @status_lock: The mutex for protecting the start/stop/flush
- *     handling on this queue.
- * @tx_lock: Spinlock to serialize tx operations on this queue.
- * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
- *     @index_crypt needs to be changed this lock should be grabbed to prevent
- *     index corruption due to concurrency.
- * @count: Number of frames handled in the queue.
- * @limit: Maximum number of entries in the queue.
- * @threshold: Minimum number of free entries before queue is kicked by force.
- * @length: Number of frames in queue.
- * @index: Index pointers to entry positions in the queue,
- *     use &enum queue_index to get a specific index field.
- * @txop: maximum burst time.
- * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
- * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
- * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
- * @data_size: Maximum data size for the frames in this queue.
- * @desc_size: Hardware descriptor size for the data in this queue.
- * @priv_size: Size of per-queue_entry private data.
- * @usb_endpoint: Device endpoint used for communication (USB only)
- * @usb_maxpacket: Max packet size for given endpoint (USB only)
- */
-struct data_queue {
-       struct rt2x00_dev *rt2x00dev;
-       struct queue_entry *entries;
-
-       enum data_queue_qid qid;
-       unsigned long flags;
-
-       struct mutex status_lock;
-       spinlock_t tx_lock;
-       spinlock_t index_lock;
-
-       unsigned int count;
-       unsigned short limit;
-       unsigned short threshold;
-       unsigned short length;
-       unsigned short index[Q_INDEX_MAX];
-
-       unsigned short txop;
-       unsigned short aifs;
-       unsigned short cw_min;
-       unsigned short cw_max;
-
-       unsigned short data_size;
-       unsigned char  desc_size;
-       unsigned char  winfo_size;
-       unsigned short priv_size;
-
-       unsigned short usb_endpoint;
-       unsigned short usb_maxpacket;
-};
-
-/**
- * queue_end - Return pointer to the last queue (HELPER MACRO).
- * @__dev: Pointer to &struct rt2x00_dev
- *
- * Using the base rx pointer and the maximum number of available queues,
- * this macro will return the address of 1 position beyond  the end of the
- * queues array.
- */
-#define queue_end(__dev) \
-       &(__dev)->rx[(__dev)->data_queues]
-
-/**
- * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
- * @__dev: Pointer to &struct rt2x00_dev
- *
- * Using the base tx pointer and the maximum number of available TX
- * queues, this macro will return the address of 1 position beyond
- * the end of the TX queue array.
- */
-#define tx_queue_end(__dev) \
-       &(__dev)->tx[(__dev)->ops->tx_queues]
-
-/**
- * queue_next - Return pointer to next queue in list (HELPER MACRO).
- * @__queue: Current queue for which we need the next queue
- *
- * Using the current queue address we take the address directly
- * after the queue to take the next queue. Note that this macro
- * should be used carefully since it does not protect against
- * moving past the end of the list. (See macros &queue_end and
- * &tx_queue_end for determining the end of the queue).
- */
-#define queue_next(__queue) \
-       &(__queue)[1]
-
-/**
- * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
- * @__entry: Pointer where the current queue entry will be stored in.
- * @__start: Start queue pointer.
- * @__end: End queue pointer.
- *
- * This macro will loop through all queues between &__start and &__end.
- */
-#define queue_loop(__entry, __start, __end)                    \
-       for ((__entry) = (__start);                             \
-            prefetch(queue_next(__entry)), (__entry) != (__end);\
-            (__entry) = queue_next(__entry))
-
-/**
- * queue_for_each - Loop through all queues
- * @__dev: Pointer to &struct rt2x00_dev
- * @__entry: Pointer where the current queue entry will be stored in.
- *
- * This macro will loop through all available queues.
- */
-#define queue_for_each(__dev, __entry) \
-       queue_loop(__entry, (__dev)->rx, queue_end(__dev))
-
-/**
- * tx_queue_for_each - Loop through the TX queues
- * @__dev: Pointer to &struct rt2x00_dev
- * @__entry: Pointer where the current queue entry will be stored in.
- *
- * This macro will loop through all TX related queues excluding
- * the Beacon and Atim queues.
- */
-#define tx_queue_for_each(__dev, __entry) \
-       queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
-
-/**
- * txall_queue_for_each - Loop through all TX related queues
- * @__dev: Pointer to &struct rt2x00_dev
- * @__entry: Pointer where the current queue entry will be stored in.
- *
- * This macro will loop through all TX related queues including
- * the Beacon and Atim queues.
- */
-#define txall_queue_for_each(__dev, __entry) \
-       queue_loop(__entry, (__dev)->tx, queue_end(__dev))
-
-/**
- * rt2x00queue_for_each_entry - Loop through all entries in the queue
- * @queue: Pointer to @data_queue
- * @start: &enum queue_index Pointer to start index
- * @end: &enum queue_index Pointer to end index
- * @data: Data to pass to the callback function
- * @fn: The function to call for each &struct queue_entry
- *
- * This will walk through all entries in the queue, in chronological
- * order. This means it will start at the current @start pointer
- * and will walk through the queue until it reaches the @end pointer.
- *
- * If fn returns true for an entry rt2x00queue_for_each_entry will stop
- * processing and return true as well.
- */
-bool rt2x00queue_for_each_entry(struct data_queue *queue,
-                               enum queue_index start,
-                               enum queue_index end,
-                               void *data,
-                               bool (*fn)(struct queue_entry *entry,
-                                          void *data));
-
-/**
- * rt2x00queue_empty - Check if the queue is empty.
- * @queue: Queue to check if empty.
- */
-static inline int rt2x00queue_empty(struct data_queue *queue)
-{
-       return queue->length == 0;
-}
-
-/**
- * rt2x00queue_full - Check if the queue is full.
- * @queue: Queue to check if full.
- */
-static inline int rt2x00queue_full(struct data_queue *queue)
-{
-       return queue->length == queue->limit;
-}
-
-/**
- * rt2x00queue_free - Check the number of available entries in queue.
- * @queue: Queue to check.
- */
-static inline int rt2x00queue_available(struct data_queue *queue)
-{
-       return queue->limit - queue->length;
-}
-
-/**
- * rt2x00queue_threshold - Check if the queue is below threshold
- * @queue: Queue to check.
- */
-static inline int rt2x00queue_threshold(struct data_queue *queue)
-{
-       return rt2x00queue_available(queue) < queue->threshold;
-}
-/**
- * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers
- * @entry: Queue entry to check.
- */
-static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
-{
-       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return false;
-       return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
-}
-
-/**
- * _rt2x00_desc_read - Read a word from the hardware descriptor.
- * @desc: Base descriptor address
- * @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
- */
-static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value)
-{
-       *value = desc[word];
-}
-
-/**
- * rt2x00_desc_read - Read a word from the hardware descriptor, this
- * function will take care of the byte ordering.
- * @desc: Base descriptor address
- * @word: Word index from where the descriptor should be read.
- * @value: Address where the descriptor value should be written into.
- */
-static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
-{
-       __le32 tmp;
-       _rt2x00_desc_read(desc, word, &tmp);
-       *value = le32_to_cpu(tmp);
-}
-
-/**
- * rt2x00_desc_write - write a word to the hardware descriptor, this
- * function will take care of the byte ordering.
- * @desc: Base descriptor address
- * @word: Word index from where the descriptor should be written.
- * @value: Value that should be written into the descriptor.
- */
-static inline void _rt2x00_desc_write(__le32 *desc, const u8 word, __le32 value)
-{
-       desc[word] = value;
-}
-
-/**
- * rt2x00_desc_write - write a word to the hardware descriptor.
- * @desc: Base descriptor address
- * @word: Word index from where the descriptor should be written.
- * @value: Value that should be written into the descriptor.
- */
-static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
-{
-       _rt2x00_desc_write(desc, word, cpu_to_le32(value));
-}
-
-#endif /* RT2X00QUEUE_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
deleted file mode 100644 (file)
index 3cc541d..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00
-       Abstract: rt2x00 generic register information.
- */
-
-#ifndef RT2X00REG_H
-#define RT2X00REG_H
-
-/*
- * RX crypto status
- */
-enum rx_crypto {
-       RX_CRYPTO_SUCCESS = 0,
-       RX_CRYPTO_FAIL_ICV = 1,
-       RX_CRYPTO_FAIL_MIC = 2,
-       RX_CRYPTO_FAIL_KEY = 3,
-};
-
-/*
- * Antenna values
- */
-enum antenna {
-       ANTENNA_SW_DIVERSITY = 0,
-       ANTENNA_A = 1,
-       ANTENNA_B = 2,
-       ANTENNA_HW_DIVERSITY = 3,
-};
-
-/*
- * Led mode values.
- */
-enum led_mode {
-       LED_MODE_DEFAULT = 0,
-       LED_MODE_TXRX_ACTIVITY = 1,
-       LED_MODE_SIGNAL_STRENGTH = 2,
-       LED_MODE_ASUS = 3,
-       LED_MODE_ALPHA = 4,
-};
-
-/*
- * TSF sync values
- */
-enum tsf_sync {
-       TSF_SYNC_NONE = 0,
-       TSF_SYNC_INFRA = 1,
-       TSF_SYNC_ADHOC = 2,
-       TSF_SYNC_AP_NONE = 3,
-};
-
-/*
- * Device states
- */
-enum dev_state {
-       STATE_DEEP_SLEEP = 0,
-       STATE_SLEEP = 1,
-       STATE_STANDBY = 2,
-       STATE_AWAKE = 3,
-
-/*
- * Additional device states, these values are
- * not strict since they are not directly passed
- * into the device.
- */
-       STATE_RADIO_ON,
-       STATE_RADIO_OFF,
-       STATE_RADIO_IRQ_ON,
-       STATE_RADIO_IRQ_OFF,
-};
-
-/*
- * IFS backoff values
- */
-enum ifs {
-       IFS_BACKOFF = 0,
-       IFS_SIFS = 1,
-       IFS_NEW_BACKOFF = 2,
-       IFS_NONE = 3,
-};
-
-/*
- * IFS backoff values for HT devices
- */
-enum txop {
-       TXOP_HTTXOP = 0,
-       TXOP_PIFS = 1,
-       TXOP_SIFS = 2,
-       TXOP_BACKOFF = 3,
-};
-
-/*
- * Cipher types for hardware encryption
- */
-enum cipher {
-       CIPHER_NONE = 0,
-       CIPHER_WEP64 = 1,
-       CIPHER_WEP128 = 2,
-       CIPHER_TKIP = 3,
-       CIPHER_AES = 4,
-/*
- * The following fields were added by rt61pci and rt73usb.
- */
-       CIPHER_CKIP64 = 5,
-       CIPHER_CKIP128 = 6,
-       CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
-
-/*
- * Max cipher type.
- * Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
- * are excluded due to limitations in mac80211.
- */
-       CIPHER_MAX = 4,
-};
-
-/*
- * Rate modulations
- */
-enum rate_modulation {
-       RATE_MODE_CCK = 0,
-       RATE_MODE_OFDM = 1,
-       RATE_MODE_HT_MIX = 2,
-       RATE_MODE_HT_GREENFIELD = 3,
-};
-
-/*
- * Firmware validation error codes
- */
-enum firmware_errors {
-       FW_OK,
-       FW_BAD_CRC,
-       FW_BAD_LENGTH,
-       FW_BAD_VERSION,
-};
-
-/*
- * Register handlers.
- * We store the position of a register field inside a field structure,
- * This will simplify the process of setting and reading a certain field
- * inside the register while making sure the process remains byte order safe.
- */
-struct rt2x00_field8 {
-       u8 bit_offset;
-       u8 bit_mask;
-};
-
-struct rt2x00_field16 {
-       u16 bit_offset;
-       u16 bit_mask;
-};
-
-struct rt2x00_field32 {
-       u32 bit_offset;
-       u32 bit_mask;
-};
-
-/*
- * Power of two check, this will check
- * if the mask that has been given contains and contiguous set of bits.
- * Note that we cannot use the is_power_of_2() function since this
- * check must be done at compile-time.
- */
-#define is_power_of_two(x)     ( !((x) & ((x)-1)) )
-#define low_bit_mask(x)                ( ((x)-1) & ~(x) )
-#define is_valid_mask(x)       is_power_of_two(1LU + (x) + low_bit_mask(x))
-
-/*
- * Macros to find first set bit in a variable.
- * These macros behave the same as the __ffs() functions but
- * the most important difference that this is done during
- * compile-time rather then run-time.
- */
-#define compile_ffs2(__x) \
-       __builtin_choose_expr(((__x) & 0x1), 0, 1)
-
-#define compile_ffs4(__x) \
-       __builtin_choose_expr(((__x) & 0x3), \
-                             (compile_ffs2((__x))), \
-                             (compile_ffs2((__x) >> 2) + 2))
-
-#define compile_ffs8(__x) \
-       __builtin_choose_expr(((__x) & 0xf), \
-                             (compile_ffs4((__x))), \
-                             (compile_ffs4((__x) >> 4) + 4))
-
-#define compile_ffs16(__x) \
-       __builtin_choose_expr(((__x) & 0xff), \
-                             (compile_ffs8((__x))), \
-                             (compile_ffs8((__x) >> 8) + 8))
-
-#define compile_ffs32(__x) \
-       __builtin_choose_expr(((__x) & 0xffff), \
-                             (compile_ffs16((__x))), \
-                             (compile_ffs16((__x) >> 16) + 16))
-
-/*
- * This macro will check the requirements for the FIELD{8,16,32} macros
- * The mask should be a constant non-zero contiguous set of bits which
- * does not exceed the given typelimit.
- */
-#define FIELD_CHECK(__mask, __type)                    \
-       BUILD_BUG_ON(!(__mask) ||                       \
-                    !is_valid_mask(__mask) ||          \
-                    (__mask) != (__type)(__mask))      \
-
-#define FIELD8(__mask)                         \
-({                                             \
-       FIELD_CHECK(__mask, u8);                \
-       (struct rt2x00_field8) {                \
-               compile_ffs8(__mask), (__mask)  \
-       };                                      \
-})
-
-#define FIELD16(__mask)                                \
-({                                             \
-       FIELD_CHECK(__mask, u16);               \
-       (struct rt2x00_field16) {               \
-               compile_ffs16(__mask), (__mask) \
-       };                                      \
-})
-
-#define FIELD32(__mask)                                \
-({                                             \
-       FIELD_CHECK(__mask, u32);               \
-       (struct rt2x00_field32) {               \
-               compile_ffs32(__mask), (__mask) \
-       };                                      \
-})
-
-#define SET_FIELD(__reg, __type, __field, __value)\
-({                                             \
-       typecheck(__type, __field);             \
-       *(__reg) &= ~((__field).bit_mask);      \
-       *(__reg) |= ((__value) <<               \
-           ((__field).bit_offset)) &           \
-           ((__field).bit_mask);               \
-})
-
-#define GET_FIELD(__reg, __type, __field)      \
-({                                             \
-       typecheck(__type, __field);             \
-       ((__reg) & ((__field).bit_mask)) >>     \
-           ((__field).bit_offset);             \
-})
-
-#define rt2x00_set_field32(__reg, __field, __value) \
-       SET_FIELD(__reg, struct rt2x00_field32, __field, __value)
-#define rt2x00_get_field32(__reg, __field) \
-       GET_FIELD(__reg, struct rt2x00_field32, __field)
-
-#define rt2x00_set_field16(__reg, __field, __value) \
-       SET_FIELD(__reg, struct rt2x00_field16, __field, __value)
-#define rt2x00_get_field16(__reg, __field) \
-       GET_FIELD(__reg, struct rt2x00_field16, __field)
-
-#define rt2x00_set_field8(__reg, __field, __value) \
-       SET_FIELD(__reg, struct rt2x00_field8, __field, __value)
-#define rt2x00_get_field8(__reg, __field) \
-       GET_FIELD(__reg, struct rt2x00_field8, __field)
-
-#endif /* RT2X00REG_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c
deleted file mode 100644 (file)
index 69a0cda..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       Copyright (C) 2004 - 2009 Felix Fietkau <nbd@openwrt.org>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00soc
-       Abstract: rt2x00 generic soc device routines.
- */
-
-#include <linux/bug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "rt2x00.h"
-#include "rt2x00soc.h"
-
-static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev)
-{
-       kfree(rt2x00dev->rf);
-       rt2x00dev->rf = NULL;
-
-       kfree(rt2x00dev->eeprom);
-       rt2x00dev->eeprom = NULL;
-
-       iounmap(rt2x00dev->csr.base);
-}
-
-static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
-{
-       struct platform_device *pdev = to_platform_device(rt2x00dev->dev);
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-
-       rt2x00dev->csr.base = ioremap(res->start, resource_size(res));
-       if (!rt2x00dev->csr.base)
-               return -ENOMEM;
-
-       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
-       if (!rt2x00dev->eeprom)
-               goto exit;
-
-       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
-       if (!rt2x00dev->rf)
-               goto exit;
-
-       return 0;
-
-exit:
-       rt2x00_probe_err("Failed to allocate registers\n");
-       rt2x00soc_free_reg(rt2x00dev);
-
-       return -ENOMEM;
-}
-
-int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
-{
-       struct ieee80211_hw *hw;
-       struct rt2x00_dev *rt2x00dev;
-       int retval;
-
-       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
-       if (!hw) {
-               rt2x00_probe_err("Failed to allocate hardware\n");
-               return -ENOMEM;
-       }
-
-       platform_set_drvdata(pdev, hw);
-
-       rt2x00dev = hw->priv;
-       rt2x00dev->dev = &pdev->dev;
-       rt2x00dev->ops = ops;
-       rt2x00dev->hw = hw;
-       rt2x00dev->irq = platform_get_irq(pdev, 0);
-       rt2x00dev->name = pdev->dev.driver->name;
-
-       rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
-
-       retval = rt2x00soc_alloc_reg(rt2x00dev);
-       if (retval)
-               goto exit_free_device;
-
-       retval = rt2x00lib_probe_dev(rt2x00dev);
-       if (retval)
-               goto exit_free_reg;
-
-       return 0;
-
-exit_free_reg:
-       rt2x00soc_free_reg(rt2x00dev);
-
-exit_free_device:
-       ieee80211_free_hw(hw);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rt2x00soc_probe);
-
-int rt2x00soc_remove(struct platform_device *pdev)
-{
-       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * Free all allocated data.
-        */
-       rt2x00lib_remove_dev(rt2x00dev);
-       rt2x00soc_free_reg(rt2x00dev);
-       ieee80211_free_hw(hw);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00soc_remove);
-
-#ifdef CONFIG_PM
-int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       return rt2x00lib_suspend(rt2x00dev, state);
-}
-EXPORT_SYMBOL_GPL(rt2x00soc_suspend);
-
-int rt2x00soc_resume(struct platform_device *pdev)
-{
-       struct ieee80211_hw *hw = platform_get_drvdata(pdev);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       return rt2x00lib_resume(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00soc_resume);
-#endif /* CONFIG_PM */
-
-/*
- * rt2x00soc module information.
- */
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2x00 soc library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h
deleted file mode 100644 (file)
index 9948d35..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00soc
-       Abstract: Data structures for the rt2x00soc module.
- */
-
-#ifndef RT2X00SOC_H
-#define RT2X00SOC_H
-
-/*
- * SoC driver handlers.
- */
-int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops);
-int rt2x00soc_remove(struct platform_device *pdev);
-#ifdef CONFIG_PM
-int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state);
-int rt2x00soc_resume(struct platform_device *pdev);
-#else
-#define rt2x00soc_suspend      NULL
-#define rt2x00soc_resume       NULL
-#endif /* CONFIG_PM */
-
-#endif /* RT2X00SOC_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
deleted file mode 100644 (file)
index 7627af6..0000000
+++ /dev/null
@@ -1,884 +0,0 @@
-/*
-       Copyright (C) 2010 Willow Garage <http://www.willowgarage.com>
-       Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00usb
-       Abstract: rt2x00 generic usb device routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/bug.h>
-
-#include "rt2x00.h"
-#include "rt2x00usb.h"
-
-/*
- * Interfacing with the HW.
- */
-int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
-                            const u8 request, const u8 requesttype,
-                            const u16 offset, const u16 value,
-                            void *buffer, const u16 buffer_length,
-                            const int timeout)
-{
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       int status;
-       unsigned int pipe =
-           (requesttype == USB_VENDOR_REQUEST_IN) ?
-           usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
-       unsigned long expire = jiffies + msecs_to_jiffies(timeout);
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return -ENODEV;
-
-       do {
-               status = usb_control_msg(usb_dev, pipe, request, requesttype,
-                                        value, offset, buffer, buffer_length,
-                                        timeout / 2);
-               if (status >= 0)
-                       return 0;
-
-               if (status == -ENODEV) {
-                       /* Device has disappeared. */
-                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-                       break;
-               }
-       } while (time_before(jiffies, expire));
-
-       rt2x00_err(rt2x00dev,
-                  "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
-                  request, offset, status);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
-
-int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
-                                  const u8 request, const u8 requesttype,
-                                  const u16 offset, void *buffer,
-                                  const u16 buffer_length, const int timeout)
-{
-       int status;
-
-       BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex));
-
-       /*
-        * Check for Cache availability.
-        */
-       if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
-               rt2x00_err(rt2x00dev, "CSR cache not available\n");
-               return -ENOMEM;
-       }
-
-       if (requesttype == USB_VENDOR_REQUEST_OUT)
-               memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
-
-       status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
-                                         offset, 0, rt2x00dev->csr.cache,
-                                         buffer_length, timeout);
-
-       if (!status && requesttype == USB_VENDOR_REQUEST_IN)
-               memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
-
-int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
-                                 const u8 request, const u8 requesttype,
-                                 const u16 offset, void *buffer,
-                                 const u16 buffer_length)
-{
-       int status = 0;
-       unsigned char *tb;
-       u16 off, len, bsize;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       tb  = (char *)buffer;
-       off = offset;
-       len = buffer_length;
-       while (len && !status) {
-               bsize = min_t(u16, CSR_CACHE_SIZE, len);
-               status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
-                                                       requesttype, off, tb,
-                                                       bsize, REGISTER_TIMEOUT);
-
-               tb  += bsize;
-               len -= bsize;
-               off += bsize;
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
-
-int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                          const unsigned int offset,
-                          const struct rt2x00_field32 field,
-                          u32 *reg)
-{
-       unsigned int i;
-
-       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-               return -ENODEV;
-
-       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
-               if (!rt2x00_get_field32(*reg, field))
-                       return 1;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
-                  offset, *reg);
-       *reg = ~0;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
-
-
-struct rt2x00_async_read_data {
-       __le32 reg;
-       struct usb_ctrlrequest cr;
-       struct rt2x00_dev *rt2x00dev;
-       bool (*callback)(struct rt2x00_dev *, int, u32);
-};
-
-static void rt2x00usb_register_read_async_cb(struct urb *urb)
-{
-       struct rt2x00_async_read_data *rd = urb->context;
-       if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) {
-               if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
-                       kfree(rd);
-       } else
-               kfree(rd);
-}
-
-void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int offset,
-                                  bool (*callback)(struct rt2x00_dev*, int, u32))
-{
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct urb *urb;
-       struct rt2x00_async_read_data *rd;
-
-       rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
-       if (!rd)
-               return;
-
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               kfree(rd);
-               return;
-       }
-
-       rd->rt2x00dev = rt2x00dev;
-       rd->callback = callback;
-       rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
-       rd->cr.bRequest = USB_MULTI_READ;
-       rd->cr.wValue = 0;
-       rd->cr.wIndex = cpu_to_le16(offset);
-       rd->cr.wLength = cpu_to_le16(sizeof(u32));
-
-       usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-                            (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
-                            rt2x00usb_register_read_async_cb, rd);
-       if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
-               kfree(rd);
-       usb_free_urb(urb);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
-
-/*
- * TX data handlers.
- */
-static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)
-{
-       /*
-        * If the transfer to hardware succeeded, it does not mean the
-        * frame was send out correctly. It only means the frame
-        * was successfully pushed to the hardware, we have no
-        * way to determine the transmission status right now.
-        * (Only indirectly by looking at the failed TX counters
-        * in the register).
-        */
-       if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
-               rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
-       else
-               rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
-}
-
-static void rt2x00usb_work_txdone(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, txdone_work);
-       struct data_queue *queue;
-       struct queue_entry *entry;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               while (!rt2x00queue_empty(queue)) {
-                       entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-                               break;
-
-                       rt2x00usb_work_txdone_entry(entry);
-               }
-       }
-}
-
-static void rt2x00usb_interrupt_txdone(struct urb *urb)
-{
-       struct queue_entry *entry = (struct queue_entry *)urb->context;
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-
-       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return;
-       /*
-        * Check if the frame was correctly uploaded
-        */
-       if (urb->status)
-               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
-       /*
-        * Report the frame as DMA done
-        */
-       rt2x00lib_dmadone(entry);
-
-       if (rt2x00dev->ops->lib->tx_dma_done)
-               rt2x00dev->ops->lib->tx_dma_done(entry);
-       /*
-        * Schedule the delayed work for reading the TX status
-        * from the device.
-        */
-       if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TXSTATUS_FIFO) ||
-           !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-}
-
-static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
-       u32 length;
-       int status;
-
-       if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
-           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-               return false;
-
-       /*
-        * USB devices require certain padding at the end of each frame
-        * and urb. Those paddings are not included in skbs. Pass entry
-        * to the driver to determine what the overall length should be.
-        */
-       length = rt2x00dev->ops->lib->get_tx_data_len(entry);
-
-       status = skb_padto(entry->skb, length);
-       if (unlikely(status)) {
-               /* TODO: report something more appropriate than IO_FAILED. */
-               rt2x00_warn(rt2x00dev, "TX SKB padding error, out of memory\n");
-               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
-               rt2x00lib_dmadone(entry);
-
-               return false;
-       }
-
-       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-                         usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
-                         entry->skb->data, length,
-                         rt2x00usb_interrupt_txdone, entry);
-
-       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
-       if (status) {
-               if (status == -ENODEV)
-                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
-               rt2x00lib_dmadone(entry);
-       }
-
-       return false;
-}
-
-/*
- * RX data handlers.
- */
-static void rt2x00usb_work_rxdone(struct work_struct *work)
-{
-       struct rt2x00_dev *rt2x00dev =
-           container_of(work, struct rt2x00_dev, rxdone_work);
-       struct queue_entry *entry;
-       struct skb_frame_desc *skbdesc;
-       u8 rxd[32];
-
-       while (!rt2x00queue_empty(rt2x00dev->rx)) {
-               entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
-
-               if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-                   !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-                       break;
-
-               /*
-                * Fill in desc fields of the skb descriptor
-                */
-               skbdesc = get_skb_frame_desc(entry->skb);
-               skbdesc->desc = rxd;
-               skbdesc->desc_len = entry->queue->desc_size;
-
-               /*
-                * Send the frame to rt2x00lib for further processing.
-                */
-               rt2x00lib_rxdone(entry, GFP_KERNEL);
-       }
-}
-
-static void rt2x00usb_interrupt_rxdone(struct urb *urb)
-{
-       struct queue_entry *entry = (struct queue_entry *)urb->context;
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-
-       if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return;
-
-       /*
-        * Report the frame as DMA done
-        */
-       rt2x00lib_dmadone(entry);
-
-       /*
-        * Check if the received data is simply too small
-        * to be actually valid, or if the urb is signaling
-        * a problem.
-        */
-       if (urb->actual_length < entry->queue->desc_size || urb->status)
-               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
-
-       /*
-        * Schedule the delayed work for reading the RX status
-        * from the device.
-        */
-       queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
-}
-
-static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
-       int status;
-
-       if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-               return false;
-
-       rt2x00lib_dmastart(entry);
-
-       usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-                         usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint),
-                         entry->skb->data, entry->skb->len,
-                         rt2x00usb_interrupt_rxdone, entry);
-
-       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
-       if (status) {
-               if (status == -ENODEV)
-                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
-               rt2x00lib_dmadone(entry);
-       }
-
-       return false;
-}
-
-void rt2x00usb_kick_queue(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               if (!rt2x00queue_empty(queue))
-                       rt2x00queue_for_each_entry(queue,
-                                                  Q_INDEX_DONE,
-                                                  Q_INDEX,
-                                                  NULL,
-                                                  rt2x00usb_kick_tx_entry);
-               break;
-       case QID_RX:
-               if (!rt2x00queue_full(queue))
-                       rt2x00queue_for_each_entry(queue,
-                                                  Q_INDEX,
-                                                  Q_INDEX_DONE,
-                                                  NULL,
-                                                  rt2x00usb_kick_rx_entry);
-               break;
-       default:
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
-
-static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct queue_entry_priv_usb *entry_priv = entry->priv_data;
-       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
-
-       if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-               return false;
-
-       usb_kill_urb(entry_priv->urb);
-
-       /*
-        * Kill guardian urb (if required by driver).
-        */
-       if ((entry->queue->qid == QID_BEACON) &&
-           (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD)))
-               usb_kill_urb(bcn_priv->guardian_urb);
-
-       return false;
-}
-
-void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
-{
-       struct work_struct *completion;
-       unsigned int i;
-
-       if (drop)
-               rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
-                                          rt2x00usb_flush_entry);
-
-       /*
-        * Obtain the queue completion handler
-        */
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               completion = &queue->rt2x00dev->txdone_work;
-               break;
-       case QID_RX:
-               completion = &queue->rt2x00dev->rxdone_work;
-               break;
-       default:
-               return;
-       }
-
-       for (i = 0; i < 10; i++) {
-               /*
-                * Check if the driver is already done, otherwise we
-                * have to sleep a little while to give the driver/hw
-                * the oppurtunity to complete interrupt process itself.
-                */
-               if (rt2x00queue_empty(queue))
-                       break;
-
-               /*
-                * Schedule the completion handler manually, when this
-                * worker function runs, it should cleanup the queue.
-                */
-               queue_work(queue->rt2x00dev->workqueue, completion);
-
-               /*
-                * Wait for a little while to give the driver
-                * the oppurtunity to recover itself.
-                */
-               msleep(10);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue);
-
-static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
-{
-       rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
-                   queue->qid);
-
-       rt2x00queue_stop_queue(queue);
-       rt2x00queue_flush_queue(queue, true);
-       rt2x00queue_start_queue(queue);
-}
-
-static int rt2x00usb_dma_timeout(struct data_queue *queue)
-{
-       struct queue_entry *entry;
-
-       entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
-       return rt2x00queue_dma_timeout(entry);
-}
-
-void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       tx_queue_for_each(rt2x00dev, queue) {
-               if (!rt2x00queue_empty(queue)) {
-                       if (rt2x00usb_dma_timeout(queue))
-                               rt2x00usb_watchdog_tx_dma(queue);
-               }
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
-
-/*
- * Radio handlers
- */
-void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0,
-                                   REGISTER_TIMEOUT);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
-
-/*
- * Device initialization handlers.
- */
-void rt2x00usb_clear_entry(struct queue_entry *entry)
-{
-       entry->flags = 0;
-
-       if (entry->queue->qid == QID_RX)
-               rt2x00usb_kick_rx_entry(entry, NULL);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
-
-static void rt2x00usb_assign_endpoint(struct data_queue *queue,
-                                     struct usb_endpoint_descriptor *ep_desc)
-{
-       struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev);
-       int pipe;
-
-       queue->usb_endpoint = usb_endpoint_num(ep_desc);
-
-       if (queue->qid == QID_RX) {
-               pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
-               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
-       } else {
-               pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
-               queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
-       }
-
-       if (!queue->usb_maxpacket)
-               queue->usb_maxpacket = 1;
-}
-
-static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
-{
-       struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
-       struct usb_host_interface *intf_desc = intf->cur_altsetting;
-       struct usb_endpoint_descriptor *ep_desc;
-       struct data_queue *queue = rt2x00dev->tx;
-       struct usb_endpoint_descriptor *tx_ep_desc = NULL;
-       unsigned int i;
-
-       /*
-        * Walk through all available endpoints to search for "bulk in"
-        * and "bulk out" endpoints. When we find such endpoints collect
-        * the information we need from the descriptor and assign it
-        * to the queue.
-        */
-       for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
-               ep_desc = &intf_desc->endpoint[i].desc;
-
-               if (usb_endpoint_is_bulk_in(ep_desc)) {
-                       rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
-               } else if (usb_endpoint_is_bulk_out(ep_desc) &&
-                          (queue != queue_end(rt2x00dev))) {
-                       rt2x00usb_assign_endpoint(queue, ep_desc);
-                       queue = queue_next(queue);
-
-                       tx_ep_desc = ep_desc;
-               }
-       }
-
-       /*
-        * At least 1 endpoint for RX and 1 endpoint for TX must be available.
-        */
-       if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
-               rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
-               return -EPIPE;
-       }
-
-       /*
-        * It might be possible not all queues have a dedicated endpoint.
-        * Loop through all TX queues and copy the endpoint information
-        * which we have gathered from already assigned endpoints.
-        */
-       txall_queue_for_each(rt2x00dev, queue) {
-               if (!queue->usb_endpoint)
-                       rt2x00usb_assign_endpoint(queue, tx_ep_desc);
-       }
-
-       return 0;
-}
-
-static int rt2x00usb_alloc_entries(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       struct queue_entry_priv_usb *entry_priv;
-       struct queue_entry_priv_usb_bcn *bcn_priv;
-       unsigned int i;
-
-       for (i = 0; i < queue->limit; i++) {
-               entry_priv = queue->entries[i].priv_data;
-               entry_priv->urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!entry_priv->urb)
-                       return -ENOMEM;
-       }
-
-       /*
-        * If this is not the beacon queue or
-        * no guardian byte was required for the beacon,
-        * then we are done.
-        */
-       if (queue->qid != QID_BEACON ||
-           !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD))
-               return 0;
-
-       for (i = 0; i < queue->limit; i++) {
-               bcn_priv = queue->entries[i].priv_data;
-               bcn_priv->guardian_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!bcn_priv->guardian_urb)
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static void rt2x00usb_free_entries(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       struct queue_entry_priv_usb *entry_priv;
-       struct queue_entry_priv_usb_bcn *bcn_priv;
-       unsigned int i;
-
-       if (!queue->entries)
-               return;
-
-       for (i = 0; i < queue->limit; i++) {
-               entry_priv = queue->entries[i].priv_data;
-               usb_kill_urb(entry_priv->urb);
-               usb_free_urb(entry_priv->urb);
-       }
-
-       /*
-        * If this is not the beacon queue or
-        * no guardian byte was required for the beacon,
-        * then we are done.
-        */
-       if (queue->qid != QID_BEACON ||
-           !rt2x00_has_cap_flag(rt2x00dev, REQUIRE_BEACON_GUARD))
-               return;
-
-       for (i = 0; i < queue->limit; i++) {
-               bcn_priv = queue->entries[i].priv_data;
-               usb_kill_urb(bcn_priv->guardian_urb);
-               usb_free_urb(bcn_priv->guardian_urb);
-       }
-}
-
-int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       int status;
-
-       /*
-        * Find endpoints for each queue
-        */
-       status = rt2x00usb_find_endpoints(rt2x00dev);
-       if (status)
-               goto exit;
-
-       /*
-        * Allocate DMA
-        */
-       queue_for_each(rt2x00dev, queue) {
-               status = rt2x00usb_alloc_entries(queue);
-               if (status)
-                       goto exit;
-       }
-
-       return 0;
-
-exit:
-       rt2x00usb_uninitialize(rt2x00dev);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
-
-void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-
-       queue_for_each(rt2x00dev, queue)
-               rt2x00usb_free_entries(queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
-
-/*
- * USB driver handlers.
- */
-static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
-{
-       kfree(rt2x00dev->rf);
-       rt2x00dev->rf = NULL;
-
-       kfree(rt2x00dev->eeprom);
-       rt2x00dev->eeprom = NULL;
-
-       kfree(rt2x00dev->csr.cache);
-       rt2x00dev->csr.cache = NULL;
-}
-
-static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
-{
-       rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
-       if (!rt2x00dev->csr.cache)
-               goto exit;
-
-       rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
-       if (!rt2x00dev->eeprom)
-               goto exit;
-
-       rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
-       if (!rt2x00dev->rf)
-               goto exit;
-
-       return 0;
-
-exit:
-       rt2x00_probe_err("Failed to allocate registers\n");
-
-       rt2x00usb_free_reg(rt2x00dev);
-
-       return -ENOMEM;
-}
-
-int rt2x00usb_probe(struct usb_interface *usb_intf,
-                   const struct rt2x00_ops *ops)
-{
-       struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
-       struct ieee80211_hw *hw;
-       struct rt2x00_dev *rt2x00dev;
-       int retval;
-
-       usb_dev = usb_get_dev(usb_dev);
-       usb_reset_device(usb_dev);
-
-       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
-       if (!hw) {
-               rt2x00_probe_err("Failed to allocate hardware\n");
-               retval = -ENOMEM;
-               goto exit_put_device;
-       }
-
-       usb_set_intfdata(usb_intf, hw);
-
-       rt2x00dev = hw->priv;
-       rt2x00dev->dev = &usb_intf->dev;
-       rt2x00dev->ops = ops;
-       rt2x00dev->hw = hw;
-
-       rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
-
-       INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
-       INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
-       hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
-                    HRTIMER_MODE_REL);
-
-       retval = rt2x00usb_alloc_reg(rt2x00dev);
-       if (retval)
-               goto exit_free_device;
-
-       retval = rt2x00lib_probe_dev(rt2x00dev);
-       if (retval)
-               goto exit_free_reg;
-
-       return 0;
-
-exit_free_reg:
-       rt2x00usb_free_reg(rt2x00dev);
-
-exit_free_device:
-       ieee80211_free_hw(hw);
-
-exit_put_device:
-       usb_put_dev(usb_dev);
-
-       usb_set_intfdata(usb_intf, NULL);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_probe);
-
-void rt2x00usb_disconnect(struct usb_interface *usb_intf)
-{
-       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       /*
-        * Free all allocated data.
-        */
-       rt2x00lib_remove_dev(rt2x00dev);
-       rt2x00usb_free_reg(rt2x00dev);
-       ieee80211_free_hw(hw);
-
-       /*
-        * Free the USB device data.
-        */
-       usb_set_intfdata(usb_intf, NULL);
-       usb_put_dev(interface_to_usbdev(usb_intf));
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_disconnect);
-
-#ifdef CONFIG_PM
-int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
-{
-       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       return rt2x00lib_suspend(rt2x00dev, state);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_suspend);
-
-int rt2x00usb_resume(struct usb_interface *usb_intf)
-{
-       struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       return rt2x00lib_resume(rt2x00dev);
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_resume);
-#endif /* CONFIG_PM */
-
-/*
- * rt2x00usb module information.
- */
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("rt2x00 usb library");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
deleted file mode 100644 (file)
index 569363d..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt2x00usb
-       Abstract: Data structures for the rt2x00usb module.
- */
-
-#ifndef RT2X00USB_H
-#define RT2X00USB_H
-
-#include <linux/usb.h>
-
-#define to_usb_device_intf(d) \
-({ \
-       struct usb_interface *intf = to_usb_interface(d); \
-       interface_to_usbdev(intf); \
-})
-
-/*
- * For USB vendor requests we need to pass a timeout time in ms, for this we
- * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM
- * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE
- * and EEPROM_TIMEOUT.
- */
-#define REGISTER_TIMEOUT               100
-#define REGISTER_TIMEOUT_FIRMWARE      1000
-#define EEPROM_TIMEOUT                 2000
-
-/*
- * Cache size
- */
-#define CSR_CACHE_SIZE                 64
-
-/*
- * USB request types.
- */
-#define USB_VENDOR_REQUEST     ( USB_TYPE_VENDOR | USB_RECIP_DEVICE )
-#define USB_VENDOR_REQUEST_IN  ( USB_DIR_IN | USB_VENDOR_REQUEST )
-#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
-
-/**
- * enum rt2x00usb_vendor_request: USB vendor commands.
- */
-enum rt2x00usb_vendor_request {
-       USB_DEVICE_MODE = 1,
-       USB_SINGLE_WRITE = 2,
-       USB_SINGLE_READ = 3,
-       USB_MULTI_WRITE = 6,
-       USB_MULTI_READ = 7,
-       USB_EEPROM_WRITE = 8,
-       USB_EEPROM_READ = 9,
-       USB_LED_CONTROL = 10, /* RT73USB */
-       USB_RX_CONTROL = 12,
-};
-
-/**
- * enum rt2x00usb_mode_offset: Device modes offset.
- */
-enum rt2x00usb_mode_offset {
-       USB_MODE_RESET = 1,
-       USB_MODE_UNPLUG = 2,
-       USB_MODE_FUNCTION = 3,
-       USB_MODE_TEST = 4,
-       USB_MODE_SLEEP = 7,     /* RT73USB */
-       USB_MODE_FIRMWARE = 8,  /* RT73USB */
-       USB_MODE_WAKEUP = 9,    /* RT73USB */
-       USB_MODE_AUTORUN = 17, /* RT2800USB */
-};
-
-/**
- * rt2x00usb_vendor_request - Send register command to device
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
- * @requesttype: Request type &USB_VENDOR_REQUEST_*
- * @offset: Register offset to perform action on
- * @value: Value to write to device
- * @buffer: Buffer where information will be read/written to by device
- * @buffer_length: Size of &buffer
- * @timeout: Operation timeout
- *
- * This is the main function to communicate with the device,
- * the &buffer argument _must_ either be NULL or point to
- * a buffer allocated by kmalloc. Failure to do so can lead
- * to unexpected behavior depending on the architecture.
- */
-int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
-                            const u8 request, const u8 requesttype,
-                            const u16 offset, const u16 value,
-                            void *buffer, const u16 buffer_length,
-                            const int timeout);
-
-/**
- * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
- * @requesttype: Request type &USB_VENDOR_REQUEST_*
- * @offset: Register offset to perform action on
- * @buffer: Buffer where information will be read/written to by device
- * @buffer_length: Size of &buffer
- *
- * This function will use a previously with kmalloc allocated cache
- * to communicate with the device. The contents of the buffer pointer
- * will be copied to this cache when writing, or read from the cache
- * when reading.
- * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
- * kmalloc. Hence the reason for using a previously allocated cache
- * which has been allocated properly.
- */
-int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
-                                 const u8 request, const u8 requesttype,
-                                 const u16 offset, void *buffer,
-                                 const u16 buffer_length);
-
-/**
- * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
- * @requesttype: Request type &USB_VENDOR_REQUEST_*
- * @offset: Register offset to perform action on
- * @buffer: Buffer where information will be read/written to by device
- * @buffer_length: Size of &buffer
- * @timeout: Operation timeout
- *
- * A version of &rt2x00usb_vendor_request_buff which must be called
- * if the usb_cache_mutex is already held.
- */
-int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
-                                  const u8 request, const u8 requesttype,
-                                  const u16 offset, void *buffer,
-                                  const u16 buffer_length, const int timeout);
-
-/**
- * rt2x00usb_vendor_request_sw - Send single register command to device
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
- * @offset: Register offset to perform action on
- * @value: Value to write to device
- * @timeout: Operation timeout
- *
- * Simple wrapper around rt2x00usb_vendor_request to write a single
- * command to the device. Since we don't use the buffer argument we
- * don't have to worry about kmalloc here.
- */
-static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
-                                             const u8 request,
-                                             const u16 offset,
-                                             const u16 value,
-                                             const int timeout)
-{
-       return rt2x00usb_vendor_request(rt2x00dev, request,
-                                       USB_VENDOR_REQUEST_OUT, offset,
-                                       value, NULL, 0, timeout);
-}
-
-/**
- * rt2x00usb_eeprom_read - Read eeprom from device
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- * @eeprom: Pointer to eeprom array to store the information in
- * @length: Number of bytes to read from the eeprom
- *
- * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
- * from the device. Note that the eeprom argument _must_ be allocated using
- * kmalloc for correct handling inside the kernel USB layer.
- */
-static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
-                                       __le16 *eeprom, const u16 length)
-{
-       return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
-                                       USB_VENDOR_REQUEST_IN, 0, 0,
-                                       eeprom, length, EEPROM_TIMEOUT);
-}
-
-/**
- * rt2x00usb_register_read - Read 32bit register word
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Pointer to where register contents should be stored
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_request_buff().
- */
-static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                          const unsigned int offset,
-                                          u32 *value)
-{
-       __le32 reg = 0;
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     &reg, sizeof(reg));
-       *value = le32_to_cpu(reg);
-}
-
-/**
- * rt2x00usb_register_read_lock - Read 32bit register word
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Pointer to where register contents should be stored
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_req_buff_lock().
- */
-static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               u32 *value)
-{
-       __le32 reg = 0;
-       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
-                                      USB_VENDOR_REQUEST_IN, offset,
-                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
-       *value = le32_to_cpu(reg);
-}
-
-/**
- * rt2x00usb_register_multiread - Read 32bit register words
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Pointer to where register contents should be stored
- * @length: Length of the data
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_request_buff().
- */
-static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                               const unsigned int offset,
-                                               void *value, const u32 length)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     value, length);
-}
-
-/**
- * rt2x00usb_register_write - Write 32bit register word
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Data which should be written
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_request_buff().
- */
-static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
-                                           const unsigned int offset,
-                                           u32 value)
-{
-       __le32 reg = cpu_to_le32(value);
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     &reg, sizeof(reg));
-}
-
-/**
- * rt2x00usb_register_write_lock - Write 32bit register word
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Data which should be written
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_req_buff_lock().
- */
-static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                u32 value)
-{
-       __le32 reg = cpu_to_le32(value);
-       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
-                                      USB_VENDOR_REQUEST_OUT, offset,
-                                      &reg, sizeof(reg), REGISTER_TIMEOUT);
-}
-
-/**
- * rt2x00usb_register_multiwrite - Write 32bit register words
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @value: Data which should be written
- * @length: Length of the data
- *
- * This function is a simple wrapper for 32bit register access
- * through rt2x00usb_vendor_request_buff().
- */
-static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                                const unsigned int offset,
-                                                const void *value,
-                                                const u32 length)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     (void *)value, length);
-}
-
-/**
- * rt2x00usb_regbusy_read - Read from register with busy check
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @field: Field to check if register is busy
- * @reg: Pointer to where register contents should be stored
- *
- * This function will read the given register, and checks if the
- * register is busy. If it is, it will sleep for a couple of
- * microseconds before reading the register again. If the register
- * is not read after a certain timeout, this function will return
- * FALSE.
- */
-int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
-                          const unsigned int offset,
-                          const struct rt2x00_field32 field,
-                          u32 *reg);
-
-/**
- * rt2x00usb_register_read_async - Asynchronously read 32bit register word
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @callback: Functon to call when read completes.
- *
- * Submit a control URB to read a 32bit register. This safe to
- * be called from atomic context.  The callback will be called
- * when the URB completes. Otherwise the function is similar
- * to rt2x00usb_register_read().
- * When the callback function returns false, the memory will be cleaned up,
- * when it returns true, the urb will be fired again.
- */
-void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
-                                  const unsigned int offset,
-                                  bool (*callback)(struct rt2x00_dev*, int, u32));
-
-/*
- * Radio handlers
- */
-void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
-
-/**
- * struct queue_entry_priv_usb: Per entry USB specific information
- *
- * @urb: Urb structure used for device communication.
- */
-struct queue_entry_priv_usb {
-       struct urb *urb;
-};
-
-/**
- * struct queue_entry_priv_usb_bcn: Per TX entry USB specific information
- *
- * The first section should match &struct queue_entry_priv_usb exactly.
- * rt2500usb can use this structure to send a guardian byte when working
- * with beacons.
- *
- * @urb: Urb structure used for device communication.
- * @guardian_data: Set to 0, used for sending the guardian data.
- * @guardian_urb: Urb structure used to send the guardian data.
- */
-struct queue_entry_priv_usb_bcn {
-       struct urb *urb;
-
-       unsigned int guardian_data;
-       struct urb *guardian_urb;
-};
-
-/**
- * rt2x00usb_kick_queue - Kick data queue
- * @queue: Data queue to kick
- *
- * This will walk through all entries of the queue and push all pending
- * frames to the hardware as a single burst.
- */
-void rt2x00usb_kick_queue(struct data_queue *queue);
-
-/**
- * rt2x00usb_flush_queue - Flush data queue
- * @queue: Data queue to stop
- * @drop: True to drop all pending frames.
- *
- * This will walk through all entries of the queue and will optionally
- * kill all URB's which were send to the device, or at least wait until
- * they have been returned from the device..
- */
-void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
-
-/**
- * rt2x00usb_watchdog - Watchdog for USB communication
- * @rt2x00dev: Pointer to &struct rt2x00_dev
- *
- * Check the health of the USB communication and determine
- * if timeouts have occurred. If this is the case, this function
- * will reset all communication to restore functionality again.
- */
-void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
-
-/*
- * Device initialization handlers.
- */
-void rt2x00usb_clear_entry(struct queue_entry *entry);
-int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
-
-/*
- * USB driver handlers.
- */
-int rt2x00usb_probe(struct usb_interface *usb_intf,
-                   const struct rt2x00_ops *ops);
-void rt2x00usb_disconnect(struct usb_interface *usb_intf);
-#ifdef CONFIG_PM
-int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
-int rt2x00usb_resume(struct usb_interface *usb_intf);
-#else
-#define rt2x00usb_suspend      NULL
-#define rt2x00usb_resume       NULL
-#endif /* CONFIG_PM */
-
-#endif /* RT2X00USB_H */
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
deleted file mode 100644 (file)
index c0e730e..0000000
+++ /dev/null
@@ -1,3111 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt61pci
-       Abstract: rt61pci device specific routines.
-       Supported chipsets: RT2561, RT2561s, RT2661.
- */
-
-#include <linux/crc-itu-t.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/eeprom_93cx6.h>
-
-#include "rt2x00.h"
-#include "rt2x00mmio.h"
-#include "rt2x00pci.h"
-#include "rt61pci.h"
-
-/*
- * Allow hardware encryption to be disabled.
- */
-static bool modparam_nohwcrypt = false;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-/*
- * Register access.
- * BBP and RF register require indirect register access,
- * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attempt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
-#define WAIT_FOR_MCU(__dev, __reg) \
-       rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \
-                               H2M_MAILBOX_CSR_OWNER, (__reg))
-
-static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
-               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
-               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
-               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
-
-               rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
-               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
-               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
-
-               WAIT_FOR_BBP(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, const u32 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
-               rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS, 21);
-               rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
-               rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
-
-               rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
-                               const u8 command, const u8 token,
-                               const u8 arg0, const u8 arg1)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the MCU becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
-               rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
-               rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
-               rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
-               rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
-               rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-
-}
-
-static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
-
-       eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
-       eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
-       eeprom->reg_data_clock =
-           !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK);
-       eeprom->reg_chip_select =
-           !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT);
-}
-
-static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
-{
-       struct rt2x00_dev *rt2x00dev = eeprom->data;
-       u32 reg = 0;
-
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in);
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out);
-       rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK,
-                          !!eeprom->reg_data_clock);
-       rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
-                          !!eeprom->reg_chip_select);
-
-       rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt61pci_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = rt2x00mmio_register_read,
-               .write          = rt2x00mmio_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = CSR_REG_SIZE / sizeof(u32),
-       },
-       .eeprom = {
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt61pci_bbp_read,
-               .write          = rt61pci_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt61pci_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
-       return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt61pci_brightness_set(struct led_classdev *led_cdev,
-                                  enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       unsigned int a_mode =
-           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-       unsigned int bg_mode =
-           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-
-       if (led->type == LED_TYPE_RADIO) {
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_RADIO_STATUS, enabled);
-
-               rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
-                                   (led->rt2x00dev->led_mcu_reg & 0xff),
-                                   ((led->rt2x00dev->led_mcu_reg >> 8)));
-       } else if (led->type == LED_TYPE_ASSOC) {
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_LINK_BG_STATUS, bg_mode);
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_LINK_A_STATUS, a_mode);
-
-               rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
-                                   (led->rt2x00dev->led_mcu_reg & 0xff),
-                                   ((led->rt2x00dev->led_mcu_reg >> 8)));
-       } else if (led->type == LED_TYPE_QUALITY) {
-               /*
-                * The brightness is divided into 6 levels (0 - 5),
-                * this means we need to convert the brightness
-                * argument into the matching level within that range.
-                */
-               rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-                                   brightness / (LED_FULL / 6), 0);
-       }
-}
-
-static int rt61pci_blink_set(struct led_classdev *led_cdev,
-                            unsigned long *delay_on,
-                            unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u32 reg;
-
-       rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
-       rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
-       rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
-
-       return 0;
-}
-
-static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00_led *led,
-                            enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt61pci_brightness_set;
-       led->led_dev.blink_set = rt61pci_blink_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
-                                    struct rt2x00lib_crypto *crypto,
-                                    struct ieee80211_key_conf *key)
-{
-       struct hw_key_entry key_entry;
-       struct rt2x00_field32 field;
-       u32 mask;
-       u32 reg;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * rt2x00lib can't determine the correct free
-                * key_idx for shared keys. We have 1 register
-                * with key valid bits. The goal is simple, read
-                * the register, if that is full we have no slots
-                * left.
-                * Note that each BSS is allowed to have up to 4
-                * shared keys, so put a mask over the allowed
-                * entries.
-                */
-               mask = (0xf << crypto->bssidx);
-
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
-               reg &= mask;
-
-               if (reg && reg == mask)
-                       return -ENOSPC;
-
-               key->hw_key_idx += reg ? ffz(reg) : 0;
-
-               /*
-                * Upload key to hardware
-                */
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               reg = SHARED_KEY_ENTRY(key->hw_key_idx);
-               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
-                                              &key_entry, sizeof(key_entry));
-
-               /*
-                * The cipher types are stored over 2 registers.
-                * bssidx 0 and 1 keys are stored in SEC_CSR1 and
-                * bssidx 1 and 2 keys are stored in SEC_CSR5.
-                * Using the correct defines correctly will cause overhead,
-                * so just calculate the correct offset.
-                */
-               if (key->hw_key_idx < 8) {
-                       field.bit_offset = (3 * key->hw_key_idx);
-                       field.bit_mask = 0x7 << field.bit_offset;
-
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
-                       rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
-               } else {
-                       field.bit_offset = (3 * (key->hw_key_idx - 8));
-                       field.bit_mask = 0x7 << field.bit_offset;
-
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
-                       rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
-               }
-
-               /*
-                * The driver does not support the IV/EIV generation
-                * in hardware. However it doesn't support the IV/EIV
-                * inside the ieee80211 frame either, but requires it
-                * to be provided separately for the descriptor.
-                * rt2x00lib will cut the IV/EIV data out of all frames
-                * given to us by mac80211, but we must tell mac80211
-                * to generate the IV/EIV data.
-                */
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       }
-
-       /*
-        * SEC_CSR0 contains only single-bit fields to indicate
-        * a particular key is valid. Because using the FIELD32()
-        * defines directly will cause a lot of overhead, we use
-        * a calculation to determine the correct bit directly.
-        */
-       mask = 1 << key->hw_key_idx;
-
-       rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
-       if (crypto->cmd == SET_KEY)
-               reg |= mask;
-       else if (crypto->cmd == DISABLE_KEY)
-               reg &= ~mask;
-       rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
-
-       return 0;
-}
-
-static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00lib_crypto *crypto,
-                                      struct ieee80211_key_conf *key)
-{
-       struct hw_pairwise_ta_entry addr_entry;
-       struct hw_key_entry key_entry;
-       u32 mask;
-       u32 reg;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * rt2x00lib can't determine the correct free
-                * key_idx for pairwise keys. We have 2 registers
-                * with key valid bits. The goal is simple: read
-                * the first register. If that is full, move to
-                * the next register.
-                * When both registers are full, we drop the key.
-                * Otherwise, we use the first invalid entry.
-                */
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
-               if (reg && reg == ~0) {
-                       key->hw_key_idx = 32;
-                       rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
-                       if (reg && reg == ~0)
-                               return -ENOSPC;
-               }
-
-               key->hw_key_idx += reg ? ffz(reg) : 0;
-
-               /*
-                * Upload key to hardware
-                */
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               memset(&addr_entry, 0, sizeof(addr_entry));
-               memcpy(&addr_entry, crypto->address, ETH_ALEN);
-               addr_entry.cipher = crypto->cipher;
-
-               reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
-               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
-                                              &key_entry, sizeof(key_entry));
-
-               reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
-               rt2x00mmio_register_multiwrite(rt2x00dev, reg,
-                                              &addr_entry, sizeof(addr_entry));
-
-               /*
-                * Enable pairwise lookup table for given BSS idx.
-                * Without this, received frames will not be decrypted
-                * by the hardware.
-                */
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
-               reg |= (1 << crypto->bssidx);
-               rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
-
-               /*
-                * The driver does not support the IV/EIV generation
-                * in hardware. However it doesn't support the IV/EIV
-                * inside the ieee80211 frame either, but requires it
-                * to be provided separately for the descriptor.
-                * rt2x00lib will cut the IV/EIV data out of all frames
-                * given to us by mac80211, but we must tell mac80211
-                * to generate the IV/EIV data.
-                */
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       }
-
-       /*
-        * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
-        * a particular key is valid. Because using the FIELD32()
-        * defines directly will cause a lot of overhead, we use
-        * a calculation to determine the correct bit directly.
-        */
-       if (key->hw_key_idx < 32) {
-               mask = 1 << key->hw_key_idx;
-
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
-               if (crypto->cmd == SET_KEY)
-                       reg |= mask;
-               else if (crypto->cmd == DISABLE_KEY)
-                       reg &= ~mask;
-               rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg);
-       } else {
-               mask = 1 << (key->hw_key_idx - 32);
-
-               rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
-               if (crypto->cmd == SET_KEY)
-                       reg |= mask;
-               else if (crypto->cmd == DISABLE_KEY)
-                       reg &= ~mask;
-               rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg);
-       }
-
-       return 0;
-}
-
-static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int filter_flags)
-{
-       u32 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * and broadcast frames will always be accepted since
-        * there is no filter for it at this time.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-                          !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-                          !rt2x00dev->intf_ap_count);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-                          !(filter_flags & FIF_ALLMULTI));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
-}
-
-static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00_intf *intf,
-                               struct rt2x00intf_conf *conf,
-                               const unsigned int flags)
-{
-       u32 reg;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable synchronisation.
-                */
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-       }
-
-       if (flags & CONFIG_UPDATE_MAC) {
-               reg = le32_to_cpu(conf->mac[1]);
-               rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-               conf->mac[1] = cpu_to_le32(reg);
-
-               rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2,
-                                              conf->mac, sizeof(conf->mac));
-       }
-
-       if (flags & CONFIG_UPDATE_BSSID) {
-               reg = le32_to_cpu(conf->bssid[1]);
-               rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
-               conf->bssid[1] = cpu_to_le32(reg);
-
-               rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4,
-                                              conf->bssid,
-                                              sizeof(conf->bssid));
-       }
-}
-
-static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00lib_erp *erp,
-                              u32 changed)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
-       rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-                                  !!erp->short_preamble);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES)
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5,
-                                         erp->basic_rates);
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-                                  erp->beacon_int * 16);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-       }
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
-               rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-               rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg);
-       }
-}
-
-static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
-                                     struct antenna_setup *ant)
-{
-       u8 r3;
-       u8 r4;
-       u8 r77;
-
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
-
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325));
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-                                 (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               break;
-       }
-
-       rt61pci_bbp_write(rt2x00dev, 77, r77);
-       rt61pci_bbp_write(rt2x00dev, 3, r3);
-       rt61pci_bbp_write(rt2x00dev, 4, r4);
-}
-
-static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
-                                     struct antenna_setup *ant)
-{
-       u8 r3;
-       u8 r4;
-       u8 r77;
-
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
-
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
-       rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-                         !rt2x00_has_cap_frame_type(rt2x00dev));
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               break;
-       }
-
-       rt61pci_bbp_write(rt2x00dev, 77, r77);
-       rt61pci_bbp_write(rt2x00dev, 3, r3);
-       rt61pci_bbp_write(rt2x00dev, 4, r4);
-}
-
-static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
-                                          const int p1, const int p2)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
-
-       rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
-       rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
-
-       rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
-       rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
-
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
-}
-
-static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
-                                       struct antenna_setup *ant)
-{
-       u8 r3;
-       u8 r4;
-       u8 r77;
-
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt61pci_bbp_read(rt2x00dev, 4, &r4);
-       rt61pci_bbp_read(rt2x00dev, 77, &r77);
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_A:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
-               break;
-       case ANTENNA_HW_DIVERSITY:
-               /*
-                * FIXME: Antenna selection for the rf 2529 is very confusing
-                * in the legacy driver. Just default to antenna B until the
-                * legacy code can be properly translated into rt2x00 code.
-                */
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
-               break;
-       }
-
-       rt61pci_bbp_write(rt2x00dev, 77, r77);
-       rt61pci_bbp_write(rt2x00dev, 3, r3);
-       rt61pci_bbp_write(rt2x00dev, 4, r4);
-}
-
-struct antenna_sel {
-       u8 word;
-       /*
-        * value[0] -> non-LNA
-        * value[1] -> LNA
-        */
-       u8 value[2];
-};
-
-static const struct antenna_sel antenna_sel_a[] = {
-       { 96,  { 0x58, 0x78 } },
-       { 104, { 0x38, 0x48 } },
-       { 75,  { 0xfe, 0x80 } },
-       { 86,  { 0xfe, 0x80 } },
-       { 88,  { 0xfe, 0x80 } },
-       { 35,  { 0x60, 0x60 } },
-       { 97,  { 0x58, 0x58 } },
-       { 98,  { 0x58, 0x58 } },
-};
-
-static const struct antenna_sel antenna_sel_bg[] = {
-       { 96,  { 0x48, 0x68 } },
-       { 104, { 0x2c, 0x3c } },
-       { 75,  { 0xfe, 0x80 } },
-       { 86,  { 0xfe, 0x80 } },
-       { 88,  { 0xfe, 0x80 } },
-       { 35,  { 0x50, 0x50 } },
-       { 97,  { 0x48, 0x48 } },
-       { 98,  { 0x48, 0x48 } },
-};
-
-static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
-                              struct antenna_setup *ant)
-{
-       const struct antenna_sel *sel;
-       unsigned int lna;
-       unsigned int i;
-       u32 reg;
-
-       /*
-        * We should never come here because rt2x00lib is supposed
-        * to catch this and send us the correct antenna explicitely.
-        */
-       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-              ant->tx == ANTENNA_SW_DIVERSITY);
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               sel = antenna_sel_a;
-               lna = rt2x00_has_cap_external_lna_a(rt2x00dev);
-       } else {
-               sel = antenna_sel_bg;
-               lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
-               rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
-
-       rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
-
-       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-                          rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-                          rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-
-       rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg);
-
-       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
-               rt61pci_config_antenna_5x(rt2x00dev, ant);
-       else if (rt2x00_rf(rt2x00dev, RF2527))
-               rt61pci_config_antenna_2x(rt2x00dev, ant);
-       else if (rt2x00_rf(rt2x00dev, RF2529)) {
-               if (rt2x00_has_cap_double_antenna(rt2x00dev))
-                       rt61pci_config_antenna_2x(rt2x00dev, ant);
-               else
-                       rt61pci_config_antenna_2529(rt2x00dev, ant);
-       }
-}
-
-static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_conf *libconf)
-{
-       u16 eeprom;
-       short lna_gain = 0;
-
-       if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
-               if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
-                       lna_gain += 14;
-
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
-               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
-       } else {
-               if (rt2x00_has_cap_external_lna_a(rt2x00dev))
-                       lna_gain += 14;
-
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
-               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
-       }
-
-       rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
-                                  struct rf_channel *rf, const int txpower)
-{
-       u8 r3;
-       u8 r94;
-       u8 smart;
-
-       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
-       smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
-
-       rt61pci_bbp_read(rt2x00dev, 3, &r3);
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
-       rt61pci_bbp_write(rt2x00dev, 3, r3);
-
-       r94 = 6;
-       if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
-               r94 += txpower - MAX_TXPOWER;
-       else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
-               r94 += txpower;
-       rt61pci_bbp_write(rt2x00dev, 94, r94);
-
-       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-       udelay(200);
-
-       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
-       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-       udelay(200);
-
-       rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
-       rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
-       rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
-       msleep(1);
-}
-
-static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                  const int txpower)
-{
-       struct rf_channel rf;
-
-       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
-
-       rt61pci_config_channel(rt2x00dev, &rf, txpower);
-}
-
-static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_conf *libconf)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
-                          libconf->conf->long_frame_max_tx_count);
-       rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
-                          libconf->conf->short_frame_max_tx_count);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
-
-static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u32 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
-                                  rt2x00dev->beacon_int - 10);
-               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
-                                  libconf->conf->listen_interval - 1);
-               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
-
-               /* We must first disable autowake before it can be enabled */
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
-                                         0x00000005);
-               rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
-               rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
-
-               rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
-       } else {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
-                                         0x00000007);
-               rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
-               rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
-
-               rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
-       }
-}
-
-static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
-                          struct rt2x00lib_conf *libconf,
-                          const unsigned int flags)
-{
-       /* Always recalculate LNA gain before changing configuration */
-       rt61pci_config_lna_gain(rt2x00dev, libconf);
-
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt61pci_config_channel(rt2x00dev, &libconf->rf,
-                                      libconf->conf->power_level);
-       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
-           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
-               rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
-               rt61pci_config_retry_limit(rt2x00dev, libconf);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt61pci_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
-                              struct link_qual *qual)
-{
-       u32 reg;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
-       qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
-
-       /*
-        * Update False CCA count from register.
-        */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
-       qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
-}
-
-static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev,
-                                  struct link_qual *qual, u8 vgc_level)
-{
-       if (qual->vgc_level != vgc_level) {
-               rt61pci_bbp_write(rt2x00dev, 17, vgc_level);
-               qual->vgc_level = vgc_level;
-               qual->vgc_level_reg = vgc_level;
-       }
-}
-
-static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
-                               struct link_qual *qual)
-{
-       rt61pci_set_vgc(rt2x00dev, qual, 0x20);
-}
-
-static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
-                              struct link_qual *qual, const u32 count)
-{
-       u8 up_bound;
-       u8 low_bound;
-
-       /*
-        * Determine r17 bounds.
-        */
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               low_bound = 0x28;
-               up_bound = 0x48;
-               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
-                       low_bound += 0x10;
-                       up_bound += 0x10;
-               }
-       } else {
-               low_bound = 0x20;
-               up_bound = 0x40;
-               if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-                       low_bound += 0x10;
-                       up_bound += 0x10;
-               }
-       }
-
-       /*
-        * If we are not associated, we should go straight to the
-        * dynamic CCA tuning.
-        */
-       if (!rt2x00dev->intf_associated)
-               goto dynamic_cca_tune;
-
-       /*
-        * Special big-R17 for very short distance
-        */
-       if (qual->rssi >= -35) {
-               rt61pci_set_vgc(rt2x00dev, qual, 0x60);
-               return;
-       }
-
-       /*
-        * Special big-R17 for short distance
-        */
-       if (qual->rssi >= -58) {
-               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
-               return;
-       }
-
-       /*
-        * Special big-R17 for middle-short distance
-        */
-       if (qual->rssi >= -66) {
-               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10);
-               return;
-       }
-
-       /*
-        * Special mid-R17 for middle distance
-        */
-       if (qual->rssi >= -74) {
-               rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08);
-               return;
-       }
-
-       /*
-        * Special case: Change up_bound based on the rssi.
-        * Lower up_bound when rssi is weaker then -74 dBm.
-        */
-       up_bound -= 2 * (-74 - qual->rssi);
-       if (low_bound > up_bound)
-               up_bound = low_bound;
-
-       if (qual->vgc_level > up_bound) {
-               rt61pci_set_vgc(rt2x00dev, qual, up_bound);
-               return;
-       }
-
-dynamic_cca_tune:
-
-       /*
-        * r17 does not yet exceed upper limit, continue and base
-        * the r17 tuning on the false CCA count.
-        */
-       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
-               rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
-       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
-               rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
-}
-
-/*
- * Queue handlers.
- */
-static void rt61pci_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt61pci_kick_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_BE:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_BK:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt61pci_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_AC_VO:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_VI:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_BE:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_AC_BK:
-               rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
-               rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
-               rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-               break;
-       case QID_RX:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-               /*
-                * Wait for possibly running tbtt tasklets.
-                */
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * Firmware functions
- */
-static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
-       u16 chip;
-       char *fw_name;
-
-       pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip);
-       switch (chip) {
-       case RT2561_PCI_ID:
-               fw_name = FIRMWARE_RT2561;
-               break;
-       case RT2561s_PCI_ID:
-               fw_name = FIRMWARE_RT2561s;
-               break;
-       case RT2661_PCI_ID:
-               fw_name = FIRMWARE_RT2661;
-               break;
-       default:
-               fw_name = NULL;
-               break;
-       }
-
-       return fw_name;
-}
-
-static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev,
-                                 const u8 *data, const size_t len)
-{
-       u16 fw_crc;
-       u16 crc;
-
-       /*
-        * Only support 8kb firmware files.
-        */
-       if (len != 8192)
-               return FW_BAD_LENGTH;
-
-       /*
-        * The last 2 bytes in the firmware array are the crc checksum itself.
-        * This means that we should never pass those 2 bytes to the crc
-        * algorithm.
-        */
-       fw_crc = (data[len - 2] << 8 | data[len - 1]);
-
-       /*
-        * Use the crc itu-t algorithm.
-        */
-       crc = crc_itu_t(0, data, len - 2);
-       crc = crc_itu_t_byte(crc, 0);
-       crc = crc_itu_t_byte(crc, 0);
-
-       return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
-}
-
-static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
-                                const u8 *data, const size_t len)
-{
-       int i;
-       u32 reg;
-
-       /*
-        * Wait for stable hardware.
-        */
-       for (i = 0; i < 100; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
-               if (reg)
-                       break;
-               msleep(1);
-       }
-
-       if (!reg) {
-               rt2x00_err(rt2x00dev, "Unstable hardware\n");
-               return -EBUSY;
-       }
-
-       /*
-        * Prepare MCU and mailbox for firmware loading.
-        */
-       reg = 0;
-       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
-       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
-       rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-       rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0);
-
-       /*
-        * Write firmware to device.
-        */
-       reg = 0;
-       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
-       rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 1);
-       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
-
-       rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-                                      data, len);
-
-       rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 0);
-       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
-
-       rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 0);
-       rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
-
-       for (i = 0; i < 100; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
-               if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
-                       break;
-               msleep(1);
-       }
-
-       if (i == 100) {
-               rt2x00_err(rt2x00dev, "MCU Control register not ready\n");
-               return -EBUSY;
-       }
-
-       /*
-        * Hardware needs another millisecond before it is ready.
-        */
-       msleep(1);
-
-       /*
-        * Reset MAC and BBP registers.
-        */
-       reg = 0;
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       return 0;
-}
-
-/*
- * Initialization functions.
- */
-static bool rt61pci_get_entry_state(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                       rt2x00_get_field32(word, TXD_W0_VALID));
-       }
-}
-
-static void rt61pci_clear_entry(struct queue_entry *entry)
-{
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       u32 word;
-
-       if (entry->queue->qid == QID_RX) {
-               rt2x00_desc_read(entry_priv->desc, 5, &word);
-               rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
-                                  skbdesc->skb_dma);
-               rt2x00_desc_write(entry_priv->desc, 5, word);
-
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       } else {
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(entry_priv->desc, 0, word);
-       }
-}
-
-static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
-{
-       struct queue_entry_priv_mmio *entry_priv;
-       u32 reg;
-
-       /*
-        * Initialize registers.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
-       rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
-                          rt2x00dev->tx[0].limit);
-       rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
-                          rt2x00dev->tx[1].limit);
-       rt2x00_set_field32(&reg, TX_RING_CSR0_AC2_RING_SIZE,
-                          rt2x00dev->tx[2].limit);
-       rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
-                          rt2x00dev->tx[3].limit);
-       rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
-       rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
-                          rt2x00dev->tx[0].desc_size / 4);
-       rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
-
-       entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
-       rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
-
-       entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
-       rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
-
-       entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
-       rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
-
-       entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
-       rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
-       rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
-       rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
-                          rt2x00dev->rx->desc_size / 4);
-       rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
-       rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
-
-       entry_priv = rt2x00dev->rx->entries[0].priv_data;
-       rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
-       rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
-                          entry_priv->desc_dma);
-       rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
-       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC0, 2);
-       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
-       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
-       rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
-       rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
-       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1);
-       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
-       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
-       rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
-       rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
-       rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
-       rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
-
-       return 0;
-}
-
-static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg);
-
-       /*
-        * CCK TXD BBP registers
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2, 11);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg);
-
-       /*
-        * OFDM TXD BBP registers
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
-
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
-
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               return -EBUSY;
-
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
-
-       /*
-        * Invalidate all Shared Keys (SEC_CSR0),
-        * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
-        */
-       rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
-       rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
-       rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
-
-       rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
-       rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
-       rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
-       rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
-
-       rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
-
-       rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
-
-       rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
-
-       /*
-        * Clear all beacons
-        * For the Beacon base registers we only need to clear
-        * the first byte since that byte contains the VALID and OWNER
-        * bits which (when set to 0) will invalidate the entire beacon.
-        */
-       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-       rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-
-       /*
-        * We must clear the error counters.
-        * These registers are cleared on read,
-        * so we may pass a useless variable to store the value.
-        */
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
-       rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
-
-       /*
-        * Reset MAC and BBP registers.
-        */
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       return 0;
-}
-
-static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt61pci_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
-       u8 value;
-
-       if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev)))
-               return -EACCES;
-
-       rt61pci_bbp_write(rt2x00dev, 3, 0x00);
-       rt61pci_bbp_write(rt2x00dev, 15, 0x30);
-       rt61pci_bbp_write(rt2x00dev, 21, 0xc8);
-       rt61pci_bbp_write(rt2x00dev, 22, 0x38);
-       rt61pci_bbp_write(rt2x00dev, 23, 0x06);
-       rt61pci_bbp_write(rt2x00dev, 24, 0xfe);
-       rt61pci_bbp_write(rt2x00dev, 25, 0x0a);
-       rt61pci_bbp_write(rt2x00dev, 26, 0x0d);
-       rt61pci_bbp_write(rt2x00dev, 34, 0x12);
-       rt61pci_bbp_write(rt2x00dev, 37, 0x07);
-       rt61pci_bbp_write(rt2x00dev, 39, 0xf8);
-       rt61pci_bbp_write(rt2x00dev, 41, 0x60);
-       rt61pci_bbp_write(rt2x00dev, 53, 0x10);
-       rt61pci_bbp_write(rt2x00dev, 54, 0x18);
-       rt61pci_bbp_write(rt2x00dev, 60, 0x10);
-       rt61pci_bbp_write(rt2x00dev, 61, 0x04);
-       rt61pci_bbp_write(rt2x00dev, 62, 0x04);
-       rt61pci_bbp_write(rt2x00dev, 75, 0xfe);
-       rt61pci_bbp_write(rt2x00dev, 86, 0xfe);
-       rt61pci_bbp_write(rt2x00dev, 88, 0xfe);
-       rt61pci_bbp_write(rt2x00dev, 90, 0x0f);
-       rt61pci_bbp_write(rt2x00dev, 99, 0x00);
-       rt61pci_bbp_write(rt2x00dev, 102, 0x16);
-       rt61pci_bbp_write(rt2x00dev, 107, 0x04);
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt61pci_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
-                              enum dev_state state)
-{
-       int mask = (state == STATE_RADIO_IRQ_OFF);
-       u32 reg;
-       unsigned long flags;
-
-       /*
-        * When interrupts are being enabled, the interrupt registers
-        * should clear the register to assure a clean state.
-        */
-       if (state == STATE_RADIO_IRQ_ON) {
-               rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-               rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-               rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
-               rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
-       }
-
-       /*
-        * Only toggle the interrupts bits we are going to use.
-        * Non-checked interrupt bits are disabled by default.
-        */
-       spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_3, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_4, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
-       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
-       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
-
-       spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
-
-       if (state == STATE_RADIO_IRQ_OFF) {
-               /*
-                * Ensure that all tasklets are finished.
-                */
-               tasklet_kill(&rt2x00dev->txstatus_tasklet);
-               tasklet_kill(&rt2x00dev->rxdone_tasklet);
-               tasklet_kill(&rt2x00dev->autowake_tasklet);
-               tasklet_kill(&rt2x00dev->tbtt_tasklet);
-       }
-}
-
-static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       /*
-        * Initialize all registers.
-        */
-       if (unlikely(rt61pci_init_queues(rt2x00dev) ||
-                    rt61pci_init_registers(rt2x00dev) ||
-                    rt61pci_init_bbp(rt2x00dev)))
-               return -EIO;
-
-       /*
-        * Enable RX.
-        */
-       rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
-       rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
-       rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
-
-       return 0;
-}
-
-static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Disable power
-        */
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
-}
-
-static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
-{
-       u32 reg, reg2;
-       unsigned int i;
-       char put_to_sleep;
-
-       put_to_sleep = (state != STATE_AWAKE);
-
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
-       rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
-
-       /*
-        * Device is not guaranteed to be in the requested state yet.
-        * We must wait until the register indicates that the
-        * device has entered the correct state.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
-               state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
-               if (state == !put_to_sleep)
-                       return 0;
-               rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
-               msleep(10);
-       }
-
-       return -EBUSY;
-}
-
-static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                   enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt61pci_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               rt61pci_disable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               rt61pci_toggle_irq(rt2x00dev, state);
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt61pci_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * TX descriptor initialization
- */
-static void rt61pci_write_tx_desc(struct queue_entry *entry,
-                                 struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       __le32 *txd = entry_priv->desc;
-       u32 word;
-
-       /*
-        * Start writing the descriptor words.
-        */
-       rt2x00_desc_read(txd, 1, &word);
-       rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
-       rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
-       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
-       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
-       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
-       rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
-                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
-       rt2x00_desc_write(txd, 1, word);
-
-       rt2x00_desc_read(txd, 2, &word);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
-                          txdesc->u.plcp.length_low);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
-                          txdesc->u.plcp.length_high);
-       rt2x00_desc_write(txd, 2, word);
-
-       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
-               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
-       }
-
-       rt2x00_desc_read(txd, 5, &word);
-       rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
-       rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
-                          skbdesc->entry->entry_idx);
-       rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-                          TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
-       rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
-       rt2x00_desc_write(txd, 5, word);
-
-       if (entry->queue->qid != QID_BEACON) {
-               rt2x00_desc_read(txd, 6, &word);
-               rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
-                                  skbdesc->skb_dma);
-               rt2x00_desc_write(txd, 6, word);
-
-               rt2x00_desc_read(txd, 11, &word);
-               rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
-                                  txdesc->length);
-               rt2x00_desc_write(txd, 11, word);
-       }
-
-       /*
-        * Writing TXD word 0 must the last to prevent a race condition with
-        * the device, whereby the device may take hold of the TXD before we
-        * finished updating it.
-        */
-       rt2x00_desc_read(txd, 0, &word);
-       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
-       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
-       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          (txdesc->rate_mode == RATE_MODE_OFDM));
-       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
-       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
-                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
-                          test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
-                          test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
-       rt2x00_set_field32(&word, TXD_W0_BURST,
-                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
-       rt2x00_desc_write(txd, 0, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->desc = txd;
-       skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE :
-                           TXD_DESC_SIZE;
-}
-
-/*
- * TX data initialization
- */
-static void rt61pci_write_beacon(struct queue_entry *entry,
-                                struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       unsigned int beacon_base;
-       unsigned int padding_len;
-       u32 orig_reg, reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       orig_reg = reg;
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Write the TX descriptor for the beacon.
-        */
-       rt61pci_write_tx_desc(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
-       /*
-        * Write entire beacon with descriptor and padding to register.
-        */
-       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-       if (padding_len && skb_pad(entry->skb, padding_len)) {
-               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
-               /* skb freed by skb_pad() on failure */
-               entry->skb = NULL;
-               rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
-               return;
-       }
-
-       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
-       rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base,
-                                      entry_priv->desc, TXINFO_SIZE);
-       rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
-                                      entry->skb->data,
-                                      entry->skb->len + padding_len);
-
-       /*
-        * Enable beaconing again.
-        *
-        * For Wi-Fi faily generated beacons between participating
-        * stations. Set TBTT phase adaptive adjustment step to 8us.
-        */
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
-
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Clean up beacon skb.
-        */
-       dev_kfree_skb_any(entry->skb);
-       entry->skb = NULL;
-}
-
-static void rt61pci_clear_beacon(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       u32 orig_reg, reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
-       reg = orig_reg;
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Clear beacon.
-        */
-       rt2x00mmio_register_write(rt2x00dev,
-                                 HW_BEACON_OFFSET(entry->entry_idx), 0);
-
-       /*
-        * Restore global beaconing state.
-        */
-       rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
-}
-
-/*
- * RX control handlers
- */
-static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
-{
-       u8 offset = rt2x00dev->lna_gain;
-       u8 lna;
-
-       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
-       switch (lna) {
-       case 3:
-               offset += 90;
-               break;
-       case 2:
-               offset += 74;
-               break;
-       case 1:
-               offset += 64;
-               break;
-       default:
-               return 0;
-       }
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               if (lna == 3 || lna == 2)
-                       offset += 10;
-       }
-
-       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
-}
-
-static void rt61pci_fill_rxdone(struct queue_entry *entry,
-                               struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
-       u32 word0;
-       u32 word1;
-
-       rt2x00_desc_read(entry_priv->desc, 0, &word0);
-       rt2x00_desc_read(entry_priv->desc, 1, &word1);
-
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
-       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
-       rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
-
-       if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
-               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
-
-               _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
-               rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
-
-               /*
-                * Hardware has stripped IV/EIV data from 802.11 frame during
-                * decryption. It has provided the data separately but rt2x00lib
-                * should decide if it should be reinserted.
-                */
-               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
-
-               /*
-                * The hardware has already checked the Michael Mic and has
-                * stripped it from the frame. Signal this to mac80211.
-                */
-               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-
-               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
-                       rxdesc->flags |= RX_FLAG_DECRYPTED;
-               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
-                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
-       }
-
-       /*
-        * Obtain the status about this packet.
-        * When frame was received with an OFDM bitrate,
-        * the signal is the PLCP value. If it was received with
-        * a CCK bitrate the signal is the rate in 100kbit/s.
-        */
-       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       rxdesc->rssi = rt61pci_agc_to_rssi(rt2x00dev, word1);
-       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
-       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-       else
-               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
-       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-}
-
-/*
- * Interrupt functions.
- */
-static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_queue *queue;
-       struct queue_entry *entry;
-       struct queue_entry *entry_done;
-       struct queue_entry_priv_mmio *entry_priv;
-       struct txdone_entry_desc txdesc;
-       u32 word;
-       u32 reg;
-       int type;
-       int index;
-       int i;
-
-       /*
-        * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
-        * at most X times and also stop processing once the TX_STA_FIFO_VALID
-        * flag is not set anymore.
-        *
-        * The legacy drivers use X=TX_RING_SIZE but state in a comment
-        * that the TX_STA_FIFO stack has a size of 16. We stick to our
-        * tx ring size for now.
-        */
-       for (i = 0; i < rt2x00dev->tx->limit; i++) {
-               rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
-               if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
-                       break;
-
-               /*
-                * Skip this entry when it contains an invalid
-                * queue identication number.
-                */
-               type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
-               queue = rt2x00queue_get_tx_queue(rt2x00dev, type);
-               if (unlikely(!queue))
-                       continue;
-
-               /*
-                * Skip this entry when it contains an invalid
-                * index number.
-                */
-               index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
-               if (unlikely(index >= queue->limit))
-                       continue;
-
-               entry = &queue->entries[index];
-               entry_priv = entry->priv_data;
-               rt2x00_desc_read(entry_priv->desc, 0, &word);
-
-               if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
-                   !rt2x00_get_field32(word, TXD_W0_VALID))
-                       return;
-
-               entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               while (entry != entry_done) {
-                       /* Catch up.
-                        * Just report any entries we missed as failed.
-                        */
-                       rt2x00_warn(rt2x00dev, "TX status report missed for entry %d\n",
-                                   entry_done->entry_idx);
-
-                       rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
-                       entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               }
-
-               /*
-                * Obtain the status about this packet.
-                */
-               txdesc.flags = 0;
-               switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
-               case 0: /* Success, maybe with retry */
-                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
-                       break;
-               case 6: /* Failure, excessive retries */
-                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
-                       /* Don't break, this is a failed frame! */
-               default: /* Failure */
-                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
-               }
-               txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
-
-               /*
-                * the frame was retried at least once
-                * -> hw used fallback rates
-                */
-               if (txdesc.retry)
-                       __set_bit(TXDONE_FALLBACK, &txdesc.flags);
-
-               rt2x00lib_txdone(entry, &txdesc);
-       }
-}
-
-static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
-{
-       struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };
-
-       rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
-}
-
-static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-                                           struct rt2x00_field32 irq_field)
-{
-       u32 reg;
-
-       /*
-        * Enable a single interrupt. The interrupt mask register
-        * access needs locking.
-        */
-       spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, irq_field, 0);
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-
-       spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
-                                        struct rt2x00_field32 irq_field)
-{
-       u32 reg;
-
-       /*
-        * Enable a single MCU interrupt. The interrupt mask register
-        * access needs locking.
-        */
-       spin_lock_irq(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
-       rt2x00_set_field32(&reg, irq_field, 0);
-       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
-
-       spin_unlock_irq(&rt2x00dev->irqmask_lock);
-}
-
-static void rt61pci_txstatus_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt61pci_txdone(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
-}
-
-static void rt61pci_tbtt_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt2x00lib_beacondone(rt2x00dev);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
-}
-
-static void rt61pci_rxdone_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       if (rt2x00mmio_rxdone(rt2x00dev))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-       else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
-}
-
-static void rt61pci_autowake_tasklet(unsigned long data)
-{
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-       rt61pci_wakeup(rt2x00dev);
-       rt2x00mmio_register_write(rt2x00dev,
-                                 M2H_CMD_DONE_CSR, 0xffffffff);
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
-}
-
-static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
-{
-       struct rt2x00_dev *rt2x00dev = dev_instance;
-       u32 reg_mcu, mask_mcu;
-       u32 reg, mask;
-
-       /*
-        * Get the interrupt sources & saved to local variable.
-        * Write register value back to clear pending interrupts.
-        */
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
-       rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
-
-       rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-       rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-       if (!reg && !reg_mcu)
-               return IRQ_NONE;
-
-       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               return IRQ_HANDLED;
-
-       /*
-        * Schedule tasklets for interrupt handling.
-        */
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
-               tasklet_schedule(&rt2x00dev->rxdone_tasklet);
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
-               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
-               tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
-
-       if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
-               tasklet_schedule(&rt2x00dev->autowake_tasklet);
-
-       /*
-        * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
-        * for interrupts and interrupt masks we can just use the value of
-        * INT_SOURCE_CSR to create the interrupt mask.
-        */
-       mask = reg;
-       mask_mcu = reg_mcu;
-
-       /*
-        * Disable all interrupts for which a tasklet was scheduled right now,
-        * the tasklet will reenable the appropriate interrupts.
-        */
-       spin_lock(&rt2x00dev->irqmask_lock);
-
-       rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-       reg |= mask;
-       rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
-       reg |= mask_mcu;
-       rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
-
-       spin_unlock(&rt2x00dev->irqmask_lock);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Device probe functions.
- */
-static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       struct eeprom_93cx6 eeprom;
-       u32 reg;
-       u16 word;
-       u8 *mac;
-       s8 value;
-
-       rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
-
-       eeprom.data = rt2x00dev;
-       eeprom.register_read = rt61pci_eepromregister_read;
-       eeprom.register_write = rt61pci_eepromregister_write;
-       eeprom.width = rt2x00_get_field32(reg, E2PROM_CSR_TYPE_93C46) ?
-           PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
-       eeprom.reg_data_in = 0;
-       eeprom.reg_data_out = 0;
-       eeprom.reg_data_clock = 0;
-       eeprom.reg_chip_select = 0;
-
-       eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,
-                              EEPROM_SIZE / sizeof(u16));
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
-                                  ANTENNA_B);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
-                                  ANTENNA_B);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_RX_FIXED, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_TX_FIXED, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
-               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
-                                  LED_MODE_DEFAULT);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-               rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
-       } else {
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
-       } else {
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-       }
-
-       return 0;
-}
-
-static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 value;
-       u16 eeprom;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-       /*
-        * Identify RF chipset.
-        */
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
-                       value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
-
-       if (!rt2x00_rf(rt2x00dev, RF5225) &&
-           !rt2x00_rf(rt2x00dev, RF5325) &&
-           !rt2x00_rf(rt2x00dev, RF2527) &&
-           !rt2x00_rf(rt2x00dev, RF2529)) {
-               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
-               return -ENODEV;
-       }
-
-       /*
-        * Determine number of antennas.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
-               __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->default_ant.rx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
-
-       /*
-        * Read the Frame type.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
-
-       /*
-        * Detect if this device has a hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-
-       /*
-        * Read frequency offset and RF programming sequence.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-       if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
-               __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
-
-       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
-
-       /*
-        * Read external LNA informations.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
-
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
-
-       /*
-        * When working with a RF2529 chip without double antenna,
-        * the antenna settings should be gathered from the NIC
-        * eeprom word.
-        */
-       if (rt2x00_rf(rt2x00dev, RF2529) &&
-           !rt2x00_has_cap_double_antenna(rt2x00dev)) {
-               rt2x00dev->default_ant.rx =
-                   ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
-               rt2x00dev->default_ant.tx =
-                   ANTENNA_B - rt2x00_get_field16(eeprom, EEPROM_NIC_TX_FIXED);
-
-               if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
-                       rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
-               if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY))
-                       rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY;
-       }
-
-       /*
-        * Store led settings, for correct led behaviour.
-        * If the eeprom value is invalid,
-        * switch to default led mode.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-       value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
-
-       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
-       if (value == LED_MODE_SIGNAL_STRENGTH)
-               rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
-                                LED_TYPE_QUALITY);
-
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_0));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_1));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_2));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_3));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_4));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
-                          rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_RDY_G));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_RDY_A));
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       return 0;
-}
-
-/*
- * RF value list for RF5225 & RF5325
- * Supports: 2.4 GHz & 5.2 GHz, rf_sequence disabled
- */
-static const struct rf_channel rf_vals_noseq[] = {
-       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
-       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
-       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
-       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
-       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
-       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
-       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
-       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
-       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
-       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
-       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
-       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
-       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
-       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 },
-       { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 },
-       { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b },
-       { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 },
-       { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b },
-       { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 },
-       { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 },
-       { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 },
-       { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b },
-       { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 },
-       { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b },
-       { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 },
-       { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 },
-       { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b },
-       { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 },
-       { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b },
-       { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 },
-
-       /* 802.11 UNII */
-       { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 },
-       { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f },
-       { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 },
-       { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 },
-       { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f },
-       { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 },
-
-       /* MMAC(Japan)J52 ch 34,38,42,46 */
-       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b },
-       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 },
-       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b },
-       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 },
-};
-
-/*
- * RF value list for RF5225 & RF5325
- * Supports: 2.4 GHz & 5.2 GHz, rf_sequence enabled
- */
-static const struct rf_channel rf_vals_seq[] = {
-       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
-       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
-       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
-       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
-       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
-       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
-       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
-       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
-       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
-       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
-       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
-       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
-       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
-       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00002cd4, 0x0004481a, 0x00098455, 0x000c0a03 },
-       { 40, 0x00002cd0, 0x00044682, 0x00098455, 0x000c0a03 },
-       { 44, 0x00002cd0, 0x00044686, 0x00098455, 0x000c0a1b },
-       { 48, 0x00002cd0, 0x0004468e, 0x00098655, 0x000c0a0b },
-       { 52, 0x00002cd0, 0x00044692, 0x00098855, 0x000c0a23 },
-       { 56, 0x00002cd0, 0x0004469a, 0x00098c55, 0x000c0a13 },
-       { 60, 0x00002cd0, 0x000446a2, 0x00098e55, 0x000c0a03 },
-       { 64, 0x00002cd0, 0x000446a6, 0x00099255, 0x000c0a1b },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00002cd4, 0x0004489a, 0x000b9855, 0x000c0a03 },
-       { 104, 0x00002cd4, 0x000448a2, 0x000b9855, 0x000c0a03 },
-       { 108, 0x00002cd4, 0x000448aa, 0x000b9855, 0x000c0a03 },
-       { 112, 0x00002cd4, 0x000448b2, 0x000b9a55, 0x000c0a03 },
-       { 116, 0x00002cd4, 0x000448ba, 0x000b9a55, 0x000c0a03 },
-       { 120, 0x00002cd0, 0x00044702, 0x000b9a55, 0x000c0a03 },
-       { 124, 0x00002cd0, 0x00044706, 0x000b9a55, 0x000c0a1b },
-       { 128, 0x00002cd0, 0x0004470e, 0x000b9c55, 0x000c0a0b },
-       { 132, 0x00002cd0, 0x00044712, 0x000b9c55, 0x000c0a23 },
-       { 136, 0x00002cd0, 0x0004471a, 0x000b9e55, 0x000c0a13 },
-
-       /* 802.11 UNII */
-       { 140, 0x00002cd0, 0x00044722, 0x000b9e55, 0x000c0a03 },
-       { 149, 0x00002cd0, 0x0004472e, 0x000ba255, 0x000c0a1b },
-       { 153, 0x00002cd0, 0x00044736, 0x000ba255, 0x000c0a0b },
-       { 157, 0x00002cd4, 0x0004490a, 0x000ba255, 0x000c0a17 },
-       { 161, 0x00002cd4, 0x00044912, 0x000ba255, 0x000c0a17 },
-       { 165, 0x00002cd4, 0x0004491a, 0x000ba255, 0x000c0a17 },
-
-       /* MMAC(Japan)J52 ch 34,38,42,46 */
-       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000c0a0b },
-       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000c0a13 },
-       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000c0a1b },
-       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000c0a23 },
-};
-
-static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *tx_power;
-       unsigned int i;
-
-       /*
-        * Disable powersaving as default.
-        */
-       rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
-
-       /*
-        * Initialize all hw fields.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-       ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2x00_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * As rt61 has a global fallback table we cannot specify
-        * more then one tx rate per frame but since the hw will
-        * try several rates (based on the fallback table) we should
-        * initialize max_report_rates to the maximum number of rates
-        * we are going to try. Otherwise mac80211 will truncate our
-        * reported tx rates and the rc algortihm will end up with
-        * incorrect data.
-        */
-       rt2x00dev->hw->max_rates = 1;
-       rt2x00dev->hw->max_report_rates = 7;
-       rt2x00dev->hw->max_rate_tries = 1;
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-       if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) {
-               spec->num_channels = 14;
-               spec->channels = rf_vals_noseq;
-       } else {
-               spec->num_channels = 14;
-               spec->channels = rf_vals_seq;
-       }
-
-       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_seq);
-       }
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-       for (i = 0; i < 14; i++) {
-               info[i].max_power = MAX_TXPOWER;
-               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
-       }
-
-       if (spec->num_channels > 14) {
-               tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-               for (i = 14; i < spec->num_channels; i++) {
-                       info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 =
-                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
-               }
-       }
-
-       return 0;
-}
-
-static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u32 reg;
-
-       /*
-        * Disable power saving.
-        */
-       rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt61pci_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt61pci_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
-       rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt61pci_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * This device has multiple filters for control frames,
-        * but has no a separate filter for PS Poll frames.
-        */
-       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
-
-       /*
-        * This device requires firmware and DMA mapped skbs.
-        */
-       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
-       if (!modparam_nohwcrypt)
-               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
-       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-
-/*
- * IEEE80211 stack callback functions.
- */
-static int rt61pci_conf_tx(struct ieee80211_hw *hw,
-                          struct ieee80211_vif *vif, u16 queue_idx,
-                          const struct ieee80211_tx_queue_params *params)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-       struct rt2x00_field32 field;
-       int retval;
-       u32 reg;
-       u32 offset;
-
-       /*
-        * First pass the configuration through rt2x00lib, that will
-        * update the queue settings and validate the input. After that
-        * we are free to update the registers based on the value
-        * in the queue parameter.
-        */
-       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
-       if (retval)
-               return retval;
-
-       /*
-        * We only need to perform additional register initialization
-        * for WMM queues.
-        */
-       if (queue_idx >= 4)
-               return 0;
-
-       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-
-       /* Update WMM TXOP register */
-       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
-       field.bit_offset = (queue_idx & 1) * 16;
-       field.bit_mask = 0xffff << field.bit_offset;
-
-       rt2x00mmio_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, field, queue->txop);
-       rt2x00mmio_register_write(rt2x00dev, offset, reg);
-
-       /* Update WMM registers */
-       field.bit_offset = queue_idx * 4;
-       field.bit_mask = 0xf << field.bit_offset;
-
-       rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->aifs);
-       rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_min);
-       rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
-
-       rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_max);
-       rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
-
-       return 0;
-}
-
-static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u64 tsf;
-       u32 reg;
-
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
-       tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
-       rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
-       tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
-
-       return tsf;
-}
-
-static const struct ieee80211_ops rt61pci_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt61pci_conf_tx,
-       .get_tsf                = rt61pci_get_tsf,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .flush                  = rt2x00mac_flush,
-       .set_antenna            = rt2x00mac_set_antenna,
-       .get_antenna            = rt2x00mac_get_antenna,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
-       .irq_handler            = rt61pci_interrupt,
-       .txstatus_tasklet       = rt61pci_txstatus_tasklet,
-       .tbtt_tasklet           = rt61pci_tbtt_tasklet,
-       .rxdone_tasklet         = rt61pci_rxdone_tasklet,
-       .autowake_tasklet       = rt61pci_autowake_tasklet,
-       .probe_hw               = rt61pci_probe_hw,
-       .get_firmware_name      = rt61pci_get_firmware_name,
-       .check_firmware         = rt61pci_check_firmware,
-       .load_firmware          = rt61pci_load_firmware,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt61pci_get_entry_state,
-       .clear_entry            = rt61pci_clear_entry,
-       .set_device_state       = rt61pci_set_device_state,
-       .rfkill_poll            = rt61pci_rfkill_poll,
-       .link_stats             = rt61pci_link_stats,
-       .reset_tuner            = rt61pci_reset_tuner,
-       .link_tuner             = rt61pci_link_tuner,
-       .start_queue            = rt61pci_start_queue,
-       .kick_queue             = rt61pci_kick_queue,
-       .stop_queue             = rt61pci_stop_queue,
-       .flush_queue            = rt2x00mmio_flush_queue,
-       .write_tx_desc          = rt61pci_write_tx_desc,
-       .write_beacon           = rt61pci_write_beacon,
-       .clear_beacon           = rt61pci_clear_beacon,
-       .fill_rxdone            = rt61pci_fill_rxdone,
-       .config_shared_key      = rt61pci_config_shared_key,
-       .config_pairwise_key    = rt61pci_config_pairwise_key,
-       .config_filter          = rt61pci_config_filter,
-       .config_intf            = rt61pci_config_intf,
-       .config_erp             = rt61pci_config_erp,
-       .config_ant             = rt61pci_config_ant,
-       .config                 = rt61pci_config,
-};
-
-static void rt61pci_queue_init(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 4;
-               queue->data_size = 0; /* No DMA required for beacons */
-               queue->desc_size = TXINFO_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_mmio);
-               break;
-
-       case QID_ATIM:
-               /* fallthrough */
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt61pci_ops = {
-       .name                   = KBUILD_MODNAME,
-       .max_ap_intf            = 4,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt61pci_queue_init,
-       .lib                    = &rt61pci_rt2x00_ops,
-       .hw                     = &rt61pci_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt61pci_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * RT61pci module information.
- */
-static const struct pci_device_id rt61pci_device_table[] = {
-       /* RT2561s */
-       { PCI_DEVICE(0x1814, 0x0301) },
-       /* RT2561 v2 */
-       { PCI_DEVICE(0x1814, 0x0302) },
-       /* RT2661 */
-       { PCI_DEVICE(0x1814, 0x0401) },
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT61 PCI & PCMCIA Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2561, RT2561s & RT2661 "
-                       "PCI & PCMCIA chipset based cards");
-MODULE_DEVICE_TABLE(pci, rt61pci_device_table);
-MODULE_FIRMWARE(FIRMWARE_RT2561);
-MODULE_FIRMWARE(FIRMWARE_RT2561s);
-MODULE_FIRMWARE(FIRMWARE_RT2661);
-MODULE_LICENSE("GPL");
-
-static int rt61pci_probe(struct pci_dev *pci_dev,
-                        const struct pci_device_id *id)
-{
-       return rt2x00pci_probe(pci_dev, &rt61pci_ops);
-}
-
-static struct pci_driver rt61pci_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt61pci_device_table,
-       .probe          = rt61pci_probe,
-       .remove         = rt2x00pci_remove,
-       .suspend        = rt2x00pci_suspend,
-       .resume         = rt2x00pci_resume,
-};
-
-module_pci_driver(rt61pci_driver);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
deleted file mode 100644 (file)
index 1442075..0000000
+++ /dev/null
@@ -1,1500 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt61pci
-       Abstract: Data structures and registers for the rt61pci module.
-       Supported chipsets: RT2561, RT2561s, RT2661.
- */
-
-#ifndef RT61PCI_H
-#define RT61PCI_H
-
-/*
- * RT chip PCI IDs.
- */
-#define RT2561s_PCI_ID                 0x0301
-#define RT2561_PCI_ID                  0x0302
-#define RT2661_PCI_ID                  0x0401
-
-/*
- * RF chip defines.
- */
-#define RF5225                         0x0001
-#define RF5325                         0x0002
-#define RF2527                         0x0003
-#define RF2529                         0x0004
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET            120
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x3000
-#define CSR_REG_SIZE                   0x04b0
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x0100
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x0080
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  4
-
-/*
- * PCI registers.
- */
-
-/*
- * HOST_CMD_CSR: For HOST to interrupt embedded processor
- */
-#define HOST_CMD_CSR                   0x0008
-#define HOST_CMD_CSR_HOST_COMMAND      FIELD32(0x0000007f)
-#define HOST_CMD_CSR_INTERRUPT_MCU     FIELD32(0x00000080)
-
-/*
- * MCU_CNTL_CSR
- * SELECT_BANK: Select 8051 program bank.
- * RESET: Enable 8051 reset state.
- * READY: Ready state for 8051.
- */
-#define MCU_CNTL_CSR                   0x000c
-#define MCU_CNTL_CSR_SELECT_BANK       FIELD32(0x00000001)
-#define MCU_CNTL_CSR_RESET             FIELD32(0x00000002)
-#define MCU_CNTL_CSR_READY             FIELD32(0x00000004)
-
-/*
- * SOFT_RESET_CSR
- * FORCE_CLOCK_ON: Host force MAC clock ON
- */
-#define SOFT_RESET_CSR                 0x0010
-#define SOFT_RESET_CSR_FORCE_CLOCK_ON  FIELD32(0x00000002)
-
-/*
- * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register.
- */
-#define MCU_INT_SOURCE_CSR             0x0014
-#define MCU_INT_SOURCE_CSR_0           FIELD32(0x00000001)
-#define MCU_INT_SOURCE_CSR_1           FIELD32(0x00000002)
-#define MCU_INT_SOURCE_CSR_2           FIELD32(0x00000004)
-#define MCU_INT_SOURCE_CSR_3           FIELD32(0x00000008)
-#define MCU_INT_SOURCE_CSR_4           FIELD32(0x00000010)
-#define MCU_INT_SOURCE_CSR_5           FIELD32(0x00000020)
-#define MCU_INT_SOURCE_CSR_6           FIELD32(0x00000040)
-#define MCU_INT_SOURCE_CSR_7           FIELD32(0x00000080)
-#define MCU_INT_SOURCE_CSR_TWAKEUP     FIELD32(0x00000100)
-#define MCU_INT_SOURCE_CSR_TBTT_EXPIRE FIELD32(0x00000200)
-
-/*
- * MCU_INT_MASK_CSR: MCU interrupt source/mask register.
- */
-#define MCU_INT_MASK_CSR               0x0018
-#define MCU_INT_MASK_CSR_0             FIELD32(0x00000001)
-#define MCU_INT_MASK_CSR_1             FIELD32(0x00000002)
-#define MCU_INT_MASK_CSR_2             FIELD32(0x00000004)
-#define MCU_INT_MASK_CSR_3             FIELD32(0x00000008)
-#define MCU_INT_MASK_CSR_4             FIELD32(0x00000010)
-#define MCU_INT_MASK_CSR_5             FIELD32(0x00000020)
-#define MCU_INT_MASK_CSR_6             FIELD32(0x00000040)
-#define MCU_INT_MASK_CSR_7             FIELD32(0x00000080)
-#define MCU_INT_MASK_CSR_TWAKEUP       FIELD32(0x00000100)
-#define MCU_INT_MASK_CSR_TBTT_EXPIRE   FIELD32(0x00000200)
-
-/*
- * PCI_USEC_CSR
- */
-#define PCI_USEC_CSR                   0x001c
-
-/*
- * Security key table memory.
- * 16 entries 32-byte for shared key table
- * 64 entries 32-byte for pairwise key table
- * 64 entries 8-byte for pairwise ta key table
- */
-#define SHARED_KEY_TABLE_BASE          0x1000
-#define PAIRWISE_KEY_TABLE_BASE                0x1200
-#define PAIRWISE_TA_TABLE_BASE         0x1a00
-
-#define SHARED_KEY_ENTRY(__idx) \
-       ( SHARED_KEY_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_key_entry)) )
-#define PAIRWISE_KEY_ENTRY(__idx) \
-       ( PAIRWISE_KEY_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_key_entry)) )
-#define PAIRWISE_TA_ENTRY(__idx) \
-       ( PAIRWISE_TA_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
-
-struct hw_key_entry {
-       u8 key[16];
-       u8 tx_mic[8];
-       u8 rx_mic[8];
-} __packed;
-
-struct hw_pairwise_ta_entry {
-       u8 address[6];
-       u8 cipher;
-       u8 reserved;
-} __packed;
-
-/*
- * Other on-chip shared memory space.
- */
-#define HW_CIS_BASE                    0x2000
-#define HW_NULL_BASE                   0x2b00
-
-/*
- * Since NULL frame won't be that long (256 byte),
- * We steal 16 tail bytes to save debugging settings.
- */
-#define HW_DEBUG_SETTING_BASE          0x2bf0
-
-/*
- * On-chip BEACON frame space.
- */
-#define HW_BEACON_BASE0                        0x2c00
-#define HW_BEACON_BASE1                        0x2d00
-#define HW_BEACON_BASE2                        0x2e00
-#define HW_BEACON_BASE3                        0x2f00
-
-#define HW_BEACON_OFFSET(__index) \
-       ( HW_BEACON_BASE0 + (__index * 0x0100) )
-
-/*
- * HOST-MCU shared memory.
- */
-
-/*
- * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
- */
-#define H2M_MAILBOX_CSR                        0x2100
-#define H2M_MAILBOX_CSR_ARG0           FIELD32(0x000000ff)
-#define H2M_MAILBOX_CSR_ARG1           FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CSR_CMD_TOKEN      FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CSR_OWNER          FIELD32(0xff000000)
-
-/*
- * MCU_LEDCS: LED control for MCU Mailbox.
- */
-#define MCU_LEDCS_LED_MODE             FIELD16(0x001f)
-#define MCU_LEDCS_RADIO_STATUS         FIELD16(0x0020)
-#define MCU_LEDCS_LINK_BG_STATUS       FIELD16(0x0040)
-#define MCU_LEDCS_LINK_A_STATUS                FIELD16(0x0080)
-#define MCU_LEDCS_POLARITY_GPIO_0      FIELD16(0x0100)
-#define MCU_LEDCS_POLARITY_GPIO_1      FIELD16(0x0200)
-#define MCU_LEDCS_POLARITY_GPIO_2      FIELD16(0x0400)
-#define MCU_LEDCS_POLARITY_GPIO_3      FIELD16(0x0800)
-#define MCU_LEDCS_POLARITY_GPIO_4      FIELD16(0x1000)
-#define MCU_LEDCS_POLARITY_ACT         FIELD16(0x2000)
-#define MCU_LEDCS_POLARITY_READY_BG    FIELD16(0x4000)
-#define MCU_LEDCS_POLARITY_READY_A     FIELD16(0x8000)
-
-/*
- * M2H_CMD_DONE_CSR.
- */
-#define M2H_CMD_DONE_CSR               0x2104
-
-/*
- * MCU_TXOP_ARRAY_BASE.
- */
-#define MCU_TXOP_ARRAY_BASE            0x2110
-
-/*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- */
-#define MAC_CSR0                       0x3000
-#define MAC_CSR0_REVISION              FIELD32(0x0000000f)
-#define MAC_CSR0_CHIPSET               FIELD32(0x000ffff0)
-
-/*
- * MAC_CSR1: System control register.
- * SOFT_RESET: Software reset bit, 1: reset, 0: normal.
- * BBP_RESET: Hardware reset BBP.
- * HOST_READY: Host is ready after initialization, 1: ready.
- */
-#define MAC_CSR1                       0x3004
-#define MAC_CSR1_SOFT_RESET            FIELD32(0x00000001)
-#define MAC_CSR1_BBP_RESET             FIELD32(0x00000002)
-#define MAC_CSR1_HOST_READY            FIELD32(0x00000004)
-
-/*
- * MAC_CSR2: STA MAC register 0.
- */
-#define MAC_CSR2                       0x3008
-#define MAC_CSR2_BYTE0                 FIELD32(0x000000ff)
-#define MAC_CSR2_BYTE1                 FIELD32(0x0000ff00)
-#define MAC_CSR2_BYTE2                 FIELD32(0x00ff0000)
-#define MAC_CSR2_BYTE3                 FIELD32(0xff000000)
-
-/*
- * MAC_CSR3: STA MAC register 1.
- * UNICAST_TO_ME_MASK:
- *     Used to mask off bits from byte 5 of the MAC address
- *     to determine the UNICAST_TO_ME bit for RX frames.
- *     The full mask is complemented by BSS_ID_MASK:
- *             MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
-#define MAC_CSR3                       0x300c
-#define MAC_CSR3_BYTE4                 FIELD32(0x000000ff)
-#define MAC_CSR3_BYTE5                 FIELD32(0x0000ff00)
-#define MAC_CSR3_UNICAST_TO_ME_MASK    FIELD32(0x00ff0000)
-
-/*
- * MAC_CSR4: BSSID register 0.
- */
-#define MAC_CSR4                       0x3010
-#define MAC_CSR4_BYTE0                 FIELD32(0x000000ff)
-#define MAC_CSR4_BYTE1                 FIELD32(0x0000ff00)
-#define MAC_CSR4_BYTE2                 FIELD32(0x00ff0000)
-#define MAC_CSR4_BYTE3                 FIELD32(0xff000000)
-
-/*
- * MAC_CSR5: BSSID register 1.
- * BSS_ID_MASK:
- *     This mask is used to mask off bits 0 and 1 of byte 5 of the
- *     BSSID. This will make sure that those bits will be ignored
- *     when determining the MY_BSS of RX frames.
- *             0: 1-BSSID mode (BSS index = 0)
- *             1: 2-BSSID mode (BSS index: Byte5, bit 0)
- *             2: 2-BSSID mode (BSS index: byte5, bit 1)
- *             3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- */
-#define MAC_CSR5                       0x3014
-#define MAC_CSR5_BYTE4                 FIELD32(0x000000ff)
-#define MAC_CSR5_BYTE5                 FIELD32(0x0000ff00)
-#define MAC_CSR5_BSS_ID_MASK           FIELD32(0x00ff0000)
-
-/*
- * MAC_CSR6: Maximum frame length register.
- */
-#define MAC_CSR6                       0x3018
-#define MAC_CSR6_MAX_FRAME_UNIT                FIELD32(0x00000fff)
-
-/*
- * MAC_CSR7: Reserved
- */
-#define MAC_CSR7                       0x301c
-
-/*
- * MAC_CSR8: SIFS/EIFS register.
- * All units are in US.
- */
-#define MAC_CSR8                       0x3020
-#define MAC_CSR8_SIFS                  FIELD32(0x000000ff)
-#define MAC_CSR8_SIFS_AFTER_RX_OFDM    FIELD32(0x0000ff00)
-#define MAC_CSR8_EIFS                  FIELD32(0xffff0000)
-
-/*
- * MAC_CSR9: Back-Off control register.
- * SLOT_TIME: Slot time, default is 20us for 802.11BG.
- * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1).
- * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1).
- * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD.
- */
-#define MAC_CSR9                       0x3024
-#define MAC_CSR9_SLOT_TIME             FIELD32(0x000000ff)
-#define MAC_CSR9_CWMIN                 FIELD32(0x00000f00)
-#define MAC_CSR9_CWMAX                 FIELD32(0x0000f000)
-#define MAC_CSR9_CW_SELECT             FIELD32(0x00010000)
-
-/*
- * MAC_CSR10: Power state configuration.
- */
-#define MAC_CSR10                      0x3028
-
-/*
- * MAC_CSR11: Power saving transition time register.
- * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU.
- * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
- * WAKEUP_LATENCY: In unit of TU.
- */
-#define MAC_CSR11                      0x302c
-#define MAC_CSR11_DELAY_AFTER_TBCN     FIELD32(0x000000ff)
-#define MAC_CSR11_TBCN_BEFORE_WAKEUP   FIELD32(0x00007f00)
-#define MAC_CSR11_AUTOWAKE             FIELD32(0x00008000)
-#define MAC_CSR11_WAKEUP_LATENCY       FIELD32(0x000f0000)
-
-/*
- * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1).
- * CURRENT_STATE: 0:sleep, 1:awake.
- * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP.
- * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake.
- */
-#define MAC_CSR12                      0x3030
-#define MAC_CSR12_CURRENT_STATE                FIELD32(0x00000001)
-#define MAC_CSR12_PUT_TO_SLEEP         FIELD32(0x00000002)
-#define MAC_CSR12_FORCE_WAKEUP         FIELD32(0x00000004)
-#define MAC_CSR12_BBP_CURRENT_STATE    FIELD32(0x00000008)
-
-/*
- * MAC_CSR13: GPIO.
- *     MAC_CSR13_VALx: GPIO value
- *     MAC_CSR13_DIRx: GPIO direction: 0 = output; 1 = input
- */
-#define MAC_CSR13                      0x3034
-#define MAC_CSR13_VAL0                 FIELD32(0x00000001)
-#define MAC_CSR13_VAL1                 FIELD32(0x00000002)
-#define MAC_CSR13_VAL2                 FIELD32(0x00000004)
-#define MAC_CSR13_VAL3                 FIELD32(0x00000008)
-#define MAC_CSR13_VAL4                 FIELD32(0x00000010)
-#define MAC_CSR13_VAL5                 FIELD32(0x00000020)
-#define MAC_CSR13_DIR0                 FIELD32(0x00000100)
-#define MAC_CSR13_DIR1                 FIELD32(0x00000200)
-#define MAC_CSR13_DIR2                 FIELD32(0x00000400)
-#define MAC_CSR13_DIR3                 FIELD32(0x00000800)
-#define MAC_CSR13_DIR4                 FIELD32(0x00001000)
-#define MAC_CSR13_DIR5                 FIELD32(0x00002000)
-
-/*
- * MAC_CSR14: LED control register.
- * ON_PERIOD: On period, default 70ms.
- * OFF_PERIOD: Off period, default 30ms.
- * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON.
- * SW_LED: s/w LED, 1: ON, 0: OFF.
- * HW_LED_POLARITY: 0: active low, 1: active high.
- */
-#define MAC_CSR14                      0x3038
-#define MAC_CSR14_ON_PERIOD            FIELD32(0x000000ff)
-#define MAC_CSR14_OFF_PERIOD           FIELD32(0x0000ff00)
-#define MAC_CSR14_HW_LED               FIELD32(0x00010000)
-#define MAC_CSR14_SW_LED               FIELD32(0x00020000)
-#define MAC_CSR14_HW_LED_POLARITY      FIELD32(0x00040000)
-#define MAC_CSR14_SW_LED2              FIELD32(0x00080000)
-
-/*
- * MAC_CSR15: NAV control.
- */
-#define MAC_CSR15                      0x303c
-
-/*
- * TXRX control registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * TXRX_CSR0: TX/RX configuration register.
- * TSF_OFFSET: Default is 24.
- * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame.
- * DISABLE_RX: Disable Rx engine.
- * DROP_CRC: Drop CRC error.
- * DROP_PHYSICAL: Drop physical error.
- * DROP_CONTROL: Drop control frame.
- * DROP_NOT_TO_ME: Drop not to me unicast frame.
- * DROP_TO_DS: Drop fram ToDs bit is true.
- * DROP_VERSION_ERROR: Drop version error frame.
- * DROP_MULTICAST: Drop multicast frames.
- * DROP_BORADCAST: Drop broadcast frames.
- * DROP_ACK_CTS: Drop received ACK and CTS.
- */
-#define TXRX_CSR0                      0x3040
-#define TXRX_CSR0_RX_ACK_TIMEOUT       FIELD32(0x000001ff)
-#define TXRX_CSR0_TSF_OFFSET           FIELD32(0x00007e00)
-#define TXRX_CSR0_AUTO_TX_SEQ          FIELD32(0x00008000)
-#define TXRX_CSR0_DISABLE_RX           FIELD32(0x00010000)
-#define TXRX_CSR0_DROP_CRC             FIELD32(0x00020000)
-#define TXRX_CSR0_DROP_PHYSICAL                FIELD32(0x00040000)
-#define TXRX_CSR0_DROP_CONTROL         FIELD32(0x00080000)
-#define TXRX_CSR0_DROP_NOT_TO_ME       FIELD32(0x00100000)
-#define TXRX_CSR0_DROP_TO_DS           FIELD32(0x00200000)
-#define TXRX_CSR0_DROP_VERSION_ERROR   FIELD32(0x00400000)
-#define TXRX_CSR0_DROP_MULTICAST       FIELD32(0x00800000)
-#define TXRX_CSR0_DROP_BROADCAST       FIELD32(0x01000000)
-#define TXRX_CSR0_DROP_ACK_CTS         FIELD32(0x02000000)
-#define TXRX_CSR0_TX_WITHOUT_WAITING   FIELD32(0x04000000)
-
-/*
- * TXRX_CSR1
- */
-#define TXRX_CSR1                      0x3044
-#define TXRX_CSR1_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR1_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR1_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR1_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR1_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR1_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR1_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR1_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR2
- */
-#define TXRX_CSR2                      0x3048
-#define TXRX_CSR2_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR2_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR2_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR2_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR2_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR2_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR2_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR2_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR3
- */
-#define TXRX_CSR3                      0x304c
-#define TXRX_CSR3_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR3_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR3_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR3_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR3_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR3_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR3_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR3_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR4: Auto-Responder/Tx-retry register.
- * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble.
- * OFDM_TX_RATE_DOWN: 1:enable.
- * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step.
- * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M.
- */
-#define TXRX_CSR4                      0x3050
-#define TXRX_CSR4_TX_ACK_TIMEOUT       FIELD32(0x000000ff)
-#define TXRX_CSR4_CNTL_ACK_POLICY      FIELD32(0x00000700)
-#define TXRX_CSR4_ACK_CTS_PSM          FIELD32(0x00010000)
-#define TXRX_CSR4_AUTORESPOND_ENABLE   FIELD32(0x00020000)
-#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000)
-#define TXRX_CSR4_OFDM_TX_RATE_DOWN    FIELD32(0x00080000)
-#define TXRX_CSR4_OFDM_TX_RATE_STEP    FIELD32(0x00300000)
-#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000)
-#define TXRX_CSR4_LONG_RETRY_LIMIT     FIELD32(0x0f000000)
-#define TXRX_CSR4_SHORT_RETRY_LIMIT    FIELD32(0xf0000000)
-
-/*
- * TXRX_CSR5
- */
-#define TXRX_CSR5                      0x3054
-
-/*
- * TXRX_CSR6: ACK/CTS payload consumed time
- */
-#define TXRX_CSR6                      0x3058
-
-/*
- * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
- */
-#define TXRX_CSR7                      0x305c
-#define TXRX_CSR7_ACK_CTS_6MBS         FIELD32(0x000000ff)
-#define TXRX_CSR7_ACK_CTS_9MBS         FIELD32(0x0000ff00)
-#define TXRX_CSR7_ACK_CTS_12MBS                FIELD32(0x00ff0000)
-#define TXRX_CSR7_ACK_CTS_18MBS                FIELD32(0xff000000)
-
-/*
- * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
- */
-#define TXRX_CSR8                      0x3060
-#define TXRX_CSR8_ACK_CTS_24MBS                FIELD32(0x000000ff)
-#define TXRX_CSR8_ACK_CTS_36MBS                FIELD32(0x0000ff00)
-#define TXRX_CSR8_ACK_CTS_48MBS                FIELD32(0x00ff0000)
-#define TXRX_CSR8_ACK_CTS_54MBS                FIELD32(0xff000000)
-
-/*
- * TXRX_CSR9: Synchronization control register.
- * BEACON_INTERVAL: In unit of 1/16 TU.
- * TSF_TICKING: Enable TSF auto counting.
- * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
- * BEACON_GEN: Enable beacon generator.
- */
-#define TXRX_CSR9                      0x3064
-#define TXRX_CSR9_BEACON_INTERVAL      FIELD32(0x0000ffff)
-#define TXRX_CSR9_TSF_TICKING          FIELD32(0x00010000)
-#define TXRX_CSR9_TSF_SYNC             FIELD32(0x00060000)
-#define TXRX_CSR9_TBTT_ENABLE          FIELD32(0x00080000)
-#define TXRX_CSR9_BEACON_GEN           FIELD32(0x00100000)
-#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000)
-
-/*
- * TXRX_CSR10: BEACON alignment.
- */
-#define TXRX_CSR10                     0x3068
-
-/*
- * TXRX_CSR11: AES mask.
- */
-#define TXRX_CSR11                     0x306c
-
-/*
- * TXRX_CSR12: TSF low 32.
- */
-#define TXRX_CSR12                     0x3070
-#define TXRX_CSR12_LOW_TSFTIMER                FIELD32(0xffffffff)
-
-/*
- * TXRX_CSR13: TSF high 32.
- */
-#define TXRX_CSR13                     0x3074
-#define TXRX_CSR13_HIGH_TSFTIMER       FIELD32(0xffffffff)
-
-/*
- * TXRX_CSR14: TBTT timer.
- */
-#define TXRX_CSR14                     0x3078
-
-/*
- * TXRX_CSR15: TKIP MIC priority byte "AND" mask.
- */
-#define TXRX_CSR15                     0x307c
-
-/*
- * PHY control registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * PHY_CSR0: RF/PS control.
- */
-#define PHY_CSR0                       0x3080
-#define PHY_CSR0_PA_PE_BG              FIELD32(0x00010000)
-#define PHY_CSR0_PA_PE_A               FIELD32(0x00020000)
-
-/*
- * PHY_CSR1
- */
-#define PHY_CSR1                       0x3084
-
-/*
- * PHY_CSR2: Pre-TX BBP control.
- */
-#define PHY_CSR2                       0x3088
-
-/*
- * PHY_CSR3: BBP serial control register.
- * VALUE: Register value to program into BBP.
- * REG_NUM: Selected BBP register.
- * READ_CONTROL: 0: Write BBP, 1: Read BBP.
- * BUSY: 1: ASIC is busy execute BBP programming.
- */
-#define PHY_CSR3                       0x308c
-#define PHY_CSR3_VALUE                 FIELD32(0x000000ff)
-#define PHY_CSR3_REGNUM                        FIELD32(0x00007f00)
-#define PHY_CSR3_READ_CONTROL          FIELD32(0x00008000)
-#define PHY_CSR3_BUSY                  FIELD32(0x00010000)
-
-/*
- * PHY_CSR4: RF serial control register
- * VALUE: Register value (include register id) serial out to RF/IF chip.
- * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22).
- * IF_SELECT: 1: select IF to program, 0: select RF to program.
- * PLL_LD: RF PLL_LD status.
- * BUSY: 1: ASIC is busy execute RF programming.
- */
-#define PHY_CSR4                       0x3090
-#define PHY_CSR4_VALUE                 FIELD32(0x00ffffff)
-#define PHY_CSR4_NUMBER_OF_BITS                FIELD32(0x1f000000)
-#define PHY_CSR4_IF_SELECT             FIELD32(0x20000000)
-#define PHY_CSR4_PLL_LD                        FIELD32(0x40000000)
-#define PHY_CSR4_BUSY                  FIELD32(0x80000000)
-
-/*
- * PHY_CSR5: RX to TX signal switch timing control.
- */
-#define PHY_CSR5                       0x3094
-#define PHY_CSR5_IQ_FLIP               FIELD32(0x00000004)
-
-/*
- * PHY_CSR6: TX to RX signal timing control.
- */
-#define PHY_CSR6                       0x3098
-#define PHY_CSR6_IQ_FLIP               FIELD32(0x00000004)
-
-/*
- * PHY_CSR7: TX DAC switching timing control.
- */
-#define PHY_CSR7                       0x309c
-
-/*
- * Security control register.
- */
-
-/*
- * SEC_CSR0: Shared key table control.
- */
-#define SEC_CSR0                       0x30a0
-#define SEC_CSR0_BSS0_KEY0_VALID       FIELD32(0x00000001)
-#define SEC_CSR0_BSS0_KEY1_VALID       FIELD32(0x00000002)
-#define SEC_CSR0_BSS0_KEY2_VALID       FIELD32(0x00000004)
-#define SEC_CSR0_BSS0_KEY3_VALID       FIELD32(0x00000008)
-#define SEC_CSR0_BSS1_KEY0_VALID       FIELD32(0x00000010)
-#define SEC_CSR0_BSS1_KEY1_VALID       FIELD32(0x00000020)
-#define SEC_CSR0_BSS1_KEY2_VALID       FIELD32(0x00000040)
-#define SEC_CSR0_BSS1_KEY3_VALID       FIELD32(0x00000080)
-#define SEC_CSR0_BSS2_KEY0_VALID       FIELD32(0x00000100)
-#define SEC_CSR0_BSS2_KEY1_VALID       FIELD32(0x00000200)
-#define SEC_CSR0_BSS2_KEY2_VALID       FIELD32(0x00000400)
-#define SEC_CSR0_BSS2_KEY3_VALID       FIELD32(0x00000800)
-#define SEC_CSR0_BSS3_KEY0_VALID       FIELD32(0x00001000)
-#define SEC_CSR0_BSS3_KEY1_VALID       FIELD32(0x00002000)
-#define SEC_CSR0_BSS3_KEY2_VALID       FIELD32(0x00004000)
-#define SEC_CSR0_BSS3_KEY3_VALID       FIELD32(0x00008000)
-
-/*
- * SEC_CSR1: Shared key table security mode register.
- */
-#define SEC_CSR1                       0x30a4
-#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG  FIELD32(0x00000007)
-#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG  FIELD32(0x00000070)
-#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG  FIELD32(0x00000700)
-#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG  FIELD32(0x00007000)
-#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG  FIELD32(0x00070000)
-#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG  FIELD32(0x00700000)
-#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG  FIELD32(0x07000000)
-#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG  FIELD32(0x70000000)
-
-/*
- * Pairwise key table valid bitmap registers.
- * SEC_CSR2: pairwise key table valid bitmap 0.
- * SEC_CSR3: pairwise key table valid bitmap 1.
- */
-#define SEC_CSR2                       0x30a8
-#define SEC_CSR3                       0x30ac
-
-/*
- * SEC_CSR4: Pairwise key table lookup control.
- */
-#define SEC_CSR4                       0x30b0
-#define SEC_CSR4_ENABLE_BSS0           FIELD32(0x00000001)
-#define SEC_CSR4_ENABLE_BSS1           FIELD32(0x00000002)
-#define SEC_CSR4_ENABLE_BSS2           FIELD32(0x00000004)
-#define SEC_CSR4_ENABLE_BSS3           FIELD32(0x00000008)
-
-/*
- * SEC_CSR5: shared key table security mode register.
- */
-#define SEC_CSR5                       0x30b4
-#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG  FIELD32(0x00000007)
-#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG  FIELD32(0x00000070)
-#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG  FIELD32(0x00000700)
-#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG  FIELD32(0x00007000)
-#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG  FIELD32(0x00070000)
-#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG  FIELD32(0x00700000)
-#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG  FIELD32(0x07000000)
-#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG  FIELD32(0x70000000)
-
-/*
- * STA control registers.
- */
-
-/*
- * STA_CSR0: RX PLCP error count & RX FCS error count.
- */
-#define STA_CSR0                       0x30c0
-#define STA_CSR0_FCS_ERROR             FIELD32(0x0000ffff)
-#define STA_CSR0_PLCP_ERROR            FIELD32(0xffff0000)
-
-/*
- * STA_CSR1: RX False CCA count & RX LONG frame count.
- */
-#define STA_CSR1                       0x30c4
-#define STA_CSR1_PHYSICAL_ERROR                FIELD32(0x0000ffff)
-#define STA_CSR1_FALSE_CCA_ERROR       FIELD32(0xffff0000)
-
-/*
- * STA_CSR2: TX Beacon count and RX FIFO overflow count.
- */
-#define STA_CSR2                       0x30c8
-#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT        FIELD32(0x0000ffff)
-#define STA_CSR2_RX_OVERFLOW_COUNT     FIELD32(0xffff0000)
-
-/*
- * STA_CSR3: TX Beacon count.
- */
-#define STA_CSR3                       0x30cc
-#define STA_CSR3_TX_BEACON_COUNT       FIELD32(0x0000ffff)
-
-/*
- * STA_CSR4: TX Result status register.
- * VALID: 1:This register contains a valid TX result.
- */
-#define STA_CSR4                       0x30d0
-#define STA_CSR4_VALID                 FIELD32(0x00000001)
-#define STA_CSR4_TX_RESULT             FIELD32(0x0000000e)
-#define STA_CSR4_RETRY_COUNT           FIELD32(0x000000f0)
-#define STA_CSR4_PID_SUBTYPE           FIELD32(0x00001f00)
-#define STA_CSR4_PID_TYPE              FIELD32(0x0000e000)
-#define STA_CSR4_TXRATE                        FIELD32(0x000f0000)
-
-/*
- * QOS control registers.
- */
-
-/*
- * QOS_CSR0: TXOP holder MAC address register.
- */
-#define QOS_CSR0                       0x30e0
-#define QOS_CSR0_BYTE0                 FIELD32(0x000000ff)
-#define QOS_CSR0_BYTE1                 FIELD32(0x0000ff00)
-#define QOS_CSR0_BYTE2                 FIELD32(0x00ff0000)
-#define QOS_CSR0_BYTE3                 FIELD32(0xff000000)
-
-/*
- * QOS_CSR1: TXOP holder MAC address register.
- */
-#define QOS_CSR1                       0x30e4
-#define QOS_CSR1_BYTE4                 FIELD32(0x000000ff)
-#define QOS_CSR1_BYTE5                 FIELD32(0x0000ff00)
-
-/*
- * QOS_CSR2: TXOP holder timeout register.
- */
-#define QOS_CSR2                       0x30e8
-
-/*
- * RX QOS-CFPOLL MAC address register.
- * QOS_CSR3: RX QOS-CFPOLL MAC address 0.
- * QOS_CSR4: RX QOS-CFPOLL MAC address 1.
- */
-#define QOS_CSR3                       0x30ec
-#define QOS_CSR4                       0x30f0
-
-/*
- * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL.
- */
-#define QOS_CSR5                       0x30f4
-
-/*
- * Host DMA registers.
- */
-
-/*
- * AC0_BASE_CSR: AC_VO base address.
- */
-#define AC0_BASE_CSR                   0x3400
-#define AC0_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
-
-/*
- * AC1_BASE_CSR: AC_VI base address.
- */
-#define AC1_BASE_CSR                   0x3404
-#define AC1_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
-
-/*
- * AC2_BASE_CSR: AC_BE base address.
- */
-#define AC2_BASE_CSR                   0x3408
-#define AC2_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
-
-/*
- * AC3_BASE_CSR: AC_BK base address.
- */
-#define AC3_BASE_CSR                   0x340c
-#define AC3_BASE_CSR_RING_REGISTER     FIELD32(0xffffffff)
-
-/*
- * MGMT_BASE_CSR: MGMT ring base address.
- */
-#define MGMT_BASE_CSR                  0x3410
-#define MGMT_BASE_CSR_RING_REGISTER    FIELD32(0xffffffff)
-
-/*
- * TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK.
- */
-#define TX_RING_CSR0                   0x3418
-#define TX_RING_CSR0_AC0_RING_SIZE     FIELD32(0x000000ff)
-#define TX_RING_CSR0_AC1_RING_SIZE     FIELD32(0x0000ff00)
-#define TX_RING_CSR0_AC2_RING_SIZE     FIELD32(0x00ff0000)
-#define TX_RING_CSR0_AC3_RING_SIZE     FIELD32(0xff000000)
-
-/*
- * TX_RING_CSR1: TX Ring size for MGMT Ring, HCCA Ring
- * TXD_SIZE: In unit of 32-bit.
- */
-#define TX_RING_CSR1                   0x341c
-#define TX_RING_CSR1_MGMT_RING_SIZE    FIELD32(0x000000ff)
-#define TX_RING_CSR1_HCCA_RING_SIZE    FIELD32(0x0000ff00)
-#define TX_RING_CSR1_TXD_SIZE          FIELD32(0x003f0000)
-
-/*
- * AIFSN_CSR: AIFSN for each EDCA AC.
- * AIFSN0: For AC_VO.
- * AIFSN1: For AC_VI.
- * AIFSN2: For AC_BE.
- * AIFSN3: For AC_BK.
- */
-#define AIFSN_CSR                      0x3420
-#define AIFSN_CSR_AIFSN0               FIELD32(0x0000000f)
-#define AIFSN_CSR_AIFSN1               FIELD32(0x000000f0)
-#define AIFSN_CSR_AIFSN2               FIELD32(0x00000f00)
-#define AIFSN_CSR_AIFSN3               FIELD32(0x0000f000)
-
-/*
- * CWMIN_CSR: CWmin for each EDCA AC.
- * CWMIN0: For AC_VO.
- * CWMIN1: For AC_VI.
- * CWMIN2: For AC_BE.
- * CWMIN3: For AC_BK.
- */
-#define CWMIN_CSR                      0x3424
-#define CWMIN_CSR_CWMIN0               FIELD32(0x0000000f)
-#define CWMIN_CSR_CWMIN1               FIELD32(0x000000f0)
-#define CWMIN_CSR_CWMIN2               FIELD32(0x00000f00)
-#define CWMIN_CSR_CWMIN3               FIELD32(0x0000f000)
-
-/*
- * CWMAX_CSR: CWmax for each EDCA AC.
- * CWMAX0: For AC_VO.
- * CWMAX1: For AC_VI.
- * CWMAX2: For AC_BE.
- * CWMAX3: For AC_BK.
- */
-#define CWMAX_CSR                      0x3428
-#define CWMAX_CSR_CWMAX0               FIELD32(0x0000000f)
-#define CWMAX_CSR_CWMAX1               FIELD32(0x000000f0)
-#define CWMAX_CSR_CWMAX2               FIELD32(0x00000f00)
-#define CWMAX_CSR_CWMAX3               FIELD32(0x0000f000)
-
-/*
- * TX_DMA_DST_CSR: TX DMA destination
- * 0: TX ring0, 1: TX ring1, 2: TX ring2 3: invalid
- */
-#define TX_DMA_DST_CSR                 0x342c
-#define TX_DMA_DST_CSR_DEST_AC0                FIELD32(0x00000003)
-#define TX_DMA_DST_CSR_DEST_AC1                FIELD32(0x0000000c)
-#define TX_DMA_DST_CSR_DEST_AC2                FIELD32(0x00000030)
-#define TX_DMA_DST_CSR_DEST_AC3                FIELD32(0x000000c0)
-#define TX_DMA_DST_CSR_DEST_MGMT       FIELD32(0x00000300)
-
-/*
- * TX_CNTL_CSR: KICK/Abort TX.
- * KICK_TX_AC0: For AC_VO.
- * KICK_TX_AC1: For AC_VI.
- * KICK_TX_AC2: For AC_BE.
- * KICK_TX_AC3: For AC_BK.
- * ABORT_TX_AC0: For AC_VO.
- * ABORT_TX_AC1: For AC_VI.
- * ABORT_TX_AC2: For AC_BE.
- * ABORT_TX_AC3: For AC_BK.
- */
-#define TX_CNTL_CSR                    0x3430
-#define TX_CNTL_CSR_KICK_TX_AC0                FIELD32(0x00000001)
-#define TX_CNTL_CSR_KICK_TX_AC1                FIELD32(0x00000002)
-#define TX_CNTL_CSR_KICK_TX_AC2                FIELD32(0x00000004)
-#define TX_CNTL_CSR_KICK_TX_AC3                FIELD32(0x00000008)
-#define TX_CNTL_CSR_KICK_TX_MGMT       FIELD32(0x00000010)
-#define TX_CNTL_CSR_ABORT_TX_AC0       FIELD32(0x00010000)
-#define TX_CNTL_CSR_ABORT_TX_AC1       FIELD32(0x00020000)
-#define TX_CNTL_CSR_ABORT_TX_AC2       FIELD32(0x00040000)
-#define TX_CNTL_CSR_ABORT_TX_AC3       FIELD32(0x00080000)
-#define TX_CNTL_CSR_ABORT_TX_MGMT      FIELD32(0x00100000)
-
-/*
- * LOAD_TX_RING_CSR: Load RX desriptor
- */
-#define LOAD_TX_RING_CSR               0x3434
-#define LOAD_TX_RING_CSR_LOAD_TXD_AC0  FIELD32(0x00000001)
-#define LOAD_TX_RING_CSR_LOAD_TXD_AC1  FIELD32(0x00000002)
-#define LOAD_TX_RING_CSR_LOAD_TXD_AC2  FIELD32(0x00000004)
-#define LOAD_TX_RING_CSR_LOAD_TXD_AC3  FIELD32(0x00000008)
-#define LOAD_TX_RING_CSR_LOAD_TXD_MGMT FIELD32(0x00000010)
-
-/*
- * Several read-only registers, for debugging.
- */
-#define AC0_TXPTR_CSR                  0x3438
-#define AC1_TXPTR_CSR                  0x343c
-#define AC2_TXPTR_CSR                  0x3440
-#define AC3_TXPTR_CSR                  0x3444
-#define MGMT_TXPTR_CSR                 0x3448
-
-/*
- * RX_BASE_CSR
- */
-#define RX_BASE_CSR                    0x3450
-#define RX_BASE_CSR_RING_REGISTER      FIELD32(0xffffffff)
-
-/*
- * RX_RING_CSR.
- * RXD_SIZE: In unit of 32-bit.
- */
-#define RX_RING_CSR                    0x3454
-#define RX_RING_CSR_RING_SIZE          FIELD32(0x000000ff)
-#define RX_RING_CSR_RXD_SIZE           FIELD32(0x00003f00)
-#define RX_RING_CSR_RXD_WRITEBACK_SIZE FIELD32(0x00070000)
-
-/*
- * RX_CNTL_CSR
- */
-#define RX_CNTL_CSR                    0x3458
-#define RX_CNTL_CSR_ENABLE_RX_DMA      FIELD32(0x00000001)
-#define RX_CNTL_CSR_LOAD_RXD           FIELD32(0x00000002)
-
-/*
- * RXPTR_CSR: Read-only, for debugging.
- */
-#define RXPTR_CSR                      0x345c
-
-/*
- * PCI_CFG_CSR
- */
-#define PCI_CFG_CSR                    0x3460
-
-/*
- * BUF_FORMAT_CSR
- */
-#define BUF_FORMAT_CSR                 0x3464
-
-/*
- * INT_SOURCE_CSR: Interrupt source register.
- * Write one to clear corresponding bit.
- */
-#define INT_SOURCE_CSR                 0x3468
-#define INT_SOURCE_CSR_TXDONE          FIELD32(0x00000001)
-#define INT_SOURCE_CSR_RXDONE          FIELD32(0x00000002)
-#define INT_SOURCE_CSR_BEACON_DONE     FIELD32(0x00000004)
-#define INT_SOURCE_CSR_TX_ABORT_DONE   FIELD32(0x00000010)
-#define INT_SOURCE_CSR_AC0_DMA_DONE    FIELD32(0x00010000)
-#define INT_SOURCE_CSR_AC1_DMA_DONE    FIELD32(0x00020000)
-#define INT_SOURCE_CSR_AC2_DMA_DONE    FIELD32(0x00040000)
-#define INT_SOURCE_CSR_AC3_DMA_DONE    FIELD32(0x00080000)
-#define INT_SOURCE_CSR_MGMT_DMA_DONE   FIELD32(0x00100000)
-#define INT_SOURCE_CSR_HCCA_DMA_DONE   FIELD32(0x00200000)
-
-/*
- * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
- * MITIGATION_PERIOD: Interrupt mitigation in unit of 32 PCI clock.
- */
-#define INT_MASK_CSR                   0x346c
-#define INT_MASK_CSR_TXDONE            FIELD32(0x00000001)
-#define INT_MASK_CSR_RXDONE            FIELD32(0x00000002)
-#define INT_MASK_CSR_BEACON_DONE       FIELD32(0x00000004)
-#define INT_MASK_CSR_TX_ABORT_DONE     FIELD32(0x00000010)
-#define INT_MASK_CSR_ENABLE_MITIGATION FIELD32(0x00000080)
-#define INT_MASK_CSR_MITIGATION_PERIOD FIELD32(0x0000ff00)
-#define INT_MASK_CSR_AC0_DMA_DONE      FIELD32(0x00010000)
-#define INT_MASK_CSR_AC1_DMA_DONE      FIELD32(0x00020000)
-#define INT_MASK_CSR_AC2_DMA_DONE      FIELD32(0x00040000)
-#define INT_MASK_CSR_AC3_DMA_DONE      FIELD32(0x00080000)
-#define INT_MASK_CSR_MGMT_DMA_DONE     FIELD32(0x00100000)
-#define INT_MASK_CSR_HCCA_DMA_DONE     FIELD32(0x00200000)
-
-/*
- * E2PROM_CSR: EEPROM control register.
- * RELOAD: Write 1 to reload eeprom content.
- * TYPE_93C46: 1: 93c46, 0:93c66.
- * LOAD_STATUS: 1:loading, 0:done.
- */
-#define E2PROM_CSR                     0x3470
-#define E2PROM_CSR_RELOAD              FIELD32(0x00000001)
-#define E2PROM_CSR_DATA_CLOCK          FIELD32(0x00000002)
-#define E2PROM_CSR_CHIP_SELECT         FIELD32(0x00000004)
-#define E2PROM_CSR_DATA_IN             FIELD32(0x00000008)
-#define E2PROM_CSR_DATA_OUT            FIELD32(0x00000010)
-#define E2PROM_CSR_TYPE_93C46          FIELD32(0x00000020)
-#define E2PROM_CSR_LOAD_STATUS         FIELD32(0x00000040)
-
-/*
- * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
- * AC0_TX_OP: For AC_VO, in unit of 32us.
- * AC1_TX_OP: For AC_VI, in unit of 32us.
- */
-#define AC_TXOP_CSR0                   0x3474
-#define AC_TXOP_CSR0_AC0_TX_OP         FIELD32(0x0000ffff)
-#define AC_TXOP_CSR0_AC1_TX_OP         FIELD32(0xffff0000)
-
-/*
- * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
- * AC2_TX_OP: For AC_BE, in unit of 32us.
- * AC3_TX_OP: For AC_BK, in unit of 32us.
- */
-#define AC_TXOP_CSR1                   0x3478
-#define AC_TXOP_CSR1_AC2_TX_OP         FIELD32(0x0000ffff)
-#define AC_TXOP_CSR1_AC3_TX_OP         FIELD32(0xffff0000)
-
-/*
- * DMA_STATUS_CSR
- */
-#define DMA_STATUS_CSR                 0x3480
-
-/*
- * TEST_MODE_CSR
- */
-#define TEST_MODE_CSR                  0x3484
-
-/*
- * UART0_TX_CSR
- */
-#define UART0_TX_CSR                   0x3488
-
-/*
- * UART0_RX_CSR
- */
-#define UART0_RX_CSR                   0x348c
-
-/*
- * UART0_FRAME_CSR
- */
-#define UART0_FRAME_CSR                        0x3490
-
-/*
- * UART0_BUFFER_CSR
- */
-#define UART0_BUFFER_CSR               0x3494
-
-/*
- * IO_CNTL_CSR
- * RF_PS: Set RF interface value to power save
- */
-#define IO_CNTL_CSR                    0x3498
-#define IO_CNTL_CSR_RF_PS              FIELD32(0x00000004)
-
-/*
- * UART_INT_SOURCE_CSR
- */
-#define UART_INT_SOURCE_CSR            0x34a8
-
-/*
- * UART_INT_MASK_CSR
- */
-#define UART_INT_MASK_CSR              0x34ac
-
-/*
- * PBF_QUEUE_CSR
- */
-#define PBF_QUEUE_CSR                  0x34b0
-
-/*
- * Firmware DMA registers.
- * Firmware DMA registers are dedicated for MCU usage
- * and should not be touched by host driver.
- * Therefore we skip the definition of these registers.
- */
-#define FW_TX_BASE_CSR                 0x34c0
-#define FW_TX_START_CSR                        0x34c4
-#define FW_TX_LAST_CSR                 0x34c8
-#define FW_MODE_CNTL_CSR               0x34cc
-#define FW_TXPTR_CSR                   0x34d0
-
-/*
- * 8051 firmware image.
- */
-#define FIRMWARE_RT2561                        "rt2561.bin"
-#define FIRMWARE_RT2561s               "rt2561s.bin"
-#define FIRMWARE_RT2661                        "rt2661.bin"
-#define FIRMWARE_IMAGE_BASE            0x4000
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * R2
- */
-#define BBP_R2_BG_MODE                 FIELD8(0x20)
-
-/*
- * R3
- */
-#define BBP_R3_SMART_MODE              FIELD8(0x01)
-
-/*
- * R4: RX antenna control
- * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
- */
-
-/*
- * ANTENNA_CONTROL semantics (guessed):
- * 0x1: Software controlled antenna switching (fixed or SW diversity)
- * 0x2: Hardware diversity.
- */
-#define BBP_R4_RX_ANTENNA_CONTROL      FIELD8(0x03)
-#define BBP_R4_RX_FRAME_END            FIELD8(0x20)
-
-/*
- * R77
- */
-#define BBP_R77_RX_ANTENNA             FIELD8(0x03)
-
-/*
- * RF registers
- */
-
-/*
- * RF 3
- */
-#define RF3_TXPOWER                    FIELD32(0x00003e00)
-
-/*
- * RF 4
- */
-#define RF4_FREQ_OFFSET                        FIELD32(0x0003f000)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0              0x0002
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR1               0x0003
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2              0x0004
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM antenna.
- * ANTENNA_NUM: Number of antenna's.
- * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only.
- * DYN_TXAGC: Dynamic TX AGC control.
- * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
- * RF_TYPE: Rf_type of this adapter.
- */
-#define EEPROM_ANTENNA                 0x0010
-#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
-#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
-#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
-#define EEPROM_ANTENNA_FRAME_TYPE      FIELD16(0x0040)
-#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
-#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
-#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
-
-/*
- * EEPROM NIC config.
- * ENABLE_DIVERSITY: 1:enable, 0:disable.
- * EXTERNAL_LNA_BG: External LNA enable for 2.4G.
- * CARDBUS_ACCEL: 0:enable, 1:disable.
- * EXTERNAL_LNA_A: External LNA enable for 5G.
- */
-#define EEPROM_NIC                     0x0011
-#define EEPROM_NIC_ENABLE_DIVERSITY    FIELD16(0x0001)
-#define EEPROM_NIC_TX_DIVERSITY                FIELD16(0x0002)
-#define EEPROM_NIC_RX_FIXED            FIELD16(0x0004)
-#define EEPROM_NIC_TX_FIXED            FIELD16(0x0008)
-#define EEPROM_NIC_EXTERNAL_LNA_BG     FIELD16(0x0010)
-#define EEPROM_NIC_CARDBUS_ACCEL       FIELD16(0x0020)
-#define EEPROM_NIC_EXTERNAL_LNA_A      FIELD16(0x0040)
-
-/*
- * EEPROM geography.
- * GEO_A: Default geographical setting for 5GHz band
- * GEO: Default geographical setting.
- */
-#define EEPROM_GEOGRAPHY               0x0012
-#define EEPROM_GEOGRAPHY_GEO_A         FIELD16(0x00ff)
-#define EEPROM_GEOGRAPHY_GEO           FIELD16(0xff00)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START               0x0013
-#define EEPROM_BBP_SIZE                        16
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER 802.11G
- */
-#define EEPROM_TXPOWER_G_START         0x0023
-#define EEPROM_TXPOWER_G_SIZE          7
-#define EEPROM_TXPOWER_G_1             FIELD16(0x00ff)
-#define EEPROM_TXPOWER_G_2             FIELD16(0xff00)
-
-/*
- * EEPROM Frequency
- */
-#define EEPROM_FREQ                    0x002f
-#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
-#define EEPROM_FREQ_SEQ_MASK           FIELD16(0xff00)
-#define EEPROM_FREQ_SEQ                        FIELD16(0x0300)
-
-/*
- * EEPROM LED.
- * POLARITY_RDY_G: Polarity RDY_G setting.
- * POLARITY_RDY_A: Polarity RDY_A setting.
- * POLARITY_ACT: Polarity ACT setting.
- * POLARITY_GPIO_0: Polarity GPIO0 setting.
- * POLARITY_GPIO_1: Polarity GPIO1 setting.
- * POLARITY_GPIO_2: Polarity GPIO2 setting.
- * POLARITY_GPIO_3: Polarity GPIO3 setting.
- * POLARITY_GPIO_4: Polarity GPIO4 setting.
- * LED_MODE: Led mode.
- */
-#define EEPROM_LED                     0x0030
-#define EEPROM_LED_POLARITY_RDY_G      FIELD16(0x0001)
-#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
-#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
-#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
-#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
-#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
-#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
-#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
-#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
-
-/*
- * EEPROM TXPOWER 802.11A
- */
-#define EEPROM_TXPOWER_A_START         0x0031
-#define EEPROM_TXPOWER_A_SIZE          12
-#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
-#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
-
-/*
- * EEPROM RSSI offset 802.11BG
- */
-#define EEPROM_RSSI_OFFSET_BG          0x004d
-#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
-#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
-
-/*
- * EEPROM RSSI offset 802.11A
- */
-#define EEPROM_RSSI_OFFSET_A           0x004e
-#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
-#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
-
-/*
- * MCU mailbox commands.
- */
-#define MCU_SLEEP                      0x30
-#define MCU_WAKEUP                     0x31
-#define MCU_LED                                0x50
-#define MCU_LED_STRENGTH               0x52
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  ( 16 * sizeof(__le32) )
-#define TXINFO_SIZE                    ( 6 * sizeof(__le32) )
-#define RXD_DESC_SIZE                  ( 16 * sizeof(__le32) )
-
-/*
- * TX descriptor format for TX, PRIO and Beacon Ring.
- */
-
-/*
- * Word0
- * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used.
- * KEY_TABLE: Use per-client pairwise KEY table.
- * KEY_INDEX:
- * Key index (0~31) to the pairwise KEY table.
- * 0~3 to shared KEY table 0 (BSS0).
- * 4~7 to shared KEY table 1 (BSS1).
- * 8~11 to shared KEY table 2 (BSS2).
- * 12~15 to shared KEY table 3 (BSS3).
- * BURST: Next frame belongs to same "burst" event.
- */
-#define TXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define TXD_W0_VALID                   FIELD32(0x00000002)
-#define TXD_W0_MORE_FRAG               FIELD32(0x00000004)
-#define TXD_W0_ACK                     FIELD32(0x00000008)
-#define TXD_W0_TIMESTAMP               FIELD32(0x00000010)
-#define TXD_W0_OFDM                    FIELD32(0x00000020)
-#define TXD_W0_IFS                     FIELD32(0x00000040)
-#define TXD_W0_RETRY_MODE              FIELD32(0x00000080)
-#define TXD_W0_TKIP_MIC                        FIELD32(0x00000100)
-#define TXD_W0_KEY_TABLE               FIELD32(0x00000200)
-#define TXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
-#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define TXD_W0_BURST                   FIELD32(0x10000000)
-#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * Word1
- * HOST_Q_ID: EDCA/HCCA queue ID.
- * HW_SEQUENCE: MAC overwrites the frame sequence number.
- * BUFFER_COUNT: Number of buffers in this TXD.
- */
-#define TXD_W1_HOST_Q_ID               FIELD32(0x0000000f)
-#define TXD_W1_AIFSN                   FIELD32(0x000000f0)
-#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
-#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
-#define TXD_W1_IV_OFFSET               FIELD32(0x003f0000)
-#define TXD_W1_PIGGY_BACK              FIELD32(0x01000000)
-#define TXD_W1_HW_SEQUENCE             FIELD32(0x10000000)
-#define TXD_W1_BUFFER_COUNT            FIELD32(0xe0000000)
-
-/*
- * Word2: PLCP information
- */
-#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
-#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
-#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
-#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
-
-/*
- * Word3
- */
-#define TXD_W3_IV                      FIELD32(0xffffffff)
-
-/*
- * Word4
- */
-#define TXD_W4_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word5
- * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field).
- * TXD_W5_PID_SUBTYPE: Driver assigned packet ID index for txdone handler.
- * TXD_W5_PID_TYPE: Driver assigned packet ID type for txdone handler.
- * WAITING_DMA_DONE_INT: TXD been filled with data
- * and waiting for TxDoneISR housekeeping.
- */
-#define TXD_W5_FRAME_OFFSET            FIELD32(0x000000ff)
-#define TXD_W5_PID_SUBTYPE             FIELD32(0x00001f00)
-#define TXD_W5_PID_TYPE                        FIELD32(0x0000e000)
-#define TXD_W5_TX_POWER                        FIELD32(0x00ff0000)
-#define TXD_W5_WAITING_DMA_DONE_INT    FIELD32(0x01000000)
-
-/*
- * the above 24-byte is called TXINFO and will be DMAed to MAC block
- * through TXFIFO. MAC block use this TXINFO to control the transmission
- * behavior of this frame.
- * The following fields are not used by MAC block.
- * They are used by DMA block and HOST driver only.
- * Once a frame has been DMA to ASIC, all the following fields are useless
- * to ASIC.
- */
-
-/*
- * Word6-10: Buffer physical address
- */
-#define TXD_W6_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
-#define TXD_W7_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
-#define TXD_W8_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
-#define TXD_W9_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
-#define TXD_W10_BUFFER_PHYSICAL_ADDRESS        FIELD32(0xffffffff)
-
-/*
- * Word11-13: Buffer length
- */
-#define TXD_W11_BUFFER_LENGTH0         FIELD32(0x00000fff)
-#define TXD_W11_BUFFER_LENGTH1         FIELD32(0x0fff0000)
-#define TXD_W12_BUFFER_LENGTH2         FIELD32(0x00000fff)
-#define TXD_W12_BUFFER_LENGTH3         FIELD32(0x0fff0000)
-#define TXD_W13_BUFFER_LENGTH4         FIELD32(0x00000fff)
-
-/*
- * Word14
- */
-#define TXD_W14_SK_BUFFER              FIELD32(0xffffffff)
-
-/*
- * Word15
- */
-#define TXD_W15_NEXT_SK_BUFFER         FIELD32(0xffffffff)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key.
- * KEY_INDEX: Decryption key actually used.
- */
-#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define RXD_W0_DROP                    FIELD32(0x00000002)
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000004)
-#define RXD_W0_MULTICAST               FIELD32(0x00000008)
-#define RXD_W0_BROADCAST               FIELD32(0x00000010)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000020)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000040)
-#define RXD_W0_OFDM                    FIELD32(0x00000080)
-#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000300)
-#define RXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
-#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * Word1
- * SIGNAL: RX raw data rate reported by BBP.
- */
-#define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
-#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
-#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
-#define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
-
-/*
- * Word2
- * IV: Received IV of originally encrypted.
- */
-#define RXD_W2_IV                      FIELD32(0xffffffff)
-
-/*
- * Word3
- * EIV: Received EIV of originally encrypted.
- */
-#define RXD_W3_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word4
- * ICV: Received ICV of originally encrypted.
- * NOTE: This is a guess, the official definition is "reserved"
- */
-#define RXD_W4_ICV                     FIELD32(0xffffffff)
-
-/*
- * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
- * and passed to the HOST driver.
- * The following fields are for DMA block and HOST usage only.
- * Can't be touched by ASIC MAC block.
- */
-
-/*
- * Word5
- */
-#define RXD_W5_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff)
-
-/*
- * Word6-15: Reserved
- */
-#define RXD_W6_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W7_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W8_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W9_RESERVED                        FIELD32(0xffffffff)
-#define RXD_W10_RESERVED               FIELD32(0xffffffff)
-#define RXD_W11_RESERVED               FIELD32(0xffffffff)
-#define RXD_W12_RESERVED               FIELD32(0xffffffff)
-#define RXD_W13_RESERVED               FIELD32(0xffffffff)
-#define RXD_W14_RESERVED               FIELD32(0xffffffff)
-#define RXD_W15_RESERVED               FIELD32(0xffffffff)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_TXPOWER    0
-#define MAX_TXPOWER    31
-#define DEFAULT_TXPOWER        24
-
-#define TXPOWER_FROM_DEV(__txpower) \
-       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_TO_DEV(__txpower) \
-       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
-
-#endif /* RT61PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
deleted file mode 100644 (file)
index 7081e13..0000000
+++ /dev/null
@@ -1,2548 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt73usb
-       Abstract: rt73usb device specific routines.
-       Supported chipsets: rt2571W & rt2671.
- */
-
-#include <linux/crc-itu-t.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "rt2x00.h"
-#include "rt2x00usb.h"
-#include "rt73usb.h"
-
-/*
- * Allow hardware encryption to be disabled.
- */
-static bool modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
-MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2x00usb_register_read and rt2x00usb_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- * The _lock versions must be used if you already hold the csr_mutex
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
-       rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
-       rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
-
-static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int word, const u8 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
-               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
-               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
-               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
-
-               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, u8 *value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the BBP becomes available, afterwards we
-        * can safely write the read request into the register.
-        * After the data has been written, we wait until hardware
-        * returns the correct value, if at any time the register
-        * doesn't become available in time, reg will be 0xffffffff
-        * which means we return 0xff to the caller.
-        */
-       if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
-               rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
-               rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
-
-               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
-
-               WAIT_FOR_BBP(rt2x00dev, &reg);
-       }
-
-       *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, const u32 value)
-{
-       u32 reg;
-
-       mutex_lock(&rt2x00dev->csr_mutex);
-
-       /*
-        * Wait until the RF becomes available, afterwards we
-        * can safely write the new data into the register.
-        */
-       if (WAIT_FOR_RF(rt2x00dev, &reg)) {
-               reg = 0;
-               rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
-               /*
-                * RF5225 and RF2527 contain 21 bits per RF register value,
-                * all others contain 20 bits.
-                */
-               rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
-                                  20 + (rt2x00_rf(rt2x00dev, RF5225) ||
-                                        rt2x00_rf(rt2x00dev, RF2527)));
-               rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
-               rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
-
-               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
-               rt2x00_rf_write(rt2x00dev, word, value);
-       }
-
-       mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt73usb_rt2x00debug = {
-       .owner  = THIS_MODULE,
-       .csr    = {
-               .read           = rt2x00usb_register_read,
-               .write          = rt2x00usb_register_write,
-               .flags          = RT2X00DEBUGFS_OFFSET,
-               .word_base      = CSR_REG_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = CSR_REG_SIZE / sizeof(u32),
-       },
-       .eeprom = {
-               .read           = rt2x00_eeprom_read,
-               .write          = rt2x00_eeprom_write,
-               .word_base      = EEPROM_BASE,
-               .word_size      = sizeof(u16),
-               .word_count     = EEPROM_SIZE / sizeof(u16),
-       },
-       .bbp    = {
-               .read           = rt73usb_bbp_read,
-               .write          = rt73usb_bbp_write,
-               .word_base      = BBP_BASE,
-               .word_size      = sizeof(u8),
-               .word_count     = BBP_SIZE / sizeof(u8),
-       },
-       .rf     = {
-               .read           = rt2x00_rf_read,
-               .write          = rt73usb_rf_write,
-               .word_base      = RF_BASE,
-               .word_size      = sizeof(u32),
-               .word_count     = RF_SIZE / sizeof(u32),
-       },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
-       return rt2x00_get_field32(reg, MAC_CSR13_VAL7);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt73usb_brightness_set(struct led_classdev *led_cdev,
-                                  enum led_brightness brightness)
-{
-       struct rt2x00_led *led =
-          container_of(led_cdev, struct rt2x00_led, led_dev);
-       unsigned int enabled = brightness != LED_OFF;
-       unsigned int a_mode =
-           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-       unsigned int bg_mode =
-           (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-
-       if (led->type == LED_TYPE_RADIO) {
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_RADIO_STATUS, enabled);
-
-               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-                                           0, led->rt2x00dev->led_mcu_reg,
-                                           REGISTER_TIMEOUT);
-       } else if (led->type == LED_TYPE_ASSOC) {
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_LINK_BG_STATUS, bg_mode);
-               rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-                                  MCU_LEDCS_LINK_A_STATUS, a_mode);
-
-               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-                                           0, led->rt2x00dev->led_mcu_reg,
-                                           REGISTER_TIMEOUT);
-       } else if (led->type == LED_TYPE_QUALITY) {
-               /*
-                * The brightness is divided into 6 levels (0 - 5),
-                * this means we need to convert the brightness
-                * argument into the matching level within that range.
-                */
-               rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-                                           brightness / (LED_FULL / 6),
-                                           led->rt2x00dev->led_mcu_reg,
-                                           REGISTER_TIMEOUT);
-       }
-}
-
-static int rt73usb_blink_set(struct led_classdev *led_cdev,
-                            unsigned long *delay_on,
-                            unsigned long *delay_off)
-{
-       struct rt2x00_led *led =
-           container_of(led_cdev, struct rt2x00_led, led_dev);
-       u32 reg;
-
-       rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
-       rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
-       rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
-
-       return 0;
-}
-
-static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
-                            struct rt2x00_led *led,
-                            enum led_type type)
-{
-       led->rt2x00dev = rt2x00dev;
-       led->type = type;
-       led->led_dev.brightness_set = rt73usb_brightness_set;
-       led->led_dev.blink_set = rt73usb_blink_set;
-       led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
-                                    struct rt2x00lib_crypto *crypto,
-                                    struct ieee80211_key_conf *key)
-{
-       struct hw_key_entry key_entry;
-       struct rt2x00_field32 field;
-       u32 mask;
-       u32 reg;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * rt2x00lib can't determine the correct free
-                * key_idx for shared keys. We have 1 register
-                * with key valid bits. The goal is simple, read
-                * the register, if that is full we have no slots
-                * left.
-                * Note that each BSS is allowed to have up to 4
-                * shared keys, so put a mask over the allowed
-                * entries.
-                */
-               mask = (0xf << crypto->bssidx);
-
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
-               reg &= mask;
-
-               if (reg && reg == mask)
-                       return -ENOSPC;
-
-               key->hw_key_idx += reg ? ffz(reg) : 0;
-
-               /*
-                * Upload key to hardware
-                */
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               reg = SHARED_KEY_ENTRY(key->hw_key_idx);
-               rt2x00usb_register_multiwrite(rt2x00dev, reg,
-                                             &key_entry, sizeof(key_entry));
-
-               /*
-                * The cipher types are stored over 2 registers.
-                * bssidx 0 and 1 keys are stored in SEC_CSR1 and
-                * bssidx 1 and 2 keys are stored in SEC_CSR5.
-                * Using the correct defines correctly will cause overhead,
-                * so just calculate the correct offset.
-                */
-               if (key->hw_key_idx < 8) {
-                       field.bit_offset = (3 * key->hw_key_idx);
-                       field.bit_mask = 0x7 << field.bit_offset;
-
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
-                       rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
-               } else {
-                       field.bit_offset = (3 * (key->hw_key_idx - 8));
-                       field.bit_mask = 0x7 << field.bit_offset;
-
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
-                       rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
-               }
-
-               /*
-                * The driver does not support the IV/EIV generation
-                * in hardware. However it doesn't support the IV/EIV
-                * inside the ieee80211 frame either, but requires it
-                * to be provided separately for the descriptor.
-                * rt2x00lib will cut the IV/EIV data out of all frames
-                * given to us by mac80211, but we must tell mac80211
-                * to generate the IV/EIV data.
-                */
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       }
-
-       /*
-        * SEC_CSR0 contains only single-bit fields to indicate
-        * a particular key is valid. Because using the FIELD32()
-        * defines directly will cause a lot of overhead we use
-        * a calculation to determine the correct bit directly.
-        */
-       mask = 1 << key->hw_key_idx;
-
-       rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
-       if (crypto->cmd == SET_KEY)
-               reg |= mask;
-       else if (crypto->cmd == DISABLE_KEY)
-               reg &= ~mask;
-       rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
-
-       return 0;
-}
-
-static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00lib_crypto *crypto,
-                                      struct ieee80211_key_conf *key)
-{
-       struct hw_pairwise_ta_entry addr_entry;
-       struct hw_key_entry key_entry;
-       u32 mask;
-       u32 reg;
-
-       if (crypto->cmd == SET_KEY) {
-               /*
-                * rt2x00lib can't determine the correct free
-                * key_idx for pairwise keys. We have 2 registers
-                * with key valid bits. The goal is simple, read
-                * the first register, if that is full move to
-                * the next register.
-                * When both registers are full, we drop the key,
-                * otherwise we use the first invalid entry.
-                */
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
-               if (reg && reg == ~0) {
-                       key->hw_key_idx = 32;
-                       rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
-                       if (reg && reg == ~0)
-                               return -ENOSPC;
-               }
-
-               key->hw_key_idx += reg ? ffz(reg) : 0;
-
-               /*
-                * Upload key to hardware
-                */
-               memcpy(key_entry.key, crypto->key,
-                      sizeof(key_entry.key));
-               memcpy(key_entry.tx_mic, crypto->tx_mic,
-                      sizeof(key_entry.tx_mic));
-               memcpy(key_entry.rx_mic, crypto->rx_mic,
-                      sizeof(key_entry.rx_mic));
-
-               reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
-               rt2x00usb_register_multiwrite(rt2x00dev, reg,
-                                             &key_entry, sizeof(key_entry));
-
-               /*
-                * Send the address and cipher type to the hardware register.
-                */
-               memset(&addr_entry, 0, sizeof(addr_entry));
-               memcpy(&addr_entry, crypto->address, ETH_ALEN);
-               addr_entry.cipher = crypto->cipher;
-
-               reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
-               rt2x00usb_register_multiwrite(rt2x00dev, reg,
-                                           &addr_entry, sizeof(addr_entry));
-
-               /*
-                * Enable pairwise lookup table for given BSS idx,
-                * without this received frames will not be decrypted
-                * by the hardware.
-                */
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
-               reg |= (1 << crypto->bssidx);
-               rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
-
-               /*
-                * The driver does not support the IV/EIV generation
-                * in hardware. However it doesn't support the IV/EIV
-                * inside the ieee80211 frame either, but requires it
-                * to be provided separately for the descriptor.
-                * rt2x00lib will cut the IV/EIV data out of all frames
-                * given to us by mac80211, but we must tell mac80211
-                * to generate the IV/EIV data.
-                */
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-       }
-
-       /*
-        * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
-        * a particular key is valid. Because using the FIELD32()
-        * defines directly will cause a lot of overhead we use
-        * a calculation to determine the correct bit directly.
-        */
-       if (key->hw_key_idx < 32) {
-               mask = 1 << key->hw_key_idx;
-
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
-               if (crypto->cmd == SET_KEY)
-                       reg |= mask;
-               else if (crypto->cmd == DISABLE_KEY)
-                       reg &= ~mask;
-               rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
-       } else {
-               mask = 1 << (key->hw_key_idx - 32);
-
-               rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
-               if (crypto->cmd == SET_KEY)
-                       reg |= mask;
-               else if (crypto->cmd == DISABLE_KEY)
-                       reg &= ~mask;
-               rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
-       }
-
-       return 0;
-}
-
-static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int filter_flags)
-{
-       u32 reg;
-
-       /*
-        * Start configuration steps.
-        * Note that the version error will always be dropped
-        * and broadcast frames will always be accepted since
-        * there is no filter for it at this time.
-        */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-                          !(filter_flags & FIF_FCSFAIL));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-                          !(filter_flags & FIF_PLCPFAIL));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-                          !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-                          !rt2x00dev->intf_ap_count);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-                          !(filter_flags & FIF_ALLMULTI));
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
-                          !(filter_flags & FIF_CONTROL));
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-}
-
-static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00_intf *intf,
-                               struct rt2x00intf_conf *conf,
-                               const unsigned int flags)
-{
-       u32 reg;
-
-       if (flags & CONFIG_UPDATE_TYPE) {
-               /*
-                * Enable synchronisation.
-                */
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-       }
-
-       if (flags & CONFIG_UPDATE_MAC) {
-               reg = le32_to_cpu(conf->mac[1]);
-               rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-               conf->mac[1] = cpu_to_le32(reg);
-
-               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
-                                           conf->mac, sizeof(conf->mac));
-       }
-
-       if (flags & CONFIG_UPDATE_BSSID) {
-               reg = le32_to_cpu(conf->bssid[1]);
-               rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
-               conf->bssid[1] = cpu_to_le32(reg);
-
-               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
-                                           conf->bssid, sizeof(conf->bssid));
-       }
-}
-
-static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
-                              struct rt2x00lib_erp *erp,
-                              u32 changed)
-{
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
-       rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-                                  !!erp->short_preamble);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-       }
-
-       if (changed & BSS_CHANGED_BASIC_RATES)
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR5,
-                                        erp->basic_rates);
-
-       if (changed & BSS_CHANGED_BEACON_INT) {
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-                                  erp->beacon_int * 16);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-       }
-
-       if (changed & BSS_CHANGED_ERP_SLOT) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
-
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
-               rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-               rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
-       }
-}
-
-static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
-                                     struct antenna_setup *ant)
-{
-       u8 r3;
-       u8 r4;
-       u8 r77;
-       u8 temp;
-
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
-       rt73usb_bbp_read(rt2x00dev, 4, &r4);
-       rt73usb_bbp_read(rt2x00dev, 77, &r77);
-
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-               temp = !rt2x00_has_cap_frame_type(rt2x00dev) &&
-                      (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-               if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               else
-                       rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               break;
-       }
-
-       rt73usb_bbp_write(rt2x00dev, 77, r77);
-       rt73usb_bbp_write(rt2x00dev, 3, r3);
-       rt73usb_bbp_write(rt2x00dev, 4, r4);
-}
-
-static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
-                                     struct antenna_setup *ant)
-{
-       u8 r3;
-       u8 r4;
-       u8 r77;
-
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
-       rt73usb_bbp_read(rt2x00dev, 4, &r4);
-       rt73usb_bbp_read(rt2x00dev, 77, &r77);
-
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
-       rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-                         !rt2x00_has_cap_frame_type(rt2x00dev));
-
-       /*
-        * Configure the RX antenna.
-        */
-       switch (ant->rx) {
-       case ANTENNA_HW_DIVERSITY:
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-               break;
-       case ANTENNA_A:
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               break;
-       case ANTENNA_B:
-       default:
-               rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-               rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
-               break;
-       }
-
-       rt73usb_bbp_write(rt2x00dev, 77, r77);
-       rt73usb_bbp_write(rt2x00dev, 3, r3);
-       rt73usb_bbp_write(rt2x00dev, 4, r4);
-}
-
-struct antenna_sel {
-       u8 word;
-       /*
-        * value[0] -> non-LNA
-        * value[1] -> LNA
-        */
-       u8 value[2];
-};
-
-static const struct antenna_sel antenna_sel_a[] = {
-       { 96,  { 0x58, 0x78 } },
-       { 104, { 0x38, 0x48 } },
-       { 75,  { 0xfe, 0x80 } },
-       { 86,  { 0xfe, 0x80 } },
-       { 88,  { 0xfe, 0x80 } },
-       { 35,  { 0x60, 0x60 } },
-       { 97,  { 0x58, 0x58 } },
-       { 98,  { 0x58, 0x58 } },
-};
-
-static const struct antenna_sel antenna_sel_bg[] = {
-       { 96,  { 0x48, 0x68 } },
-       { 104, { 0x2c, 0x3c } },
-       { 75,  { 0xfe, 0x80 } },
-       { 86,  { 0xfe, 0x80 } },
-       { 88,  { 0xfe, 0x80 } },
-       { 35,  { 0x50, 0x50 } },
-       { 97,  { 0x48, 0x48 } },
-       { 98,  { 0x48, 0x48 } },
-};
-
-static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
-                              struct antenna_setup *ant)
-{
-       const struct antenna_sel *sel;
-       unsigned int lna;
-       unsigned int i;
-       u32 reg;
-
-       /*
-        * We should never come here because rt2x00lib is supposed
-        * to catch this and send us the correct antenna explicitely.
-        */
-       BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-              ant->tx == ANTENNA_SW_DIVERSITY);
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               sel = antenna_sel_a;
-               lna = rt2x00_has_cap_external_lna_a(rt2x00dev);
-       } else {
-               sel = antenna_sel_bg;
-               lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
-               rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
-
-       rt2x00usb_register_read(rt2x00dev, PHY_CSR0, &reg);
-
-       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-                          (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
-       rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-                          (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
-
-       rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
-
-       if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
-               rt73usb_config_antenna_5x(rt2x00dev, ant);
-       else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
-               rt73usb_config_antenna_2x(rt2x00dev, ant);
-}
-
-static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_conf *libconf)
-{
-       u16 eeprom;
-       short lna_gain = 0;
-
-       if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
-               if (rt2x00_has_cap_external_lna_bg(rt2x00dev))
-                       lna_gain += 14;
-
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
-               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
-       } else {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
-               lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
-       }
-
-       rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
-                                  struct rf_channel *rf, const int txpower)
-{
-       u8 r3;
-       u8 r94;
-       u8 smart;
-
-       rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-       rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
-       smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527));
-
-       rt73usb_bbp_read(rt2x00dev, 3, &r3);
-       rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
-       rt73usb_bbp_write(rt2x00dev, 3, r3);
-
-       r94 = 6;
-       if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
-               r94 += txpower - MAX_TXPOWER;
-       else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
-               r94 += txpower;
-       rt73usb_bbp_write(rt2x00dev, 94, r94);
-
-       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
-       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-       rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
-       rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
-       rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
-       rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
-
-       udelay(10);
-}
-
-static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                  const int txpower)
-{
-       struct rf_channel rf;
-
-       rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
-       rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
-       rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
-       rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
-
-       rt73usb_config_channel(rt2x00dev, &rf, txpower);
-}
-
-static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
-                                      struct rt2x00lib_conf *libconf)
-{
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
-                          libconf->conf->long_frame_max_tx_count);
-       rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
-                          libconf->conf->short_frame_max_tx_count);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
-
-static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
-                               struct rt2x00lib_conf *libconf)
-{
-       enum dev_state state =
-           (libconf->conf->flags & IEEE80211_CONF_PS) ?
-               STATE_SLEEP : STATE_AWAKE;
-       u32 reg;
-
-       if (state == STATE_SLEEP) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
-                                  rt2x00dev->beacon_int - 10);
-               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
-                                  libconf->conf->listen_interval - 1);
-               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 5);
-
-               /* We must first disable autowake before it can be enabled */
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
-                                           USB_MODE_SLEEP, REGISTER_TIMEOUT);
-       } else {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR11, &reg);
-               rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
-               rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg);
-
-               rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
-                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
-       }
-}
-
-static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
-                          struct rt2x00lib_conf *libconf,
-                          const unsigned int flags)
-{
-       /* Always recalculate LNA gain before changing configuration */
-       rt73usb_config_lna_gain(rt2x00dev, libconf);
-
-       if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
-               rt73usb_config_channel(rt2x00dev, &libconf->rf,
-                                      libconf->conf->power_level);
-       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
-           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
-               rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
-       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
-               rt73usb_config_retry_limit(rt2x00dev, libconf);
-       if (flags & IEEE80211_CONF_CHANGE_PS)
-               rt73usb_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
-                              struct link_qual *qual)
-{
-       u32 reg;
-
-       /*
-        * Update FCS error count from register.
-        */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
-
-       /*
-        * Update False CCA count from register.
-        */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
-       qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
-}
-
-static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev,
-                                  struct link_qual *qual, u8 vgc_level)
-{
-       if (qual->vgc_level != vgc_level) {
-               rt73usb_bbp_write(rt2x00dev, 17, vgc_level);
-               qual->vgc_level = vgc_level;
-               qual->vgc_level_reg = vgc_level;
-       }
-}
-
-static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
-                               struct link_qual *qual)
-{
-       rt73usb_set_vgc(rt2x00dev, qual, 0x20);
-}
-
-static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
-                              struct link_qual *qual, const u32 count)
-{
-       u8 up_bound;
-       u8 low_bound;
-
-       /*
-        * Determine r17 bounds.
-        */
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               low_bound = 0x28;
-               up_bound = 0x48;
-
-               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
-                       low_bound += 0x10;
-                       up_bound += 0x10;
-               }
-       } else {
-               if (qual->rssi > -82) {
-                       low_bound = 0x1c;
-                       up_bound = 0x40;
-               } else if (qual->rssi > -84) {
-                       low_bound = 0x1c;
-                       up_bound = 0x20;
-               } else {
-                       low_bound = 0x1c;
-                       up_bound = 0x1c;
-               }
-
-               if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
-                       low_bound += 0x14;
-                       up_bound += 0x10;
-               }
-       }
-
-       /*
-        * If we are not associated, we should go straight to the
-        * dynamic CCA tuning.
-        */
-       if (!rt2x00dev->intf_associated)
-               goto dynamic_cca_tune;
-
-       /*
-        * Special big-R17 for very short distance
-        */
-       if (qual->rssi > -35) {
-               rt73usb_set_vgc(rt2x00dev, qual, 0x60);
-               return;
-       }
-
-       /*
-        * Special big-R17 for short distance
-        */
-       if (qual->rssi >= -58) {
-               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
-               return;
-       }
-
-       /*
-        * Special big-R17 for middle-short distance
-        */
-       if (qual->rssi >= -66) {
-               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
-               return;
-       }
-
-       /*
-        * Special mid-R17 for middle distance
-        */
-       if (qual->rssi >= -74) {
-               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
-               return;
-       }
-
-       /*
-        * Special case: Change up_bound based on the rssi.
-        * Lower up_bound when rssi is weaker then -74 dBm.
-        */
-       up_bound -= 2 * (-74 - qual->rssi);
-       if (low_bound > up_bound)
-               up_bound = low_bound;
-
-       if (qual->vgc_level > up_bound) {
-               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
-               return;
-       }
-
-dynamic_cca_tune:
-
-       /*
-        * r17 does not yet exceed upper limit, continue and base
-        * the r17 tuning on the false CCA count.
-        */
-       if ((qual->false_cca > 512) && (qual->vgc_level < up_bound))
-               rt73usb_set_vgc(rt2x00dev, qual,
-                               min_t(u8, qual->vgc_level + 4, up_bound));
-       else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound))
-               rt73usb_set_vgc(rt2x00dev, qual,
-                               max_t(u8, qual->vgc_level - 4, low_bound));
-}
-
-/*
- * Queue handlers.
- */
-static void rt73usb_start_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-static void rt73usb_stop_queue(struct data_queue *queue)
-{
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-       u32 reg;
-
-       switch (queue->qid) {
-       case QID_RX:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-               break;
-       case QID_BEACON:
-               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-               rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-               rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-               break;
-       default:
-               break;
-       }
-}
-
-/*
- * Firmware functions
- */
-static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
-{
-       return FIRMWARE_RT2571;
-}
-
-static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev,
-                                 const u8 *data, const size_t len)
-{
-       u16 fw_crc;
-       u16 crc;
-
-       /*
-        * Only support 2kb firmware files.
-        */
-       if (len != 2048)
-               return FW_BAD_LENGTH;
-
-       /*
-        * The last 2 bytes in the firmware array are the crc checksum itself,
-        * this means that we should never pass those 2 bytes to the crc
-        * algorithm.
-        */
-       fw_crc = (data[len - 2] << 8 | data[len - 1]);
-
-       /*
-        * Use the crc itu-t algorithm.
-        */
-       crc = crc_itu_t(0, data, len - 2);
-       crc = crc_itu_t_byte(crc, 0);
-       crc = crc_itu_t_byte(crc, 0);
-
-       return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
-}
-
-static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
-                                const u8 *data, const size_t len)
-{
-       unsigned int i;
-       int status;
-       u32 reg;
-
-       /*
-        * Wait for stable hardware.
-        */
-       for (i = 0; i < 100; i++) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
-               if (reg)
-                       break;
-               msleep(1);
-       }
-
-       if (!reg) {
-               rt2x00_err(rt2x00dev, "Unstable hardware\n");
-               return -EBUSY;
-       }
-
-       /*
-        * Write firmware to device.
-        */
-       rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, data, len);
-
-       /*
-        * Send firmware request to device to load firmware,
-        * we need to specify a long timeout time.
-        */
-       status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
-                                            0, USB_MODE_FIRMWARE,
-                                            REGISTER_TIMEOUT_FIRMWARE);
-       if (status < 0) {
-               rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
-               return status;
-       }
-
-       return 0;
-}
-
-/*
- * Initialization functions.
- */
-static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
-       rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
-
-       /*
-        * CCK TXD BBP registers
-        */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2, 11);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
-       rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
-
-       /*
-        * OFDM TXD BBP registers
-        */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
-       rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
-       rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
-       rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
-
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
-
-       if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
-               return -EBUSY;
-
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
-
-       /*
-        * Invalidate all Shared Keys (SEC_CSR0),
-        * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
-        */
-       rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
-       rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
-       rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
-
-       reg = 0x000023b0;
-       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
-               rt2x00_set_field32(&reg, PHY_CSR1_RF_RPI, 1);
-       rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
-
-       rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
-       rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
-       rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
-
-       /*
-        * Clear all beacons
-        * For the Beacon base registers we only need to clear
-        * the first byte since that byte contains the VALID and OWNER
-        * bits which (when set to 0) will invalidate the entire beacon.
-        */
-       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-       rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-
-       /*
-        * We must clear the error counters.
-        * These registers are cleared on read,
-        * so we may pass a useless variable to store the value.
-        */
-       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
-       rt2x00usb_register_read(rt2x00dev, STA_CSR2, &reg);
-
-       /*
-        * Reset MAC and BBP registers.
-        */
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
-       rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
-
-       return 0;
-}
-
-static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u8 value;
-
-       for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
-               rt73usb_bbp_read(rt2x00dev, 0, &value);
-               if ((value != 0xff) && (value != 0x00))
-                       return 0;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
-       return -EACCES;
-}
-
-static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
-       u8 value;
-
-       if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev)))
-               return -EACCES;
-
-       rt73usb_bbp_write(rt2x00dev, 3, 0x80);
-       rt73usb_bbp_write(rt2x00dev, 15, 0x30);
-       rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
-       rt73usb_bbp_write(rt2x00dev, 22, 0x38);
-       rt73usb_bbp_write(rt2x00dev, 23, 0x06);
-       rt73usb_bbp_write(rt2x00dev, 24, 0xfe);
-       rt73usb_bbp_write(rt2x00dev, 25, 0x0a);
-       rt73usb_bbp_write(rt2x00dev, 26, 0x0d);
-       rt73usb_bbp_write(rt2x00dev, 32, 0x0b);
-       rt73usb_bbp_write(rt2x00dev, 34, 0x12);
-       rt73usb_bbp_write(rt2x00dev, 37, 0x07);
-       rt73usb_bbp_write(rt2x00dev, 39, 0xf8);
-       rt73usb_bbp_write(rt2x00dev, 41, 0x60);
-       rt73usb_bbp_write(rt2x00dev, 53, 0x10);
-       rt73usb_bbp_write(rt2x00dev, 54, 0x18);
-       rt73usb_bbp_write(rt2x00dev, 60, 0x10);
-       rt73usb_bbp_write(rt2x00dev, 61, 0x04);
-       rt73usb_bbp_write(rt2x00dev, 62, 0x04);
-       rt73usb_bbp_write(rt2x00dev, 75, 0xfe);
-       rt73usb_bbp_write(rt2x00dev, 86, 0xfe);
-       rt73usb_bbp_write(rt2x00dev, 88, 0xfe);
-       rt73usb_bbp_write(rt2x00dev, 90, 0x0f);
-       rt73usb_bbp_write(rt2x00dev, 99, 0x00);
-       rt73usb_bbp_write(rt2x00dev, 102, 0x16);
-       rt73usb_bbp_write(rt2x00dev, 107, 0x04);
-
-       for (i = 0; i < EEPROM_BBP_SIZE; i++) {
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
-               if (eeprom != 0xffff && eeprom != 0x0000) {
-                       reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
-                       value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-                       rt73usb_bbp_write(rt2x00dev, reg_id, value);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Device state switch handlers.
- */
-static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       /*
-        * Initialize all registers.
-        */
-       if (unlikely(rt73usb_init_registers(rt2x00dev) ||
-                    rt73usb_init_bbp(rt2x00dev)))
-               return -EIO;
-
-       return 0;
-}
-
-static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
-
-       /*
-        * Disable synchronisation.
-        */
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
-
-       rt2x00usb_disable_radio(rt2x00dev);
-}
-
-static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
-{
-       u32 reg, reg2;
-       unsigned int i;
-       char put_to_sleep;
-
-       put_to_sleep = (state != STATE_AWAKE);
-
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
-       rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
-
-       /*
-        * Device is not guaranteed to be in the requested state yet.
-        * We must wait until the register indicates that the
-        * device has entered the correct state.
-        */
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg2);
-               state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
-               if (state == !put_to_sleep)
-                       return 0;
-               rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
-               msleep(10);
-       }
-
-       return -EBUSY;
-}
-
-static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
-                                   enum dev_state state)
-{
-       int retval = 0;
-
-       switch (state) {
-       case STATE_RADIO_ON:
-               retval = rt73usb_enable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_OFF:
-               rt73usb_disable_radio(rt2x00dev);
-               break;
-       case STATE_RADIO_IRQ_ON:
-       case STATE_RADIO_IRQ_OFF:
-               /* No support, but no error either */
-               break;
-       case STATE_DEEP_SLEEP:
-       case STATE_SLEEP:
-       case STATE_STANDBY:
-       case STATE_AWAKE:
-               retval = rt73usb_set_state(rt2x00dev, state);
-               break;
-       default:
-               retval = -ENOTSUPP;
-               break;
-       }
-
-       if (unlikely(retval))
-               rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
-                          state, retval);
-
-       return retval;
-}
-
-/*
- * TX descriptor initialization
- */
-static void rt73usb_write_tx_desc(struct queue_entry *entry,
-                                 struct txentry_desc *txdesc)
-{
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *txd = (__le32 *) entry->skb->data;
-       u32 word;
-
-       /*
-        * Start writing the descriptor words.
-        */
-       rt2x00_desc_read(txd, 0, &word);
-       rt2x00_set_field32(&word, TXD_W0_BURST,
-                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_VALID, 1);
-       rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-                          test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_ACK,
-                          test_bit(ENTRY_TXD_ACK, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-                          test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          (txdesc->rate_mode == RATE_MODE_OFDM));
-       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
-       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
-                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
-                          test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
-                          test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
-       rt2x00_set_field32(&word, TXD_W0_BURST2,
-                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
-       rt2x00_desc_write(txd, 0, word);
-
-       rt2x00_desc_read(txd, 1, &word);
-       rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
-       rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
-       rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
-       rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
-       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
-       rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
-                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
-       rt2x00_desc_write(txd, 1, word);
-
-       rt2x00_desc_read(txd, 2, &word);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
-                          txdesc->u.plcp.length_low);
-       rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
-                          txdesc->u.plcp.length_high);
-       rt2x00_desc_write(txd, 2, word);
-
-       if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
-               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
-       }
-
-       rt2x00_desc_read(txd, 5, &word);
-       rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-                          TXPOWER_TO_DEV(entry->queue->rt2x00dev->tx_power));
-       rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
-       rt2x00_desc_write(txd, 5, word);
-
-       /*
-        * Register descriptor details in skb frame descriptor.
-        */
-       skbdesc->flags |= SKBDESC_DESC_IN_SKB;
-       skbdesc->desc = txd;
-       skbdesc->desc_len = TXD_DESC_SIZE;
-}
-
-/*
- * TX data initialization
- */
-static void rt73usb_write_beacon(struct queue_entry *entry,
-                                struct txentry_desc *txdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       unsigned int beacon_base;
-       unsigned int padding_len;
-       u32 orig_reg, reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       orig_reg = reg;
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Add space for the descriptor in front of the skb.
-        */
-       skb_push(entry->skb, TXD_DESC_SIZE);
-       memset(entry->skb->data, 0, TXD_DESC_SIZE);
-
-       /*
-        * Write the TX descriptor for the beacon.
-        */
-       rt73usb_write_tx_desc(entry, txdesc);
-
-       /*
-        * Dump beacon to userspace through debugfs.
-        */
-       rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
-
-       /*
-        * Write entire beacon with descriptor and padding to register.
-        */
-       padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-       if (padding_len && skb_pad(entry->skb, padding_len)) {
-               rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
-               /* skb freed by skb_pad() on failure */
-               entry->skb = NULL;
-               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
-               return;
-       }
-
-       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
-       rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
-                                     entry->skb->len + padding_len);
-
-       /*
-        * Enable beaconing again.
-        *
-        * For Wi-Fi faily generated beacons between participating stations.
-        * Set TBTT phase adaptive adjustment step to 8us (default 16us)
-        */
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
-
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Clean up the beacon skb.
-        */
-       dev_kfree_skb(entry->skb);
-       entry->skb = NULL;
-}
-
-static void rt73usb_clear_beacon(struct queue_entry *entry)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       unsigned int beacon_base;
-       u32 orig_reg, reg;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &orig_reg);
-       reg = orig_reg;
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Clear beacon.
-        */
-       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
-       rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
-
-       /*
-        * Restore beaconing state.
-        */
-       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
-}
-
-static int rt73usb_get_tx_data_len(struct queue_entry *entry)
-{
-       int length;
-
-       /*
-        * The length _must_ be a multiple of 4,
-        * but it must _not_ be a multiple of the USB packet size.
-        */
-       length = roundup(entry->skb->len, 4);
-       length += (4 * !(length % entry->queue->usb_maxpacket));
-
-       return length;
-}
-
-/*
- * RX control handlers
- */
-static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
-{
-       u8 offset = rt2x00dev->lna_gain;
-       u8 lna;
-
-       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
-       switch (lna) {
-       case 3:
-               offset += 90;
-               break;
-       case 2:
-               offset += 74;
-               break;
-       case 1:
-               offset += 64;
-               break;
-       default:
-               return 0;
-       }
-
-       if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-               if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {
-                       if (lna == 3 || lna == 2)
-                               offset += 10;
-               } else {
-                       if (lna == 3)
-                               offset += 6;
-                       else if (lna == 2)
-                               offset += 8;
-               }
-       }
-
-       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
-}
-
-static void rt73usb_fill_rxdone(struct queue_entry *entry,
-                               struct rxdone_entry_desc *rxdesc)
-{
-       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-       __le32 *rxd = (__le32 *)entry->skb->data;
-       u32 word0;
-       u32 word1;
-
-       /*
-        * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
-        * frame data in rt2x00usb.
-        */
-       memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
-       rxd = (__le32 *)skbdesc->desc;
-
-       /*
-        * It is now safe to read the descriptor on all architectures.
-        */
-       rt2x00_desc_read(rxd, 0, &word0);
-       rt2x00_desc_read(rxd, 1, &word1);
-
-       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
-       rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
-       rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
-
-       if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
-               _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
-               rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
-
-               _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
-               rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
-
-               /*
-                * Hardware has stripped IV/EIV data from 802.11 frame during
-                * decryption. It has provided the data separately but rt2x00lib
-                * should decide if it should be reinserted.
-                */
-               rxdesc->flags |= RX_FLAG_IV_STRIPPED;
-
-               /*
-                * The hardware has already checked the Michael Mic and has
-                * stripped it from the frame. Signal this to mac80211.
-                */
-               rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
-
-               if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
-                       rxdesc->flags |= RX_FLAG_DECRYPTED;
-               else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
-                       rxdesc->flags |= RX_FLAG_MMIC_ERROR;
-       }
-
-       /*
-        * Obtain the status about this packet.
-        * When frame was received with an OFDM bitrate,
-        * the signal is the PLCP value. If it was received with
-        * a CCK bitrate the signal is the rate in 100kbit/s.
-        */
-       rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
-       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
-       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-               rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-       else
-               rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE;
-       if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-               rxdesc->dev_flags |= RXDONE_MY_BSS;
-
-       /*
-        * Set skb pointers, and update frame information.
-        */
-       skb_pull(entry->skb, entry->queue->desc_size);
-       skb_trim(entry->skb, rxdesc->size);
-}
-
-/*
- * Device probe functions.
- */
-static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u16 word;
-       u8 *mac;
-       s8 value;
-
-       rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
-
-       /*
-        * Start validation of the data that has been read.
-        */
-       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-       if (!is_valid_ether_addr(mac)) {
-               eth_random_addr(mac);
-               rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
-                                  ANTENNA_B);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
-                                  ANTENNA_B);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
-               rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_ACT, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_0, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_1, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_2, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_3, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_4, 0);
-               rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
-                                  LED_MODE_DEFAULT);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-               rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
-       } else {
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
-       }
-
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
-       if (word == 0xffff) {
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
-               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-               rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
-       } else {
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
-               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
-               if (value < -10 || value > 10)
-                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-       }
-
-       return 0;
-}
-
-static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       u16 value;
-       u16 eeprom;
-
-       /*
-        * Read EEPROM word for configuration.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-       /*
-        * Identify RF chipset.
-        */
-       value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
-                       value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
-
-       if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
-               rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
-               return -ENODEV;
-       }
-
-       if (!rt2x00_rf(rt2x00dev, RF5226) &&
-           !rt2x00_rf(rt2x00dev, RF2528) &&
-           !rt2x00_rf(rt2x00dev, RF5225) &&
-           !rt2x00_rf(rt2x00dev, RF2527)) {
-               rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
-               return -ENODEV;
-       }
-
-       /*
-        * Identify default antenna configuration.
-        */
-       rt2x00dev->default_ant.tx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
-       rt2x00dev->default_ant.rx =
-           rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
-
-       /*
-        * Read the Frame type.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-               __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
-
-       /*
-        * Detect if this device has an hardware controlled radio.
-        */
-       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-               __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
-
-       /*
-        * Read frequency offset.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-       rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
-
-       /*
-        * Read external LNA informations.
-        */
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
-
-       if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
-               __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
-               __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
-       }
-
-       /*
-        * Store led settings, for correct led behaviour.
-        */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-       rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-
-       rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-       rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
-       if (value == LED_MODE_SIGNAL_STRENGTH)
-               rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual,
-                                LED_TYPE_QUALITY);
-
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_0));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_1));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_2));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_3));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_GPIO_4));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
-                          rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_RDY_G));
-       rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
-                          rt2x00_get_field16(eeprom,
-                                             EEPROM_LED_POLARITY_RDY_A));
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-       return 0;
-}
-
-/*
- * RF value list for RF2528
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_bg_2528[] = {
-       { 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
-       { 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
-       { 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
-       { 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
-       { 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
-       { 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
-       { 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
-       { 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
-       { 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
-       { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
-       { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
-       { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
-       { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
-       { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
-};
-
-/*
- * RF value list for RF5226
- * Supports: 2.4 GHz & 5.2 GHz
- */
-static const struct rf_channel rf_vals_5226[] = {
-       { 1,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b },
-       { 2,  0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f },
-       { 3,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b },
-       { 4,  0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f },
-       { 5,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b },
-       { 6,  0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f },
-       { 7,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b },
-       { 8,  0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f },
-       { 9,  0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b },
-       { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f },
-       { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b },
-       { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f },
-       { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b },
-       { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00002c0c, 0x0000099a, 0x00098255, 0x000fea23 },
-       { 40, 0x00002c0c, 0x000009a2, 0x00098255, 0x000fea03 },
-       { 44, 0x00002c0c, 0x000009a6, 0x00098255, 0x000fea0b },
-       { 48, 0x00002c0c, 0x000009aa, 0x00098255, 0x000fea13 },
-       { 52, 0x00002c0c, 0x000009ae, 0x00098255, 0x000fea1b },
-       { 56, 0x00002c0c, 0x000009b2, 0x00098255, 0x000fea23 },
-       { 60, 0x00002c0c, 0x000009ba, 0x00098255, 0x000fea03 },
-       { 64, 0x00002c0c, 0x000009be, 0x00098255, 0x000fea0b },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00002c0c, 0x00000a2a, 0x000b8255, 0x000fea03 },
-       { 104, 0x00002c0c, 0x00000a2e, 0x000b8255, 0x000fea0b },
-       { 108, 0x00002c0c, 0x00000a32, 0x000b8255, 0x000fea13 },
-       { 112, 0x00002c0c, 0x00000a36, 0x000b8255, 0x000fea1b },
-       { 116, 0x00002c0c, 0x00000a3a, 0x000b8255, 0x000fea23 },
-       { 120, 0x00002c0c, 0x00000a82, 0x000b8255, 0x000fea03 },
-       { 124, 0x00002c0c, 0x00000a86, 0x000b8255, 0x000fea0b },
-       { 128, 0x00002c0c, 0x00000a8a, 0x000b8255, 0x000fea13 },
-       { 132, 0x00002c0c, 0x00000a8e, 0x000b8255, 0x000fea1b },
-       { 136, 0x00002c0c, 0x00000a92, 0x000b8255, 0x000fea23 },
-
-       /* 802.11 UNII */
-       { 140, 0x00002c0c, 0x00000a9a, 0x000b8255, 0x000fea03 },
-       { 149, 0x00002c0c, 0x00000aa2, 0x000b8255, 0x000fea1f },
-       { 153, 0x00002c0c, 0x00000aa6, 0x000b8255, 0x000fea27 },
-       { 157, 0x00002c0c, 0x00000aae, 0x000b8255, 0x000fea07 },
-       { 161, 0x00002c0c, 0x00000ab2, 0x000b8255, 0x000fea0f },
-       { 165, 0x00002c0c, 0x00000ab6, 0x000b8255, 0x000fea17 },
-
-       /* MMAC(Japan)J52 ch 34,38,42,46 */
-       { 34, 0x00002c0c, 0x0008099a, 0x000da255, 0x000d3a0b },
-       { 38, 0x00002c0c, 0x0008099e, 0x000da255, 0x000d3a13 },
-       { 42, 0x00002c0c, 0x000809a2, 0x000da255, 0x000d3a1b },
-       { 46, 0x00002c0c, 0x000809a6, 0x000da255, 0x000d3a23 },
-};
-
-/*
- * RF value list for RF5225 & RF2527
- * Supports: 2.4 GHz & 5.2 GHz
- */
-static const struct rf_channel rf_vals_5225_2527[] = {
-       { 1,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b },
-       { 2,  0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f },
-       { 3,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b },
-       { 4,  0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f },
-       { 5,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b },
-       { 6,  0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f },
-       { 7,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b },
-       { 8,  0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f },
-       { 9,  0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b },
-       { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f },
-       { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b },
-       { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f },
-       { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b },
-       { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 },
-
-       /* 802.11 UNI / HyperLan 2 */
-       { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 },
-       { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 },
-       { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b },
-       { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 },
-       { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b },
-       { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 },
-       { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 },
-       { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b },
-
-       /* 802.11 HyperLan 2 */
-       { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 },
-       { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b },
-       { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 },
-       { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b },
-       { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 },
-       { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 },
-       { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b },
-       { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 },
-       { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b },
-       { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 },
-
-       /* 802.11 UNII */
-       { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 },
-       { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f },
-       { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 },
-       { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 },
-       { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f },
-       { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 },
-
-       /* MMAC(Japan)J52 ch 34,38,42,46 */
-       { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b },
-       { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 },
-       { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b },
-       { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 },
-};
-
-
-static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-       struct hw_mode_spec *spec = &rt2x00dev->spec;
-       struct channel_info *info;
-       char *tx_power;
-       unsigned int i;
-
-       /*
-        * Initialize all hw fields.
-        *
-        * Don't set IEEE80211_HOST_BROADCAST_PS_BUFFERING unless we are
-        * capable of sending the buffered frames out after the DTIM
-        * transmission using rt2x00lib_beacondone. This will send out
-        * multicast and broadcast traffic immediately instead of buffering it
-        * infinitly and thus dropping it after some time.
-        */
-       ieee80211_hw_set(rt2x00dev->hw, PS_NULLFUNC_STACK);
-       ieee80211_hw_set(rt2x00dev->hw, SIGNAL_DBM);
-       ieee80211_hw_set(rt2x00dev->hw, SUPPORTS_PS);
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-                               rt2x00_eeprom_addr(rt2x00dev,
-                                                  EEPROM_MAC_ADDR_0));
-
-       /*
-        * Initialize hw_mode information.
-        */
-       spec->supported_bands = SUPPORT_BAND_2GHZ;
-       spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-       if (rt2x00_rf(rt2x00dev, RF2528)) {
-               spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
-               spec->channels = rf_vals_bg_2528;
-       } else if (rt2x00_rf(rt2x00dev, RF5226)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_5226);
-               spec->channels = rf_vals_5226;
-       } else if (rt2x00_rf(rt2x00dev, RF2527)) {
-               spec->num_channels = 14;
-               spec->channels = rf_vals_5225_2527;
-       } else if (rt2x00_rf(rt2x00dev, RF5225)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
-               spec->channels = rf_vals_5225_2527;
-       }
-
-       /*
-        * Create channel information array
-        */
-       info = kcalloc(spec->num_channels, sizeof(*info), GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       spec->channels_info = info;
-
-       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-       for (i = 0; i < 14; i++) {
-               info[i].max_power = MAX_TXPOWER;
-               info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
-       }
-
-       if (spec->num_channels > 14) {
-               tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-               for (i = 14; i < spec->num_channels; i++) {
-                       info[i].max_power = MAX_TXPOWER;
-                       info[i].default_power1 =
-                                       TXPOWER_FROM_DEV(tx_power[i - 14]);
-               }
-       }
-
-       return 0;
-}
-
-static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
-{
-       int retval;
-       u32 reg;
-
-       /*
-        * Allocate eeprom data.
-        */
-       retval = rt73usb_validate_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       retval = rt73usb_init_eeprom(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * Enable rfkill polling by setting GPIO direction of the
-        * rfkill switch GPIO pin correctly.
-        */
-       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR13_DIR7, 0);
-       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
-
-       /*
-        * Initialize hw specifications.
-        */
-       retval = rt73usb_probe_hw_mode(rt2x00dev);
-       if (retval)
-               return retval;
-
-       /*
-        * This device has multiple filters for control frames,
-        * but has no a separate filter for PS Poll frames.
-        */
-       __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
-
-       /*
-        * This device requires firmware.
-        */
-       __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
-       if (!modparam_nohwcrypt)
-               __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
-       __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
-       __set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);
-
-       /*
-        * Set the rssi offset.
-        */
-       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
-
-       return 0;
-}
-
-/*
- * IEEE80211 stack callback functions.
- */
-static int rt73usb_conf_tx(struct ieee80211_hw *hw,
-                          struct ieee80211_vif *vif, u16 queue_idx,
-                          const struct ieee80211_tx_queue_params *params)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct data_queue *queue;
-       struct rt2x00_field32 field;
-       int retval;
-       u32 reg;
-       u32 offset;
-
-       /*
-        * First pass the configuration through rt2x00lib, that will
-        * update the queue settings and validate the input. After that
-        * we are free to update the registers based on the value
-        * in the queue parameter.
-        */
-       retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);
-       if (retval)
-               return retval;
-
-       /*
-        * We only need to perform additional register initialization
-        * for WMM queues/
-        */
-       if (queue_idx >= 4)
-               return 0;
-
-       queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
-
-       /* Update WMM TXOP register */
-       offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
-       field.bit_offset = (queue_idx & 1) * 16;
-       field.bit_mask = 0xffff << field.bit_offset;
-
-       rt2x00usb_register_read(rt2x00dev, offset, &reg);
-       rt2x00_set_field32(&reg, field, queue->txop);
-       rt2x00usb_register_write(rt2x00dev, offset, reg);
-
-       /* Update WMM registers */
-       field.bit_offset = queue_idx * 4;
-       field.bit_mask = 0xf << field.bit_offset;
-
-       rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->aifs);
-       rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
-
-       rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_min);
-       rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
-
-       rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
-       rt2x00_set_field32(&reg, field, queue->cw_max);
-       rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
-
-       return 0;
-}
-
-static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       u64 tsf;
-       u32 reg;
-
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
-       tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
-       rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
-       tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
-
-       return tsf;
-}
-
-static const struct ieee80211_ops rt73usb_mac80211_ops = {
-       .tx                     = rt2x00mac_tx,
-       .start                  = rt2x00mac_start,
-       .stop                   = rt2x00mac_stop,
-       .add_interface          = rt2x00mac_add_interface,
-       .remove_interface       = rt2x00mac_remove_interface,
-       .config                 = rt2x00mac_config,
-       .configure_filter       = rt2x00mac_configure_filter,
-       .set_tim                = rt2x00mac_set_tim,
-       .set_key                = rt2x00mac_set_key,
-       .sw_scan_start          = rt2x00mac_sw_scan_start,
-       .sw_scan_complete       = rt2x00mac_sw_scan_complete,
-       .get_stats              = rt2x00mac_get_stats,
-       .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt73usb_conf_tx,
-       .get_tsf                = rt73usb_get_tsf,
-       .rfkill_poll            = rt2x00mac_rfkill_poll,
-       .flush                  = rt2x00mac_flush,
-       .set_antenna            = rt2x00mac_set_antenna,
-       .get_antenna            = rt2x00mac_get_antenna,
-       .get_ringparam          = rt2x00mac_get_ringparam,
-       .tx_frames_pending      = rt2x00mac_tx_frames_pending,
-};
-
-static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
-       .probe_hw               = rt73usb_probe_hw,
-       .get_firmware_name      = rt73usb_get_firmware_name,
-       .check_firmware         = rt73usb_check_firmware,
-       .load_firmware          = rt73usb_load_firmware,
-       .initialize             = rt2x00usb_initialize,
-       .uninitialize           = rt2x00usb_uninitialize,
-       .clear_entry            = rt2x00usb_clear_entry,
-       .set_device_state       = rt73usb_set_device_state,
-       .rfkill_poll            = rt73usb_rfkill_poll,
-       .link_stats             = rt73usb_link_stats,
-       .reset_tuner            = rt73usb_reset_tuner,
-       .link_tuner             = rt73usb_link_tuner,
-       .watchdog               = rt2x00usb_watchdog,
-       .start_queue            = rt73usb_start_queue,
-       .kick_queue             = rt2x00usb_kick_queue,
-       .stop_queue             = rt73usb_stop_queue,
-       .flush_queue            = rt2x00usb_flush_queue,
-       .write_tx_desc          = rt73usb_write_tx_desc,
-       .write_beacon           = rt73usb_write_beacon,
-       .clear_beacon           = rt73usb_clear_beacon,
-       .get_tx_data_len        = rt73usb_get_tx_data_len,
-       .fill_rxdone            = rt73usb_fill_rxdone,
-       .config_shared_key      = rt73usb_config_shared_key,
-       .config_pairwise_key    = rt73usb_config_pairwise_key,
-       .config_filter          = rt73usb_config_filter,
-       .config_intf            = rt73usb_config_intf,
-       .config_erp             = rt73usb_config_erp,
-       .config_ant             = rt73usb_config_ant,
-       .config                 = rt73usb_config,
-};
-
-static void rt73usb_queue_init(struct data_queue *queue)
-{
-       switch (queue->qid) {
-       case QID_RX:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = RXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_AC_VO:
-       case QID_AC_VI:
-       case QID_AC_BE:
-       case QID_AC_BK:
-               queue->limit = 32;
-               queue->data_size = DATA_FRAME_SIZE;
-               queue->desc_size = TXD_DESC_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_BEACON:
-               queue->limit = 4;
-               queue->data_size = MGMT_FRAME_SIZE;
-               queue->desc_size = TXINFO_SIZE;
-               queue->priv_size = sizeof(struct queue_entry_priv_usb);
-               break;
-
-       case QID_ATIM:
-               /* fallthrough */
-       default:
-               BUG();
-               break;
-       }
-}
-
-static const struct rt2x00_ops rt73usb_ops = {
-       .name                   = KBUILD_MODNAME,
-       .max_ap_intf            = 4,
-       .eeprom_size            = EEPROM_SIZE,
-       .rf_size                = RF_SIZE,
-       .tx_queues              = NUM_TX_QUEUES,
-       .queue_init             = rt73usb_queue_init,
-       .lib                    = &rt73usb_rt2x00_ops,
-       .hw                     = &rt73usb_mac80211_ops,
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs                = &rt73usb_rt2x00debug,
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-};
-
-/*
- * rt73usb module information.
- */
-static struct usb_device_id rt73usb_device_table[] = {
-       /* AboCom */
-       { USB_DEVICE(0x07b8, 0xb21b) },
-       { USB_DEVICE(0x07b8, 0xb21c) },
-       { USB_DEVICE(0x07b8, 0xb21d) },
-       { USB_DEVICE(0x07b8, 0xb21e) },
-       { USB_DEVICE(0x07b8, 0xb21f) },
-       /* AL */
-       { USB_DEVICE(0x14b2, 0x3c10) },
-       /* Amigo */
-       { USB_DEVICE(0x148f, 0x9021) },
-       { USB_DEVICE(0x0eb0, 0x9021) },
-       /* AMIT  */
-       { USB_DEVICE(0x18c5, 0x0002) },
-       /* Askey */
-       { USB_DEVICE(0x1690, 0x0722) },
-       /* ASUS */
-       { USB_DEVICE(0x0b05, 0x1723) },
-       { USB_DEVICE(0x0b05, 0x1724) },
-       /* Belkin */
-       { USB_DEVICE(0x050d, 0x7050) }, /* FCC ID: K7SF5D7050B ver. 3.x */
-       { USB_DEVICE(0x050d, 0x705a) },
-       { USB_DEVICE(0x050d, 0x905b) },
-       { USB_DEVICE(0x050d, 0x905c) },
-       /* Billionton */
-       { USB_DEVICE(0x1631, 0xc019) },
-       { USB_DEVICE(0x08dd, 0x0120) },
-       /* Buffalo */
-       { USB_DEVICE(0x0411, 0x00d8) },
-       { USB_DEVICE(0x0411, 0x00d9) },
-       { USB_DEVICE(0x0411, 0x00e6) },
-       { USB_DEVICE(0x0411, 0x00f4) },
-       { USB_DEVICE(0x0411, 0x0116) },
-       { USB_DEVICE(0x0411, 0x0119) },
-       { USB_DEVICE(0x0411, 0x0137) },
-       /* CEIVA */
-       { USB_DEVICE(0x178d, 0x02be) },
-       /* CNet */
-       { USB_DEVICE(0x1371, 0x9022) },
-       { USB_DEVICE(0x1371, 0x9032) },
-       /* Conceptronic */
-       { USB_DEVICE(0x14b2, 0x3c22) },
-       /* Corega */
-       { USB_DEVICE(0x07aa, 0x002e) },
-       /* D-Link */
-       { USB_DEVICE(0x07d1, 0x3c03) },
-       { USB_DEVICE(0x07d1, 0x3c04) },
-       { USB_DEVICE(0x07d1, 0x3c06) },
-       { USB_DEVICE(0x07d1, 0x3c07) },
-       /* Edimax */
-       { USB_DEVICE(0x7392, 0x7318) },
-       { USB_DEVICE(0x7392, 0x7618) },
-       /* EnGenius */
-       { USB_DEVICE(0x1740, 0x3701) },
-       /* Gemtek */
-       { USB_DEVICE(0x15a9, 0x0004) },
-       /* Gigabyte */
-       { USB_DEVICE(0x1044, 0x8008) },
-       { USB_DEVICE(0x1044, 0x800a) },
-       /* Huawei-3Com */
-       { USB_DEVICE(0x1472, 0x0009) },
-       /* Hercules */
-       { USB_DEVICE(0x06f8, 0xe002) },
-       { USB_DEVICE(0x06f8, 0xe010) },
-       { USB_DEVICE(0x06f8, 0xe020) },
-       /* Linksys */
-       { USB_DEVICE(0x13b1, 0x0020) },
-       { USB_DEVICE(0x13b1, 0x0023) },
-       { USB_DEVICE(0x13b1, 0x0028) },
-       /* MSI */
-       { USB_DEVICE(0x0db0, 0x4600) },
-       { USB_DEVICE(0x0db0, 0x6877) },
-       { USB_DEVICE(0x0db0, 0x6874) },
-       { USB_DEVICE(0x0db0, 0xa861) },
-       { USB_DEVICE(0x0db0, 0xa874) },
-       /* Ovislink */
-       { USB_DEVICE(0x1b75, 0x7318) },
-       /* Ralink */
-       { USB_DEVICE(0x04bb, 0x093d) },
-       { USB_DEVICE(0x148f, 0x2573) },
-       { USB_DEVICE(0x148f, 0x2671) },
-       { USB_DEVICE(0x0812, 0x3101) },
-       /* Qcom */
-       { USB_DEVICE(0x18e8, 0x6196) },
-       { USB_DEVICE(0x18e8, 0x6229) },
-       { USB_DEVICE(0x18e8, 0x6238) },
-       /* Samsung */
-       { USB_DEVICE(0x04e8, 0x4471) },
-       /* Senao */
-       { USB_DEVICE(0x1740, 0x7100) },
-       /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x0024) },
-       { USB_DEVICE(0x0df6, 0x0027) },
-       { USB_DEVICE(0x0df6, 0x002f) },
-       { USB_DEVICE(0x0df6, 0x90ac) },
-       { USB_DEVICE(0x0df6, 0x9712) },
-       /* Surecom */
-       { USB_DEVICE(0x0769, 0x31f3) },
-       /* Tilgin */
-       { USB_DEVICE(0x6933, 0x5001) },
-       /* Philips */
-       { USB_DEVICE(0x0471, 0x200a) },
-       /* Planex */
-       { USB_DEVICE(0x2019, 0xab01) },
-       { USB_DEVICE(0x2019, 0xab50) },
-       /* WideTell */
-       { USB_DEVICE(0x7167, 0x3840) },
-       /* Zcom */
-       { USB_DEVICE(0x0cde, 0x001c) },
-       /* ZyXEL */
-       { USB_DEVICE(0x0586, 0x3415) },
-       { 0, }
-};
-
-MODULE_AUTHOR(DRV_PROJECT);
-MODULE_VERSION(DRV_VERSION);
-MODULE_DESCRIPTION("Ralink RT73 USB Wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Ralink RT2571W & RT2671 USB chipset based cards");
-MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
-MODULE_FIRMWARE(FIRMWARE_RT2571);
-MODULE_LICENSE("GPL");
-
-static int rt73usb_probe(struct usb_interface *usb_intf,
-                        const struct usb_device_id *id)
-{
-       return rt2x00usb_probe(usb_intf, &rt73usb_ops);
-}
-
-static struct usb_driver rt73usb_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rt73usb_device_table,
-       .probe          = rt73usb_probe,
-       .disconnect     = rt2x00usb_disconnect,
-       .suspend        = rt2x00usb_suspend,
-       .resume         = rt2x00usb_resume,
-       .reset_resume   = rt2x00usb_resume,
-       .disable_hub_initiated_lpm = 1,
-};
-
-module_usb_driver(rt73usb_driver);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
deleted file mode 100644 (file)
index 4a4f235..0000000
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*
-       Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-       <http://rt2x00.serialmonkey.com>
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
-       Module: rt73usb
-       Abstract: Data structures and registers for the rt73usb module.
-       Supported chipsets: rt2571W & rt2671.
- */
-
-#ifndef RT73USB_H
-#define RT73USB_H
-
-/*
- * RF chip defines.
- */
-#define RF5226                         0x0001
-#define RF2528                         0x0002
-#define RF5225                         0x0003
-#define RF2527                         0x0004
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET            120
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE                   0x3000
-#define CSR_REG_SIZE                   0x04b0
-#define EEPROM_BASE                    0x0000
-#define EEPROM_SIZE                    0x0100
-#define BBP_BASE                       0x0000
-#define BBP_SIZE                       0x0080
-#define RF_BASE                                0x0004
-#define RF_SIZE                                0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES                  4
-
-/*
- * USB registers.
- */
-
-/*
- * MCU_LEDCS: LED control for MCU Mailbox.
- */
-#define MCU_LEDCS_LED_MODE             FIELD16(0x001f)
-#define MCU_LEDCS_RADIO_STATUS         FIELD16(0x0020)
-#define MCU_LEDCS_LINK_BG_STATUS       FIELD16(0x0040)
-#define MCU_LEDCS_LINK_A_STATUS                FIELD16(0x0080)
-#define MCU_LEDCS_POLARITY_GPIO_0      FIELD16(0x0100)
-#define MCU_LEDCS_POLARITY_GPIO_1      FIELD16(0x0200)
-#define MCU_LEDCS_POLARITY_GPIO_2      FIELD16(0x0400)
-#define MCU_LEDCS_POLARITY_GPIO_3      FIELD16(0x0800)
-#define MCU_LEDCS_POLARITY_GPIO_4      FIELD16(0x1000)
-#define MCU_LEDCS_POLARITY_ACT         FIELD16(0x2000)
-#define MCU_LEDCS_POLARITY_READY_BG    FIELD16(0x4000)
-#define MCU_LEDCS_POLARITY_READY_A     FIELD16(0x8000)
-
-/*
- * 8051 firmware image.
- */
-#define FIRMWARE_RT2571                        "rt73.bin"
-#define FIRMWARE_IMAGE_BASE            0x0800
-
-/*
- * Security key table memory.
- * 16 entries 32-byte for shared key table
- * 64 entries 32-byte for pairwise key table
- * 64 entries 8-byte for pairwise ta key table
- */
-#define SHARED_KEY_TABLE_BASE          0x1000
-#define PAIRWISE_KEY_TABLE_BASE                0x1200
-#define PAIRWISE_TA_TABLE_BASE         0x1a00
-
-#define SHARED_KEY_ENTRY(__idx) \
-       ( SHARED_KEY_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_key_entry)) )
-#define PAIRWISE_KEY_ENTRY(__idx) \
-       ( PAIRWISE_KEY_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_key_entry)) )
-#define PAIRWISE_TA_ENTRY(__idx) \
-       ( PAIRWISE_TA_TABLE_BASE + \
-               ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
-
-struct hw_key_entry {
-       u8 key[16];
-       u8 tx_mic[8];
-       u8 rx_mic[8];
-} __packed;
-
-struct hw_pairwise_ta_entry {
-       u8 address[6];
-       u8 cipher;
-       u8 reserved;
-} __packed;
-
-/*
- * Since NULL frame won't be that long (256 byte),
- * We steal 16 tail bytes to save debugging settings.
- */
-#define HW_DEBUG_SETTING_BASE          0x2bf0
-
-/*
- * On-chip BEACON frame space.
- */
-#define HW_BEACON_BASE0                        0x2400
-#define HW_BEACON_BASE1                        0x2500
-#define HW_BEACON_BASE2                        0x2600
-#define HW_BEACON_BASE3                        0x2700
-
-#define HW_BEACON_OFFSET(__index) \
-       ( HW_BEACON_BASE0 + (__index * 0x0100) )
-
-/*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- */
-#define MAC_CSR0                       0x3000
-#define MAC_CSR0_REVISION              FIELD32(0x0000000f)
-#define MAC_CSR0_CHIPSET               FIELD32(0x000ffff0)
-
-/*
- * MAC_CSR1: System control register.
- * SOFT_RESET: Software reset bit, 1: reset, 0: normal.
- * BBP_RESET: Hardware reset BBP.
- * HOST_READY: Host is ready after initialization, 1: ready.
- */
-#define MAC_CSR1                       0x3004
-#define MAC_CSR1_SOFT_RESET            FIELD32(0x00000001)
-#define MAC_CSR1_BBP_RESET             FIELD32(0x00000002)
-#define MAC_CSR1_HOST_READY            FIELD32(0x00000004)
-
-/*
- * MAC_CSR2: STA MAC register 0.
- */
-#define MAC_CSR2                       0x3008
-#define MAC_CSR2_BYTE0                 FIELD32(0x000000ff)
-#define MAC_CSR2_BYTE1                 FIELD32(0x0000ff00)
-#define MAC_CSR2_BYTE2                 FIELD32(0x00ff0000)
-#define MAC_CSR2_BYTE3                 FIELD32(0xff000000)
-
-/*
- * MAC_CSR3: STA MAC register 1.
- * UNICAST_TO_ME_MASK:
- *     Used to mask off bits from byte 5 of the MAC address
- *     to determine the UNICAST_TO_ME bit for RX frames.
- *     The full mask is complemented by BSS_ID_MASK:
- *             MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
-#define MAC_CSR3                       0x300c
-#define MAC_CSR3_BYTE4                 FIELD32(0x000000ff)
-#define MAC_CSR3_BYTE5                 FIELD32(0x0000ff00)
-#define MAC_CSR3_UNICAST_TO_ME_MASK    FIELD32(0x00ff0000)
-
-/*
- * MAC_CSR4: BSSID register 0.
- */
-#define MAC_CSR4                       0x3010
-#define MAC_CSR4_BYTE0                 FIELD32(0x000000ff)
-#define MAC_CSR4_BYTE1                 FIELD32(0x0000ff00)
-#define MAC_CSR4_BYTE2                 FIELD32(0x00ff0000)
-#define MAC_CSR4_BYTE3                 FIELD32(0xff000000)
-
-/*
- * MAC_CSR5: BSSID register 1.
- * BSS_ID_MASK:
- *     This mask is used to mask off bits 0 and 1 of byte 5 of the
- *     BSSID. This will make sure that those bits will be ignored
- *     when determining the MY_BSS of RX frames.
- *             0: 1-BSSID mode (BSS index = 0)
- *             1: 2-BSSID mode (BSS index: Byte5, bit 0)
- *             2: 2-BSSID mode (BSS index: byte5, bit 1)
- *             3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- */
-#define MAC_CSR5                       0x3014
-#define MAC_CSR5_BYTE4                 FIELD32(0x000000ff)
-#define MAC_CSR5_BYTE5                 FIELD32(0x0000ff00)
-#define MAC_CSR5_BSS_ID_MASK           FIELD32(0x00ff0000)
-
-/*
- * MAC_CSR6: Maximum frame length register.
- */
-#define MAC_CSR6                       0x3018
-#define MAC_CSR6_MAX_FRAME_UNIT                FIELD32(0x00000fff)
-
-/*
- * MAC_CSR7: Reserved
- */
-#define MAC_CSR7                       0x301c
-
-/*
- * MAC_CSR8: SIFS/EIFS register.
- * All units are in US.
- */
-#define MAC_CSR8                       0x3020
-#define MAC_CSR8_SIFS                  FIELD32(0x000000ff)
-#define MAC_CSR8_SIFS_AFTER_RX_OFDM    FIELD32(0x0000ff00)
-#define MAC_CSR8_EIFS                  FIELD32(0xffff0000)
-
-/*
- * MAC_CSR9: Back-Off control register.
- * SLOT_TIME: Slot time, default is 20us for 802.11BG.
- * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1).
- * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1).
- * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD.
- */
-#define MAC_CSR9                       0x3024
-#define MAC_CSR9_SLOT_TIME             FIELD32(0x000000ff)
-#define MAC_CSR9_CWMIN                 FIELD32(0x00000f00)
-#define MAC_CSR9_CWMAX                 FIELD32(0x0000f000)
-#define MAC_CSR9_CW_SELECT             FIELD32(0x00010000)
-
-/*
- * MAC_CSR10: Power state configuration.
- */
-#define MAC_CSR10                      0x3028
-
-/*
- * MAC_CSR11: Power saving transition time register.
- * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU.
- * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup.
- * WAKEUP_LATENCY: In unit of TU.
- */
-#define MAC_CSR11                      0x302c
-#define MAC_CSR11_DELAY_AFTER_TBCN     FIELD32(0x000000ff)
-#define MAC_CSR11_TBCN_BEFORE_WAKEUP   FIELD32(0x00007f00)
-#define MAC_CSR11_AUTOWAKE             FIELD32(0x00008000)
-#define MAC_CSR11_WAKEUP_LATENCY       FIELD32(0x000f0000)
-
-/*
- * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1).
- * CURRENT_STATE: 0:sleep, 1:awake.
- * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP.
- * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake.
- */
-#define MAC_CSR12                      0x3030
-#define MAC_CSR12_CURRENT_STATE                FIELD32(0x00000001)
-#define MAC_CSR12_PUT_TO_SLEEP         FIELD32(0x00000002)
-#define MAC_CSR12_FORCE_WAKEUP         FIELD32(0x00000004)
-#define MAC_CSR12_BBP_CURRENT_STATE    FIELD32(0x00000008)
-
-/*
- * MAC_CSR13: GPIO.
- *     MAC_CSR13_VALx: GPIO value
- *     MAC_CSR13_DIRx: GPIO direction: 0 = input; 1 = output
- */
-#define MAC_CSR13                      0x3034
-#define MAC_CSR13_VAL0                 FIELD32(0x00000001)
-#define MAC_CSR13_VAL1                 FIELD32(0x00000002)
-#define MAC_CSR13_VAL2                 FIELD32(0x00000004)
-#define MAC_CSR13_VAL3                 FIELD32(0x00000008)
-#define MAC_CSR13_VAL4                 FIELD32(0x00000010)
-#define MAC_CSR13_VAL5                 FIELD32(0x00000020)
-#define MAC_CSR13_VAL6                 FIELD32(0x00000040)
-#define MAC_CSR13_VAL7                 FIELD32(0x00000080)
-#define MAC_CSR13_DIR0                 FIELD32(0x00000100)
-#define MAC_CSR13_DIR1                 FIELD32(0x00000200)
-#define MAC_CSR13_DIR2                 FIELD32(0x00000400)
-#define MAC_CSR13_DIR3                 FIELD32(0x00000800)
-#define MAC_CSR13_DIR4                 FIELD32(0x00001000)
-#define MAC_CSR13_DIR5                 FIELD32(0x00002000)
-#define MAC_CSR13_DIR6                 FIELD32(0x00004000)
-#define MAC_CSR13_DIR7                 FIELD32(0x00008000)
-
-/*
- * MAC_CSR14: LED control register.
- * ON_PERIOD: On period, default 70ms.
- * OFF_PERIOD: Off period, default 30ms.
- * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON.
- * SW_LED: s/w LED, 1: ON, 0: OFF.
- * HW_LED_POLARITY: 0: active low, 1: active high.
- */
-#define MAC_CSR14                      0x3038
-#define MAC_CSR14_ON_PERIOD            FIELD32(0x000000ff)
-#define MAC_CSR14_OFF_PERIOD           FIELD32(0x0000ff00)
-#define MAC_CSR14_HW_LED               FIELD32(0x00010000)
-#define MAC_CSR14_SW_LED               FIELD32(0x00020000)
-#define MAC_CSR14_HW_LED_POLARITY      FIELD32(0x00040000)
-#define MAC_CSR14_SW_LED2              FIELD32(0x00080000)
-
-/*
- * MAC_CSR15: NAV control.
- */
-#define MAC_CSR15                      0x303c
-
-/*
- * TXRX control registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * TXRX_CSR0: TX/RX configuration register.
- * TSF_OFFSET: Default is 24.
- * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame.
- * DISABLE_RX: Disable Rx engine.
- * DROP_CRC: Drop CRC error.
- * DROP_PHYSICAL: Drop physical error.
- * DROP_CONTROL: Drop control frame.
- * DROP_NOT_TO_ME: Drop not to me unicast frame.
- * DROP_TO_DS: Drop fram ToDs bit is true.
- * DROP_VERSION_ERROR: Drop version error frame.
- * DROP_MULTICAST: Drop multicast frames.
- * DROP_BORADCAST: Drop broadcast frames.
- * DROP_ACK_CTS: Drop received ACK and CTS.
- */
-#define TXRX_CSR0                      0x3040
-#define TXRX_CSR0_RX_ACK_TIMEOUT       FIELD32(0x000001ff)
-#define TXRX_CSR0_TSF_OFFSET           FIELD32(0x00007e00)
-#define TXRX_CSR0_AUTO_TX_SEQ          FIELD32(0x00008000)
-#define TXRX_CSR0_DISABLE_RX           FIELD32(0x00010000)
-#define TXRX_CSR0_DROP_CRC             FIELD32(0x00020000)
-#define TXRX_CSR0_DROP_PHYSICAL                FIELD32(0x00040000)
-#define TXRX_CSR0_DROP_CONTROL         FIELD32(0x00080000)
-#define TXRX_CSR0_DROP_NOT_TO_ME       FIELD32(0x00100000)
-#define TXRX_CSR0_DROP_TO_DS           FIELD32(0x00200000)
-#define TXRX_CSR0_DROP_VERSION_ERROR   FIELD32(0x00400000)
-#define TXRX_CSR0_DROP_MULTICAST       FIELD32(0x00800000)
-#define TXRX_CSR0_DROP_BROADCAST       FIELD32(0x01000000)
-#define TXRX_CSR0_DROP_ACK_CTS         FIELD32(0x02000000)
-#define TXRX_CSR0_TX_WITHOUT_WAITING   FIELD32(0x04000000)
-
-/*
- * TXRX_CSR1
- */
-#define TXRX_CSR1                      0x3044
-#define TXRX_CSR1_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR1_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR1_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR1_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR1_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR1_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR1_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR1_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR2
- */
-#define TXRX_CSR2                      0x3048
-#define TXRX_CSR2_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR2_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR2_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR2_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR2_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR2_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR2_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR2_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR3
- */
-#define TXRX_CSR3                      0x304c
-#define TXRX_CSR3_BBP_ID0              FIELD32(0x0000007f)
-#define TXRX_CSR3_BBP_ID0_VALID                FIELD32(0x00000080)
-#define TXRX_CSR3_BBP_ID1              FIELD32(0x00007f00)
-#define TXRX_CSR3_BBP_ID1_VALID                FIELD32(0x00008000)
-#define TXRX_CSR3_BBP_ID2              FIELD32(0x007f0000)
-#define TXRX_CSR3_BBP_ID2_VALID                FIELD32(0x00800000)
-#define TXRX_CSR3_BBP_ID3              FIELD32(0x7f000000)
-#define TXRX_CSR3_BBP_ID3_VALID                FIELD32(0x80000000)
-
-/*
- * TXRX_CSR4: Auto-Responder/Tx-retry register.
- * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble.
- * OFDM_TX_RATE_DOWN: 1:enable.
- * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step.
- * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M.
- */
-#define TXRX_CSR4                      0x3050
-#define TXRX_CSR4_TX_ACK_TIMEOUT       FIELD32(0x000000ff)
-#define TXRX_CSR4_CNTL_ACK_POLICY      FIELD32(0x00000700)
-#define TXRX_CSR4_ACK_CTS_PSM          FIELD32(0x00010000)
-#define TXRX_CSR4_AUTORESPOND_ENABLE   FIELD32(0x00020000)
-#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000)
-#define TXRX_CSR4_OFDM_TX_RATE_DOWN    FIELD32(0x00080000)
-#define TXRX_CSR4_OFDM_TX_RATE_STEP    FIELD32(0x00300000)
-#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000)
-#define TXRX_CSR4_LONG_RETRY_LIMIT     FIELD32(0x0f000000)
-#define TXRX_CSR4_SHORT_RETRY_LIMIT    FIELD32(0xf0000000)
-
-/*
- * TXRX_CSR5
- */
-#define TXRX_CSR5                      0x3054
-
-/*
- * TXRX_CSR6: ACK/CTS payload consumed time
- */
-#define TXRX_CSR6                      0x3058
-
-/*
- * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
- */
-#define TXRX_CSR7                      0x305c
-#define TXRX_CSR7_ACK_CTS_6MBS         FIELD32(0x000000ff)
-#define TXRX_CSR7_ACK_CTS_9MBS         FIELD32(0x0000ff00)
-#define TXRX_CSR7_ACK_CTS_12MBS                FIELD32(0x00ff0000)
-#define TXRX_CSR7_ACK_CTS_18MBS                FIELD32(0xff000000)
-
-/*
- * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
- */
-#define TXRX_CSR8                      0x3060
-#define TXRX_CSR8_ACK_CTS_24MBS                FIELD32(0x000000ff)
-#define TXRX_CSR8_ACK_CTS_36MBS                FIELD32(0x0000ff00)
-#define TXRX_CSR8_ACK_CTS_48MBS                FIELD32(0x00ff0000)
-#define TXRX_CSR8_ACK_CTS_54MBS                FIELD32(0xff000000)
-
-/*
- * TXRX_CSR9: Synchronization control register.
- * BEACON_INTERVAL: In unit of 1/16 TU.
- * TSF_TICKING: Enable TSF auto counting.
- * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode.
- * BEACON_GEN: Enable beacon generator.
- */
-#define TXRX_CSR9                      0x3064
-#define TXRX_CSR9_BEACON_INTERVAL      FIELD32(0x0000ffff)
-#define TXRX_CSR9_TSF_TICKING          FIELD32(0x00010000)
-#define TXRX_CSR9_TSF_SYNC             FIELD32(0x00060000)
-#define TXRX_CSR9_TBTT_ENABLE          FIELD32(0x00080000)
-#define TXRX_CSR9_BEACON_GEN           FIELD32(0x00100000)
-#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000)
-
-/*
- * TXRX_CSR10: BEACON alignment.
- */
-#define TXRX_CSR10                     0x3068
-
-/*
- * TXRX_CSR11: AES mask.
- */
-#define TXRX_CSR11                     0x306c
-
-/*
- * TXRX_CSR12: TSF low 32.
- */
-#define TXRX_CSR12                     0x3070
-#define TXRX_CSR12_LOW_TSFTIMER                FIELD32(0xffffffff)
-
-/*
- * TXRX_CSR13: TSF high 32.
- */
-#define TXRX_CSR13                     0x3074
-#define TXRX_CSR13_HIGH_TSFTIMER       FIELD32(0xffffffff)
-
-/*
- * TXRX_CSR14: TBTT timer.
- */
-#define TXRX_CSR14                     0x3078
-
-/*
- * TXRX_CSR15: TKIP MIC priority byte "AND" mask.
- */
-#define TXRX_CSR15                     0x307c
-
-/*
- * PHY control registers.
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * PHY_CSR0: RF/PS control.
- */
-#define PHY_CSR0                       0x3080
-#define PHY_CSR0_PA_PE_BG              FIELD32(0x00010000)
-#define PHY_CSR0_PA_PE_A               FIELD32(0x00020000)
-
-/*
- * PHY_CSR1
- */
-#define PHY_CSR1                       0x3084
-#define PHY_CSR1_RF_RPI                        FIELD32(0x00010000)
-
-/*
- * PHY_CSR2: Pre-TX BBP control.
- */
-#define PHY_CSR2                       0x3088
-
-/*
- * PHY_CSR3: BBP serial control register.
- * VALUE: Register value to program into BBP.
- * REG_NUM: Selected BBP register.
- * READ_CONTROL: 0: Write BBP, 1: Read BBP.
- * BUSY: 1: ASIC is busy execute BBP programming.
- */
-#define PHY_CSR3                       0x308c
-#define PHY_CSR3_VALUE                 FIELD32(0x000000ff)
-#define PHY_CSR3_REGNUM                        FIELD32(0x00007f00)
-#define PHY_CSR3_READ_CONTROL          FIELD32(0x00008000)
-#define PHY_CSR3_BUSY                  FIELD32(0x00010000)
-
-/*
- * PHY_CSR4: RF serial control register
- * VALUE: Register value (include register id) serial out to RF/IF chip.
- * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22).
- * IF_SELECT: 1: select IF to program, 0: select RF to program.
- * PLL_LD: RF PLL_LD status.
- * BUSY: 1: ASIC is busy execute RF programming.
- */
-#define PHY_CSR4                       0x3090
-#define PHY_CSR4_VALUE                 FIELD32(0x00ffffff)
-#define PHY_CSR4_NUMBER_OF_BITS                FIELD32(0x1f000000)
-#define PHY_CSR4_IF_SELECT             FIELD32(0x20000000)
-#define PHY_CSR4_PLL_LD                        FIELD32(0x40000000)
-#define PHY_CSR4_BUSY                  FIELD32(0x80000000)
-
-/*
- * PHY_CSR5: RX to TX signal switch timing control.
- */
-#define PHY_CSR5                       0x3094
-#define PHY_CSR5_IQ_FLIP               FIELD32(0x00000004)
-
-/*
- * PHY_CSR6: TX to RX signal timing control.
- */
-#define PHY_CSR6                       0x3098
-#define PHY_CSR6_IQ_FLIP               FIELD32(0x00000004)
-
-/*
- * PHY_CSR7: TX DAC switching timing control.
- */
-#define PHY_CSR7                       0x309c
-
-/*
- * Security control register.
- */
-
-/*
- * SEC_CSR0: Shared key table control.
- */
-#define SEC_CSR0                       0x30a0
-#define SEC_CSR0_BSS0_KEY0_VALID       FIELD32(0x00000001)
-#define SEC_CSR0_BSS0_KEY1_VALID       FIELD32(0x00000002)
-#define SEC_CSR0_BSS0_KEY2_VALID       FIELD32(0x00000004)
-#define SEC_CSR0_BSS0_KEY3_VALID       FIELD32(0x00000008)
-#define SEC_CSR0_BSS1_KEY0_VALID       FIELD32(0x00000010)
-#define SEC_CSR0_BSS1_KEY1_VALID       FIELD32(0x00000020)
-#define SEC_CSR0_BSS1_KEY2_VALID       FIELD32(0x00000040)
-#define SEC_CSR0_BSS1_KEY3_VALID       FIELD32(0x00000080)
-#define SEC_CSR0_BSS2_KEY0_VALID       FIELD32(0x00000100)
-#define SEC_CSR0_BSS2_KEY1_VALID       FIELD32(0x00000200)
-#define SEC_CSR0_BSS2_KEY2_VALID       FIELD32(0x00000400)
-#define SEC_CSR0_BSS2_KEY3_VALID       FIELD32(0x00000800)
-#define SEC_CSR0_BSS3_KEY0_VALID       FIELD32(0x00001000)
-#define SEC_CSR0_BSS3_KEY1_VALID       FIELD32(0x00002000)
-#define SEC_CSR0_BSS3_KEY2_VALID       FIELD32(0x00004000)
-#define SEC_CSR0_BSS3_KEY3_VALID       FIELD32(0x00008000)
-
-/*
- * SEC_CSR1: Shared key table security mode register.
- */
-#define SEC_CSR1                       0x30a4
-#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG  FIELD32(0x00000007)
-#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG  FIELD32(0x00000070)
-#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG  FIELD32(0x00000700)
-#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG  FIELD32(0x00007000)
-#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG  FIELD32(0x00070000)
-#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG  FIELD32(0x00700000)
-#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG  FIELD32(0x07000000)
-#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG  FIELD32(0x70000000)
-
-/*
- * Pairwise key table valid bitmap registers.
- * SEC_CSR2: pairwise key table valid bitmap 0.
- * SEC_CSR3: pairwise key table valid bitmap 1.
- */
-#define SEC_CSR2                       0x30a8
-#define SEC_CSR3                       0x30ac
-
-/*
- * SEC_CSR4: Pairwise key table lookup control.
- */
-#define SEC_CSR4                       0x30b0
-#define SEC_CSR4_ENABLE_BSS0           FIELD32(0x00000001)
-#define SEC_CSR4_ENABLE_BSS1           FIELD32(0x00000002)
-#define SEC_CSR4_ENABLE_BSS2           FIELD32(0x00000004)
-#define SEC_CSR4_ENABLE_BSS3           FIELD32(0x00000008)
-
-/*
- * SEC_CSR5: shared key table security mode register.
- */
-#define SEC_CSR5                       0x30b4
-#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG  FIELD32(0x00000007)
-#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG  FIELD32(0x00000070)
-#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG  FIELD32(0x00000700)
-#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG  FIELD32(0x00007000)
-#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG  FIELD32(0x00070000)
-#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG  FIELD32(0x00700000)
-#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG  FIELD32(0x07000000)
-#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG  FIELD32(0x70000000)
-
-/*
- * STA control registers.
- */
-
-/*
- * STA_CSR0: RX PLCP error count & RX FCS error count.
- */
-#define STA_CSR0                       0x30c0
-#define STA_CSR0_FCS_ERROR             FIELD32(0x0000ffff)
-#define STA_CSR0_PLCP_ERROR            FIELD32(0xffff0000)
-
-/*
- * STA_CSR1: RX False CCA count & RX LONG frame count.
- */
-#define STA_CSR1                       0x30c4
-#define STA_CSR1_PHYSICAL_ERROR                FIELD32(0x0000ffff)
-#define STA_CSR1_FALSE_CCA_ERROR       FIELD32(0xffff0000)
-
-/*
- * STA_CSR2: TX Beacon count and RX FIFO overflow count.
- */
-#define STA_CSR2                       0x30c8
-#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT        FIELD32(0x0000ffff)
-#define STA_CSR2_RX_OVERFLOW_COUNT     FIELD32(0xffff0000)
-
-/*
- * STA_CSR3: TX Beacon count.
- */
-#define STA_CSR3                       0x30cc
-#define STA_CSR3_TX_BEACON_COUNT       FIELD32(0x0000ffff)
-
-/*
- * STA_CSR4: TX Retry count.
- */
-#define STA_CSR4                       0x30d0
-#define STA_CSR4_TX_NO_RETRY_COUNT     FIELD32(0x0000ffff)
-#define STA_CSR4_TX_ONE_RETRY_COUNT    FIELD32(0xffff0000)
-
-/*
- * STA_CSR5: TX Retry count.
- */
-#define STA_CSR5                       0x30d4
-#define STA_CSR4_TX_MULTI_RETRY_COUNT  FIELD32(0x0000ffff)
-#define STA_CSR4_TX_RETRY_FAIL_COUNT   FIELD32(0xffff0000)
-
-/*
- * QOS control registers.
- */
-
-/*
- * QOS_CSR1: TXOP holder MAC address register.
- */
-#define QOS_CSR1                       0x30e4
-#define QOS_CSR1_BYTE4                 FIELD32(0x000000ff)
-#define QOS_CSR1_BYTE5                 FIELD32(0x0000ff00)
-
-/*
- * QOS_CSR2: TXOP holder timeout register.
- */
-#define QOS_CSR2                       0x30e8
-
-/*
- * RX QOS-CFPOLL MAC address register.
- * QOS_CSR3: RX QOS-CFPOLL MAC address 0.
- * QOS_CSR4: RX QOS-CFPOLL MAC address 1.
- */
-#define QOS_CSR3                       0x30ec
-#define QOS_CSR4                       0x30f0
-
-/*
- * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL.
- */
-#define QOS_CSR5                       0x30f4
-
-/*
- * WMM Scheduler Register
- */
-
-/*
- * AIFSN_CSR: AIFSN for each EDCA AC.
- * AIFSN0: For AC_VO.
- * AIFSN1: For AC_VI.
- * AIFSN2: For AC_BE.
- * AIFSN3: For AC_BK.
- */
-#define AIFSN_CSR                      0x0400
-#define AIFSN_CSR_AIFSN0               FIELD32(0x0000000f)
-#define AIFSN_CSR_AIFSN1               FIELD32(0x000000f0)
-#define AIFSN_CSR_AIFSN2               FIELD32(0x00000f00)
-#define AIFSN_CSR_AIFSN3               FIELD32(0x0000f000)
-
-/*
- * CWMIN_CSR: CWmin for each EDCA AC.
- * CWMIN0: For AC_VO.
- * CWMIN1: For AC_VI.
- * CWMIN2: For AC_BE.
- * CWMIN3: For AC_BK.
- */
-#define CWMIN_CSR                      0x0404
-#define CWMIN_CSR_CWMIN0               FIELD32(0x0000000f)
-#define CWMIN_CSR_CWMIN1               FIELD32(0x000000f0)
-#define CWMIN_CSR_CWMIN2               FIELD32(0x00000f00)
-#define CWMIN_CSR_CWMIN3               FIELD32(0x0000f000)
-
-/*
- * CWMAX_CSR: CWmax for each EDCA AC.
- * CWMAX0: For AC_VO.
- * CWMAX1: For AC_VI.
- * CWMAX2: For AC_BE.
- * CWMAX3: For AC_BK.
- */
-#define CWMAX_CSR                      0x0408
-#define CWMAX_CSR_CWMAX0               FIELD32(0x0000000f)
-#define CWMAX_CSR_CWMAX1               FIELD32(0x000000f0)
-#define CWMAX_CSR_CWMAX2               FIELD32(0x00000f00)
-#define CWMAX_CSR_CWMAX3               FIELD32(0x0000f000)
-
-/*
- * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
- * AC0_TX_OP: For AC_VO, in unit of 32us.
- * AC1_TX_OP: For AC_VI, in unit of 32us.
- */
-#define AC_TXOP_CSR0                   0x040c
-#define AC_TXOP_CSR0_AC0_TX_OP         FIELD32(0x0000ffff)
-#define AC_TXOP_CSR0_AC1_TX_OP         FIELD32(0xffff0000)
-
-/*
- * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
- * AC2_TX_OP: For AC_BE, in unit of 32us.
- * AC3_TX_OP: For AC_BK, in unit of 32us.
- */
-#define AC_TXOP_CSR1                   0x0410
-#define AC_TXOP_CSR1_AC2_TX_OP         FIELD32(0x0000ffff)
-#define AC_TXOP_CSR1_AC3_TX_OP         FIELD32(0xffff0000)
-
-/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * R2
- */
-#define BBP_R2_BG_MODE                 FIELD8(0x20)
-
-/*
- * R3
- */
-#define BBP_R3_SMART_MODE              FIELD8(0x01)
-
-/*
- * R4: RX antenna control
- * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
- */
-
-/*
- * ANTENNA_CONTROL semantics (guessed):
- * 0x1: Software controlled antenna switching (fixed or SW diversity)
- * 0x2: Hardware diversity.
- */
-#define BBP_R4_RX_ANTENNA_CONTROL      FIELD8(0x03)
-#define BBP_R4_RX_FRAME_END            FIELD8(0x20)
-
-/*
- * R77
- */
-#define BBP_R77_RX_ANTENNA             FIELD8(0x03)
-
-/*
- * RF registers
- */
-
-/*
- * RF 3
- */
-#define RF3_TXPOWER                    FIELD32(0x00003e00)
-
-/*
- * RF 4
- */
-#define RF4_FREQ_OFFSET                        FIELD32(0x0003f000)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0              0x0002
-#define EEPROM_MAC_ADDR_BYTE0          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR1               0x0003
-#define EEPROM_MAC_ADDR_BYTE2          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3          FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2              0x0004
-#define EEPROM_MAC_ADDR_BYTE4          FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5          FIELD16(0xff00)
-
-/*
- * EEPROM antenna.
- * ANTENNA_NUM: Number of antennas.
- * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
- * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only.
- * DYN_TXAGC: Dynamic TX AGC control.
- * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0.
- * RF_TYPE: Rf_type of this adapter.
- */
-#define EEPROM_ANTENNA                 0x0010
-#define EEPROM_ANTENNA_NUM             FIELD16(0x0003)
-#define EEPROM_ANTENNA_TX_DEFAULT      FIELD16(0x000c)
-#define EEPROM_ANTENNA_RX_DEFAULT      FIELD16(0x0030)
-#define EEPROM_ANTENNA_FRAME_TYPE      FIELD16(0x0040)
-#define EEPROM_ANTENNA_DYN_TXAGC       FIELD16(0x0200)
-#define EEPROM_ANTENNA_HARDWARE_RADIO  FIELD16(0x0400)
-#define EEPROM_ANTENNA_RF_TYPE         FIELD16(0xf800)
-
-/*
- * EEPROM NIC config.
- * EXTERNAL_LNA: External LNA.
- */
-#define EEPROM_NIC                     0x0011
-#define EEPROM_NIC_EXTERNAL_LNA                FIELD16(0x0010)
-
-/*
- * EEPROM geography.
- * GEO_A: Default geographical setting for 5GHz band
- * GEO: Default geographical setting.
- */
-#define EEPROM_GEOGRAPHY               0x0012
-#define EEPROM_GEOGRAPHY_GEO_A         FIELD16(0x00ff)
-#define EEPROM_GEOGRAPHY_GEO           FIELD16(0xff00)
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START               0x0013
-#define EEPROM_BBP_SIZE                        16
-#define EEPROM_BBP_VALUE               FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID              FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER 802.11G
- */
-#define EEPROM_TXPOWER_G_START         0x0023
-#define EEPROM_TXPOWER_G_SIZE          7
-#define EEPROM_TXPOWER_G_1             FIELD16(0x00ff)
-#define EEPROM_TXPOWER_G_2             FIELD16(0xff00)
-
-/*
- * EEPROM Frequency
- */
-#define EEPROM_FREQ                    0x002f
-#define EEPROM_FREQ_OFFSET             FIELD16(0x00ff)
-#define EEPROM_FREQ_SEQ_MASK           FIELD16(0xff00)
-#define EEPROM_FREQ_SEQ                        FIELD16(0x0300)
-
-/*
- * EEPROM LED.
- * POLARITY_RDY_G: Polarity RDY_G setting.
- * POLARITY_RDY_A: Polarity RDY_A setting.
- * POLARITY_ACT: Polarity ACT setting.
- * POLARITY_GPIO_0: Polarity GPIO0 setting.
- * POLARITY_GPIO_1: Polarity GPIO1 setting.
- * POLARITY_GPIO_2: Polarity GPIO2 setting.
- * POLARITY_GPIO_3: Polarity GPIO3 setting.
- * POLARITY_GPIO_4: Polarity GPIO4 setting.
- * LED_MODE: Led mode.
- */
-#define EEPROM_LED                     0x0030
-#define EEPROM_LED_POLARITY_RDY_G      FIELD16(0x0001)
-#define EEPROM_LED_POLARITY_RDY_A      FIELD16(0x0002)
-#define EEPROM_LED_POLARITY_ACT                FIELD16(0x0004)
-#define EEPROM_LED_POLARITY_GPIO_0     FIELD16(0x0008)
-#define EEPROM_LED_POLARITY_GPIO_1     FIELD16(0x0010)
-#define EEPROM_LED_POLARITY_GPIO_2     FIELD16(0x0020)
-#define EEPROM_LED_POLARITY_GPIO_3     FIELD16(0x0040)
-#define EEPROM_LED_POLARITY_GPIO_4     FIELD16(0x0080)
-#define EEPROM_LED_LED_MODE            FIELD16(0x1f00)
-
-/*
- * EEPROM TXPOWER 802.11A
- */
-#define EEPROM_TXPOWER_A_START         0x0031
-#define EEPROM_TXPOWER_A_SIZE          12
-#define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
-#define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
-
-/*
- * EEPROM RSSI offset 802.11BG
- */
-#define EEPROM_RSSI_OFFSET_BG          0x004d
-#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
-#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
-
-/*
- * EEPROM RSSI offset 802.11A
- */
-#define EEPROM_RSSI_OFFSET_A           0x004e
-#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
-#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
-
-/*
- * DMA descriptor defines.
- */
-#define TXD_DESC_SIZE                  ( 6 * sizeof(__le32) )
-#define TXINFO_SIZE                    ( 6 * sizeof(__le32) )
-#define RXD_DESC_SIZE                  ( 6 * sizeof(__le32) )
-
-/*
- * TX descriptor format for TX, PRIO and Beacon Ring.
- */
-
-/*
- * Word0
- * BURST: Next frame belongs to same "burst" event.
- * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used.
- * KEY_TABLE: Use per-client pairwise KEY table.
- * KEY_INDEX:
- * Key index (0~31) to the pairwise KEY table.
- * 0~3 to shared KEY table 0 (BSS0).
- * 4~7 to shared KEY table 1 (BSS1).
- * 8~11 to shared KEY table 2 (BSS2).
- * 12~15 to shared KEY table 3 (BSS3).
- * BURST2: For backward compatibility, set to same value as BURST.
- */
-#define TXD_W0_BURST                   FIELD32(0x00000001)
-#define TXD_W0_VALID                   FIELD32(0x00000002)
-#define TXD_W0_MORE_FRAG               FIELD32(0x00000004)
-#define TXD_W0_ACK                     FIELD32(0x00000008)
-#define TXD_W0_TIMESTAMP               FIELD32(0x00000010)
-#define TXD_W0_OFDM                    FIELD32(0x00000020)
-#define TXD_W0_IFS                     FIELD32(0x00000040)
-#define TXD_W0_RETRY_MODE              FIELD32(0x00000080)
-#define TXD_W0_TKIP_MIC                        FIELD32(0x00000100)
-#define TXD_W0_KEY_TABLE               FIELD32(0x00000200)
-#define TXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
-#define TXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define TXD_W0_BURST2                  FIELD32(0x10000000)
-#define TXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * Word1
- * HOST_Q_ID: EDCA/HCCA queue ID.
- * HW_SEQUENCE: MAC overwrites the frame sequence number.
- * BUFFER_COUNT: Number of buffers in this TXD.
- */
-#define TXD_W1_HOST_Q_ID               FIELD32(0x0000000f)
-#define TXD_W1_AIFSN                   FIELD32(0x000000f0)
-#define TXD_W1_CWMIN                   FIELD32(0x00000f00)
-#define TXD_W1_CWMAX                   FIELD32(0x0000f000)
-#define TXD_W1_IV_OFFSET               FIELD32(0x003f0000)
-#define TXD_W1_HW_SEQUENCE             FIELD32(0x10000000)
-#define TXD_W1_BUFFER_COUNT            FIELD32(0xe0000000)
-
-/*
- * Word2: PLCP information
- */
-#define TXD_W2_PLCP_SIGNAL             FIELD32(0x000000ff)
-#define TXD_W2_PLCP_SERVICE            FIELD32(0x0000ff00)
-#define TXD_W2_PLCP_LENGTH_LOW         FIELD32(0x00ff0000)
-#define TXD_W2_PLCP_LENGTH_HIGH                FIELD32(0xff000000)
-
-/*
- * Word3
- */
-#define TXD_W3_IV                      FIELD32(0xffffffff)
-
-/*
- * Word4
- */
-#define TXD_W4_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word5
- * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field).
- * PACKET_ID: Driver assigned packet ID to categorize TXResult in interrupt.
- * WAITING_DMA_DONE_INT: TXD been filled with data
- * and waiting for TxDoneISR housekeeping.
- */
-#define TXD_W5_FRAME_OFFSET            FIELD32(0x000000ff)
-#define TXD_W5_PACKET_ID               FIELD32(0x0000ff00)
-#define TXD_W5_TX_POWER                        FIELD32(0x00ff0000)
-#define TXD_W5_WAITING_DMA_DONE_INT    FIELD32(0x01000000)
-
-/*
- * RX descriptor format for RX Ring.
- */
-
-/*
- * Word0
- * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key.
- * KEY_INDEX: Decryption key actually used.
- */
-#define RXD_W0_OWNER_NIC               FIELD32(0x00000001)
-#define RXD_W0_DROP                    FIELD32(0x00000002)
-#define RXD_W0_UNICAST_TO_ME           FIELD32(0x00000004)
-#define RXD_W0_MULTICAST               FIELD32(0x00000008)
-#define RXD_W0_BROADCAST               FIELD32(0x00000010)
-#define RXD_W0_MY_BSS                  FIELD32(0x00000020)
-#define RXD_W0_CRC_ERROR               FIELD32(0x00000040)
-#define RXD_W0_OFDM                    FIELD32(0x00000080)
-#define RXD_W0_CIPHER_ERROR            FIELD32(0x00000300)
-#define RXD_W0_KEY_INDEX               FIELD32(0x0000fc00)
-#define RXD_W0_DATABYTE_COUNT          FIELD32(0x0fff0000)
-#define RXD_W0_CIPHER_ALG              FIELD32(0xe0000000)
-
-/*
- * WORD1
- * SIGNAL: RX raw data rate reported by BBP.
- * RSSI: RSSI reported by BBP.
- */
-#define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
-#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
-#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
-#define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
-
-/*
- * Word2
- * IV: Received IV of originally encrypted.
- */
-#define RXD_W2_IV                      FIELD32(0xffffffff)
-
-/*
- * Word3
- * EIV: Received EIV of originally encrypted.
- */
-#define RXD_W3_EIV                     FIELD32(0xffffffff)
-
-/*
- * Word4
- * ICV: Received ICV of originally encrypted.
- * NOTE: This is a guess, the official definition is "reserved"
- */
-#define RXD_W4_ICV                     FIELD32(0xffffffff)
-
-/*
- * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
- * and passed to the HOST driver.
- * The following fields are for DMA block and HOST usage only.
- * Can't be touched by ASIC MAC block.
- */
-
-/*
- * Word5
- */
-#define RXD_W5_RESERVED                        FIELD32(0xffffffff)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_TXPOWER    0
-#define MAX_TXPOWER    31
-#define DEFAULT_TXPOWER        24
-
-#define TXPOWER_FROM_DEV(__txpower) \
-       (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_TO_DEV(__txpower) \
-       clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
-
-#endif /* RT73USB_H */