Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-core.c
	drivers/net/wireless/rt2x00/rt2x00queue.c
	drivers/net/wireless/rt2x00/rt2x00queue.h
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index f630552..c457731 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -59,7 +59,6 @@
 	select RT2800_LIB
 	select RT2X00_LIB_PCI if PCI
 	select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
-	select RT2X00_LIB_HT
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
@@ -74,17 +73,13 @@
 if RT2800PCI
 
 config RT2800PCI_RT33XX
-	bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	default n
+	bool "rt2800pci - Include support for rt33xx devices"
+	default y
 	---help---
 	  This adds support for rt33xx wireless chipset family to the
 	  rt2800pci driver.
 	  Supported chips: RT3390
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
-
 config RT2800PCI_RT35XX
 	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -100,15 +95,12 @@
 config RT2800PCI_RT53XX
        bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       default n
+       default y
        ---help---
          This adds support for rt53xx wireless chipset family to the
          rt2800pci driver.
          Supported chips: RT5390
 
-         Support for these devices is non-functional at the moment and is
-         intended for testers and developers.
-
 endif
 
 config RT2500USB
@@ -140,7 +132,6 @@
 	depends on USB
 	select RT2800_LIB
 	select RT2X00_LIB_USB
-	select RT2X00_LIB_HT
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
@@ -153,17 +144,13 @@
 if RT2800USB
 
 config RT2800USB_RT33XX
-	bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	default n
+	bool "rt2800usb - Include support for rt33xx devices"
+	default y
 	---help---
 	  This adds support for rt33xx wireless chipset family to the
 	  rt2800usb driver.
 	  Supported chips: RT3370
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
-
 config RT2800USB_RT35XX
 	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -207,9 +194,6 @@
 config RT2X00_LIB
 	tristate
 
-config RT2X00_LIB_HT
-	boolean
-
 config RT2X00_LIB_FIRMWARE
 	boolean
 	select FW_LOADER
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 9713398..349d5b8 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -7,7 +7,6 @@
 rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)	+= rt2x00crypto.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_HT)	+= rt2x00ht.o
 
 obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o
 obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 137a24e..937f9e8 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1314,8 +1314,8 @@
 	}
 }
 
-static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
@@ -1536,13 +1536,13 @@
 	 * 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);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Check if the BBP tuning should be enabled.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
-		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	return 0;
 }
@@ -1640,9 +1640,9 @@
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1720,6 +1720,9 @@
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
@@ -1740,6 +1743,7 @@
 	.start_queue		= rt2400pci_start_queue,
 	.kick_queue		= rt2400pci_kick_queue,
 	.stop_queue		= rt2400pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2400pci_write_tx_desc,
 	.write_beacon		= rt2400pci_write_beacon,
 	.fill_rxdone		= rt2400pci_fill_rxdone,
@@ -1801,10 +1805,11 @@
  * RT2400pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0101) },
 	{ 0, }
 };
 
+
 MODULE_AUTHOR(DRV_PROJECT);
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
@@ -1812,10 +1817,16 @@
 MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2400pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
 static struct pci_driver rt2400pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2400pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2400pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 198fc0a..d27d7b8 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1446,8 +1446,8 @@
 	}
 }
 
-static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
@@ -1687,14 +1687,14 @@
 	 * 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);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Check if the BBP tuning should be enabled.
 	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
-		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read the RSSI <-> dBm offset information.
@@ -1958,9 +1958,9 @@
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -2013,6 +2013,9 @@
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
@@ -2033,6 +2036,7 @@
 	.start_queue		= rt2500pci_start_queue,
 	.kick_queue		= rt2500pci_kick_queue,
 	.stop_queue		= rt2500pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2500pci_write_tx_desc,
 	.write_beacon		= rt2500pci_write_beacon,
 	.fill_rxdone		= rt2500pci_fill_rxdone,
@@ -2094,7 +2098,7 @@
  * RT2500pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0201) },
 	{ 0, }
 };
 
@@ -2105,10 +2109,16 @@
 MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
 static struct pci_driver rt2500pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2500pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index eac7881..b21f8123 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1519,7 +1519,7 @@
 	 * 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);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read the RSSI <-> dBm offset information.
@@ -1790,13 +1790,13 @@
 	/*
 	 * This device requires the atim queue
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt) {
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+		__set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
 	}
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1823,6 +1823,9 @@
 	.conf_tx		= rt2x00mac_conf_tx,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1904,54 +1907,54 @@
  */
 static struct usb_device_id rt2500usb_device_table[] = {
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1706) },
+	{ USB_DEVICE(0x0b05, 0x1707) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x050d, 0x7050) },
+	{ USB_DEVICE(0x050d, 0x7051) },
 	/* Cisco Systems */
-	{ USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x000d) },
+	{ USB_DEVICE(0x13b1, 0x0011) },
+	{ USB_DEVICE(0x13b1, 0x001a) },
 	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c02) },
 	/* D-LINK */
-	{ USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x2001, 0x3c00) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x1044, 0x8001) },
+	{ USB_DEVICE(0x1044, 0x8007) },
 	/* Hercules */
-	{ USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x06f8, 0xe000) },
 	/* Melco */
-	{ USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0411, 0x005e) },
+	{ USB_DEVICE(0x0411, 0x0066) },
+	{ USB_DEVICE(0x0411, 0x0067) },
+	{ USB_DEVICE(0x0411, 0x008b) },
+	{ USB_DEVICE(0x0411, 0x0097) },
 	/* MSI */
-	{ USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x6861) },
+	{ USB_DEVICE(0x0db0, 0x6865) },
+	{ USB_DEVICE(0x0db0, 0x6869) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x148f, 0x1706) },
+	{ USB_DEVICE(0x148f, 0x2570) },
+	{ USB_DEVICE(0x148f, 0x9020) },
 	/* Sagem */
-	{ USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x079b, 0x004b) },
 	/* Siemens */
-	{ USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0681, 0x3c06) },
 	/* SMC */
-	{ USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0707, 0xee13) },
 	/* Spairon */
-	{ USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x114b, 0x0110) },
 	/* SURECOM */
-	{ USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0769, 0x11f3) },
 	/* Trust */
-	{ USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0eb0, 0x9020) },
 	/* VTech */
-	{ USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0f88, 0x3012) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0260) },
 	{ 0, }
 };
 
@@ -1962,10 +1965,16 @@
 MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500usb_probe(struct usb_interface *usb_intf,
+			   const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
 static struct usb_driver rt2500usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt2500usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 6331c61..5cd096e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -730,34 +730,20 @@
 	struct data_queue *queue;
 	struct queue_entry *entry;
 	u32 reg;
-	u8 pid;
-	int i;
+	u8 qid;
 
-	/*
-	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
-	 * at most X times and also stop processing once the TX_STA_FIFO_VALID
-	 * flag is not set anymore.
-	 *
-	 * The legacy drivers use X=TX_RING_SIZE but state in a comment
-	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
-	 * tx ring size for now.
-	 */
-	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
-		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
-			break;
+	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
 
-		/*
-		 * Skip this entry when it contains an invalid
-		 * queue identication number.
+		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+		 * qid is guaranteed to be one of the TX QIDs
 		 */
-		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
-		if (pid >= QID_RX)
+		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+		if (unlikely(!queue)) {
+			WARNING(rt2x00dev, "Got TX status for an unavailable "
+					   "queue %u, dropping\n", qid);
 			continue;
-
-		queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
-		if (unlikely(!queue))
-			continue;
+		}
 
 		/*
 		 * Inside each queue, we process each entry in a chronological
@@ -949,25 +935,49 @@
 	unsigned int ledmode =
 		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
 				   EEPROM_FREQ_LED_MODE);
+	u32 reg;
 
-	if (led->type == LED_TYPE_RADIO) {
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-				      enabled ? 0x20 : 0);
-	} else if (led->type == LED_TYPE_ASSOC) {
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
-	} else if (led->type == LED_TYPE_QUALITY) {
-		/*
-		 * The brightness is divided into 6 levels (0 - 5),
-		 * The specs tell us the following levels:
-		 *	0, 1 ,3, 7, 15, 31
-		 * to determine the level in a simple way we can simply
-		 * work with bitshifting:
-		 *	(1 << level) - 1
-		 */
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-				      (1 << brightness / (LED_FULL / 6)) - 1,
-				      polarity);
+	/* Check for SoC (SOC devices don't support MCU requests) */
+	if (rt2x00_is_soc(led->rt2x00dev)) {
+		rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+
+		/* Set LED Polarity */
+		rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
+
+		/* Set LED Mode */
+		if (led->type == LED_TYPE_RADIO) {
+			rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
+					   enabled ? 3 : 0);
+		} else if (led->type == LED_TYPE_ASSOC) {
+			rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
+					   enabled ? 3 : 0);
+		} else if (led->type == LED_TYPE_QUALITY) {
+			rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
+					   enabled ? 3 : 0);
+		}
+
+		rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+	} else {
+		if (led->type == LED_TYPE_RADIO) {
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+					      enabled ? 0x20 : 0);
+		} else if (led->type == LED_TYPE_ASSOC) {
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+		} else if (led->type == LED_TYPE_QUALITY) {
+			/*
+			 * The brightness is divided into 6 levels (0 - 5),
+			 * The specs tell us the following levels:
+			 *	0, 1 ,3, 7, 15, 31
+			 * to determine the level in a simple way we can simply
+			 * work with bitshifting:
+			 *	(1 << level) - 1
+			 */
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+					      (1 << brightness / (LED_FULL / 6)) - 1,
+					      polarity);
+		}
 	}
 }
 
