Merge branch 'for-next' into for-linus
[safe/jmp/linux-2.6] / drivers / net / wireless / rt2x00 / rt73usb.c
index d5a6c21..e77aec8 100644 (file)
@@ -1,5 +1,5 @@
 /*
-       Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
+       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
 #include "rt73usb.h"
 
 /*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 0;
+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
- * rt73usb_register_read and rt73usb_register_write.
+ * 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,
  * 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 usb_cache_mutex
+ * The _lock versions must be used if you already hold the csr_mutex
  */
-static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
-                                        const unsigned int offset, u32 *value)
-{
-       __le32 reg;
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     &reg, sizeof(u32), REGISTER_TIMEOUT);
-       *value = le32_to_cpu(reg);
-}
-
-static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
-                                             const unsigned int offset, u32 *value)
-{
-       __le32 reg;
-       rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
-                                      USB_VENDOR_REQUEST_IN, offset,
-                                      &reg, sizeof(u32), REGISTER_TIMEOUT);
-       *value = le32_to_cpu(reg);
-}
-
-static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev,
-                                             const unsigned int offset,
-                                             void *value, const u32 length)
-{
-       int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     value, length, timeout);
-}
-
-static inline void rt73usb_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(u32), REGISTER_TIMEOUT);
-}
-
-static inline void rt73usb_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(u32), REGISTER_TIMEOUT);
-}
-
-static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
-                                              const unsigned int offset,
-                                              void *value, const u32 length)
-{
-       int timeout = REGISTER_TIMEOUT * (length / sizeof(u32));
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     value, length, timeout);
-}
-
-static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
-       u32 reg;
-       unsigned int i;
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, &reg);
-               if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
-                       break;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       return reg;
-}
+#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->usb_cache_mutex);
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        /*
-        * Wait until the BBP becomes ready.
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
         */
-       reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
-               goto exit_fail;
-
-       /*
-        * Write the data into the BBP.
-        */
-       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);
-
-       rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
-       return;
-
-exit_fail:
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+       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);
+       }
 
-       ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
+       mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
 static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -162,130 +91,107 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       mutex_lock(&rt2x00dev->usb_cache_mutex);
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        /*
-        * Wait until the BBP becomes ready.
+        * 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.
         */
-       reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
-               goto exit_fail;
+       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);
 
-       /*
-        * Write the request into the BBP.
-        */
-       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);
-
-       rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+               rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
 
-       /*
-        * Wait until the BBP becomes ready.
-        */
-       reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
-               goto exit_fail;
+               WAIT_FOR_BBP(rt2x00dev, &reg);
+       }
 
        *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
-       return;
-
-exit_fail:
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
 
-       ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
-       *value = 0xff;
+       mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
 static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
                             const unsigned int word, const u32 value)
 {
        u32 reg;
-       unsigned int i;
-
-       if (!word)
-               return;
 
-       mutex_lock(&rt2x00dev->usb_cache_mutex);
-
-       for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
-               if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
-                       goto rf_write;
-               udelay(REGISTER_BUSY_DELAY);
-       }
-
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
-       ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
-       return;
-
-rf_write:
-       reg = 0;
-       rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        /*
-        * RF5225 and RF2527 contain 21 bits per RF register value,
-        * all others contain 20 bits.
+        * Wait until the RF becomes available, afterwards we
+        * can safely write the new data into the register.
         */
-       rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
-                          20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-                                rt2x00_rf(&rt2x00dev->chip, RF2527)));
-       rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
-       rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
+       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);
+       }
 
-       rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
-       rt2x00_rf_write(rt2x00dev, word, value);
-       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+       mutex_unlock(&rt2x00dev->csr_mutex);
 }
 
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word)     ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev,
-                            const unsigned int word, u32 *data)
-{
-       rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev,
-                             const unsigned int word, u32 data)
-{
-       rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
 static const struct rt2x00debug rt73usb_rt2x00debug = {
        .owner  = THIS_MODULE,
        .csr    = {
-               .read           = rt73usb_read_csr,
-               .write          = rt73usb_write_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 */
 
-#ifdef CONFIG_RT73USB_LEDS
+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_BIT7);
+}
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
 static void rt73usb_brightness_set(struct led_classdev *led_cdev,
                                   enum led_brightness brightness)
 {
@@ -334,18 +240,242 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev,
            container_of(led_cdev, struct rt2x00_led, led_dev);
        u32 reg;
 
-       rt73usb_register_read(led->rt2x00dev, MAC_CSR14, &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);
-       rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
+       rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
 
        return 0;
 }
-#endif /* CONFIG_RT73USB_LEDS */
+
+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;
+       int timeout;
+       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);
+               timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+               rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                                   USB_VENDOR_REQUEST_OUT, reg,
+                                                   &key_entry,
+                                                   sizeof(key_entry),
+                                                   timeout);
+
+               /*
+                * 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;
+       int timeout;
+       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);
+               timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+               rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                                   USB_VENDOR_REQUEST_OUT, reg,
+                                                   &key_entry,
+                                                   sizeof(key_entry),
+                                                   timeout);
+
+               /*
+                * Send the address and cipher type to the hardware register.
+                * This data fits within the CSR cache size, so we can use
+                * rt2x00usb_register_multiwrite() directly.
+                */
+               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)
 {
@@ -357,13 +487,13 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
         * and broadcast frames will always be accepted since
         * there is no filter for it at this time.
         */
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       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));
+                          !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
                           !(filter_flags & FIF_PROMISC_IN_BSS));
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
@@ -375,7 +505,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
        rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
                           !(filter_flags & FIF_CONTROL));
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 }
 
 static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -394,16 +524,16 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
                 * bits which (when set to 0) will invalidate the entire beacon.
                 */
                beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-               rt73usb_register_write(rt2x00dev, beacon_base, 0);
