summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig26
-rw-r--r--drivers/net/wireless/rt2x00/Makefile1
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c35
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c34
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c90
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h106
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c333
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c263
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c622
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h104
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c77
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c43
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c51
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00ht.c133
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h57
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c61
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c95
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c19
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c177
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h34
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c126
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h31
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c70
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c191
28 files changed, 1755 insertions, 1048 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index f630552427b7..c45773108283 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -59,7 +59,6 @@ config RT2800PCI
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 @@ config RT2800PCI
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_RT35XX
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 @@ config RT2800USB
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 @@ config RT2800USB
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_USB
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 971339858297..349d5b8284a4 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
-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 329f3283697b..937f9e8bf05f 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}
-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;
@@ -1368,8 +1368,10 @@ static void rt2400pci_tbtt_tasklet(unsigned long data)
static void rt2400pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2x00pci_rxdone(rt2x00dev);
- rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
+ if (rt2x00pci_rxdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else
+ rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
@@ -1534,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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;
}
@@ -1638,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* 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.
@@ -1718,6 +1720,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.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 = {
@@ -1738,6 +1743,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.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,
@@ -1799,10 +1805,11 @@ static const struct rt2x00_ops rt2400pci_ops = {
* 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.");
@@ -1810,10 +1817,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
MODULE_LICENSE("GPL");
+static int rt2400pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
static struct pci_driver rt2400pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2400pci_device_table,
- .probe = 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 58277878889e..d27d7b8ba3b6 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}
-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;
@@ -1500,8 +1500,10 @@ static void rt2500pci_tbtt_tasklet(unsigned long data)
static void rt2500pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2x00pci_rxdone(rt2x00dev);
- rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
+ if (rt2x00pci_rxdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else
+ rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
}
static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
@@ -1685,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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.
@@ -1956,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* 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.
@@ -2011,6 +2013,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.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 = {
@@ -2031,6 +2036,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.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,
@@ -2092,7 +2098,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
* 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, }
};
@@ -2103,10 +2109,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
MODULE_LICENSE("GPL");
+static int rt2500pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
static struct pci_driver rt2500pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2500pci_device_table,
- .probe = 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 979fe6596a2d..b21f81231a09 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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,14 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* 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_SUPPORT_WATCHDOG, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+ __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
/*
* Set the rssi offset.
@@ -1824,6 +1823,9 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.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 = {
@@ -1905,58 +1907,54 @@ static const struct rt2x00_ops rt2500usb_ops = {
*/
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, 0x705a), 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) },
- /* CNet */
- { USB_DEVICE(0x1371, 0x9022), 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, 0x2573), 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, }
};
@@ -1967,10 +1965,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
MODULE_LICENSE("GPL");
+static int rt2500usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
static struct usb_driver rt2500usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2500usb_device_table,
- .probe = rt2x00usb_probe,
+ .probe = rt2500usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 8fbc5fa965e0..ce2010952886 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2104,6 +2104,59 @@ struct mac_iveiv_entry {
#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00)
/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -4)
+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -3)
+ */
+#define EEPROM_TSSI_BOUND_BG1 0x0037
+#define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -2)
+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -1)
+ */
+#define EEPROM_TSSI_BOUND_BG2 0x0038
+#define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * REF: Reference TSSI value, no tx power changes needed
+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 1)
+ */
+#define EEPROM_TSSI_BOUND_BG3 0x0039
+#define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 2)
+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 3)
+ */
+#define EEPROM_TSSI_BOUND_BG4 0x003a
+#define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11BG
+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 4)
+ * AGC_STEP: Temperature compensation step.
+ */
+#define EEPROM_TSSI_BOUND_BG5 0x003b
+#define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00)
+
+/*
* EEPROM TXPOWER 802.11A
*/
#define EEPROM_TXPOWER_A1 0x003c
@@ -2113,6 +2166,59 @@ struct mac_iveiv_entry {
#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * MINUS4: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -4)
+ * MINUS3: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -3)
+ */
+#define EEPROM_TSSI_BOUND_A1 0x006a
+#define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * MINUS2: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -2)
+ * MINUS1: If the actual TSSI is below this boundary, tx power needs to be
+ * reduced by (agc_step * -1)
+ */
+#define EEPROM_TSSI_BOUND_A2 0x006b
+#define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * REF: Reference TSSI value, no tx power changes needed
+ * PLUS1: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 1)
+ */
+#define EEPROM_TSSI_BOUND_A3 0x006c
+#define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * PLUS2: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 2)
+ * PLUS3: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 3)
+ */
+#define EEPROM_TSSI_BOUND_A4 0x006d
+#define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00)
+
+/*
+ * EEPROM temperature compensation boundaries 802.11A
+ * PLUS4: If the actual TSSI is above this boundary, tx power needs to be
+ * increased by (agc_step * 4)
+ * AGC_STEP: Temperature compensation step.
+ */
+#define EEPROM_TSSI_BOUND_A5 0x006e
+#define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff)
+#define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00)
+
+/*
* EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode
*/
#define EEPROM_TXPOWER_BYRATE 0x006f
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index dbf74d07d947..5cd096e2ae36 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -687,6 +687,9 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
mcs = real_mcs;
}
+ if (aggr == 1 || ampdu == 1)
+ __set_bit(TXDONE_AMPDU, &txdesc.flags);
+
/*
* Ralink has a retry mechanism using a global fallback
* table. We setup this fallback table to try the immediate
@@ -727,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
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)
- continue;
-
- queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
- if (unlikely(!queue))
+ 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;
+ }
/*
* Inside each queue, we process each entry in a chronological
@@ -946,25 +935,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
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);
+ }
}
}
@@ -1218,6 +1231,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
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) {
@@ -1736,8 +1768,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
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 {
@@ -1748,7 +1780,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
} 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);
@@ -1813,17 +1845,131 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
}
+static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
+{
+ u8 tssi_bounds[9];
+ u8 current_tssi;
+ u16 eeprom;
+ u8 step;
+ int i;
+
+ /*
+ * Read TSSI boundaries for temperature compensation from
+ * the EEPROM.
+ *
+ * Array idx 0 1 2 3 4 5 6 7 8
+ * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4
+ * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00
+ */
+ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom);
+ tssi_bounds[0] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG1_MINUS4);
+ tssi_bounds[1] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG1_MINUS3);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom);
+ tssi_bounds[2] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG2_MINUS2);
+ tssi_bounds[3] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG2_MINUS1);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom);
+ tssi_bounds[4] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG3_REF);
+ tssi_bounds[5] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG3_PLUS1);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom);
+ tssi_bounds[6] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG4_PLUS2);
+ tssi_bounds[7] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG4_PLUS3);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom);
+ tssi_bounds[8] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG5_PLUS4);
+
+ step = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_BG5_AGC_STEP);
+ } else {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom);
+ tssi_bounds[0] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A1_MINUS4);
+ tssi_bounds[1] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A1_MINUS3);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom);
+ tssi_bounds[2] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A2_MINUS2);
+ tssi_bounds[3] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A2_MINUS1);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom);
+ tssi_bounds[4] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A3_REF);
+ tssi_bounds[5] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A3_PLUS1);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom);
+ tssi_bounds[6] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A4_PLUS2);
+ tssi_bounds[7] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A4_PLUS3);
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom);
+ tssi_bounds[8] = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A5_PLUS4);
+
+ step = rt2x00_get_field16(eeprom,
+ EEPROM_TSSI_BOUND_A5_AGC_STEP);
+ }
+
+ /*
+ * Check if temperature compensation is supported.
+ */
+ if (tssi_bounds[4] == 0xff)
+ return 0;
+
+ /*
+ * Read current TSSI (BBP 49).
+ */
+ rt2800_bbp_read(rt2x00dev, 49, &current_tssi);
+
+ /*
+ * Compare TSSI value (BBP49) with the compensation boundaries
+ * from the EEPROM and increase or decrease tx power.
+ */
+ for (i = 0; i <= 3; i++) {
+ if (current_tssi > tssi_bounds[i])
+ break;
+ }
+
+ if (i == 4) {
+ for (i = 8; i >= 5; i--) {
+ if (current_tssi < tssi_bounds[i])
+ break;
+ }
+ }
+
+ return (i - 4) * step;
+}
+
static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
enum ieee80211_band band)
{
u16 eeprom;
u8 comp_en;
u8 comp_type;
- int comp_value;
+ int comp_value = 0;
rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
- if (eeprom == 0xffff)
+ /*
+ * HT40 compensation not required.
+ */
+ if (eeprom == 0xffff ||
+ !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
return 0;
if (band == IEEE80211_BAND_2GHZ) {
@@ -1853,11 +1999,9 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
return comp_value;
}
-static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev,
- int is_rate_b,
- enum ieee80211_band band,
- int power_level,
- u8 txpower)
+static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
+ enum ieee80211_band band, int power_level,
+ u8 txpower, int delta)
{
u32 reg;
u16 eeprom;
@@ -1865,15 +2009,11 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev,
u8 eirp_txpower;
u8 eirp_txpower_criterion;
u8 reg_limit;
- int bw_comp = 0;
if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
return txpower;
- if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
- bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band);
-
- 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
@@ -1895,18 +2035,19 @@ static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev,
EEPROM_EIRP_MAX_TX_POWER_5GHZ);
eirp_txpower = eirp_txpower_criterion + (txpower - criterion) +
- (is_rate_b ? 4 : 0) + bw_comp;
+ (is_rate_b ? 4 : 0) + delta;
reg_limit = (eirp_txpower > power_level) ?
(eirp_txpower - power_level) : 0;
} else
reg_limit = 0;
- return txpower + bw_comp - reg_limit;
+ return txpower + delta - reg_limit;
}
static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf)
+ enum ieee80211_band band,
+ int power_level)
{
u8 txpower;
u16 eeprom;
@@ -1914,8 +2055,17 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
u32 reg;
u8 r1;
u32 offset;
- enum ieee80211_band band = conf->channel->band;
- int power_level = conf->power_level;
+ int delta;
+
+ /*
+ * Calculate HT40 compensation delta
+ */
+ delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
+
+ /*
+ * calculate temperature compensation delta
+ */
+ delta += rt2800_get_gain_calibration_delta(rt2x00dev);
/*
* set to normal bbp tx power control mode: +/- 0dBm
@@ -1944,8 +2094,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE0);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
/*
@@ -1955,8 +2105,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE1);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
/*
@@ -1966,8 +2116,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE2);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
/*
@@ -1977,8 +2127,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE3);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
/* read the next four txpower values */
@@ -1993,8 +2143,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE0);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
/*
@@ -2004,8 +2154,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE1);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
/*
@@ -2015,8 +2165,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE2);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
/*
@@ -2026,8 +2176,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
*/
txpower = rt2x00_get_field16(eeprom,
EEPROM_TXPOWER_BYRATE_RATE3);
- txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
- power_level, txpower);
+ txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band,
+ power_level, txpower, delta);
rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
rt2800_register_write(rt2x00dev, offset, reg);
@@ -2037,6 +2187,13 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
}
}
+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
+{
+ rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
+ rt2x00dev->tx_power);
+}
+EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
+
static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
{
@@ -2090,10 +2247,12 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
rt2800_config_channel(rt2x00dev, libconf->conf,
&libconf->rf, &libconf->channel);
- rt2800_config_txpower(rt2x00dev, libconf->conf);
+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+ libconf->conf->power_level);
}
if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800_config_txpower(rt2x00dev, libconf->conf);
+ rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
+ libconf->conf->power_level);
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
rt2800_config_retry_limit(rt2x00dev, libconf);
if (flags & IEEE80211_CONF_CHANGE_PS)
@@ -2254,7 +2413,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
} 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);
@@ -3155,8 +3314,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
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);
@@ -3579,15 +3738,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
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.
@@ -3607,7 +3766,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
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/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 0c92d86a36f4..f2d15941c71a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -181,6 +181,7 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
const u32 count);
+void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 808073aa9dcc..08d3947fcb26 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
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 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
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 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
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 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
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 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
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 @@ static void rt2800pci_start_queue(struct data_queue *queue)
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 @@ static void rt2800pci_start_queue(struct data_queue *queue)
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 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
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 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
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 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
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 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
* 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 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
* 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 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* 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 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
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 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
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 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* 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 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
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 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
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 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
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);
}
@@ -717,12 +727,13 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}
-static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
+static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
struct queue_entry *entry;
u32 status;
u8 qid;
+ int max_tx_done = 16;
while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
@@ -759,11 +770,16 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
rt2800_txdone_entry(entry, status);
+
+ if (--max_tx_done == 0)
+ break;
}
+
+ 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;
@@ -772,15 +788,17 @@ static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
* 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);
}
static void rt2800pci_txstatus_tasklet(unsigned long data)
{
- rt2800pci_txdone((struct rt2x00_dev *)data);
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+ if (rt2800pci_txdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
/*
* No need to enable the tx status interrupt here as we always
@@ -806,8 +824,10 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
static void rt2800pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2x00pci_rxdone(rt2x00dev);
- rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+ if (rt2x00pci_rxdone(rt2x00dev))
+ tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+ else
+ rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
}
static void rt2800pci_autowake_tasklet(unsigned long data)
@@ -841,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* 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;
@@ -863,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
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;
@@ -904,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
* 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;
@@ -956,28 +976,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* 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.
@@ -1008,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.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 = {
@@ -1043,9 +1064,11 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.link_stats = rt2800_link_stats,
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
+ .gain_calibration = rt2800_gain_calibration,
.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,
@@ -1105,36 +1128,36 @@ static const struct rt2x00_ops rt2800pci_ops = {
*/
#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, }
};
@@ -1170,10 +1193,16 @@ static struct platform_driver rt2800soc_driver = {
#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 37509d019910..0d4e8fa3e1f8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue)
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 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
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 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
}
/*
+ * 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 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
/*
* 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 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
}
msleep(10);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
return 0;
}
@@ -166,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
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 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
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 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
/ 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 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
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 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
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 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
break;
}
- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
}
rt2x00usb_watchdog(rt2x00dev);
@@ -420,13 +476,24 @@ static void rt2800usb_work_txdone(struct work_struct *work)
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;
+ 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;
-
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
}
}
+
+ /*
+ * 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,19 +620,23 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* 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_SUPPORT_WATCHDOG, &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.
@@ -602,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.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 = {
@@ -630,11 +702,13 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.link_stats = rt2800_link_stats,
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
+ .gain_calibration = rt2800_gain_calibration,
.watchdog = rt2800usb_watchdog,
.start_queue = rt2800usb_start_queue,
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt2800usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
+ .tx_dma_done = rt2800usb_tx_dma_done,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2800usb_write_tx_data,
.write_beacon = rt2800_write_beacon,
@@ -695,294 +769,332 @@ static const struct rt2x00_ops rt2800usb_ops = {
*/
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, 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, }
};
@@ -995,10 +1107,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2870);
MODULE_LICENSE("GPL");
+static int rt2800usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
static struct usb_driver rt2800usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2800usb_device_table,
- .probe = 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 7f10239f56a8..9d1a158e2c33 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>
@@ -348,6 +349,11 @@ struct link {
* to bring the device/driver back into the desired state.
*/
struct delayed_work watchdog_work;
+
+ /*
+ * Work structure for scheduling periodic AGC adjustments.
+ */
+ struct delayed_work agc_work;
};
enum rt2x00_delayed_flags {
@@ -556,6 +562,7 @@ struct rt2x00lib_ops {
struct link_qual *qual);
void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
struct link_qual *qual, const u32 count);
+ void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
/*
* Data queue handlers.
@@ -564,7 +571,8 @@ struct rt2x00lib_ops {
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
@@ -637,11 +645,11 @@ struct rt2x00_ops {
};
/*
- * 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,
@@ -651,43 +659,47 @@ enum rt2x00_flags {
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_SUPPORT_WATCHDOG,
-
- /*
* 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 {
@@ -733,13 +745,20 @@ struct rt2x00_dev {
#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;
@@ -906,6 +925,11 @@ struct rt2x00_dev {
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;
@@ -1230,6 +1254,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
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 9416e36de29e..f78726404592 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
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 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
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 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
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 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
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 3f5688fbf3f7..1bb9d46077ff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
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 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
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 c92db3264741..78787fcc919e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -63,7 +63,8 @@ struct rt2x00debug_intf {
* - 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 rt2x00debug_intf {
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 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
.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,
@@ -568,7 +599,6 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
blob->data = data;
data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);
data += sprintf(data, "version:\t%s\n", DRV_VERSION);
- data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__);
blob->size = strlen(blob->data);
return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
@@ -653,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
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)
@@ -706,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
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);
@@ -744,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
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 84eb6ad36377..7776d9f1f297 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/log2.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
@@ -70,6 +71,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
rt2x00queue_start_queues(rt2x00dev);
rt2x00link_start_tuner(rt2x00dev);
+ rt2x00link_start_agc(rt2x00dev);
/*
* Start watchdog monitoring.
@@ -92,6 +94,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Stop all queues
*/
+ rt2x00link_stop_agc(rt2x00dev);
rt2x00link_stop_tuner(rt2x00dev);
rt2x00queue_stop_queues(rt2x00dev);
rt2x00queue_flush_queues(rt2x00dev, true);
@@ -197,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
* 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 */
@@ -222,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
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);
@@ -230,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry)
{
set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+ rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
}
EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
@@ -268,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
/*
* 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);
/*
@@ -277,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* 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);
/*
@@ -350,10 +353,14 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* which would allow the rc algorithm to better decide on
* which rates are suitable.
*/
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+ if (test_bit(TXDONE_AMPDU, &txdesc->flags) ||
+ tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
+
+ if (!success)
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
}
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
@@ -370,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* 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);
@@ -385,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
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
@@ -511,8 +518,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
(rxdesc.size > header_length) &&
(rxdesc.dev_flags & RXDONE_L2PAD))
rt2x00queue_remove_l2pad(entry->skb, header_length);
- else
- rt2x00queue_align_payload(entry->skb, header_length);
/* Trim buffer to correct size */
skb_trim(entry->skb, rxdesc.size);
@@ -554,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
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);
@@ -801,23 +806,28 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* 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 txstatus fifo and tasklet, we use a size of 512
- * for the kfifo which is big enough to store 512/4=128 tx
- * status reports. In the worst case (tx status for all tx
- * queues gets reported before we've got a chance to handle
- * them) 24*4=384 tx status reports need to be cached.
+ * Allocate the txstatus fifo. In the worst case the tx
+ * status fifo has to hold the tx status of all entries
+ * in all tx queues. Hence, calculate the kfifo size as
+ * tx_queues * entry_num and round up to the nearest
+ * power of 2.
*/
- status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512,
+ int kfifo_size =
+ roundup_pow_of_two(rt2x00dev->ops->tx_queues *
+ rt2x00dev->ops->tx->entry_num *
+ sizeof(u32));
+
+ status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size,
GFP_KERNEL);
if (status)
return status;
@@ -1061,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
/*
* 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 be0ff78c1b16..f316aad30612 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
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 ae1219dffaae..000000000000
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ /dev/null
@@ -1,133 +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? */
-
- txdesc->u.ht.stbc =
- (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT;
-
- /*
- * 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 2d94cbaf5f4a..322cc4f3de5d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -32,6 +32,7 @@
*/
#define WATCHDOG_INTERVAL round_jiffies_relative(HZ)
#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)
+#define AGC_INTERVAL round_jiffies_relative(4 * HZ)
/*
* rt2x00_rate: Per rate device information
@@ -119,16 +120,6 @@ void rt2x00queue_free_skb(struct queue_entry *entry);
void rt2x00queue_align_frame(struct sk_buff *skb);
/**
- * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary
- * @skb: The skb to align
- * @header_length: Length of 802.11 header
- *
- * Align the 802.11 payload to a 4-byte boundary, this could
- * mean the header is not aligned properly though.
- */
-void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length);
-
-/**
* rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary
* @skb: The skb to align
* @header_length: Length of 802.11 header
@@ -184,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
/**
* 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
@@ -281,6 +272,18 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
/**
+ * rt2x00link_start_agc - Start periodic gain calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_agc - Stop periodic gain calibration
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ */
+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev);
+
+/**
* rt2x00link_register - Initialize link tuning & watchdog functionality
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*
@@ -385,41 +388,17 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
#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 29abfdeb0b65..ea10b0068f82 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
/*
* 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 @@ static void rt2x00link_tuner(struct work_struct *work)
* 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);
/*
@@ -413,12 +403,11 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
{
struct link *link = &rt2x00dev->link;
- if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
- !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
- return;
-
- ieee80211_queue_delayed_work(rt2x00dev->hw,
- &link->watchdog_work, WATCHDOG_INTERVAL);
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ rt2x00dev->ops->lib->watchdog)
+ ieee80211_queue_delayed_work(rt2x00dev->hw,
+ &link->watchdog_work,
+ WATCHDOG_INTERVAL);
}
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -447,8 +436,46 @@ static void rt2x00link_watchdog(struct work_struct *work)
WATCHDOG_INTERVAL);
}
+void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
+{
+ struct link *link = &rt2x00dev->link;
+
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ rt2x00dev->ops->lib->gain_calibration)
+ ieee80211_queue_delayed_work(rt2x00dev->hw,
+ &link->agc_work,
+ AGC_INTERVAL);
+}
+
+void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
+{
+ cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
+}
+
+static void rt2x00link_agc(struct work_struct *work)
+{
+ struct rt2x00_dev *rt2x00dev =
+ container_of(work, struct rt2x00_dev, link.agc_work.work);
+ struct link *link = &rt2x00dev->link;
+
+ /*
+ * When the radio is shutting down we should
+ * immediately cease the watchdog monitoring.
+ */
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
+ rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
+
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ ieee80211_queue_delayed_work(rt2x00dev->hw,
+ &link->agc_work,
+ AGC_INTERVAL);
+}
+
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
{
+ INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 661c6baad2b9..93bec140e598 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* 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 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
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 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
* 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 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
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 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
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 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
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 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
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 4dd82b0b0520..17148bb24426 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -60,14 +60,15 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
-void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue = rt2x00dev->rx;
struct queue_entry *entry;
struct queue_entry_priv_pci *entry_priv;
struct skb_frame_desc *skbdesc;
+ int max_rx = 16;
- while (1) {
+ while (--max_rx) {
entry = rt2x00queue_get_entry(queue, Q_INDEX);
entry_priv = entry->priv_data;
@@ -93,9 +94,20 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
*/
rt2x00lib_rxdone(entry);
}
+
+ return !max_rx;
}
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.
*/
@@ -239,9 +251,8 @@ exit:
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 746ce8fe8cf4..e2c99f2b9a14 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -101,8 +101,21 @@ struct queue_entry_priv_pci {
/**
* rt2x00pci_rxdone - Handle RX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ *
+ * Returns true if there are still rx frames pending and false if all
+ * pending rx frames were processed.
+ */
+bool 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_rxdone(struct rt2x00_dev *rt2x00dev);
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
/*
* Device initialization handlers.
@@ -113,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
/*
* 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 4358051bfe1a..ab8c16f8bcaf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
* 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 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
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,
@@ -148,19 +148,6 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
skb_trim(skb, frame_length);
}
-void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)
-{
- unsigned int frame_length = skb->len;
- unsigned int align = ALIGN_SIZE(skb, header_length);
-
- if (!align)
- return;
-
- skb_push(skb, align);
- memmove(skb->data, skb->data + align, frame_length);
- skb_trim(skb, frame_length);
-}
-
void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
{
unsigned int payload_length = skb->len - header_length;
@@ -226,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
__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;
/*
@@ -315,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
}
}
+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)
{
@@ -409,8 +475,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
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);
}
@@ -449,7 +515,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
/*
* 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;
@@ -495,8 +561,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
struct skb_frame_desc *skbdesc;
u8 rate_idx, rate_flags;
- if (unlikely(rt2x00queue_full(queue)))
+ if (unlikely(rt2x00queue_full(queue))) {
+ ERROR(queue->rt2x00dev,
+ "Dropping frame due to full tx queue %d.\n", queue->qid);
return -ENOBUFS;
+ }
if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
&entry->flags))) {
@@ -539,7 +608,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
*/
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);
@@ -553,9 +622,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* 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);
/*
@@ -571,7 +640,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
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);
@@ -660,10 +729,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
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;
@@ -674,7 +745,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
ERROR(queue->rt2x00dev,
"Entry requested from invalid index range (%d - %d)\n",
start, end);
- return;
+ return true;
}
/*
@@ -693,15 +764,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
* 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);
@@ -727,8 +806,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
}
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)) {
@@ -743,7 +823,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
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++;
@@ -848,7 +928,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
{
- unsigned int i;
bool started;
bool tx_queue =
(queue->qid == QID_AC_VO) ||
@@ -883,20 +962,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
}
/*
- * 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).
- */
- 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.
+ * 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.
*/
- 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...
@@ -969,10 +1040,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
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);
}
@@ -1079,7 +1148,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
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)
@@ -1131,7 +1200,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
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 217861f8d95f..167d45873dca 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -217,6 +217,7 @@ enum txdone_entry_desc_flags {
TXDONE_FALLBACK,
TXDONE_FAILURE,
TXDONE_EXCESSIVE_RETRY,
+ TXDONE_AMPDU,
};
/**
@@ -363,6 +364,7 @@ enum queue_entry_flags {
* 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).
@@ -372,6 +374,7 @@ enum queue_entry_flags {
*/
struct queue_entry {
unsigned long flags;
+ unsigned long last_action;
struct data_queue *queue;
@@ -462,7 +465,6 @@ struct data_queue {
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;
@@ -579,16 +581,22 @@ struct data_queue_desc {
* @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.
@@ -628,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
/**
* 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 36f388f97d65..cb208d589ff8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
}
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 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
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 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
* 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 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
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 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
+
+ return false;
}
/*
@@ -323,7 +380,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
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 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
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 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
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 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
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 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
}
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 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
* 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 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
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 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
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 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
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 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)
* 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 @@ static void rt2x00usb_free_entries(struct data_queue *queue)
* 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 @@ exit:
}
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 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
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 e11c759ac9ed..64be34f612f6 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 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
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 @@ void rt2x00usb_kick_queue(struct data_queue *queue);
/**
* rt2x00usb_flush_queue - Flush data queue
* @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
*
- * This will walk through all entries of the queue and 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 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
* 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 77e8113b91e1..9d35ec16a3a5 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
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;
@@ -2313,8 +2313,10 @@ static void rt61pci_tbtt_tasklet(unsigned long data)
static void rt61pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- rt2x00pci_rxdone(rt2x00dev);
- rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
+ if (rt2x00pci_rxdone(rt2x00dev))
+ rt2x00pci_rxdone(rt2x00dev);
+ else
+ rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
}
static void rt61pci_autowake_tasklet(unsigned long data)
@@ -2535,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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.
@@ -2549,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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);
@@ -2572,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
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,
@@ -2582,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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 =
@@ -2797,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
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 {
@@ -2867,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* 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.
@@ -2977,6 +2979,9 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.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 = {
@@ -3001,6 +3006,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.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,
@@ -3058,11 +3064,11 @@ static const struct rt2x00_ops rt61pci_ops = {
*/
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, }
};
@@ -3077,10 +3083,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);
MODULE_FIRMWARE(FIRMWARE_RT2661);
MODULE_LICENSE("GPL");
+static int rt61pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
static struct pci_driver rt61pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt61pci_device_table,
- .probe = 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 02f1148c577e..a6ce7d6cbdfa 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
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 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
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 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
}
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 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* 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 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
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,16 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* 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(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
/*
* Set the rssi offset.
@@ -2311,6 +2310,9 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.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 = {
@@ -2389,114 +2391,113 @@ static const struct rt2x00_ops rt73usb_ops = {
*/
static struct usb_device_id rt73usb_device_table[] = {
/* AboCom */
- { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+ { 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, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) },
- { 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, }
};
@@ -2508,10 +2509,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2571);
MODULE_LICENSE("GPL");
+static int rt73usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
static struct usb_driver rt73usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt73usb_device_table,
- .probe = rt2x00usb_probe,
+ .probe = rt73usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,