@@ -1221,6 +1231,25 @@
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		if (conf->sync == TSF_SYNC_AP_NONE) {
+			/*
+			 * Tune beacon queue transmit parameters for AP mode
+			 */
+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+		} else {
+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+		}
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
@@ -1739,8 +1768,8 @@
 
 	if (rf->channel <= 14) {
 		if (!rt2x00_rt(rt2x00dev, RT5390)) {
-			if (test_bit(CONFIG_EXTERNAL_LNA_BG,
-				     &rt2x00dev->flags)) {
+			if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+				     &rt2x00dev->cap_flags)) {
 				rt2800_bbp_write(rt2x00dev, 82, 0x62);
 				rt2800_bbp_write(rt2x00dev, 75, 0x46);
 			} else {
@@ -1751,7 +1780,7 @@
 	} else {
 		rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			rt2800_bbp_write(rt2x00dev, 75, 0x46);
 		else
 			rt2800_bbp_write(rt2x00dev, 75, 0x50);
@@ -1984,7 +2013,7 @@
 	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
 		return txpower;
 
-	if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
 		/*
 		 * Check if eirp txpower exceed txpower_limit.
 		 * We use OFDM 6M as criterion and its eirp txpower
@@ -2384,7 +2413,7 @@
 	} else if (rt2800_is_305x_soc(rt2x00dev)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
 	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -3285,8 +3314,8 @@
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-			if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
-				      &rt2x00dev->flags))
+			if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+				      &rt2x00dev->cap_flags))
 				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
 		}
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
@@ -3709,15 +3738,15 @@
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Store led settings, for correct led behaviour.
@@ -3737,7 +3766,7 @@
 
 	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
 					EIRP_MAX_TX_POWER_LIMIT)
-		__set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index adc3534..08d3947 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -66,7 +66,7 @@
 		return;
 
 	for (i = 0; i < 200; i++) {
-		rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+		rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
 
 		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
 		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -80,8 +80,8 @@
 	if (i == 200)
 		ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
 
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 }
 
 #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
@@ -105,7 +105,7 @@
 	struct rt2x00_dev *rt2x00dev = eeprom->data;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
 	eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
 	eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -127,7 +127,7 @@
 	rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
 			   !!eeprom->reg_chip_select);
 
-	rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
 }
 
 static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -135,7 +135,7 @@
 	struct eeprom_93cx6 eeprom;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
 	eeprom.data = rt2x00dev;
 	eeprom.register_read = rt2800pci_eepromregister_read;
@@ -195,9 +195,9 @@
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
 		/*
@@ -207,15 +207,15 @@
 		tasklet_enable(&rt2x00dev->tbtt_tasklet);
 		tasklet_enable(&rt2x00dev->pretbtt_tasklet);
 
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
 		break;
 	default:
 		break;
@@ -233,11 +233,13 @@
 	case QID_AC_BE:
 	case QID_AC_BK:
 		entry = rt2x00queue_get_entry(queue, Q_INDEX);
-		rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx);
+		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+					 entry->entry_idx);
 		break;
 	case QID_MGMT:
 		entry = rt2x00queue_get_entry(queue, Q_INDEX);
-		rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx);
+		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
+					 entry->entry_idx);
 		break;
 	default:
 		break;
@@ -251,20 +253,20 @@
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
 
 		/*
 		 * Wait for tbtt tasklets to finish.
@@ -295,7 +297,7 @@
 	 */
 	reg = 0;
 	rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
 
 	/*
 	 * Write firmware to device.
@@ -303,11 +305,11 @@
 	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
 				   data, len);
 
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
 
-	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
 	return 0;
 }
@@ -351,7 +353,7 @@
 		 * Set RX IDX in register to inform hardware that we have
 		 * handled this entry and it is available for reuse again.
 		 */
-		rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+		rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
 				      entry->entry_idx);
 	} else {
 		rt2x00_desc_read(entry_priv->desc, 1, &word);
@@ -369,45 +371,51 @@
 	 * Initialize registers.
 	 */
 	entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
+				 rt2x00dev->tx[0].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
 
 	entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
+				 rt2x00dev->tx[1].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
 
 	entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
+				 rt2x00dev->tx[2].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
 
 	entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
+				 rt2x00dev->tx[3].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
 
 	entry_priv = rt2x00dev->rx->entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
-	rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
-	rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0);
+	rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
+				 rt2x00dev->rx[0].limit);
+	rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
+				 rt2x00dev->rx[0].limit - 1);
+	rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
 
 	/*
 	 * Enable global DMA configuration
 	 */
-	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+	rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
-	rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+	rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
 
 	return 0;
 }
@@ -427,8 +435,8 @@
 	 * should clear the register to assure a clean state.
 	 */
 	if (state == STATE_RADIO_IRQ_ON) {
-		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+		rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+		rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
 		/*
 		 * Enable tasklets. The beacon related tasklets are
@@ -440,7 +448,7 @@
 	}
 
 	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
@@ -459,7 +467,7 @@
 	rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 
 	if (state == STATE_RADIO_IRQ_OFF) {
@@ -480,7 +488,7 @@
 	/*
 	 * Reset DMA indexes
 	 */
-	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+	rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -488,26 +496,26 @@
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+	rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
 	if (rt2x00_rt(rt2x00dev, RT5390)) {
-		rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
 		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
 		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
-		rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
 	}
 
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+	rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
 	return 0;
 }
@@ -525,8 +533,8 @@
 {
 	if (rt2x00_is_soc(rt2x00dev)) {
 		rt2800_disable_radio(rt2x00dev);
-		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+		rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+		rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
 	}
 }
 
@@ -537,8 +545,10 @@
 		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
 	} else if (state == STATE_SLEEP) {
-		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
-		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+					 0xffffffff);
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
+					 0xffffffff);
 		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
 	}
 
@@ -768,8 +778,8 @@
 	return !max_tx_done;
 }
 
-static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
@@ -778,9 +788,9 @@
 	 * access needs locking.
 	 */
 	spin_lock_irq(&rt2x00dev->irqmask_lock);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, irq_field, 1);
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock_irq(&rt2x00dev->irqmask_lock);
 }
 
@@ -851,7 +861,7 @@
 	 * need to lock the kfifo.
 	 */
 	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+		rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
 
 		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
 			break;
@@ -873,8 +883,8 @@
 	u32 reg, mask;
 
 	/* Read status and ACK all interrupts */
-	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
 	if (!reg)
 		return IRQ_NONE;
@@ -914,9 +924,9 @@
 	 * the tasklet will reenable the appropriate interrupts.
 	 */
 	spin_lock(&rt2x00dev->irqmask_lock);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	reg &= mask;
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock(&rt2x00dev->irqmask_lock);
 
 	return IRQ_HANDLED;
@@ -966,28 +976,28 @@
 	 * This device has multiple filters for control frames
 	 * and has a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device has a pre tbtt interrupt and thus fetches
 	 * a new beacon directly prior to transmission.
 	 */
-	__set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
 	if (!rt2x00_is_soc(rt2x00dev))
-		__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
+		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1018,6 +1028,7 @@
 	.ampdu_action		= rt2800_ampdu_action,
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1057,6 +1068,7 @@
 	.start_queue		= rt2800pci_start_queue,
 	.kick_queue		= rt2800pci_kick_queue,
 	.stop_queue		= rt2800pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2800pci_write_tx_desc,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
@@ -1116,36 +1128,36 @@
  */
 #ifdef CONFIG_PCI
 static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0601) },
+	{ PCI_DEVICE(0x1814, 0x0681) },
+	{ PCI_DEVICE(0x1814, 0x0701) },
+	{ PCI_DEVICE(0x1814, 0x0781) },
+	{ PCI_DEVICE(0x1814, 0x3090) },
+	{ PCI_DEVICE(0x1814, 0x3091) },
+	{ PCI_DEVICE(0x1814, 0x3092) },
+	{ PCI_DEVICE(0x1432, 0x7708) },
+	{ PCI_DEVICE(0x1432, 0x7727) },
+	{ PCI_DEVICE(0x1432, 0x7728) },
+	{ PCI_DEVICE(0x1432, 0x7738) },
+	{ PCI_DEVICE(0x1432, 0x7748) },
+	{ PCI_DEVICE(0x1432, 0x7758) },
+	{ PCI_DEVICE(0x1432, 0x7768) },
+	{ PCI_DEVICE(0x1462, 0x891a) },
+	{ PCI_DEVICE(0x1a3b, 0x1059) },
 #ifdef CONFIG_RT2800PCI_RT33XX
-	{ PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x3390) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT35XX
-	{ PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1432, 0x7711) },
+	{ PCI_DEVICE(0x1432, 0x7722) },
+	{ PCI_DEVICE(0x1814, 0x3060) },
+	{ PCI_DEVICE(0x1814, 0x3062) },
+	{ PCI_DEVICE(0x1814, 0x3562) },
+	{ PCI_DEVICE(0x1814, 0x3592) },
+	{ PCI_DEVICE(0x1814, 0x3593) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT53XX
-	{ PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x5390) },
 #endif
 	{ 0, }
 };
@@ -1181,10 +1193,16 @@
 #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
 
 #ifdef CONFIG_PCI
+static int rt2800pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
+}
+
 static struct pci_driver rt2800pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2800pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2800pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6ba31a0..0d4e8fa 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -59,16 +59,16 @@
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 		break;
 	default:
 		break;
@@ -82,16 +82,16 @@
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 		break;
 	default:
 		break;
@@ -99,6 +99,62 @@
 }
 
 /*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+		    rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+			return true;
+	}
+	return false;
+}
+
+static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+						 int urb_status, u32 tx_status)
+{
+	if (urb_status) {
+		WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
+		return;
+	}
+
+	/* try to read all TX_STA_FIFO entries before scheduling txdone_work */
+	if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
+		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
+			WARNING(rt2x00dev, "TX status FIFO overrun, "
+				"drop tx status report.\n");
+			queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+		} else
+			rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+						      rt2800usb_tx_sta_fifo_read_completed);
+	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
+	}
+}
+
+static void rt2800usb_tx_dma_done(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+				      rt2800usb_tx_sta_fifo_read_completed);
+}
+
+static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+				      rt2800usb_tx_sta_fifo_read_completed);
+}
+
+/*
  * Firmware functions
  */
 static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
@@ -129,11 +185,11 @@
 	/*
 	 * Write firmware to device.
 	 */