+               rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
 
                /*
                 * Enable synchronisation.
                 */
-               rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+               rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
                rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
                rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
-               rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
 
        if (flags & CONFIG_UPDATE_MAC) {
@@ -411,7 +541,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
                conf->mac[1] = cpu_to_le32(reg);
 
-               rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
+               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
                                            conf->mac, sizeof(conf->mac));
        }
 
@@ -420,7 +550,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
                rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
                conf->bssid[1] = cpu_to_le32(reg);
 
-               rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
+               rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
                                            conf->bssid, sizeof(conf->bssid));
        }
 }
@@ -430,75 +560,33 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, 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);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
-
-static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
-                                  const int basic_rate_mask)
-{
-       rt73usb_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
-}
-
-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->chip, RF5225) ||
-                 rt2x00_rf(&rt2x00dev->chip, 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);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 
-       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);
-}
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
-static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                  const int txpower)
-{
-       struct rf_channel rf;
+       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);
 
-       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);
+       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);
 
-       rt73usb_config_channel(rt2x00dev, &rf, txpower);
+       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,
@@ -618,8 +706,8 @@ static const struct antenna_sel antenna_sel_bg[] = {
        { 98,  { 0x48, 0x48 } },
 };
 
-static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
-                                  struct antenna_setup *ant)
+static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
+                              struct antenna_setup *ant)
 {
        const struct antenna_sel *sel;
        unsigned int lna;
@@ -644,67 +732,163 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
        for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
                rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
 
-       rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+       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));
 
-       rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
 
-       if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
-           rt2x00_rf(&rt2x00dev->chip, RF5225))
+       if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225))
                rt73usb_config_antenna_5x(rt2x00dev, ant);
-       else if (rt2x00_rf(&rt2x00dev->chip, RF2528) ||
-                rt2x00_rf(&rt2x00dev->chip, RF2527))
+       else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527))
                rt73usb_config_antenna_2x(rt2x00dev, ant);
 }
 
-static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
+static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
                                    struct rt2x00lib_conf *libconf)
 {
+       u16 eeprom;
+       short lna_gain = 0;
+
+       if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+                       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;
 
-       rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
-       rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+       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);
+}
 
-       rt73usb_register_read(rt2x00dev, MAC_CSR8, &reg);
-       rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
-       rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
-       rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
-       rt73usb_register_write(rt2x00dev, MAC_CSR8, 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;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, 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);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+               /* 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);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
-                          libconf->conf->beacon_int * 16);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, 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_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+                                           USB_MODE_WAKEUP, REGISTER_TIMEOUT);
+
+               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);
+       }
 }
 
 static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
                           struct rt2x00lib_conf *libconf,
                           const unsigned int flags)
 {
-       if (flags & CONFIG_UPDATE_PHYMODE)
-               rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
-       if (flags & CONFIG_UPDATE_CHANNEL)
+       /* 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 & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+       if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+           !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
                rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
-       if (flags & CONFIG_UPDATE_ANTENNA)
-               rt73usb_config_antenna(rt2x00dev, &libconf->ant);
-       if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
-               rt73usb_config_duration(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+               rt73usb_config_retry_limit(rt2x00dev, libconf);
+       if (flags & IEEE80211_CONF_CHANGE_PS)
+               rt73usb_config_ps(rt2x00dev, libconf);
 }
 
 /*
@@ -718,31 +902,38 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
        /*
         * Update FCS error count from register.
         */
-       rt73usb_register_read(rt2x00dev, STA_CSR0, &reg);
+       rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
        qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
 
        /*
         * Update False CCA count from register.
         */
-       rt73usb_register_read(rt2x00dev, STA_CSR1, &reg);
+       rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
        qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
 }
 
