Merge branch 'for-next' into for-linus
[safe/jmp/linux-2.6] / drivers / net / wireless / rt2x00 / rt73usb.c
index f58fd05..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
@@ -46,7 +46,7 @@ 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,
@@ -55,113 +55,35 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
  * 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)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
-                                     USB_VENDOR_REQUEST_IN, offset,
-                                     value, length,
-                                     REGISTER_TIMEOUT32(length));
-}
-
-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)
-{
-       rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
-                                     USB_VENDOR_REQUEST_OUT, offset,
-                                     value, length,
-                                     REGISTER_TIMEOUT32(length));
-}
-
-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);
-
-       /*
-        * Wait until the BBP becomes ready.
-        */
-       reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
-               goto exit_fail;
+       mutex_lock(&rt2x00dev->csr_mutex);
 
        /*
-        * Write the data into the BBP.
+        * Wait until the BBP becomes available, afterwards we
+        * can safely write the new data into the register.
         */
-       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,
@@ -169,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)
 {
@@ -341,10 +240,10 @@ 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;
 }
@@ -359,7 +258,7 @@ static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
        led->led_dev.blink_set = rt73usb_blink_set;
        led->flags = LED_INITIALIZED;
 }
-#endif /* CONFIG_RT73USB_LEDS */
+#endif /* CONFIG_RT2X00_LIB_LEDS */
 
 /*
  * Configuration handlers.
@@ -387,13 +286,13 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
                 */
                mask = (0xf << crypto->bssidx);
 
-               rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
                reg &= mask;
 
                if (reg && reg == mask)
                        return -ENOSPC;
 
-               key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
+               key->hw_key_idx += reg ? ffz(reg) : 0;
 
                /*
                 * Upload key to hardware
@@ -424,23 +323,23 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
                        field.bit_offset = (3 * key->hw_key_idx);
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt73usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt73usb_register_write(rt2x00dev, SEC_CSR1, reg);
+                       rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
                } else {
                        field.bit_offset = (3 * (key->hw_key_idx - 8));
                        field.bit_mask = 0x7 << field.bit_offset;
 
-                       rt73usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
                        rt2x00_set_field32(&reg, field, crypto->cipher);
-                       rt73usb_register_write(rt2x00dev, SEC_CSR5, reg);
+                       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 seperately for the descriptor.
+                * 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.
@@ -456,12 +355,12 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
         */
        mask = 1 << key->hw_key_idx;
 
-       rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+       rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
        if (crypto->cmd == SET_KEY)
                reg |= mask;
        else if (crypto->cmd == DISABLE_KEY)
                reg &= ~mask;
-       rt73usb_register_write(rt2x00dev, SEC_CSR0, reg);
+       rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
 
        return 0;
 }
@@ -486,15 +385,15 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * When both registers are full, we drop the key,
                 * otherwise we use the first invalid entry.
                 */
-               rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
                if (reg && reg == ~0) {
                        key->hw_key_idx = 32;
-                       rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
                        if (reg && reg == ~0)
                                return -ENOSPC;
                }
 
-               key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
+               key->hw_key_idx += reg ? ffz(reg) : 0;
 
                /*
                 * Upload key to hardware
@@ -517,14 +416,14 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                /*
                 * Send the address and cipher type to the hardware register.
                 * This data fits within the CSR cache size, so we can use
-                * rt73usb_register_multiwrite() directly.
+                * 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);
-               rt73usb_register_multiwrite(rt2x00dev, reg,
+               rt2x00usb_register_multiwrite(rt2x00dev, reg,
                                            &addr_entry, sizeof(addr_entry));
 
                /*
@@ -532,15 +431,15 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * without this received frames will not be decrypted
                 * by the hardware.
                 */
-               rt73usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
                reg |= (1 << crypto->bssidx);
-               rt73usb_register_write(rt2x00dev, SEC_CSR4, reg);
+               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 seperately for the descriptor.
+                * 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.
@@ -557,21 +456,21 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
        if (key->hw_key_idx < 32) {
                mask = 1 << key->hw_key_idx;
 
-               rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
                        reg &= ~mask;
-               rt73usb_register_write(rt2x00dev, SEC_CSR2, reg);
+               rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
        } else {
                mask = 1 << (key->hw_key_idx - 32);
 
-               rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+               rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
                if (crypto->cmd == SET_KEY)
                        reg |= mask;
                else if (crypto->cmd == DISABLE_KEY)
                        reg &= ~mask;
-               rt73usb_register_write(rt2x00dev, SEC_CSR3, reg);
+               rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
        }
 
        return 0;
@@ -588,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,
@@ -606,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,
@@ -625,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) {
@@ -642,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));
        }
 
@@ -651,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));
        }
 }
@@ -661,95 +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_lna_gain(struct rt2x00_dev *rt2x00dev,
-                                   struct rt2x00lib_conf *libconf)
-{
-       u16 eeprom;
-       short lna_gain = 0;
-
-       if (libconf->band == IEEE80211_BAND_2GHZ) {
-               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-                       lna_gain += 14;
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
 
-               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);
-       }
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
 
-       rt2x00dev->lna_gain = lna_gain;
-}
-
-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);
-
-       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_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
+                          erp->beacon_int * 16);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
-static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
-                                  const int txpower)
-{
-       struct rf_channel rf;
+       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);
 