-	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-				   data + offset, length);
+	rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+				      data + offset, length);
 
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 
 	/*
 	 * Send firmware request to device to load firmware,
@@ -148,7 +204,7 @@
 	}
 
 	msleep(10);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
 	return 0;
 }
@@ -166,22 +222,22 @@
 	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
 
-	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-	rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
 
 	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
 				    USB_MODE_RESET, REGISTER_TIMEOUT);
 
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
 	return 0;
 }
@@ -193,7 +249,7 @@
 	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
 		return -EIO;
 
-	rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
@@ -206,7 +262,7 @@
 			    / 1024) - 3);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
-	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
 
 	return rt2800_enable_radio(rt2x00dev);
 }
@@ -282,12 +338,12 @@
 	unsigned int i;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
 	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
 		WARNING(rt2x00dev, "TX HW queue 0 timed out,"
 			" invoke forced kick\n");
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
 
 		for (i = 0; i < 10; i++) {
 			udelay(10);
@@ -295,15 +351,15 @@
 				break;
 		}
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
 	}
 
-	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
 	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
 		WARNING(rt2x00dev, "TX HW queue 1 timed out,"
 			" invoke forced kick\n");
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
 
 		for (i = 0; i < 10; i++) {
 			udelay(10);
@@ -311,7 +367,7 @@
 				break;
 		}
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
 	}
 
 	rt2x00usb_watchdog(rt2x00dev);
@@ -420,13 +476,24 @@
 		while (!rt2x00queue_empty(queue)) {
 			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-			    !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
 				break;
-
-			rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+			if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+				rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+			else if (rt2x00queue_status_timeout(entry))
+				rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+			else
+				break;
 		}
 	}
+
+	/*
+	 * The hw may delay sending the packet after DMA complete
+	 * if the medium is busy, thus the TX_STA_FIFO entry is
+	 * also delayed -> use a timer to retrieve it.
+	 */
+	if (rt2800usb_txstatus_pending(rt2x00dev))
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
 }
 
 /*
@@ -553,18 +620,23 @@
 	 * This device has multiple filters for control frames
 	 * and has a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+
+	setup_timer(&rt2x00dev->txstatus_timer,
+		    rt2800usb_tx_sta_fifo_timeout,
+		    (unsigned long) rt2x00dev);
 
 	/*
 	 * Set the rssi offset.
@@ -601,6 +673,7 @@
 	.ampdu_action		= rt2800_ampdu_action,
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -635,6 +708,7 @@
 	.kick_queue		= rt2x00usb_kick_queue,
 	.stop_queue		= rt2800usb_stop_queue,
 	.flush_queue		= rt2x00usb_flush_queue,
+	.tx_dma_done		= rt2800usb_tx_dma_done,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
@@ -695,295 +769,332 @@
  */
 static struct usb_device_id rt2800usb_device_table[] = {
 	/* Abocom */
-	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x2870) },
+	{ USB_DEVICE(0x07b8, 0x2770) },
+	{ USB_DEVICE(0x07b8, 0x3070) },
+	{ USB_DEVICE(0x07b8, 0x3071) },
+	{ USB_DEVICE(0x07b8, 0x3072) },
+	{ USB_DEVICE(0x1482, 0x3c09) },
 	/* AirTies */
-	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1eda, 0x2012) },
+	{ USB_DEVICE(0x1eda, 0x2310) },
 	/* Allwin */
-	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x8516, 0x2070) },
+	{ USB_DEVICE(0x8516, 0x2770) },
+	{ USB_DEVICE(0x8516, 0x2870) },
+	{ USB_DEVICE(0x8516, 0x3070) },
+	{ USB_DEVICE(0x8516, 0x3071) },
+	{ USB_DEVICE(0x8516, 0x3072) },
+	/* Alpha Networks */
+	{ USB_DEVICE(0x14b2, 0x3c06) },
+	{ USB_DEVICE(0x14b2, 0x3c07) },
+	{ USB_DEVICE(0x14b2, 0x3c09) },
+	{ USB_DEVICE(0x14b2, 0x3c12) },
+	{ USB_DEVICE(0x14b2, 0x3c23) },
+	{ USB_DEVICE(0x14b2, 0x3c25) },
+	{ USB_DEVICE(0x14b2, 0x3c27) },
+	{ USB_DEVICE(0x14b2, 0x3c28) },
+	{ USB_DEVICE(0x14b2, 0x3c2c) },
 	/* Amit */
-	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15c5, 0x0008) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0740) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1731) },
+	{ USB_DEVICE(0x0b05, 0x1732) },
+	{ USB_DEVICE(0x0b05, 0x1742) },
+	{ USB_DEVICE(0x0b05, 0x1784) },
+	{ USB_DEVICE(0x1761, 0x0b05) },
 	/* AzureWave */
-	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3247) },
+	{ USB_DEVICE(0x13d3, 0x3273) },
+	{ USB_DEVICE(0x13d3, 0x3305) },
+	{ USB_DEVICE(0x13d3, 0x3307) },
+	{ USB_DEVICE(0x13d3, 0x3321) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x8053) },
+	{ USB_DEVICE(0x050d, 0x805c) },
+	{ USB_DEVICE(0x050d, 0x815c) },
+	{ USB_DEVICE(0x050d, 0x825b) },
+	{ USB_DEVICE(0x050d, 0x935a) },
+	{ USB_DEVICE(0x050d, 0x935b) },
 	/* Buffalo */
-	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x00e8) },
+	{ USB_DEVICE(0x0411, 0x016f) },
+	{ USB_DEVICE(0x0411, 0x01a2) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x002f) },
+	{ USB_DEVICE(0x07aa, 0x003c) },
+	{ USB_DEVICE(0x07aa, 0x003f) },
+	{ USB_DEVICE(0x18c5, 0x0012) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c09) },
+	{ USB_DEVICE(0x07d1, 0x3c0a) },
+	{ USB_DEVICE(0x07d1, 0x3c0d) },
+	{ USB_DEVICE(0x07d1, 0x3c0e) },
+	{ USB_DEVICE(0x07d1, 0x3c0f) },
+	{ USB_DEVICE(0x07d1, 0x3c11) },
+	{ USB_DEVICE(0x07d1, 0x3c16) },
 	/* Draytek */
-	{ USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07fa, 0x7712) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7711) },
+	{ USB_DEVICE(0x7392, 0x7717) },
+	{ USB_DEVICE(0x7392, 0x7718) },
 	/* Encore */
-	{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x203d, 0x1480) },
+	{ USB_DEVICE(0x203d, 0x14a9) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9701) },
+	{ USB_DEVICE(0x1740, 0x9702) },
+	{ USB_DEVICE(0x1740, 0x9703) },
+	{ USB_DEVICE(0x1740, 0x9705) },
+	{ USB_DEVICE(0x1740, 0x9706) },
+	{ USB_DEVICE(0x1740, 0x9707) },
+	{ USB_DEVICE(0x1740, 0x9708) },
+	{ USB_DEVICE(0x1740, 0x9709) },
+	/* Gemtek */
+	{ USB_DEVICE(0x15a9, 0x0012) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800b) },
+	{ USB_DEVICE(0x1044, 0x800d) },
 	/* Hawking */
-	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e66, 0x0001) },
+	{ USB_DEVICE(0x0e66, 0x0003) },
+	{ USB_DEVICE(0x0e66, 0x0009) },
+	{ USB_DEVICE(0x0e66, 0x000b) },
+	{ USB_DEVICE(0x0e66, 0x0013) },
+	{ USB_DEVICE(0x0e66, 0x0017) },
+	{ USB_DEVICE(0x0e66, 0x0018) },
 	/* I-O DATA */
-	{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x0945) },
+	{ USB_DEVICE(0x04bb, 0x0947) },
+	{ USB_DEVICE(0x04bb, 0x0948) },
 	/* Linksys */
-	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x0031) },
+	{ USB_DEVICE(0x1737, 0x0070) },
+	{ USB_DEVICE(0x1737, 0x0071) },
 	/* Logitec */
-	{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0789, 0x0162) },
+	{ USB_DEVICE(0x0789, 0x0163) },
+	{ USB_DEVICE(0x0789, 0x0164) },
+	{ USB_DEVICE(0x0789, 0x0166) },
 	/* Motorola */
-	{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x100d, 0x9031) },
 	/* MSI */
-	{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x3820) },
+	{ USB_DEVICE(0x0db0, 0x3821) },
+	{ USB_DEVICE(0x0db0, 0x3822) },
+	{ USB_DEVICE(0x0db0, 0x3870) },
+	{ USB_DEVICE(0x0db0, 0x3871) },
+	{ USB_DEVICE(0x0db0, 0x6899) },
+	{ USB_DEVICE(0x0db0, 0x821a) },
+	{ USB_DEVICE(0x0db0, 0x822a) },
+	{ USB_DEVICE(0x0db0, 0x822b) },
+	{ USB_DEVICE(0x0db0, 0x822c) },
+	{ USB_DEVICE(0x0db0, 0x870a) },
+	{ USB_DEVICE(0x0db0, 0x871a) },
+	{ USB_DEVICE(0x0db0, 0x871b) },
+	{ USB_DEVICE(0x0db0, 0x871c) },
+	{ USB_DEVICE(0x0db0, 0x899a) },
 	/* Para */
-	{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x20b8, 0x8888) },
 	/* Pegatron */
-	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x000c) },
+	{ USB_DEVICE(0x1d4d, 0x000e) },
+	{ USB_DEVICE(0x1d4d, 0x0011) },
 	/* Philips */
-	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0471, 0x200f) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab25) },
+	{ USB_DEVICE(0x2019, 0xed06) },
 	/* Quanta */
-	{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1a32, 0x0304) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x2070) },
+	{ USB_DEVICE(0x148f, 0x2770) },
+	{ USB_DEVICE(0x148f, 0x2870) },
+	{ USB_DEVICE(0x148f, 0x3070) },
+	{ USB_DEVICE(0x148f, 0x3071) },
+	{ USB_DEVICE(0x148f, 0x3072) },
 	/* Samsung */
-	{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04e8, 0x2018) },
 	/* Siemens */
-	{ USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x129b, 0x1828) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0017) },
+	{ USB_DEVICE(0x0df6, 0x002b) },
+	{ USB_DEVICE(0x0df6, 0x002c) },
+	{ USB_DEVICE(0x0df6, 0x002d) },
+	{ USB_DEVICE(0x0df6, 0x0039) },
+	{ USB_DEVICE(0x0df6, 0x003b) },
+	{ USB_DEVICE(0x0df6, 0x003d) },
+	{ USB_DEVICE(0x0df6, 0x003e) },
+	{ USB_DEVICE(0x0df6, 0x003f) },
+	{ USB_DEVICE(0x0df6, 0x0040) },
+	{ USB_DEVICE(0x0df6, 0x0042) },
+	{ USB_DEVICE(0x0df6, 0x0047) },
+	{ USB_DEVICE(0x0df6, 0x0048) },
+	{ USB_DEVICE(0x0df6, 0x0051) },
+	{ USB_DEVICE(0x0df6, 0x005f) },
 	/* SMC */
-	{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x6618) },
+	{ USB_DEVICE(0x083a, 0x7511) },
+	{ USB_DEVICE(0x083a, 0x7512) },
+	{ USB_DEVICE(0x083a, 0x7522) },
+	{ USB_DEVICE(0x083a, 0x8522) },
+	{ USB_DEVICE(0x083a, 0xa618) },
+	{ USB_DEVICE(0x083a, 0xa701) },
+	{ USB_DEVICE(0x083a, 0xa702) },
+	{ USB_DEVICE(0x083a, 0xa703) },
+	{ USB_DEVICE(0x083a, 0xb522) },
 	/* Sparklan */
-	{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0006) },
 	/* Sweex */
-	{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
-	/* U-Media*/
-	{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0302) },
+	/* U-Media */
+	{ USB_DEVICE(0x157e, 0x300e) },
+	{ USB_DEVICE(0x157e, 0x3013) },
 	/* ZCOM */