-static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
+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_bbp_write(rt2x00dev, 17, 0x20);
-       rt2x00dev->link.vgc_level = 0x20;
+       rt73usb_set_vgc(rt2x00dev, qual, 0x20);
 }
 
-static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
 {
-       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-       u8 r17;
        u8 up_bound;
        u8 low_bound;
 
-       rt73usb_bbp_read(rt2x00dev, 17, &r17);
-
        /*
         * Determine r17 bounds.
         */
@@ -755,10 +946,10 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
                        up_bound += 0x10;
                }
        } else {
-               if (rssi > -82) {
+               if (qual->rssi > -82) {
                        low_bound = 0x1c;
                        up_bound = 0x40;
-               } else if (rssi > -84) {
+               } else if (qual->rssi > -84) {
                        low_bound = 0x1c;
                        up_bound = 0x20;
                } else {
@@ -782,37 +973,32 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
        /*
         * Special big-R17 for very short distance
         */
-       if (rssi > -35) {
-               if (r17 != 0x60)
-                       rt73usb_bbp_write(rt2x00dev, 17, 0x60);
+       if (qual->rssi > -35) {
+               rt73usb_set_vgc(rt2x00dev, qual, 0x60);
                return;
        }
 
        /*
         * Special big-R17 for short distance
         */
-       if (rssi >= -58) {
-               if (r17 != up_bound)
-                       rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->rssi >= -58) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
        /*
         * Special big-R17 for middle-short distance
         */
-       if (rssi >= -66) {
-               low_bound += 0x10;
-               if (r17 != low_bound)
-                       rt73usb_bbp_write(rt2x00dev, 17, low_bound);
+       if (qual->rssi >= -66) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10);
                return;
        }
 
        /*
         * Special mid-R17 for middle distance
         */
-       if (rssi >= -74) {
-               if (r17 != (low_bound + 0x10))
-                       rt73usb_bbp_write(rt2x00dev, 17, low_bound + 0x08);
+       if (qual->rssi >= -74) {
+               rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08);
                return;
        }
 
@@ -820,12 +1006,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
         * Special case: Change up_bound based on the rssi.
         * Lower up_bound when rssi is weaker then -74 dBm.
         */
-       up_bound -= 2 * (-74 - rssi);
+       up_bound -= 2 * (-74 - qual->rssi);
        if (low_bound > up_bound)
                up_bound = low_bound;
 
-       if (r17 > up_bound) {
-               rt73usb_bbp_write(rt2x00dev, 17, up_bound);
+       if (qual->vgc_level > up_bound) {
+               rt73usb_set_vgc(rt2x00dev, qual, up_bound);
                return;
        }
 
@@ -835,17 +1021,12 @@ dynamic_cca_tune:
         * r17 does not yet exceed upper limit, continue and base
         * the r17 tuning on the false CCA count.
         */
-       if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-               r17 += 4;
-               if (r17 > up_bound)
-                       r17 = up_bound;
-               rt73usb_bbp_write(rt2x00dev, 17, r17);
-       } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-               r17 -= 4;
-               if (r17 < low_bound)
-                       r17 = low_bound;
-               rt73usb_bbp_write(rt2x00dev, 17, r17);
-       }
+       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));
 }
 
 /*
@@ -856,39 +1037,47 @@ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
        return FIRMWARE_RT2571;
 }
 
-static u16 rt73usb_get_firmware_crc(const void *data, const size_t len)
+static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev,
+                                 const u8 *data, const size_t len)
 {
+       u16 fw_crc;
        u16 crc;
 
        /*
-        * Use the crc itu-t algorithm.
+        * 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 crc;
+       return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
 }
 
-static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
-                                const size_t len)
+static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
+                                const u8 *data, const size_t len)
 {
        unsigned int i;
        int status;
        u32 reg;
-       const char *ptr = data;
-       char *cache;
-       int buflen;
-       int timeout;
 
        /*
         * Wait for stable hardware.
         */
        for (i = 0; i < 100; i++) {
-               rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
                if (reg)
                        break;
                msleep(1);
@@ -901,31 +1090,12 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
 
        /*
         * Write firmware to device.
-        * We setup a seperate cache for this action,
-        * since we are going to write larger chunks of data
-        * then normally used cache size.
         */
-       cache = kmalloc(CSR_CACHE_SIZE_FIRMWARE, GFP_KERNEL);
-       if (!cache) {
-               ERROR(rt2x00dev, "Failed to allocate firmware cache.\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) {
-               buflen = min_t(int, len - i, CSR_CACHE_SIZE_FIRMWARE);
-               timeout = REGISTER_TIMEOUT * (buflen / sizeof(u32));
-
-               memcpy(cache, ptr, buflen);
-
-               rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
-                                        USB_VENDOR_REQUEST_OUT,
-                                        FIRMWARE_IMAGE_BASE + i, 0,
-                                        cache, buflen, timeout);
-
-               ptr += buflen;
-       }
-
-       kfree(cache);
+       rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                           USB_VENDOR_REQUEST_OUT,
+                                           FIRMWARE_IMAGE_BASE,
+                                           data, len,
+                                           REGISTER_TIMEOUT32(len));
 
        /*
         * Send firmware request to device to load firmware,
@@ -949,13 +1119,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR1, &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 */
@@ -964,12 +1134,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
 
        /*
         * CCK TXD BBP registers
         */