-       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);
+       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,
@@ -869,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;
@@ -895,50 +732,144 @@ 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,
@@ -948,17 +879,16 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
        /* Always recalculate LNA gain before changing configuration */
        rt73usb_config_lna_gain(rt2x00dev, libconf);
 
-       if (flags & CONFIG_UPDATE_PHYMODE)
-               rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
-       if (flags & CONFIG_UPDATE_CHANNEL)
+       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);
 }
 
 /*
@@ -972,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)
 {
-       rt73usb_bbp_write(rt2x00dev, 17, 0x20);
-       rt2x00dev->link.vgc_level = 0x20;
+       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_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
+                               struct link_qual *qual)
+{
+       rt73usb_set_vgc(rt2x00dev, qual, 0x20);
+}
+
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
+                              struct link_qual *qual, const u32 count)
 {
-       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.
         */
@@ -1009,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 {
@@ -1036,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;
        }
 
@@ -1074,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;
        }
 
@@ -1089,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));
 }
 
 /*
@@ -1110,25 +1037,37 @@ 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;
@@ -1138,7 +1077,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
         * 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);
@@ -1180,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 */
@@ -1195,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);
@@ -1209,87 +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_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
        rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
-       rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+       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);
-
-       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_CSR1, reg);
 
-       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);
+       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_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
@@ -1297,36 +1225,36 @@ 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;
 }
@@ -1404,11 +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) ||
                           (state == STATE_RADIO_RX_OFF_LINK));
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 }
 
 static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1425,12 +1353,12 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 
 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);
 }
@@ -1443,10 +1371,10 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state 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.
@@ -1454,7 +1382,7 @@ 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);
+               rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
                state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
                if (state == !put_to_sleep)
                        return 0;
@@ -1536,8 +1464,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_desc_write(txd, 2, word);
 
        if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-               _rt2x00_desc_write(txd, 3, skbdesc->iv);
-               _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+               _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+               _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
        }
 
        rt2x00_desc_read(txd, 5, &word);
@@ -1557,7 +1485,7 @@ 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,
                           test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
@@ -1566,8 +1494,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        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 - skbdesc->desc_len);
+       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, txdesc->cipher);
@@ -1583,7 +1510,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
        struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
        unsigned int beacon_base;
        u32 reg;
-       u32 word, len;
 
        /*
         * Add the descriptor in front of the skb.
@@ -1593,25 +1519,12 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
        skbdesc->desc = entry->skb->data;
 
        /*
-        * Adjust the beacon databyte count. The current number is
-        * calculated before this function gets called, but falsely
-        * assumes that the descriptor was already present in the SKB.
-        */
-       rt2x00_desc_read(skbdesc->desc, 0, &word);
-       len  = rt2x00_get_field32(word, TXD_W0_DATABYTE_COUNT);
-       len += skbdesc->desc_len;
-       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, len);
-       rt2x00_desc_write(skbdesc->desc, 0, word);
-
-       /*
         * 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);
+       rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
        rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+       rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
        /*
         * Write entire beacon with descriptor to register.
@@ -1629,8 +1542,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
        entry->skb = NULL;
 }
 
-static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
-                                  struct sk_buff *skb)
+static int rt73usb_get_tx_data_len(struct queue_entry *entry)
 {
        int length;
 
@@ -1638,8 +1550,8 @@ 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;
 }
@@ -1658,14 +1570,14 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
         * 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);
        }
 }
 
@@ -1708,7 +1620,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
 }
 
 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);
@@ -1740,13 +1652,16 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
        }
 
        if (rxdesc->cipher != CIPHER_NONE) {
-               _rt2x00_desc_read(rxd, 2, &rxdesc->iv);
-               _rt2x00_desc_read(rxd, 3, &rxdesc->eiv);
+               _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 seperately but rt2x00lib
+                * decryption. It has provided the data separately but rt2x00lib
                 * should decide if it should be reinserted.
                 */
                rxdesc->flags |= RX_FLAG_IV_STRIPPED;
@@ -1776,6 +1691,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
 
        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;
 
@@ -1802,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);
@@ -1904,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;
        }
@@ -1935,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);
@@ -1953,7 +1875,7 @@ 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);
 
        rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
@@ -1986,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;
 }
@@ -2139,8 +2061,9 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
         */
        rt2x00dev->hw->flags =
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-           IEEE80211_HW_SIGNAL_DBM;
-       rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
+           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,
@@ -2153,17 +2076,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        spec->supported_bands = SUPPORT_BAND_2GHZ;
        spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
-       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;
@@ -2214,10 +2137,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
                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);
 
@@ -2232,43 +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;
+
+       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);
 
-       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);
+       /* 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 const struct ieee80211_ops rt73usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
@@ -2277,27 +2238,26 @@ 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,
+       .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,
@@ -2306,12 +2266,14 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .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,
 };
 
@@ -2337,19 +2299,20 @@ static const struct data_queue_desc rt73usb_queue_bcn = {
 };
 
 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,
-       .tx_queues      = NUM_TX_QUEUES,
-       .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 */
 };
 
@@ -2358,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 */
@@ -2371,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) },
@@ -2385,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 */
@@ -2393,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, }
 };