-	{ USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0cde, 0x0022) },
+	{ USB_DEVICE(0x0cde, 0x0025) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0280) },
+	{ USB_DEVICE(0x5a57, 0x0282) },
+	{ USB_DEVICE(0x5a57, 0x0283) },
+	{ USB_DEVICE(0x5a57, 0x5257) },
 	/* Zyxel */
-	{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0586, 0x3416) },
+	{ USB_DEVICE(0x0586, 0x3418) },
+	{ USB_DEVICE(0x0586, 0x341e) },
+	{ USB_DEVICE(0x0586, 0x343e) },
 #ifdef CONFIG_RT2800USB_RT33XX
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3370) },
+	{ USB_DEVICE(0x148f, 0x8070) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0050) },
 #endif
 #ifdef CONFIG_RT2800USB_RT35XX
 	/* Allwin */
-	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x8516, 0x3572) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0744) },
 	/* Cisco */
-	{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x167b, 0x4001) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9801) },
 	/* I-O DATA */
-	{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x0944) },
+	/* Linksys */
+	{ USB_DEVICE(0x13b1, 0x002f) },
+	{ USB_DEVICE(0x1737, 0x0079) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3572) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0041) },
 	/* Toshiba */
-	{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0930, 0x0a07) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0284) },
 #endif
 #ifdef CONFIG_RT2800USB_UNKNOWN
 	/*
 	 * Unclear what kind of devices these are (they aren't supported by the
 	 * vendor linux driver).
 	 */
+	/* Abocom */
+	{ USB_DEVICE(0x07b8, 0x3073) },
+	{ USB_DEVICE(0x07b8, 0x3074) },
+	/* Alpha Networks */
+	{ USB_DEVICE(0x14b2, 0x3c08) },
+	{ USB_DEVICE(0x14b2, 0x3c11) },
 	/* Amigo */
-	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e0b, 0x9031) },
+	{ USB_DEVICE(0x0e0b, 0x9041) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x166a) },
+	{ USB_DEVICE(0x0b05, 0x1760) },
+	{ USB_DEVICE(0x0b05, 0x1761) },
+	{ USB_DEVICE(0x0b05, 0x1790) },
+	{ USB_DEVICE(0x0b05, 0x179d) },
 	/* AzureWave */
-	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3262) },
+	{ USB_DEVICE(0x13d3, 0x3284) },
+	{ USB_DEVICE(0x13d3, 0x3322) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x1003) },
+	{ USB_DEVICE(0x050d, 0x825a) },
 	/* Buffalo */
-	{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x012e) },
+	{ USB_DEVICE(0x0411, 0x0148) },
+	{ USB_DEVICE(0x0411, 0x0150) },
+	{ USB_DEVICE(0x0411, 0x015d) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x0041) },
+	{ USB_DEVICE(0x07aa, 0x0042) },
+	{ USB_DEVICE(0x18c5, 0x0008) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0b) },
+	{ USB_DEVICE(0x07d1, 0x3c13) },
+	{ USB_DEVICE(0x07d1, 0x3c15) },
+	{ USB_DEVICE(0x07d1, 0x3c17) },
+	{ USB_DEVICE(0x2001, 0x3c17) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x4085) },
+	{ USB_DEVICE(0x7392, 0x7722) },
 	/* Encore */
-	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x203d, 0x14a1) },
 	/* Gemtek */
-	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0010) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800c) },
+	/* Huawei */
+	{ USB_DEVICE(0x148f, 0xf101) },
+	/* I-O DATA */
+	{ USB_DEVICE(0x04bb, 0x094b) },
 	/* LevelOne */
-	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x0605) },
+	{ USB_DEVICE(0x1740, 0x0615) },
 	/* Linksys */
-	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1737, 0x0077) },
+	{ USB_DEVICE(0x1737, 0x0078) },
+	/* Logitec */
+	{ USB_DEVICE(0x0789, 0x0168) },
+	{ USB_DEVICE(0x0789, 0x0169) },
 	/* Motorola */
-	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x100d, 0x9032) },
 	/* Ovislink */
-	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1b75, 0x3071) },
+	{ USB_DEVICE(0x1b75, 0x3072) },
 	/* Pegatron */
-	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x05a6, 0x0101) },
+	{ USB_DEVICE(0x1d4d, 0x0002) },
+	{ USB_DEVICE(0x1d4d, 0x0010) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0x5201) },
+	{ USB_DEVICE(0x2019, 0xab24) },
 	/* Qcom */
-	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x18e8, 0x6259) },
+	/* RadioShack */
+	{ USB_DEVICE(0x08b9, 0x1197) },
+	/* Sitecom */
+	{ USB_DEVICE(0x0df6, 0x003c) },
+	{ USB_DEVICE(0x0df6, 0x004a) },
+	{ USB_DEVICE(0x0df6, 0x004d) },
+	{ USB_DEVICE(0x0df6, 0x0053) },
+	{ USB_DEVICE(0x0df6, 0x0060) },
+	{ USB_DEVICE(0x0df6, 0x0062) },
 	/* SMC */
-	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xa512) },
+	{ USB_DEVICE(0x083a, 0xc522) },
+	{ USB_DEVICE(0x083a, 0xd522) },
+	{ USB_DEVICE(0x083a, 0xf511) },
 	/* Sweex */
-	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0153) },
+	{ USB_DEVICE(0x177f, 0x0313) },
 	/* Zyxel */
-	{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0586, 0x341a) },
 #endif
 	{ 0, }
 };
@@ -996,10 +1107,16 @@
 MODULE_FIRMWARE(FIRMWARE_RT2870);
 MODULE_LICENSE("GPL");
 
+static int rt2800usb_probe(struct usb_interface *usb_intf,
+			   const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
 static struct usb_driver rt2800usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2800usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt2800usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index a2bd5fe..9d1a158 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -37,6 +37,7 @@
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
 #include <linux/kfifo.h>
+#include <linux/timer.h>
 
 #include <net/mac80211.h>
 
@@ -570,7 +571,8 @@
 	void (*start_queue) (struct data_queue *queue);
 	void (*kick_queue) (struct data_queue *queue);
 	void (*stop_queue) (struct data_queue *queue);
-	void (*flush_queue) (struct data_queue *queue);
+	void (*flush_queue) (struct data_queue *queue, bool drop);
+	void (*tx_dma_done) (struct queue_entry *entry);
 
 	/*
 	 * TX control handlers
@@ -643,11 +645,11 @@
 };
 
 /*
- * rt2x00 device flags
+ * rt2x00 state flags
  */
-enum rt2x00_flags {
+enum rt2x00_state_flags {
 	/*
-	 * Device state flags
+	 * Device flags
 	 */
 	DEVICE_STATE_PRESENT,
 	DEVICE_STATE_REGISTERED_HW,
@@ -657,42 +659,47 @@
 	DEVICE_STATE_SCANNING,
 
 	/*
-	 * Driver requirements
-	 */
-	DRIVER_REQUIRE_FIRMWARE,
-	DRIVER_REQUIRE_BEACON_GUARD,
-	DRIVER_REQUIRE_ATIM_QUEUE,
-	DRIVER_REQUIRE_DMA,
-	DRIVER_REQUIRE_COPY_IV,
-	DRIVER_REQUIRE_L2PAD,
-	DRIVER_REQUIRE_TXSTATUS_FIFO,
-	DRIVER_REQUIRE_TASKLET_CONTEXT,
-	DRIVER_REQUIRE_SW_SEQNO,
-	DRIVER_REQUIRE_HT_TX_DESC,
-
-	/*
-	 * Driver features
-	 */
-	CONFIG_SUPPORT_HW_BUTTON,
-	CONFIG_SUPPORT_HW_CRYPTO,
-	CONFIG_SUPPORT_POWER_LIMIT,
-	DRIVER_SUPPORT_CONTROL_FILTERS,
-	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
-	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
-	DRIVER_SUPPORT_LINK_TUNING,
-
-	/*
 	 * Driver configuration
 	 */
-	CONFIG_FRAME_TYPE,
-	CONFIG_RF_SEQUENCE,
-	CONFIG_EXTERNAL_LNA_A,
-	CONFIG_EXTERNAL_LNA_BG,
-	CONFIG_DOUBLE_ANTENNA,
 	CONFIG_CHANNEL_HT40,
 };
 
 /*
+ * rt2x00 capability flags
+ */
+enum rt2x00_capability_flags {
+	/*
+	 * Requirements
+	 */
+	REQUIRE_FIRMWARE,
+	REQUIRE_BEACON_GUARD,
+	REQUIRE_ATIM_QUEUE,
+	REQUIRE_DMA,
+	REQUIRE_COPY_IV,
+	REQUIRE_L2PAD,
+	REQUIRE_TXSTATUS_FIFO,
+	REQUIRE_TASKLET_CONTEXT,
+	REQUIRE_SW_SEQNO,
+	REQUIRE_HT_TX_DESC,
+
+	/*
+	 * Capabilities
+	 */
+	CAPABILITY_HW_BUTTON,
+	CAPABILITY_HW_CRYPTO,
+	CAPABILITY_POWER_LIMIT,
+	CAPABILITY_CONTROL_FILTERS,
+	CAPABILITY_CONTROL_FILTER_PSPOLL,
+	CAPABILITY_PRE_TBTT_INTERRUPT,
+	CAPABILITY_LINK_TUNING,
+	CAPABILITY_FRAME_TYPE,
+	CAPABILITY_RF_SEQUENCE,
+	CAPABILITY_EXTERNAL_LNA_A,
+	CAPABILITY_EXTERNAL_LNA_BG,
+	CAPABILITY_DOUBLE_ANTENNA,
+};
+
+/*
  * rt2x00 device structure.
  */
 struct rt2x00_dev {
@@ -738,13 +745,20 @@
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
 	/*
-	 * Device flags.
-	 * In these flags the current status and some
-	 * of the device capabilities are stored.
+	 * Device state flags.
+	 * In these flags the current status is stored.
+	 * Access to these flags should occur atomically.
 	 */
 	unsigned long flags;
 
 	/*
+	 * Device capabiltiy flags.
+	 * In these flags the device/driver capabilities are stored.
+	 * Access to these flags should occur non-atomically.
+	 */
+	unsigned long cap_flags;
+
+	/*
 	 * Device information, Bus IRQ and name (PCI, SoC)
 	 */
 	int irq;
@@ -911,6 +925,11 @@
 	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
 	/*
+	 * Timer to ensure tx status reports are read (rt2800usb).
+	 */
+	struct timer_list txstatus_timer;
+
+	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
@@ -1235,6 +1254,10 @@
 		      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
 void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 
 /*
  * Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 9416e36..f787264 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -109,15 +109,6 @@
 	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
 }
 
-static inline
-enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
-					    enum antenna default_ant)
-{
-	if (current_ant != ANTENNA_SW_DIVERSITY)
-		return current_ant;
-	return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
-}
-
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      struct antenna_setup config)
 {
@@ -126,19 +117,35 @@
 	struct antenna_setup *active = &rt2x00dev->link.ant.active;
 
 	/*
-	 * Failsafe: Make sure we are not sending the
-	 * ANTENNA_SW_DIVERSITY state to the driver.
-	 * If that happens, fallback to hardware defaults,
-	 * or our own default.
+	 * When the caller tries to send the SW diversity,
+	 * we must update the ANTENNA_RX_DIVERSITY flag to
+	 * enable the antenna diversity in the link tuner.
+	 *
+	 * Secondly, we must guarentee we never send the
+	 * software antenna diversity command to the driver.
 	 */
-	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
-		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
-	else if (config.rx == ANTENNA_SW_DIVERSITY)
+	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
+		if (config.rx == ANTENNA_SW_DIVERSITY) {
+			ant->flags |= ANTENNA_RX_DIVERSITY;
+
+			if (def->rx == ANTENNA_SW_DIVERSITY)
+				config.rx = ANTENNA_B;
+			else
+				config.rx = def->rx;
+		}
+	} else if (config.rx == ANTENNA_SW_DIVERSITY)
 		config.rx = active->rx;
 
-	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
-		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
-	else if (config.tx == ANTENNA_SW_DIVERSITY)
+	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
+		if (config.tx == ANTENNA_SW_DIVERSITY) {
+			ant->flags |= ANTENNA_TX_DIVERSITY;
+
+			if (def->tx == ANTENNA_SW_DIVERSITY)
+				config.tx = ANTENNA_B;
+			else
+				config.tx = def->tx;
+		}
+	} else if (config.tx == ANTENNA_SW_DIVERSITY)
 		config.tx = active->tx;
 
 	/*
@@ -163,6 +170,34 @@
 		rt2x00queue_start_queue(rt2x00dev->rx);
 }
 
+static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
+				   struct ieee80211_conf *conf)
+{
+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+	int center_channel;
+	u16 i;
+
+	/*
+	 * Initialize center channel to current channel.
+	 */
+	center_channel = spec->channels[conf->channel->hw_value].channel;
+
+	/*
+	 * Adjust center channel to HT40+ and HT40- operation.
+	 */
+	if (conf_is_ht40_plus(conf))
+		center_channel += 2;
+	else if (conf_is_ht40_minus(conf))
+		center_channel -= (center_channel == 14) ? 1 : 2;
+
+	for (i = 0; i < spec->num_channels; i++)
+		if (spec->channels[i].channel == center_channel)
+			return i;
+
+	WARN_ON(1);
+	return conf->channel->hw_value;
+}
+
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 		      struct ieee80211_conf *conf,
 		      unsigned int ieee80211_flags)