-       rt73usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       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);
@@ -978,78 +1148,76 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
 
        /*
         * OFDM TXD BBP registers
         */
-       rt73usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
+       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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR7, &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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR8, &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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
 
-       rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+       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);
 
-       rt73usb_register_read(rt2x00dev, MAC_CSR6, &reg);
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
        rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
-       rt73usb_register_write(rt2x00dev, MAC_CSR6, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
 
-       rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
 
        if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
                return -EBUSY;
 
-       rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
 
        /*
         * Invalidate all Shared Keys (SEC_CSR0),
         * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
         */
-       rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
-       rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
-       rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+       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->chip, RF5225) ||
-           rt2x00_rf(&rt2x00dev->chip, RF2527))
+       if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527))
                rt2x00_set_field32(&reg, PHY_CSR1_RF_RPI, 1);
-       rt73usb_register_write(rt2x00dev, PHY_CSR1, reg);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
 
-       rt73usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
-       rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
-       rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+       rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
 
-       rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
-       rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC0_TX_OP, 0);
-       rt2x00_set_field32(&reg, AC_TXOP_CSR0_AC1_TX_OP, 0);
-       rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
-
-       rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
-       rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC2_TX_OP, 192);
-       rt2x00_set_field32(&reg, AC_TXOP_CSR1_AC3_TX_OP, 48);
-       rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-
-       rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
        rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
-       rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
        /*
         * Clear all beacons
@@ -1057,59 +1225,66 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
         * the first byte since that byte contains the VALID and OWNER
         * bits which (when set to 0) will invalidate the entire beacon.
         */
-       rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-       rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-       rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-       rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+       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.
         */
-       rt73usb_register_read(rt2x00dev, STA_CSR0, &reg);
-       rt73usb_register_read(rt2x00dev, STA_CSR1, &reg);
-       rt73usb_register_read(rt2x00dev, STA_CSR2, &reg);
+       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.
         */
-       rt73usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       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);
-       rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt73usb_register_read(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);
-       rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
-       rt73usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
        rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
-       rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
 
        return 0;
 }
 
-static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
+static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
 {
        unsigned int i;
-       u16 eeprom;
-       u8 reg_id;
        u8 value;
 
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
                rt73usb_bbp_read(rt2x00dev, 0, &value);
                if ((value != 0xff) && (value != 0x00))
-                       goto continue_csr_init;
-               NOTICE(rt2x00dev, "Waiting for BBP register.\n");
+                       return 0;
                udelay(REGISTER_BUSY_DELAY);
        }
 
        ERROR(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;
 
-continue_csr_init:
        rt73usb_bbp_write(rt2x00dev, 3, 0x80);
        rt73usb_bbp_write(rt2x00dev, 15, 0x30);
        rt73usb_bbp_write(rt2x00dev, 21, 0xc8);
@@ -1157,10 +1332,11 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
 {
        u32 reg;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
-                          state == STATE_RADIO_RX_OFF);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+                          (state == STATE_RADIO_RX_OFF) ||
+                          (state == STATE_RADIO_RX_OFF_LINK));
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 }
 
 static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1168,23 +1344,21 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize all registers.
         */
-       if (rt73usb_init_registers(rt2x00dev) ||
-           rt73usb_init_bbp(rt2x00dev)) {
-               ERROR(rt2x00dev, "Register initialization failed.\n");
+       if (unlikely(rt73usb_init_registers(rt2x00dev) ||
+                    rt73usb_init_bbp(rt2x00dev)))
                return -EIO;
-       }
 
        return 0;
 }
 
 static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
-       rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
 
        /*
         * Disable synchronisation.
         */
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
 
        rt2x00usb_disable_radio(rt2x00dev);
 }
@@ -1194,14 +1368,13 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
        u32 reg;
        unsigned int i;
        char put_to_sleep;
-       char current_state;
 
        put_to_sleep = (state != STATE_AWAKE);
 
-       rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+       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);
-       rt73usb_register_write(rt2x00dev, MAC_CSR12, reg);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
 
        /*
         * Device is not guaranteed to be in the requested state yet.
@@ -1209,17 +1382,13 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
         * device has entered the correct state.
         */
        for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-               rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
-               current_state =
-                   rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
-               if (current_state == !put_to_sleep)
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+               state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
+               if (state == !put_to_sleep)
                        return 0;
                msleep(10);
        }
 
-       NOTICE(rt2x00dev, "Device failed to enter state %d, "
-              "current device state %d.\n", !put_to_sleep, current_state);
-
        return -EBUSY;
 }
 
@@ -1237,11 +1406,13 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
                break;
        case STATE_RADIO_RX_ON:
        case STATE_RADIO_RX_ON_LINK:
-               rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
-               break;
        case STATE_RADIO_RX_OFF:
        case STATE_RADIO_RX_OFF_LINK:
-               rt73usb_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+               rt73usb_toggle_rx(rt2x00dev, state);
+               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:
@@ -1254,6 +1425,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
                break;
        }
 
+       if (unlikely(retval))
+               ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
+                     state, retval);
+
        return retval;
 }
 
@@ -1261,9 +1436,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
  * TX descriptor initialization
  */
 static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-                                   struct sk_buff *skb,
-                                   struct txentry_desc *txdesc,
-                                   struct ieee80211_tx_control *control)
+                                 struct sk_buff *skb,
+                                 struct txentry_desc *txdesc)
 {
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
        __le32 *txd = skbdesc->desc;
@@ -1277,8 +1451,9 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
        rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
        rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
-       rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
-       rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
+       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);
@@ -1288,6 +1463,11 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->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(rt2x00dev->tx_power));
@@ -1305,21 +1485,64 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
                           test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
        rt2x00_set_field32(&word, TXD_W0_OFDM,
-                          test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
+                          (txdesc->rate_mode == RATE_MODE_OFDM));
        rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
        rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
-                          !!(control->flags &
-                             IEEE80211_TXCTL_LONG_RETRY_LIMIT));
-       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
+                          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, skb->len);
        rt2x00_set_field32(&word, TXD_W0_BURST2,
                           test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
        rt2x00_desc_write(txd, 0, word);
 }
 
-static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
-                                  struct sk_buff *skb)
+/*
+ * TX data initialization
+ */
+static void rt73usb_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int beacon_base;
+       u32 reg;
+
+       /*
+        * Add the descriptor in front of the skb.
+        */
+       skb_push(entry->skb, entry->queue->desc_size);
+       memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
+       skbdesc->desc = entry->skb->data;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Write entire beacon with descriptor to register.
+        */
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                           USB_VENDOR_REQUEST_OUT, beacon_base,
+                                           entry->skb->data, entry->skb->len,
+                                           REGISTER_TIMEOUT32(entry->skb->len));
+
+       /*
+        * Clean up the beacon skb.
+        */
+       dev_kfree_skb(entry->skb);
+       entry->skb = NULL;
+}
+
+static int rt73usb_get_tx_data_len(struct queue_entry *entry)
 {
        int length;
 
@@ -1327,35 +1550,34 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
         * The length _must_ be a multiple of 4,
         * but it must _not_ be a multiple of the USB packet size.
         */
-       length = roundup(skb->len, 4);
-       length += (4 * !(length % rt2x00dev->usb_maxpacket));
+       length = roundup(entry->skb->len, 4);
+       length += (4 * !(length % entry->queue->usb_maxpacket));
 
        return length;
 }
 
-/*
- * TX data initialization
- */
 static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-                                 const unsigned int queue)
+                                 const enum data_queue_qid queue)
 {
        u32 reg;
 
-       if (queue != RT2X00_BCN_QUEUE_BEACON)
+       if (queue != QID_BEACON) {
+               rt2x00usb_kick_tx_queue(rt2x00dev, queue);
                return;
+       }
 
        /*
         * For Wi-Fi faily generated beacons between participating stations.
         * Set TBTT phase adaptive adjustment step to 8us (default 16us)
         */
-       rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
        if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
                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);
-               rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+               rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
        }
 }
 
@@ -1364,20 +1586,19 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
  */
 static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
 {
-       u16 eeprom;
-       u8 offset;
+       u8 offset = rt2x00dev->lna_gain;
        u8 lna;
 
        lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
        switch (lna) {
        case 3:
-               offset = 90;
+               offset += 90;
                break;
        case 2:
-               offset = 74;
+               offset += 74;
                break;
        case 1:
-               offset = 64;
+               offset += 64;
                break;
        default:
                return 0;
@@ -1393,47 +1614,71 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
                        else if (lna == 2)
                                offset += 8;
                }
-
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
-               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
-       } else {
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-                       offset += 14;
-
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
-               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
        }
 
        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 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;
-       unsigned int offset = entry->queue->desc_size + 2;
        u32 word0;
        u32 word1;
 
        /*
-        * Copy descriptor to the available headroom inside the skbuffer.
+        * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of
+        * frame data in rt2x00usb.
         */