@@ -176,10 +211,10 @@
 
 	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		if (conf_is_ht40(conf)) {
-			__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+			set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 			hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
 		} else {
-			__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+			clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 			hw_value = conf->channel->hw_value;
 		}
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 3f5688f..1bb9d46 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -52,7 +52,7 @@
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
 	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 
-	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key)
+	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
 		return;
 
 	__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
@@ -80,7 +80,7 @@
 	struct ieee80211_key_conf *key = tx_info->control.hw_key;
 	unsigned int overhead = 0;
 
-	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key)
+	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key)
 		return overhead;
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 66166ef..78787fc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -63,7 +63,8 @@
 	 * - driver folder
 	 *   - driver file
 	 *   - chipset file
-	 *   - device flags file
+	 *   - device state flags file
+	 *   - device capability flags file
 	 *   - register folder
 	 *     - csr offset/value files
 	 *     - eeprom offset/value files
@@ -78,6 +79,7 @@
 	struct dentry *driver_entry;
 	struct dentry *chipset_entry;
 	struct dentry *dev_flags;
+	struct dentry *cap_flags;
 	struct dentry *register_folder;
 	struct dentry *csr_off_entry;
 	struct dentry *csr_val_entry;
@@ -553,6 +555,35 @@
 	.llseek		= default_llseek,
 };
 
+static ssize_t rt2x00debug_read_cap_flags(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	char line[16];
+	size_t size;
+
+	if (*offset)
+		return 0;
+
+	size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
+
+	if (copy_to_user(buf, line, size))
+		return -EFAULT;
+
+	*offset += size;
+	return size;
+}
+
+static const struct file_operations rt2x00debug_fop_cap_flags = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_cap_flags,
+	.open		= rt2x00debug_file_open,
+	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
@@ -652,6 +683,12 @@
 	if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
 		goto exit;
 
+	intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
+					      intf->driver_folder, intf,
+					      &rt2x00debug_fop_cap_flags);
+	if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
+		goto exit;
+
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
 	if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -705,7 +742,7 @@
 				intf, &rt2x00debug_fop_queue_stats);
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		intf->crypto_stats_entry =
 		    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
 					intf, &rt2x00debug_fop_crypto_stats);
@@ -743,6 +780,7 @@
 	debugfs_remove(intf->csr_off_entry);
 	debugfs_remove(intf->register_folder);
 	debugfs_remove(intf->dev_flags);
+	debugfs_remove(intf->cap_flags);
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
 	debugfs_remove(intf->driver_folder);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9bffe84..7776d9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -200,7 +200,7 @@
 	 * here as they will fetch the next beacon directly prior to
 	 * transmission.
 	 */
-	if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags))
 		return;
 
 	/* fetch next beacon */
@@ -225,7 +225,7 @@
 void rt2x00lib_dmastart(struct queue_entry *entry)
 {
 	set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-	rt2x00queue_index_inc(entry->queue, Q_INDEX);
+	rt2x00queue_index_inc(entry, Q_INDEX);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
 
@@ -233,7 +233,7 @@
 {
 	set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
 	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
 
@@ -271,7 +271,7 @@
 	/*
 	 * Remove L2 padding which was added during
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
 		rt2x00queue_remove_l2pad(entry->skb, header_length);
 
 	/*
@@ -280,7 +280,7 @@
 	 * mac80211 will expect the same data to be present it the
 	 * frame as it was passed to us.
 	 */
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		rt2x00crypto_tx_insert_iv(entry->skb, header_length);
 
 	/*
@@ -377,7 +377,7 @@
 	 * send the status report back.
 	 */
 	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
-		if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+		if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags))
 			ieee80211_tx_status(rt2x00dev->hw, entry->skb);
 		else
 			ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
@@ -392,7 +392,7 @@
 
 	rt2x00dev->ops->lib->clear_entry(entry);
 
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DONE);
 
 	/*
 	 * If the data queue was below the threshold before the txdone
@@ -559,7 +559,7 @@
 
 submit_entry:
 	entry->flags = 0;
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DONE);
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
 	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		rt2x00dev->ops->lib->clear_entry(entry);
@@ -806,15 +806,15 @@
 	/*
 	 * Take TX headroom required for alignment into account.
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
 		rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
-	else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+	else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
 		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
 
 	/*
 	 * Allocate tx status FIFO for driver use.
 	 */
-	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
 		/*
 		 * Allocate the txstatus fifo. In the worst case the tx
 		 * status fifo has to hold the tx status of all entries
@@ -1071,6 +1071,7 @@
 	/*
 	 * Stop all work.
 	 */
+	del_timer_sync(&rt2x00dev->txstatus_timer);
 	cancel_work_sync(&rt2x00dev->intf_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
 		cancel_work_sync(&rt2x00dev->rxdone_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index be0ff78..f316aad 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -99,7 +99,7 @@
 {
 	int retval;
 
-	if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
+	if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))
 		return 0;
 
 	if (!rt2x00dev->fw) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
deleted file mode 100644
index e8c0c3e..0000000
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-	<http://rt2x00.serialmonkey.com>
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the
-	Free Software Foundation, Inc.,
-	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
-	Module: rt2x00lib
-	Abstract: rt2x00 HT specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-				   struct txentry_desc *txdesc,
-				   const struct rt2x00_rate *hwrate)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-
-	if (tx_info->control.sta)
-		txdesc->u.ht.mpdu_density =
-		    tx_info->control.sta->ht_cap.ampdu_density;
-
-	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
-
-	/*
-	 * Only one STBC stream is supported for now.
-	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_STBC)
-		txdesc->u.ht.stbc = 1;
-
-	/*
-	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
-	 * mcs rate to be used
-	 */
-	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		txdesc->u.ht.mcs = txrate->idx;
-
-		/*
-		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
-		 * when using more then one tx stream (>MCS7).
-		 */
-		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
-		    ((tx_info->control.sta->ht_cap.cap &
-		      IEEE80211_HT_CAP_SM_PS) >>
-		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
-		    WLAN_HT_CAP_SM_PS_DYNAMIC)
-			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
-	} else {
-		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
-		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->u.ht.mcs |= 0x08;
-	}
-
-	/*
-	 * This frame is eligible for an AMPDU, however, don't aggregate
-	 * frames that are intended to probe a specific tx rate.
-	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
-	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
-		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
-
-	/*
-	 * Set 40Mhz mode if necessary (for legacy rates this will
-	 * duplicate the frame to both channels).
-	 */
-	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
-	    txrate->flags & IEEE80211_TX_RC_DUP_DATA)
-		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
-	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
-		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
-
-	/*
-	 * Determine IFS values
-	 * - Use TXOP_BACKOFF for management frames
-	 * - Use TXOP_SIFS for fragment bursts
-	 * - Use TXOP_HTTXOP for everything else
-	 *
-	 * Note: rt2800 devices won't use CTS protection (if used)
-	 * for frames not transmitted with TXOP_HTTXOP
-	 */
-	if (ieee80211_is_mgmt(hdr->frame_control))
-		txdesc->u.ht.txop = TXOP_BACKOFF;
-	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-		txdesc->u.ht.txop = TXOP_SIFS;
-	else
-		txdesc->u.ht.txop = TXOP_HTTXOP;
-}
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-			    struct ieee80211_conf *conf)
-{
-	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	int center_channel;
-	u16 i;
-
-	/*
-	 * Initialize center channel to current channel.
-	 */
-	center_channel = spec->channels[conf->channel->hw_value].channel;
-
-	/*
-	 * Adjust center channel to HT40+ and HT40- operation.
-	 */
-	if (conf_is_ht40_plus(conf))
-		center_channel += 2;
-	else if (conf_is_ht40_minus(conf))
-		center_channel -= (center_channel == 14) ? 1 : 2;
-
-	for (i = 0; i < spec->num_channels; i++)
-		if (spec->channels[i].channel == center_channel)
-			return i;
-
-	WARN_ON(1);
-	return conf->channel->hw_value;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 88f2f92..322cc4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -175,14 +175,14 @@
 
 /**
  * rt2x00queue_index_inc - Index incrementation function
- * @queue: Queue (&struct data_queue) to perform the action on.
+ * @entry: Queue entry (&struct queue_entry) to perform the action on.
  * @index: Index type (&enum queue_index) to perform the action on.
  *
- * This function will increase the requested index on the queue,
+ * This function will increase the requested index on the entry's queue,
  * it will grab the appropriate locks and handle queue overflow events by
  * resetting the index to the start of the queue.
  */
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);
 
 /**
  * rt2x00queue_init_queues - Initialize all data queues
@@ -388,41 +388,17 @@
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
 /*
- * HT handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_HT
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-				   struct txentry_desc *txdesc,
-				   const struct rt2x00_rate *hwrate);
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-			    struct ieee80211_conf *conf);
-#else
-static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-						 struct txentry_desc *txdesc,
-						 const struct rt2x00_rate *hwrate)
-{
-}
-
-static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-					  struct ieee80211_conf *conf)
-{
-	return conf->channel->hw_value;
-}
-#endif /* CONFIG_RT2X00_LIB_HT */
-
-/*
  * RFkill handlers.
  */
 static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
 {
-	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
 		wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
 }
 
 static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
 {
-	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
 		wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 1435976..ea10b00 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -192,17 +192,7 @@
 	/*
 	 * Determine if software diversity is enabled for
 	 * either the TX or RX antenna (or both).
-	 * Always perform this check since within the link
-	 * tuner interval the configuration might have changed.
 	 */
-	ant->flags &= ~ANTENNA_RX_DIVERSITY;
-	ant->flags &= ~ANTENNA_TX_DIVERSITY;
-
-	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-		ant->flags |= ANTENNA_RX_DIVERSITY;
-	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-		ant->flags |= ANTENNA_TX_DIVERSITY;
-
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
 	    !(ant->flags & ANTENNA_TX_DIVERSITY)) {
 		ant->flags = 0;
@@ -383,7 +373,7 @@
 	 * do not support link tuning at all, while other devices can disable
 	 * the feature from the EEPROM.
 	 */
-	if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))
 		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 661c6ba..93bec14 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -119,7 +119,7 @@
 	 * Use the ATIM queue if appropriate and present.
 	 */
 	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