-       skb_push(entry->skb, offset);
-       memcpy(entry->skb->data, rxd, entry->queue->desc_size);
-       rxd = (__le32 *)entry->skb->data;
+       memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
+       rxd = (__le32 *)skbdesc->desc;
 
        /*
-        * The descriptor is now aligned to 4 bytes and thus it is
-        * now safe to read it on all architectures.
+        * It is now safe to read the descriptor on all architectures.
         */
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
-       rxdesc->flags = 0;
        if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
                rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
 
+       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+               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;
+
+               /*
+                * FIXME: Legacy driver indicates that the frame does
+                * contain the Michael Mic. Unfortunately, in rt2x00
+                * the MIC seems to be missing completely...
+                */
+               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,
@@ -1441,28 +1686,21 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
         * 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(entry->queue->rt2x00dev, word1);
+       rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
        rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 
-       rxdesc->dev_flags = 0;
        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.
+        * Set skb pointers, and update frame information.
         */
-       skb_pull(entry->skb, offset + entry->queue->desc_size);
+       skb_pull(entry->skb, entry->queue->desc_size);
        skb_trim(entry->skb, rxdesc->size);
-
-       /*
-        * Set descriptor and data pointer.
-        */
-       skbdesc->data = entry->skb->data;
-       skbdesc->data_len = rxdesc->size;
-       skbdesc->desc = rxd;
-       skbdesc->desc_len = entry->queue->desc_size;
 }
 
 /*
@@ -1481,10 +1719,8 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
         */
        mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        if (!is_valid_ether_addr(mac)) {
-               DECLARE_MAC_BUF(macbuf);
-
                random_ether_addr(mac);
-               EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+               EEPROM(rt2x00dev, "MAC: %pM\n", mac);
        }
 
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1583,18 +1819,19 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Identify RF chipset.
         */
        value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-       rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
-       rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
+       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_check_rev(&rt2x00dev->chip, 0x25730)) {
+       if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
                ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
                return -ENODEV;
        }
 
-       if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF2528) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF5225) &&
-           !rt2x00_rf(&rt2x00dev->chip, RF2527)) {
+       if (!rt2x00_rf(rt2x00dev, RF5226) &&
+           !rt2x00_rf(rt2x00dev, RF2528) &&
+           !rt2x00_rf(rt2x00dev, RF5225) &&
+           !rt2x00_rf(rt2x00dev, RF2527)) {
                ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
                return -ENODEV;
        }
@@ -1614,6 +1851,12 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
                __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
 
        /*
+        * Detect if this device has an hardware controlled radio.
+        */
+       if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+               __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+
+       /*
         * Read frequency offset.
         */
        rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
@@ -1632,34 +1875,14 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Store led settings, for correct led behaviour.
         */
-#ifdef CONFIG_RT73USB_LEDS
+#ifdef CONFIG_RT2X00_LIB_LEDS
        rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
 
-       rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-       rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-       rt2x00dev->led_radio.led_dev.brightness_set =
-           rt73usb_brightness_set;
-       rt2x00dev->led_radio.led_dev.blink_set =
-           rt73usb_blink_set;
-       rt2x00dev->led_radio.flags = LED_INITIALIZED;
-
-       rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
-       rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
-       rt2x00dev->led_assoc.led_dev.brightness_set =
-           rt73usb_brightness_set;
-       rt2x00dev->led_assoc.led_dev.blink_set =
-           rt73usb_blink_set;
-       rt2x00dev->led_assoc.flags = LED_INITIALIZED;
-
-       if (value == LED_MODE_SIGNAL_STRENGTH) {
-               rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-               rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
-               rt2x00dev->led_qual.led_dev.brightness_set =
-                   rt73usb_brightness_set;
-               rt2x00dev->led_qual.led_dev.blink_set =
-                   rt73usb_blink_set;
-               rt2x00dev->led_qual.flags = LED_INITIALIZED;
-       }
+       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,
@@ -1685,7 +1908,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
                           rt2x00_get_field16(eeprom,
                                              EEPROM_LED_POLARITY_RDY_A));
-#endif /* CONFIG_RT73USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
 
        return 0;
 }
@@ -1826,68 +2049,69 @@ static const struct rf_channel rf_vals_5225_2527[] = {
 };
 
 
-static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
        struct hw_mode_spec *spec = &rt2x00dev->spec;
-       u8 *txpower;
+       struct channel_info *info;
+       char *tx_power;
        unsigned int i;
 
        /*
         * Initialize all hw fields.
         */
        rt2x00dev->hw->flags =
-           IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
-       rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-       rt2x00dev->hw->max_signal = MAX_SIGNAL;
-       rt2x00dev->hw->max_rssi = MAX_RX_SSI;
-       rt2x00dev->hw->queues = 4;
-
-       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
+           IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+           IEEE80211_HW_SIGNAL_DBM |
+           IEEE80211_HW_SUPPORTS_PS |
+           IEEE80211_HW_PS_NULLFUNC_STACK;
+
+       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
                                rt2x00_eeprom_addr(rt2x00dev,
                                                   EEPROM_MAC_ADDR_0));
 
        /*
-        * Convert tx_power array in eeprom.
-        */
-       txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
-       for (i = 0; i < 14; i++)
-               txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
-       /*
         * Initialize hw_mode information.
         */
        spec->supported_bands = SUPPORT_BAND_2GHZ;
        spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-       spec->tx_power_a = NULL;
-       spec->tx_power_bg = txpower;
-       spec->tx_power_default = DEFAULT_TXPOWER;
 
-       if (rt2x00_rf(&rt2x00dev->chip, RF2528)) {
+       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->chip, RF5226)) {
+       } 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->chip, RF2527)) {
+       } else if (rt2x00_rf(rt2x00dev, RF2527)) {
                spec->num_channels = 14;
                spec->channels = rf_vals_5225_2527;
-       } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
+       } 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;
        }
 
-       if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
-           rt2x00_rf(&rt2x00dev->chip, RF5226)) {
-               txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-               for (i = 0; i < 14; i++)
-                       txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
+       /*
+        * Create channel information array
+        */
+       info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
 
-               spec->tx_power_a = txpower;
+       spec->channels_info = info;
+
+       tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
+       for (i = 0; i < 14; i++)
+               info[i].tx_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].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
        }
+
+       return 0;
 }
 
 static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1908,13 +2132,22 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw specifications.
         */
-       rt73usb_probe_hw_mode(rt2x00dev);
+       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(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
 
        /*
         * This device requires firmware.
         */
        __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-       __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+       if (!modparam_nohwcrypt)
+               __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
@@ -1927,106 +2160,76 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 /*
  * IEEE80211 stack callback functions.
  */
-static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
-                                  u32 short_retry, u32 long_retry)
+static int rt73usb_conf_tx(struct ieee80211_hw *hw, 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, queue_idx, params);
+       if (retval)
+               return retval;
+
+       /*
+        * We only need to perform additional register initialization
+        * for WMM queues/
+        */
+       if (queue_idx >= 4)
+               return 0;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT, long_retry);
-       rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT, short_retry);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+       queue = rt2x00queue_get_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;
 }
 
-#if 0
-/*
- * Mac80211 demands get_tsf must be atomic.
- * This is not possible for rt73usb since all register access
- * functions require sleeping. Untill mac80211 no longer needs
- * get_tsf to be atomic, this function should be disabled.
- */
 static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        u64 tsf;
        u32 reg;
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
        tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
-       rt73usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
        tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
 
        return tsf;
 }