-	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
+	    test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))
 		qid = QID_ATIM;
 
 	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
@@ -158,7 +158,7 @@
 	return;
 
  exit_fail:
-	ieee80211_stop_queue(rt2x00dev->hw, qid);
+	rt2x00queue_pause_queue(queue);
 	dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
@@ -411,11 +411,11 @@
 	 * of different types, but has no a separate filter for PS Poll frames,
 	 * FIF_CONTROL flag implies FIF_PSPOLL.
 	 */
-	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) {
 		if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
 			*total_flags |= FIF_CONTROL | FIF_PSPOLL;
 	}
-	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) {
 		if (*total_flags & FIF_CONTROL)
 			*total_flags |= FIF_PSPOLL;
 	}
@@ -496,7 +496,7 @@
 
 	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		return 0;
-	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		return -EOPNOTSUPP;
 	else if (key->keylen > 32)
 		return -ENOSPC;
@@ -562,7 +562,7 @@
 void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	__set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+	set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
 	rt2x00link_stop_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
@@ -570,7 +570,7 @@
 void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	__clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+	clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
 	rt2x00link_start_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
@@ -737,3 +737,84 @@
 		rt2x00queue_flush_queue(queue, drop);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_flush);
+
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct link_ant *ant = &rt2x00dev->link.ant;
+	struct antenna_setup *def = &rt2x00dev->default_ant;
+	struct antenna_setup setup;
+
+	// The antenna value is not supposed to be 0,
+	// or exceed the maximum number of antenna's.
+	if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
+		return -EINVAL;
+
+	// When the client tried to configure the antenna to or from
+	// diversity mode, we must reset the default antenna as well
+	// as that controls the diversity switch.
+	if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
+		ant->flags &= ~ANTENNA_TX_DIVERSITY;
+	if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
+		ant->flags &= ~ANTENNA_RX_DIVERSITY;
+
+	// If diversity is being enabled, check if we need hardware
+	// or software diversity. In the latter case, reset the value,
+	// and make sure we update the antenna flags to have the
+	// link tuner pick up the diversity tuning.
+	if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
+		tx_ant = ANTENNA_SW_DIVERSITY;
+		ant->flags |= ANTENNA_TX_DIVERSITY;
+	}
+
+	if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
+		rx_ant = ANTENNA_SW_DIVERSITY;
+		ant->flags |= ANTENNA_RX_DIVERSITY;
+	}
+
+	setup.tx = tx_ant;
+	setup.rx = rx_ant;
+
+	rt2x00lib_config_antenna(rt2x00dev, setup);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
+
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct link_ant *ant = &rt2x00dev->link.ant;
+	struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+	// When software diversity is active, we must report this to the
+	// client and not the current active antenna state.
+	if (ant->flags & ANTENNA_TX_DIVERSITY)
+		*tx_ant = ANTENNA_HW_DIVERSITY;
+	else
+		*tx_ant = active->tx;
+
+	if (ant->flags & ANTENNA_RX_DIVERSITY)
+		*rx_ant = ANTENNA_HW_DIVERSITY;
+	else
+		*rx_ant = active->rx;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
+
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		*tx += queue->length;
+		*tx_max += queue->limit;
+	}
+
+	*rx = rt2x00dev->rx->length;
+	*rx_max = rt2x00dev->rx->limit;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 9649bd0..17148bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -99,6 +99,15 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
 
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+	unsigned int i;
+
+	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+		msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
 /*
  * Device initialization handlers.
  */
@@ -242,9 +251,8 @@
 	return -ENOMEM;
 }
 
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 {
-	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 07961b8..e2c99f2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -107,6 +107,16 @@
  */
 bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
 
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
 /*
  * Device initialization handlers.
  */
@@ -116,7 +126,7 @@
 /*
  * PCI driver handlers.
  */
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
 void rt2x00pci_remove(struct pci_dev *pci_dev);
 #ifdef CONFIG_PM
 int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 94b8bbb..ab8c16f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -60,7 +60,7 @@
 	 * at least 8 bytes bytes available in headroom for IV/EIV
 	 * and 8 bytes for ICV data as tailroon.
 	 */
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {
 		head_size += 8;
 		tail_size += 8;
 	}
@@ -86,7 +86,7 @@
 	memset(skbdesc, 0, sizeof(*skbdesc));
 	skbdesc->entry = entry;
 
-	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
 		skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
 						  skb->data,
 						  skb->len,
@@ -213,7 +213,7 @@
 
 	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 
-	if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
+	if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
 		return;
 
 	/*
@@ -302,6 +302,85 @@
 	}
 }
 
+static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+						struct txentry_desc *txdesc,
+						const struct rt2x00_rate *hwrate)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+
+	if (tx_info->control.sta)
+		txdesc->u.ht.mpdu_density =
+		    tx_info->control.sta->ht_cap.ampdu_density;
+
+	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
+
+	/*
+	 * Only one STBC stream is supported for now.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+		txdesc->u.ht.stbc = 1;
+
+	/*
+	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
+	 * mcs rate to be used
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_MCS) {
+		txdesc->u.ht.mcs = txrate->idx;
+
+		/*
+		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
+		 * when using more then one tx stream (>MCS7).
+		 */
+		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
+		    ((tx_info->control.sta->ht_cap.cap &
+		      IEEE80211_HT_CAP_SM_PS) >>
+		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
+		    WLAN_HT_CAP_SM_PS_DYNAMIC)
+			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
+	} else {
+		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+			txdesc->u.ht.mcs |= 0x08;
+	}
+
+	/*
+	 * This frame is eligible for an AMPDU, however, don't aggregate
+	 * frames that are intended to probe a specific tx rate.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+	/*
+	 * Set 40Mhz mode if necessary (for legacy rates this will
+	 * duplicate the frame to both channels).
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+	    txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+
+	/*
+	 * Determine IFS values
+	 * - Use TXOP_BACKOFF for management frames except beacons
+	 * - Use TXOP_SIFS for fragment bursts
+	 * - Use TXOP_HTTXOP for everything else
+	 *
+	 * Note: rt2800 devices won't use CTS protection (if used)
+	 * for frames not transmitted with TXOP_HTTXOP
+	 */
+	if (ieee80211_is_mgmt(hdr->frame_control) &&
+	    !ieee80211_is_beacon(hdr->frame_control))
+		txdesc->u.ht.txop = TXOP_BACKOFF;
+	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+		txdesc->u.ht.txop = TXOP_SIFS;
+	else
+		txdesc->u.ht.txop = TXOP_HTTXOP;
+}
+
 static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 					     struct txentry_desc *txdesc)
 {
@@ -396,8 +475,8 @@
 	rt2x00crypto_create_tx_descriptor(entry, txdesc);
 	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
 
-	if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
-		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
+		rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
 	else
 		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
@@ -436,7 +515,7 @@
 	/*
 	 * Map the skb to DMA.
 	 */
-	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
 		rt2x00queue_map_txskb(entry);
 
 	return 0;
@@ -529,7 +608,7 @@
 	 */
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
 	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
-		if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
+		if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))
 			rt2x00crypto_tx_copy_iv(skb, &txdesc);
 		else
 			rt2x00crypto_tx_remove_iv(skb, &txdesc);
@@ -543,9 +622,9 @@
 	 * PCI and USB devices, while header alignment only is valid
 	 * for PCI devices.
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
 		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