-#else
-#define rt73usb_get_tsf        NULL
-#endif
-
-static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-                                struct ieee80211_tx_control *control)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_intf *intf = vif_to_intf(control->vif);
-       struct skb_frame_desc *skbdesc;
-       unsigned int beacon_base;
-       unsigned int timeout;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Add the descriptor in front of the skb.
-        */
-       skb_push(skb, intf->beacon->queue->desc_size);
-       memset(skb->data, 0, intf->beacon->queue->desc_size);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-       skbdesc->data = skb->data + intf->beacon->queue->desc_size;
-       skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
-       skbdesc->desc = skb->data;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt73usb_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);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * mac80211 doesn't provide the control->queue variable
-        * for beacons. Set our own queue identification so
-        * it can be used during descriptor initialization.
-        */
-       control->queue = RT2X00_BCN_QUEUE_BEACON;
-       rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
-       /*
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-       timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
-       rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
-                                USB_VENDOR_REQUEST_OUT, beacon_base, 0,
-                                skb->data, skb->len, timeout);
-       rt73usb_kick_tx_queue(rt2x00dev, control->queue);
-
-       return 0;
-}
 
 static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
@@ -2035,38 +2238,42 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .add_interface          = rt2x00mac_add_interface,
        .remove_interface       = rt2x00mac_remove_interface,
        .config                 = rt2x00mac_config,
-       .config_interface       = rt2x00mac_config_interface,
        .configure_filter       = rt2x00mac_configure_filter,
+       .set_tim                = rt2x00mac_set_tim,
+       .set_key                = rt2x00mac_set_key,
        .get_stats              = rt2x00mac_get_stats,
-       .set_retry_limit        = rt73usb_set_retry_limit,
        .bss_info_changed       = rt2x00mac_bss_info_changed,
-       .conf_tx                = rt2x00mac_conf_tx,
-       .get_tx_stats           = rt2x00mac_get_tx_stats,
+       .conf_tx                = rt73usb_conf_tx,
        .get_tsf                = rt73usb_get_tsf,
-       .beacon_update          = rt73usb_beacon_update,
+       .rfkill_poll            = rt2x00mac_rfkill_poll,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .probe_hw               = rt73usb_probe_hw,
        .get_firmware_name      = rt73usb_get_firmware_name,
-       .get_firmware_crc       = rt73usb_get_firmware_crc,
+       .check_firmware         = rt73usb_check_firmware,
        .load_firmware          = rt73usb_load_firmware,
        .initialize             = rt2x00usb_initialize,
        .uninitialize           = rt2x00usb_uninitialize,
-       .init_rxentry           = rt2x00usb_init_rxentry,
-       .init_txentry           = rt2x00usb_init_txentry,
+       .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,
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
+       .write_beacon           = rt73usb_write_beacon,
        .get_tx_data_len        = rt73usb_get_tx_data_len,
        .kick_tx_queue          = rt73usb_kick_tx_queue,
+       .kill_tx_queue          = rt2x00usb_kill_tx_queue,
        .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,
 };
 
@@ -2074,36 +2281,38 @@ static const struct data_queue_desc rt73usb_queue_rx = {
        .entry_num              = RX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = RXD_DESC_SIZE,
-       .priv_size              = sizeof(struct queue_entry_priv_usb_rx),
+       .priv_size              = sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct data_queue_desc rt73usb_queue_tx = {
        .entry_num              = TX_ENTRIES,
        .data_size              = DATA_FRAME_SIZE,
        .desc_size              = TXD_DESC_SIZE,
-       .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
+       .priv_size              = sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct data_queue_desc rt73usb_queue_bcn = {
        .entry_num              = 4 * BEACON_ENTRIES,
        .data_size              = MGMT_FRAME_SIZE,
        .desc_size              = TXINFO_SIZE,
-       .priv_size              = sizeof(struct queue_entry_priv_usb_tx),
+       .priv_size              = sizeof(struct queue_entry_priv_usb),
 };
 
 static const struct rt2x00_ops rt73usb_ops = {
-       .name           = KBUILD_MODNAME,
-       .max_sta_intf   = 1,
-       .max_ap_intf    = 4,
-       .eeprom_size    = EEPROM_SIZE,
-       .rf_size        = RF_SIZE,
-       .rx             = &rt73usb_queue_rx,
-       .tx             = &rt73usb_queue_tx,
-       .bcn            = &rt73usb_queue_bcn,
-       .lib            = &rt73usb_rt2x00_ops,
-       .hw             = &rt73usb_mac80211_ops,
+       .name                   = KBUILD_MODNAME,
+       .max_sta_intf           = 1,
+       .max_ap_intf            = 4,
+       .eeprom_size            = EEPROM_SIZE,
+       .rf_size                = RF_SIZE,
+       .tx_queues              = NUM_TX_QUEUES,
+       .extra_tx_headroom      = TXD_DESC_SIZE,
+       .rx                     = &rt73usb_queue_rx,
+       .tx                     = &rt73usb_queue_tx,
+       .bcn                    = &rt73usb_queue_bcn,
+       .lib                    = &rt73usb_rt2x00_ops,
+       .hw                     = &rt73usb_mac80211_ops,
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-       .debugfs        = &rt73usb_rt2x00debug,
+       .debugfs                = &rt73usb_rt2x00debug,
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 };
 
@@ -2112,7 +2321,18 @@ static const struct rt2x00_ops rt73usb_ops = {
  */
 static struct usb_device_id rt73usb_device_table[] = {
        /* AboCom */
+       { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* AL */
+       { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Amigo */
+       { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* AMIT  */
+       { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Askey */
        { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
        /* ASUS */
@@ -2125,8 +2345,13 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Billionton */
        { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Buffalo */
+       { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
        /* CNet */
        { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2139,6 +2364,11 @@ static struct usb_device_id rt73usb_device_table[] = {
        { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Edimax */
+       { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* EnGenius */
+       { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gemtek */
        { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Gigabyte */
@@ -2147,33 +2377,54 @@ static struct usb_device_id rt73usb_device_table[] = {
        /* Huawei-3Com */
        { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Hercules */
+       { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Linksys */
        { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
        /* MSI */
+       { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Ralink */
+       { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Qcom */
        { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Samsung */
+       { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Senao */
        { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Sitecom */
-       { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) },
+       { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Surecom */
        { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Tilgin */
+       { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Philips */
+       { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
        /* Planex */
        { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
        { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* WideTell */
+       { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* Zcom */
+       { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+       /* ZyXEL */
+       { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
        { 0, }
 };