-	else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
+	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
 		rt2x00queue_align_frame(entry->skb);
 
 	/*
@@ -561,7 +640,7 @@
 
 	set_bit(ENTRY_DATA_PENDING, &entry->flags);
 
-	rt2x00queue_index_inc(queue, Q_INDEX);
+	rt2x00queue_index_inc(entry, Q_INDEX);
 	rt2x00queue_write_tx_descriptor(entry, &txdesc);
 	rt2x00queue_kick_tx_queue(queue, &txdesc);
 
@@ -650,10 +729,12 @@
 	return ret;
 }
 
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				void (*fn)(struct queue_entry *entry))
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data))
 {
 	unsigned long irqflags;
 	unsigned int index_start;
@@ -664,7 +745,7 @@
 		ERROR(queue->rt2x00dev,
 		      "Entry requested from invalid index range (%d - %d)\n",
 		      start, end);
-		return;
+		return true;
 	}
 
 	/*
@@ -683,15 +764,23 @@
 	 * send out all frames in the correct order.
 	 */
 	if (index_start < index_end) {
-		for (i = index_start; i < index_end; i++)
-			fn(&queue->entries[i]);
+		for (i = index_start; i < index_end; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 	} else {
-		for (i = index_start; i < queue->limit; i++)
-			fn(&queue->entries[i]);
+		for (i = index_start; i < queue->limit; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 
-		for (i = 0; i < index_end; i++)
-			fn(&queue->entries[i]);
+		for (i = 0; i < index_end; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 	}
+
+	return false;
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
 
@@ -717,8 +806,9 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
 
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
 {
+	struct data_queue *queue = entry->queue;
 	unsigned long irqflags;
 
 	if (unlikely(index >= Q_INDEX_MAX)) {
@@ -733,7 +823,7 @@
 	if (queue->index[index] >= queue->limit)
 		queue->index[index] = 0;
 
-	queue->last_action[index] = jiffies;
+	entry->last_action = jiffies;
 
 	if (index == Q_INDEX) {
 		queue->length++;
@@ -838,7 +928,6 @@
 
 void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
 {
-	unsigned int i;
 	bool started;
 	bool tx_queue =
 		(queue->qid == QID_AC_VO) ||
@@ -873,20 +962,12 @@
 	}
 
 	/*
-	 * Check if driver supports flushing, we can only guarantee
-	 * full support for flushing if the driver is able
-	 * to cancel all pending frames (drop = true).
+	 * Check if driver supports flushing, if that is the case we can
+	 * defer the flushing to the driver. Otherwise we must use the
+	 * alternative which just waits for the queue to become empty.
 	 */
-	if (drop && queue->rt2x00dev->ops->lib->flush_queue)
-		queue->rt2x00dev->ops->lib->flush_queue(queue);
-
-	/*
-	 * When we don't want to drop any frames, or when
-	 * the driver doesn't fully flush the queue correcly,
-	 * we must wait for the queue to become empty.
-	 */
-	for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
-		msleep(10);
+	if (likely(queue->rt2x00dev->ops->lib->flush_queue))
+		queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
 
 	/*
 	 * The queue flush has failed...
@@ -959,10 +1040,8 @@
 	queue->count = 0;
 	queue->length = 0;
 
-	for (i = 0; i < Q_INDEX_MAX; i++) {
+	for (i = 0; i < Q_INDEX_MAX; i++)
 		queue->index[i] = 0;
-		queue->last_action[i] = jiffies;
-	}
 
 	spin_unlock_irqrestore(&queue->index_lock, irqflags);
 }
@@ -1069,7 +1148,7 @@
 	if (status)
 		goto exit;
 
-	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {
 		status = rt2x00queue_alloc_entries(rt2x00dev->atim,
 						   rt2x00dev->ops->atim);
 		if (status)
@@ -1121,7 +1200,7 @@
 	struct data_queue *queue;
 	enum data_queue_qid qid;
 	unsigned int req_atim =
-	    !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+	    !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
 
 	/*
 	 * We need the following queues:
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 5db6a99..167d458 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -364,6 +364,7 @@
  * struct queue_entry: Entry inside the &struct data_queue
  *
  * @flags: Entry flags, see &enum queue_entry_flags.
+ * @last_action: Timestamp of last change.
  * @queue: The data queue (&struct data_queue) to which this entry belongs.
  * @skb: The buffer which is currently being transmitted (for TX queue),
  *	or used to directly receive data in (for RX queue).
@@ -373,6 +374,7 @@
  */
 struct queue_entry {
 	unsigned long flags;
+	unsigned long last_action;
 
 	struct data_queue *queue;
 
@@ -463,7 +465,6 @@
 	unsigned short threshold;
 	unsigned short length;
 	unsigned short index[Q_INDEX_MAX];
-	unsigned long last_action[Q_INDEX_MAX];
 
 	unsigned short txop;
 	unsigned short aifs;
@@ -580,16 +581,22 @@
  * @queue: Pointer to @data_queue
  * @start: &enum queue_index Pointer to start index
  * @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
  * @fn: The function to call for each &struct queue_entry
  *
  * This will walk through all entries in the queue, in chronological
  * order. This means it will start at the current @start pointer
  * and will walk through the queue until it reaches the @end pointer.
+ *
+ * If fn returns true for an entry rt2x00queue_for_each_entry will stop
+ * processing and return true as well.
  */
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				void (*fn)(struct queue_entry *entry));
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data));
 
 /**
  * rt2x00queue_empty - Check if the queue is empty.
@@ -629,22 +636,24 @@
 
 /**
  * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports
- * @queue: Queue to check.
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_status_timeout(struct data_queue *queue)
+static inline int rt2x00queue_status_timeout(struct queue_entry *entry)
 {
-	return time_after(queue->last_action[Q_INDEX_DMA_DONE],
-			  queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+		return false;
+	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occurred for DMA transfers
- * @queue: Queue to check.
+ * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
 {
-	return time_after(queue->last_action[Q_INDEX],
-			  queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
+	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+		return false;
+	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 36f388f..cb208d5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -165,6 +165,56 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
 
+
+struct rt2x00_async_read_data {
+	__le32 reg;
+	struct usb_ctrlrequest cr;
+	struct rt2x00_dev *rt2x00dev;
+	void (*callback)(struct rt2x00_dev *,int,u32);
+};
+
+static void rt2x00usb_register_read_async_cb(struct urb *urb)
+{
+	struct rt2x00_async_read_data *rd = urb->context;
+	rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg));
+	kfree(urb->context);
+}
+
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+				   const unsigned int offset,
+				   void (*callback)(struct rt2x00_dev*,int,u32))
+{
+	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+	struct urb *urb;
+	struct rt2x00_async_read_data *rd;
+
+	rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+	if (!rd)
+		return;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(rd);
+		return;
+	}
+
+	rd->rt2x00dev = rt2x00dev;
+	rd->callback = callback;
+	rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
+	rd->cr.bRequest = USB_MULTI_READ;
+	rd->cr.wValue = 0;
+	rd->cr.wIndex = cpu_to_le16(offset);
+	rd->cr.wLength = cpu_to_le16(sizeof(u32));
+
+	usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			     (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
+			     rt2x00usb_register_read_async_cb, rd);
+	if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+		kfree(rd);
+	usb_free_urb(urb);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
+
 /*
  * TX data handlers.
  */
@@ -212,6 +262,9 @@
 	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
 		return;
 
+	if (rt2x00dev->ops->lib->tx_dma_done)
+		rt2x00dev->ops->lib->tx_dma_done(entry);
+
 	/*
 	 * Report the frame as DMA done
 	 */
@@ -227,10 +280,12 @@
 	 * Schedule the delayed work for reading the TX status
 	 * from the device.
 	 */
-	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
+	    !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
-static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -240,7 +295,7 @@
 
 	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return;
+		return true;
 
 	/*
 	 * USB devices cannot blindly pass the skb->len as the
@@ -261,6 +316,8 @@
 		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 		rt2x00lib_dmadone(entry);
 	}
+
+	return false;
 }
 
 /*
@@ -323,7 +380,7 @@
 	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
-static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -332,7 +389,7 @@
 
 	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return;
+		return true;
 
 	rt2x00lib_dmastart(entry);
 
@@ -348,6 +405,8 @@
 		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 		rt2x00lib_dmadone(entry);
 	}
+
+	return false;
 }
 
 void rt2x00usb_kick_queue(struct data_queue *queue)
@@ -358,12 +417,18 @@
 	case QID_AC_BE:
 	case QID_AC_BK:
 		if (!rt2x00queue_empty(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX_DONE,
+						   Q_INDEX,
+						   NULL,
 						   rt2x00usb_kick_tx_entry);
 		break;
 	case QID_RX:
 		if (!rt2x00queue_full(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX_DONE,
+						   Q_INDEX,
+						   NULL,
 						   rt2x00usb_kick_rx_entry);
 		break;
 	default:
@@ -372,14 +437,14 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
 
-static void rt2x00usb_flush_entry(struct queue_entry *entry)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
 
 	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-		return;
+		return true;
 
 	usb_kill_urb(entry_priv->urb);
 
@@ -387,17 +452,20 @@
 	 * Kill guardian urb (if required by driver).
 	 */
 	if ((entry->queue->qid == QID_BEACON) &&
-	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+	    (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
 		usb_kill_urb(bcn_priv->guardian_urb);
+
+	return false;
 }
 
-void rt2x00usb_flush_queue(struct data_queue *queue)
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
 {
 	struct work_struct *completion;
 	unsigned int i;
 
-	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
-				   rt2x00usb_flush_entry);
+	if (drop)
+		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+					   rt2x00usb_flush_entry);
 
 	/*
 	 * Obtain the queue completion handler
@@ -416,7 +484,7 @@
 		return;
 	}
 
-	for (i = 0; i < 20; i++) {
+	for (i = 0; i < 10; i++) {
 		/*
 		 * Check if the driver is already done, otherwise we
 		 * have to sleep a little while to give the driver/hw
@@ -456,15 +524,31 @@
 	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
 }
 
+static int rt2x00usb_status_timeout(struct data_queue *queue)
+{
+	struct queue_entry *entry;
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+	return rt2x00queue_status_timeout(entry);
+}
+
+static int rt2x00usb_dma_timeout(struct data_queue *queue)
+{
+	struct queue_entry *entry;
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+	return rt2x00queue_dma_timeout(entry);
+}
+
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_queue *queue;
 
 	tx_queue_for_each(rt2x00dev, queue) {
 		if (!rt2x00queue_empty(queue)) {
-			if (rt2x00queue_dma_timeout(queue))
+			if (rt2x00usb_dma_timeout(queue))
 				rt2x00usb_watchdog_tx_dma(queue);
-			if (rt2x00queue_status_timeout(queue))
+			if (rt2x00usb_status_timeout(queue))
 				rt2x00usb_watchdog_tx_status(queue);
 		}
 	}
@@ -489,7 +573,7 @@
 	entry->flags = 0;
 
 	if (entry->queue->qid == QID_RX)
-		rt2x00usb_kick_rx_entry(entry);
+		rt2x00usb_kick_rx_entry(entry, NULL);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
 
@@ -583,7 +667,7 @@
 	 * then we are done.
 	 */
 	if (queue->qid != QID_BEACON ||
-	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
 		return 0;
 
 	for (i = 0; i < queue->limit; i++) {
@@ -618,7 +702,7 @@
 	 * then we are done.
 	 */
 	if (queue->qid != QID_BEACON ||
-	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
 		return;
 
 	for (i = 0; i < queue->limit; i++) {
@@ -707,10 +791,9 @@
 }
 
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-		    const struct usb_device_id *id)
+		    const struct rt2x00_ops *ops)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
-	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
@@ -735,6 +818,7 @@
 
 	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+	init_timer(&rt2x00dev->txstatus_timer);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index e11c759..64be34f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -35,12 +35,6 @@
 })
 
 /*
- * This variable should be used with the
- * usb_driver structure initialization.
- */
-#define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops)
-
-/*
  * For USB vendor requests we need to pass a timeout
  * time in ms, for this we use the REGISTER_TIMEOUT,
  * however when loading firmware a higher value is
@@ -345,6 +339,21 @@
 			   const struct rt2x00_field32 field,
 			   u32 *reg);
 
+/**
+ * rt2x00usb_register_read_async - Asynchronously read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @callback: Functon to call when read completes.
+ *
+ * Submit a control URB to read a 32bit register. This safe to
+ * be called from atomic context.  The callback will be called
+ * when the URB completes. Otherwise the function is similar
+ * to rt2x00usb_register_read().
+ */
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+				   const unsigned int offset,
+				   void (*callback)(struct rt2x00_dev*,int,u32));
+
 /*
  * Radio handlers
  */
@@ -389,11 +398,13 @@
 /**
  * rt2x00usb_flush_queue - Flush data queue
  * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
  *
- * This will walk through all entries of the queue and kill all
- * URB's which were send to the device.
+ * This will walk through all entries of the queue and will optionally
+ * kill all URB's which were send to the device, or at least wait until
+ * they have been returned from the device..
  */
-void rt2x00usb_flush_queue(struct data_queue *queue);
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
 
 /**
  * rt2x00usb_watchdog - Watchdog for USB communication
@@ -416,7 +427,7 @@
  * USB driver handlers.
  */
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-		    const struct usb_device_id *id);
+		    const struct rt2x00_ops *ops);
 void rt2x00usb_disconnect(struct usb_interface *usb_intf);
 #ifdef CONFIG_PM
 int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 8ee1514..9d35ec1 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -683,7 +683,7 @@
 
 	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
 	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
 	/*
 	 * Configure the RX antenna.
@@ -811,10 +811,10 @@
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	} else {
 		sel = antenna_sel_bg;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -834,7 +834,7 @@
 	else if (rt2x00_rf(rt2x00dev, RF2527))
 		rt61pci_config_antenna_2x(rt2x00dev, ant);
 	else if (rt2x00_rf(rt2x00dev, RF2529)) {
-		if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags))
 			rt61pci_config_antenna_2x(rt2x00dev, ant);
 		else
 			rt61pci_config_antenna_2529(rt2x00dev, ant);
@@ -848,13 +848,13 @@
 	short lna_gain = 0;
 
 	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_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 {
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			lna_gain += 14;
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
@@ -1050,14 +1050,14 @@
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
 	} else {
 		low_bound = 0x20;
 		up_bound = 0x40;
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
@@ -2260,8 +2260,8 @@
 	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				     struct rt2x00_field32 irq_field)
+static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					    struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
@@ -2537,7 +2537,7 @@
 	 * Determine number of antennas.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
-		__set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);
 
 	/*
 	 * Identify default antenna configuration.
@@ -2551,20 +2551,20 @@
 	 * Read the Frame type.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has a hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read frequency offset and RF programming sequence.
 	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
 	if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
-		__set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
 
 	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
@@ -2574,9 +2574,9 @@
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
 	/*
 	 * When working with a RF2529 chip without double antenna,
@@ -2584,7 +2584,7 @@
 	 * eeprom word.
 	 */
 	if (rt2x00_rf(rt2x00dev, RF2529) &&
-	    !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+	    !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) {
 		rt2x00dev->default_ant.rx =
 		    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
 		rt2x00dev->default_ant.tx =
@@ -2799,7 +2799,7 @@
 	spec->supported_bands = SUPPORT_BAND_2GHZ;
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
-	if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals_noseq;
 	} else {
@@ -2869,16 +2869,16 @@
 	 * 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);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware and DMA mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -2979,6 +2979,9 @@
 	.get_tsf		= rt61pci_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -3003,6 +3006,7 @@
 	.start_queue		= rt61pci_start_queue,
 	.kick_queue		= rt61pci_kick_queue,
 	.stop_queue		= rt61pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt61pci_write_tx_desc,
 	.write_beacon		= rt61pci_write_beacon,
 	.clear_beacon		= rt61pci_clear_beacon,
@@ -3060,11 +3064,11 @@
  */
 static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
 	/* RT2561s */
-	{ PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0301) },
 	/* RT2561 v2 */
-	{ PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0302) },
 	/* RT2661 */
-	{ PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0401) },
 	{ 0, }
 };
 
@@ -3079,10 +3083,16 @@
 MODULE_FIRMWARE(FIRMWARE_RT2661);
 MODULE_LICENSE("GPL");
 
+static int rt61pci_probe(struct pci_dev *pci_dev,
+			 const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
 static struct pci_driver rt61pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt61pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt61pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 6593059..a6ce7d6 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -595,7 +595,7 @@
 	switch (ant->rx) {
 	case ANTENNA_HW_DIVERSITY:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+		temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)
 		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
 		break;
@@ -636,7 +636,7 @@
 
 	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
 	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
 	/*
 	 * Configure the RX antenna.
@@ -709,10 +709,10 @@
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	} else {
 		sel = antenna_sel_bg;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -740,7 +740,7 @@
 	short lna_gain = 0;
 
 	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
 			lna_gain += 14;
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
@@ -930,7 +930,7 @@
 		low_bound = 0x28;
 		up_bound = 0x48;
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
@@ -946,7 +946,7 @@
 			up_bound = 0x1c;
 		}
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
 			low_bound += 0x14;
 			up_bound += 0x10;
 		}
@@ -1661,7 +1661,7 @@
 	}
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			if (lna == 3 || lna == 2)
 				offset += 10;
 		} else {
@@ -1899,13 +1899,13 @@
 	 * Read the Frame type.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read frequency offset.
@@ -1919,8 +1919,8 @@
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	/*
@@ -2200,15 +2200,15 @@
 	 * 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);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -2310,6 +2310,9 @@
 	.get_tsf		= rt73usb_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2388,113 +2391,113 @@
  */
 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) },
+	{ USB_DEVICE(0x07b8, 0xb21b) },
+	{ USB_DEVICE(0x07b8, 0xb21c) },
+	{ USB_DEVICE(0x07b8, 0xb21d) },
+	{ USB_DEVICE(0x07b8, 0xb21e) },
+	{ USB_DEVICE(0x07b8, 0xb21f) },
 	/* AL */
-	{ USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c10) },
 	/* Amigo */
-	{ USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x148f, 0x9021) },
+	{ USB_DEVICE(0x0eb0, 0x9021) },
 	/* AMIT  */
-	{ USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x18c5, 0x0002) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0722) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1723) },
+	{ USB_DEVICE(0x0b05, 0x1724) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x050d, 0x705a) },
+	{ USB_DEVICE(0x050d, 0x905b) },
+	{ USB_DEVICE(0x050d, 0x905c) },
 	/* Billionton */
-	{ USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1631, 0xc019) },
+	{ USB_DEVICE(0x08dd, 0x0120) },
 	/* 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) },
-	{ USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0411, 0x00d8) },
+	{ USB_DEVICE(0x0411, 0x00d9) },
+	{ USB_DEVICE(0x0411, 0x00f4) },
+	{ USB_DEVICE(0x0411, 0x0116) },
+	{ USB_DEVICE(0x0411, 0x0119) },
+	{ USB_DEVICE(0x0411, 0x0137) },
 	/* CEIVA */
-	{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x178d, 0x02be) },
 	/* CNet */
-	{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1371, 0x9022) },
+	{ USB_DEVICE(0x1371, 0x9032) },
 	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c22) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x002e) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ 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) },
+	{ USB_DEVICE(0x07d1, 0x3c03) },
+	{ USB_DEVICE(0x07d1, 0x3c04) },
+	{ USB_DEVICE(0x07d1, 0x3c06) },
+	{ USB_DEVICE(0x07d1, 0x3c07) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7318) },
+	{ USB_DEVICE(0x7392, 0x7618) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1740, 0x3701) },
 	/* Gemtek */
-	{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0004) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1044, 0x8008) },
+	{ USB_DEVICE(0x1044, 0x800a) },
 	/* Huawei-3Com */
-	{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1472, 0x0009) },
 	/* 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) },
+	{ USB_DEVICE(0x06f8, 0xe002) },
+	{ USB_DEVICE(0x06f8, 0xe010) },
+	{ USB_DEVICE(0x06f8, 0xe020) },
 	/* 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) },
+	{ USB_DEVICE(0x13b1, 0x0020) },
+	{ USB_DEVICE(0x13b1, 0x0023) },
+	{ USB_DEVICE(0x13b1, 0x0028) },
 	/* 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) },
+	{ USB_DEVICE(0x0db0, 0x4600) },
+	{ USB_DEVICE(0x0db0, 0x6877) },
+	{ USB_DEVICE(0x0db0, 0x6874) },
+	{ USB_DEVICE(0x0db0, 0xa861) },
+	{ USB_DEVICE(0x0db0, 0xa874) },
 	/* Ovislink */
-	{ USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1b75, 0x7318) },
 	/* 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) },
-	{ USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x093d) },
+	{ USB_DEVICE(0x148f, 0x2573) },
+	{ USB_DEVICE(0x148f, 0x2671) },
+	{ USB_DEVICE(0x0812, 0x3101) },
 	/* 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) },
+	{ USB_DEVICE(0x18e8, 0x6196) },
+	{ USB_DEVICE(0x18e8, 0x6229) },
+	{ USB_DEVICE(0x18e8, 0x6238) },
 	/* Samsung */
-	{ USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x04e8, 0x4471) },
 	/* Senao */
-	{ USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1740, 0x7100) },
 	/* Sitecom */
-	{ 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) },
+	{ USB_DEVICE(0x0df6, 0x0024) },
+	{ USB_DEVICE(0x0df6, 0x0027) },
+	{ USB_DEVICE(0x0df6, 0x002f) },
+	{ USB_DEVICE(0x0df6, 0x90ac) },
+	{ USB_DEVICE(0x0df6, 0x9712) },
 	/* Surecom */
-	{ USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0769, 0x31f3) },
 	/* Tilgin */
-	{ USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x6933, 0x5001) },
 	/* Philips */
-	{ USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0471, 0x200a) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab01) },
+	{ USB_DEVICE(0x2019, 0xab50) },
 	/* WideTell */
-	{ USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x7167, 0x3840) },
 	/* Zcom */
-	{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0cde, 0x001c) },
 	/* ZyXEL */
-	{ USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0586, 0x3415) },
 	{ 0, }
 };
 
@@ -2506,10 +2509,16 @@
 MODULE_FIRMWARE(FIRMWARE_RT2571);
 MODULE_LICENSE("GPL");
 
+static int rt73usb_probe(struct usb_interface *usb_intf,
+			 const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
 static struct usb_driver rt73usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt73usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt73usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,