diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
33 files changed, 1789 insertions, 1113 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 4396d4b9bfb9..6f383cd684b0 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -53,51 +53,41 @@ config RT61PCI When compiled as a module, this driver will be called rt61pci. -config RT2800PCI_PCI - boolean - depends on PCI - default y - -config RT2800PCI_SOC - boolean - depends on RALINK_RT288X || RALINK_RT305X - default y - config RT2800PCI - tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" - depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" + depends on PCI || RALINK_RT288X || RALINK_RT305X select RT2800_LIB - select RT2X00_LIB_PCI if RT2800PCI_PCI - select RT2X00_LIB_SOC if RT2800PCI_SOC + 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 select EEPROM_93CX6 ---help--- - This adds support for rt2800/rt3000/rt3500 wireless chipset family. - Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 - - This driver is non-functional at the moment and is intended for - developers. + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890, RT3052, + RT3090, RT3091 & RT3092 When compiled as a module, this driver will be called "rt2800pci.ko". if RT2800PCI -config RT2800PCI_RT30XX - bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" - default y +config RT2800PCI_RT33XX + bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800pci driver. - Supported chips: RT3090, RT3091 & RT3092 + 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 (PCI/PCIe/PCMCIA) devices" + bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -134,8 +124,8 @@ config RT73USB When compiled as a module, this driver will be called rt73usb. config RT2800USB - tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)" - depends on USB && EXPERIMENTAL + tristate "Ralink rt27xx/rt28xx/rt30xx (USB) support" + depends on USB select RT2800_LIB select RT2X00_LIB_USB select RT2X00_LIB_HT @@ -143,30 +133,28 @@ config RT2800USB select RT2X00_LIB_CRYPTO select CRC_CCITT ---help--- - This adds experimental support for rt2800 wireless chipset family. - Supported chips: RT2770, RT2870 & RT3070. - - Known issues: - - support for RT2870 chips doesn't work with 802.11n APs yet - - support for RT3070 chips is non-functional at the moment + This adds support for rt27xx/rt28xx/rt30xx wireless chipset family. + Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072 When compiled as a module, this driver will be called "rt2800usb.ko". if RT2800USB -config RT2800USB_RT30XX - bool "rt2800usb - Include support for rt30xx (USB) devices" - default y +config RT2800USB_RT33XX + bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n ---help--- - This adds support for rt30xx wireless chipset family to the + This adds support for rt33xx wireless chipset family to the rt2800usb driver. - Supported chips: RT3070, RT3071 & RT3072 + 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 (USB) devices" + bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" + depends on EXPERIMENTAL default n ---help--- This adds support for rt35xx wireless chipset family to the @@ -180,9 +168,9 @@ config RT2800USB_UNKNOWN bool "rt2800usb - Include support for unknown (USB) devices" default n ---help--- - This adds support for rt2800 family devices that are known to - have a rt2800 family chipset, but for which the exact chipset - is unknown. + This adds support for rt2800usb devices that are known to + have a rt28xx family compatible chipset, but for which the exact + chipset is unknown. Support status for these devices is unknown, and enabling these devices may or may not work. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4f420a9ec5dc..54ca49ad3472 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -633,6 +633,88 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, } /* + * Queue handlers. + */ +static void rt2400pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +static void rt2400pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + default: + break; + } +} + +static void rt2400pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static bool rt2400pci_get_entry_state(struct queue_entry *entry) @@ -878,18 +960,6 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -988,12 +1058,6 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2400pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2400pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1125,32 +1189,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2400pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2400pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - /* * RX control handlers */ @@ -1284,13 +1322,13 @@ static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BE); + rt2400pci_txdone(rt2x00dev, QID_AC_VO); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BK); + rt2400pci_txdone(rt2x00dev, QID_AC_VI); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, @@ -1612,6 +1650,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .get_tsf = rt2400pci_get_tsf, .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { @@ -1627,10 +1666,11 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_stats = rt2400pci_link_stats, .reset_tuner = rt2400pci_reset_tuner, .link_tuner = rt2400pci_link_tuner, + .start_queue = rt2400pci_start_queue, + .kick_queue = rt2400pci_kick_queue, + .stop_queue = rt2400pci_stop_queue, .write_tx_desc = rt2400pci_write_tx_desc, .write_beacon = rt2400pci_write_beacon, - .kick_tx_queue = rt2400pci_kick_tx_queue, - .kill_tx_queue = rt2400pci_kill_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, @@ -1640,28 +1680,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { }; static const struct data_queue_desc rt2400pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 24, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2400pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index c048b18f4133..d3a4a68cc439 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -809,8 +809,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 8 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 8 * sizeof(__le32) ) +#define TXD_DESC_SIZE (8 * sizeof(__le32)) +#define RXD_DESC_SIZE (8 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. @@ -948,6 +948,6 @@ ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER) #define TXPOWER_TO_DEV(__txpower) \ - MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER) + (MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)) #endif /* RT2400PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 97feb7aef809..a9ff26a27724 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -723,6 +723,88 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt2500pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +static void rt2500pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + default: + break; + } +} + +static void rt2500pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_ATIM: + rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); + rt2x00_set_field32(®, TXCSR0_ABORT, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static bool rt2500pci_get_entry_state(struct queue_entry *entry) @@ -1033,18 +1115,6 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -1143,12 +1213,6 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2500pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1193,9 +1257,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -1279,32 +1343,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2500pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2500pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - /* * RX control handlers */ @@ -1417,13 +1455,13 @@ static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) * 4 - Priority ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BE); + rt2500pci_txdone(rt2x00dev, QID_AC_VO); /* * 5 - Tx ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BK); + rt2500pci_txdone(rt2x00dev, QID_AC_VI); /* Enable interrupts again. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, @@ -1909,6 +1947,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .get_tsf = rt2500pci_get_tsf, .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { @@ -1924,10 +1963,11 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_stats = rt2500pci_link_stats, .reset_tuner = rt2500pci_reset_tuner, .link_tuner = rt2500pci_link_tuner, + .start_queue = rt2500pci_start_queue, + .kick_queue = rt2500pci_kick_queue, + .stop_queue = rt2500pci_stop_queue, .write_tx_desc = rt2500pci_write_tx_desc, .write_beacon = rt2500pci_write_beacon, - .kick_tx_queue = rt2500pci_kick_tx_queue, - .kill_tx_queue = rt2500pci_kill_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, @@ -1937,28 +1977,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { }; static const struct data_queue_desc rt2500pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2500pci_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index d708031361ac..2aad7ba8a100 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1088,8 +1088,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 11 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 11 * sizeof(__le32) ) +#define TXD_DESC_SIZE (11 * sizeof(__le32)) +#define RXD_DESC_SIZE (11 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 93e44c7f3a74..6b3b1de46792 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -39,7 +39,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -739,6 +739,55 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, } /* + * Queue handlers. + */ +static void rt2500usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u16 reg; + + switch (queue->qid) { + case QID_RX: + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); + break; + case QID_BEACON: + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + break; + default: + break; + } +} + +static void rt2500usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u16 reg; + + switch (queue->qid) { + case QID_RX: + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); + break; + case QID_BEACON: + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + break; + default: + break; + } +} + +/* * Initialization functions. */ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) @@ -931,18 +980,6 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) { /* @@ -1018,12 +1055,6 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt2500usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1081,9 +1112,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1206,14 +1237,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt2500usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -1801,6 +1824,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1813,11 +1837,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, .watchdog = rt2x00usb_watchdog, + .start_queue = rt2500usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt2500usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt2500usb_write_tx_desc, .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2500usb_kill_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_shared_key = rt2500usb_config_key, .config_pairwise_key = rt2500usb_config_key, @@ -1829,28 +1855,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { }; static const struct data_queue_desc rt2500usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2500usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 1, .data_size = MGMT_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_bcn), }; static const struct data_queue_desc rt2500usb_queue_atim = { - .entry_num = ATIM_ENTRIES, + .entry_num = 8, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index eb8b6cab9925..4c55e8525cad 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -46,7 +46,11 @@ * RF2020 2.4G B/G * RF3021 2.4G 1T2R * RF3022 2.4G 2T2R - * RF3052 2.4G 2T2R + * RF3052 2.4G/5G 2T2R + * RF2853 2.4G/5G 3T3R + * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) + * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) + * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) */ #define RF2820 0x0001 #define RF2850 0x0002 @@ -57,7 +61,10 @@ #define RF3021 0x0007 #define RF3022 0x0008 #define RF3052 0x0009 +#define RF2853 0x000a #define RF3320 0x000b +#define RF3322 0x000c +#define RF3853 0x000d /* * Chipset revisions. @@ -206,10 +213,10 @@ /* * WMM_AIFSN_CFG: Aifsn for each EDCA AC - * AIFSN0: AC_BE - * AIFSN1: AC_BK - * AIFSN2: AC_VI - * AIFSN3: AC_VO + * AIFSN0: AC_VO + * AIFSN1: AC_VI + * AIFSN2: AC_BE + * AIFSN3: AC_BK */ #define WMM_AIFSN_CFG 0x0214 #define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) @@ -219,10 +226,10 @@ /* * WMM_CWMIN_CSR: CWmin for each EDCA AC - * CWMIN0: AC_BE - * CWMIN1: AC_BK - * CWMIN2: AC_VI - * CWMIN3: AC_VO + * CWMIN0: AC_VO + * CWMIN1: AC_VI + * CWMIN2: AC_BE + * CWMIN3: AC_BK */ #define WMM_CWMIN_CFG 0x0218 #define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) @@ -232,10 +239,10 @@ /* * WMM_CWMAX_CSR: CWmax for each EDCA AC - * CWMAX0: AC_BE - * CWMAX1: AC_BK - * CWMAX2: AC_VI - * CWMAX3: AC_VO + * CWMAX0: AC_VO + * CWMAX1: AC_VI + * CWMAX2: AC_BE + * CWMAX3: AC_BK */ #define WMM_CWMAX_CFG 0x021c #define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) @@ -244,18 +251,18 @@ #define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) /* - * AC_TXOP0: AC_BK/AC_BE TXOP register - * AC0TXOP: AC_BK in unit of 32us - * AC1TXOP: AC_BE in unit of 32us + * AC_TXOP0: AC_VO/AC_VI TXOP register + * AC0TXOP: AC_VO in unit of 32us + * AC1TXOP: AC_VI in unit of 32us */ #define WMM_TXOP0_CFG 0x0220 #define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) #define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) /* - * AC_TXOP1: AC_VO/AC_VI TXOP register - * AC2TXOP: AC_VI in unit of 32us - * AC3TXOP: AC_VO in unit of 32us + * AC_TXOP1: AC_BE/AC_BK TXOP register + * AC2TXOP: AC_BE in unit of 32us + * AC3TXOP: AC_BK in unit of 32us */ #define WMM_TXOP1_CFG 0x0224 #define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) @@ -281,7 +288,7 @@ #define MCU_CMD_CFG 0x022c /* - * AC_BK register offsets + * AC_VO register offsets */ #define TX_BASE_PTR0 0x0230 #define TX_MAX_CNT0 0x0234 @@ -289,7 +296,7 @@ #define TX_DTX_IDX0 0x023c /* - * AC_BE register offsets + * AC_VI register offsets */ #define TX_BASE_PTR1 0x0240 #define TX_MAX_CNT1 0x0244 @@ -297,7 +304,7 @@ #define TX_DTX_IDX1 0x024c /* - * AC_VI register offsets + * AC_BE register offsets */ #define TX_BASE_PTR2 0x0250 #define TX_MAX_CNT2 0x0254 @@ -305,7 +312,7 @@ #define TX_DTX_IDX2 0x025c /* - * AC_VO register offsets + * AC_BK register offsets */ #define TX_BASE_PTR3 0x0260 #define TX_MAX_CNT3 0x0264 @@ -412,10 +419,22 @@ #define BCN_OFFSET1_BCN7 FIELD32(0xff000000) /* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. + * TXRXQ_PCNT: PBF register + * PCNT_TX0Q: Page count for TX hardware queue 0 + * PCNT_TX1Q: Page count for TX hardware queue 1 + * PCNT_TX2Q: Page count for TX hardware queue 2 + * PCNT_RX0Q: Page count for RX hardware queue */ #define TXRXQ_PCNT 0x0438 +#define TXRXQ_PCNT_TX0Q FIELD32(0x000000ff) +#define TXRXQ_PCNT_TX1Q FIELD32(0x0000ff00) +#define TXRXQ_PCNT_TX2Q FIELD32(0x00ff0000) +#define TXRXQ_PCNT_RX0Q FIELD32(0xff000000) + +/* + * PBF register + * Debug. Driver doesn't touch PBF register. + */ #define PBF_DBG 0x043c /* @@ -686,8 +705,18 @@ /* * CH_TIME_CFG: count as channel busy + * EIFS_BUSY: Count EIFS as channel busy + * NAV_BUSY: Count NAS as channel busy + * RX_BUSY: Count RX as channel busy + * TX_BUSY: Count TX as channel busy + * TMR_EN: Enable channel statistics timer */ #define CH_TIME_CFG 0x110c +#define CH_TIME_CFG_EIFS_BUSY FIELD32(0x00000010) +#define CH_TIME_CFG_NAV_BUSY FIELD32(0x00000008) +#define CH_TIME_CFG_RX_BUSY FIELD32(0x00000004) +#define CH_TIME_CFG_TX_BUSY FIELD32(0x00000002) +#define CH_TIME_CFG_TMR_EN FIELD32(0x00000001) /* * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us @@ -960,8 +989,31 @@ /* * TXOP_CTRL_CFG: + * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation + * AC_TRUN_EN: Enable/Disable truncation for AC change + * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change + * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode + * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS + * RESERVED_TRUN_EN: Reserved + * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection + * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz + * transmissions if extension CCA is clear). + * EXT_CCA_DLY: Extension CCA signal delay time (unit: us) + * EXT_CWMIN: CwMin for extension channel backoff + * 0: Disabled + * */ #define TXOP_CTRL_CFG 0x1340 +#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN FIELD32(0x00000001) +#define TXOP_CTRL_CFG_AC_TRUN_EN FIELD32(0x00000002) +#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN FIELD32(0x00000004) +#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN FIELD32(0x00000008) +#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN FIELD32(0x00000010) +#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020) +#define TXOP_CTRL_CFG_LSIG_TXOP_EN FIELD32(0x00000040) +#define TXOP_CTRL_CFG_EXT_CCA_EN FIELD32(0x00000080) +#define TXOP_CTRL_CFG_EXT_CCA_DLY FIELD32(0x0000ff00) +#define TXOP_CTRL_CFG_EXT_CWMIN FIELD32(0x000f0000) /* * TX_RTS_CFG: @@ -1485,17 +1537,17 @@ #define SHARED_KEY_MODE_BASE 0x7000 #define MAC_WCID_ENTRY(__idx) \ - ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) + (MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry))) #define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) ) + (MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry))) #define MAC_WCID_ATTR_ENTRY(__idx) \ - ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) + (MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32))) #define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) + (SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry))) #define SHARED_KEY_MODE_ENTRY(__idx) \ - ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) + (SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32))) struct mac_wcid_entry { u8 mac[6]; @@ -1635,9 +1687,9 @@ struct mac_iveiv_entry { #define HW_BEACON_BASE7 0x5bc0 #define HW_BEACON_OFFSET(__index) \ - ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ - (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ - (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) + (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \ + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) /* * BBP registers. @@ -1805,32 +1857,51 @@ struct mac_iveiv_entry { #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) /* - * EEPROM ANTENNA config + * EEPROM NIC Configuration 0 * RXPATH: 1: 1R, 2: 2R, 3: 3R - * TXPATH: 1: 1T, 2: 2T - */ -#define EEPROM_ANTENNA 0x001a -#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) -#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) - -/* - * EEPROM NIC config - * CARDBUS_ACCEL: 0 - enable, 1 - disable - */ -#define EEPROM_NIC 0x001b -#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) -#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) -#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) -#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) -#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) -#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) -#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) -#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) -#define EEPROM_NIC_BW40M_A FIELD16(0x0200) -#define EEPROM_NIC_ANT_DIVERSITY FIELD16(0x0800) -#define EEPROM_NIC_DAC_TEST FIELD16(0x8000) + * TXPATH: 1: 1T, 2: 2T, 3: 3T + * RF_TYPE: RFIC type + */ +#define EEPROM_NIC_CONF0 0x001a +#define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f) +#define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0) +#define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00) + +/* + * EEPROM NIC Configuration 1 + * HW_RADIO: 0: disable, 1: enable + * EXTERNAL_TX_ALC: 0: disable, 1: enable + * EXTERNAL_LNA_2G: 0: disable, 1: enable + * EXTERNAL_LNA_5G: 0: disable, 1: enable + * CARDBUS_ACCEL: 0: enable, 1: disable + * BW40M_SB_2G: 0: disable, 1: enable + * BW40M_SB_5G: 0: disable, 1: enable + * WPS_PBC: 0: disable, 1: enable + * BW40M_2G: 0: enable, 1: disable + * BW40M_5G: 0: enable, 1: disable + * BROADBAND_EXT_LNA: 0: disable, 1: enable + * ANT_DIVERSITY: 00: Disable, 01: Diversity, + * 10: Main antenna, 11: Aux antenna + * INTERNAL_TX_ALC: 0: disable, 1: enable + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable + */ +#define EEPROM_NIC_CONF1 0x001b +#define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) +#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008) +#define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010) +#define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020) +#define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040) +#define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080) +#define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100) +#define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200) +#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400) +#define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800) +#define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) +#define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) +#define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) /* * EEPROM frequency @@ -1852,9 +1923,9 @@ struct mac_iveiv_entry { * POLARITY_GPIO_4: Polarity GPIO4 setting. * LED_MODE: Led mode. */ -#define EEPROM_LED1 0x001e -#define EEPROM_LED2 0x001f -#define EEPROM_LED3 0x0020 +#define EEPROM_LED_AG_CONF 0x001e +#define EEPROM_LED_ACT_CONF 0x001f +#define EEPROM_LED_POLARITY 0x0020 #define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) #define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) #define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) @@ -1866,6 +1937,17 @@ struct mac_iveiv_entry { #define EEPROM_LED_LED_MODE FIELD16(0x1f00) /* + * EEPROM NIC Configuration 2 + * RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved + */ +#define EEPROM_NIC_CONF2 0x0021 +#define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f) +#define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0) +#define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600) + +/* * EEPROM LNA */ #define EEPROM_LNA 0x0022 @@ -1915,7 +1997,7 @@ struct mac_iveiv_entry { /* * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. - * This is delta in 40MHZ. + * This is delta in 40MHZ. * VALUE: Tx Power dalta value (MAX=4) * TYPE: 1: Plus the delta value, 0: minus the delta value * TXPOWER: Enable: @@ -1971,9 +2053,9 @@ struct mac_iveiv_entry { #define MCU_CURRENT 0x36 #define MCU_LED 0x50 #define MCU_LED_STRENGTH 0x51 -#define MCU_LED_1 0x52 -#define MCU_LED_2 0x53 -#define MCU_LED_3 0x54 +#define MCU_LED_AG_CONF 0x52 +#define MCU_LED_ACT_CONF 0x53 +#define MCU_LED_LED_POLARITY 0x54 #define MCU_RADAR 0x60 #define MCU_BOOT_SIGNAL 0x72 #define MCU_BBP_SIGNAL 0x80 @@ -1987,8 +2069,8 @@ struct mac_iveiv_entry { /* * DMA descriptor defines. */ -#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXWI_DESC_SIZE (4 * sizeof(__le32)) +#define RXWI_DESC_SIZE (4 * sizeof(__le32)) /* * TX WI structure diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5f00e00789d8..54917a281398 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) unsigned int i; u32 reg; + /* + * Some devices are really slow to respond here. Wait a whole second + * before timing out. + */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) return 0; - msleep(1); + msleep(10); } ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); @@ -483,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, txdesc->key_idx : 0xff); rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, txdesc->length); - rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid); + rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1); rt2x00_desc_write(txwi, 1, word); @@ -727,7 +731,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) break; @@ -768,6 +772,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -802,11 +807,13 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with TXWI to register. + * Write entire beacon with TXWI and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2800_register_multiwrite(rt2x00dev, beacon_base, - entry->skb->data, entry->skb->len); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -824,7 +831,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) } EXPORT_SYMBOL_GPL(rt2800_write_beacon); -static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, +static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, unsigned int beacon_base) { int i; @@ -1144,6 +1151,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, const unsigned int flags) { u32 reg; + bool update_bssid = false; if (flags & CONFIG_UPDATE_TYPE) { /* @@ -1173,6 +1181,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, } if (flags & CONFIG_UPDATE_MAC) { + if (flags & CONFIG_UPDATE_TYPE && + conf->sync == TSF_SYNC_AP_NONE) { + /* + * The BSSID register has to be set to our own mac + * address in AP mode. + */ + memcpy(conf->bssid, conf->mac, sizeof(conf->mac)); + update_bssid = true; + } + if (!is_zero_ether_addr((const u8 *)conf->mac)) { reg = le32_to_cpu(conf->mac[1]); rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); @@ -1183,7 +1201,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, conf->mac, sizeof(conf->mac)); } - if (flags & CONFIG_UPDATE_BSSID) { + if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) { if (!is_zero_ether_addr((const u8 *)conf->bssid)) { reg = le32_to_cpu(conf->bssid[1]); rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); @@ -1529,7 +1547,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF3021) || rt2x00_rf(rt2x00dev, RF3022) || - rt2x00_rf(rt2x00dev, RF3052)) + rt2x00_rf(rt2x00dev, RF3052) || + rt2x00_rf(rt2x00dev, RF3320)) rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); else rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); @@ -1609,6 +1628,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } msleep(1); + + /* + * Clear channel statistic counters + */ + rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®); + rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®); + rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); } static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, @@ -1914,8 +1940,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c); else @@ -2097,7 +2123,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); } - rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); + /* + * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1 + * although it is reserved. + */ + rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, ®); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_AC_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1); + rt2x00_set_field32(®, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_EN, 0); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_DLY, 88); + rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0); + rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); + rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); @@ -2134,7 +2176,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) SHARED_KEY_MODE_ENTRY(i), 0); for (i = 0; i < 256; i++) { - u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), wcid, sizeof(wcid)); @@ -2227,6 +2269,17 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4); rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); + /* + * Set up channel statistics timer + */ + rt2800_register_read(rt2x00dev, CH_TIME_CFG, ®); + rt2x00_set_field32(®, CH_TIME_CFG_EIFS_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_NAV_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_RX_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_TX_BUSY, 1); + rt2x00_set_field32(®, CH_TIME_CFG_TMR_EN, 1); + rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg); + return 0; } @@ -2344,10 +2397,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2x00_rt(rt2x00dev, RT3390)) { rt2800_bbp_read(rt2x00dev, 138, &value); - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) value |= 0x20; - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) value &= ~0x02; rt2800_bbp_write(rt2x00dev, 138, value); @@ -2559,8 +2612,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); else rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); @@ -2633,10 +2686,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3090)) { rt2800_bbp_read(rt2x00dev, 138, &bbp); - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); rt2800_bbp_write(rt2x00dev, 138, bbp); @@ -2735,16 +2788,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize LED control */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, + rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); + rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff, word & 0xff, (word >> 8) & 0xff); return 0; @@ -2838,38 +2891,41 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "MAC: %pM\n", mac); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872)) { /* * There is a max of 2 RX streams for RT28x0 series */ - if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); + rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); } @@ -2884,9 +2940,9 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) LED_MODE_TXRX_ACTIVITY); rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); + rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word); } @@ -2950,12 +3006,12 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read EEPROM word for configuration. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Identify RF chipset. */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); + value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); rt2800_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), @@ -2981,7 +3037,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) !rt2x00_rf(rt2x00dev, RF2020) && !rt2x00_rf(rt2x00dev, RF3021) && !rt2x00_rf(rt2x00dev, RF3022) && - !rt2x00_rf(rt2x00dev, RF3052)) { + !rt2x00_rf(rt2x00dev, RF3052) && + !rt2x00_rf(rt2x00dev, RF3320)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2990,9 +3047,9 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) * Identify default antenna configuration. */ rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH); rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); /* * Read frequency offset and RF programming sequence. @@ -3003,17 +3060,17 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read external LNA informations. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); /* * Detect if this device has an hardware controlled radio. */ - if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* @@ -3225,7 +3282,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->max_report_rates = 7; rt2x00dev->hw->max_rate_tries = 1; - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Initialize hw_mode information. @@ -3245,7 +3302,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) } else if (rt2x00_rf(rt2x00dev, RF3020) || rt2x00_rf(rt2x00dev, RF2020) || rt2x00_rf(rt2x00dev, RF3021) || - rt2x00_rf(rt2x00dev, RF3022)) { + rt2x00_rf(rt2x00dev, RF3022) || + rt2x00_rf(rt2x00dev, RF3320)) { spec->num_channels = 14; spec->channels = rf_vals_3x; } else if (rt2x00_rf(rt2x00dev, RF3052)) { @@ -3268,11 +3326,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40; - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2) spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; spec->ht.cap |= - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) << + rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) << IEEE80211_HT_CAP_RX_STBC_SHIFT; spec->ht.ampdu_factor = 3; @@ -3280,10 +3338,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->ht.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED | IEEE80211_HT_MCS_TX_RX_DIFF | - ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << + ((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { + switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) { case 3: spec->ht.mcs.rx_mask[2] = 0xff; case 2: @@ -3502,6 +3560,37 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2800_ampdu_action); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + u32 idle, busy, busy_ext; + + if (idx != 0) + return -ENOENT; + + survey->channel = conf->channel; + + rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle); + rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy); + rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); + + if (idle || busy) { + survey->filled = SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; + + survey->channel_time = (idle + busy) / 1000; + survey->channel_time_busy = busy / 1000; + survey->channel_time_ext_busy = busy_ext / 1000; + } + + return 0; + +} +EXPORT_SYMBOL_GPL(rt2800_get_survey); + MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2800 library"); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 81cbc92e7857..e3c995a9dec4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -199,5 +199,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey); #endif /* RT2800LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 09a67905c230..aa97971a38af 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -84,20 +84,22 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { - u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ + void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); + + iounmap(base_addr); } #else static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { struct rt2x00_dev *rt2x00dev = eeprom->data; @@ -181,7 +183,78 @@ static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ + +/* + * Queue handlers. + */ +static void rt2800pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + }; +} + +static void rt2800pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + struct queue_entry *entry; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + entry = rt2x00queue_get_entry(queue, Q_INDEX); + rt2800_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); + break; + default: + break; + } +} + +static void rt2800pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} /* * Firmware functions @@ -321,18 +394,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -442,7 +503,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, * if the device is booting and wasn't asleep it will return * failure when attempting to wakeup. */ - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); if (state == STATE_AWAKE) { rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); @@ -476,12 +537,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800pci_disable_radio(rt2x00dev); rt2800pci_set_state(rt2x00dev, STATE_SLEEP); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2800pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -567,41 +622,6 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, } /* - * TX data initialization - */ -static void rt2800pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); - unsigned int qidx; - - if (queue->qid == QID_MGMT) - qidx = 5; - else - qidx = queue->qid; - - rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx); -} - -static void rt2800pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0); - return; - } - - rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO)); - rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); -} - -/* * RX control handlers */ static void rt2800pci_fill_rxdone(struct queue_entry *entry, @@ -668,14 +688,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) u32 status; u8 qid; - while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { - /* Now remove the tx status from the FIFO */ - if (kfifo_out(&rt2x00dev->txstatus_fifo, &status, - sizeof(status)) != sizeof(status)) { - WARN_ON(1); - break; - } - + while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); if (qid >= QID_RX) { /* @@ -683,7 +696,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * this tx status. */ WARNING(rt2x00dev, "Got TX status report with " - "unexpected pid %u, dropping", qid); + "unexpected pid %u, dropping\n", qid); break; } @@ -694,7 +707,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * processing here and drop the tx status */ WARNING(rt2x00dev, "Got TX status for an unavailable " - "queue %u, dropping", qid); + "queue %u, dropping\n", qid); break; } @@ -704,7 +717,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) * and drop the tx status. */ WARNING(rt2x00dev, "Got TX status for an empty " - "queue %u, dropping", qid); + "queue %u, dropping\n", qid); break; } @@ -777,20 +790,13 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * Since we have only one producer and one consumer we don't * need to lock the kfifo. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) break; - if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) { - WARNING(rt2x00dev, "TX status FIFO overrun," - " drop tx status report.\n"); - break; - } - - if (kfifo_in(&rt2x00dev->txstatus_fifo, &status, - sizeof(status)) != sizeof(status)) { + if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) { WARNING(rt2x00dev, "TX status FIFO overrun," "drop tx status report.\n"); break; @@ -944,6 +950,8 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, + .get_survey = rt2800_get_survey, }; static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -976,11 +984,12 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, + .start_queue = rt2800pci_start_queue, + .kick_queue = rt2800pci_kick_queue, + .stop_queue = rt2800pci_stop_queue, .write_tx_desc = rt2800pci_write_tx_desc, .write_tx_data = rt2800_write_tx_data, .write_beacon = rt2800_write_beacon, - .kick_tx_queue = rt2800pci_kick_tx_queue, - .kill_tx_queue = rt2800pci_kill_tx_queue, .fill_rxdone = rt2800pci_fill_rxdone, .config_shared_key = rt2800_config_shared_key, .config_pairwise_key = rt2800_config_pairwise_key, @@ -992,21 +1001,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { }; static const struct data_queue_desc rt2800pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt2800pci_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), @@ -1034,12 +1043,15 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ -#ifdef CONFIG_RT2800PCI_PCI +#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) }, @@ -1047,12 +1059,10 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { 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(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, -#ifdef CONFIG_RT2800PCI_RT30XX - { 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(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#ifdef CONFIG_RT2800PCI_RT33XX + { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, #endif #ifdef CONFIG_RT2800PCI_RT35XX { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1063,19 +1073,19 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { #endif { 0, } }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI MODULE_FIRMWARE(FIRMWARE_RT2860); MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ MODULE_LICENSE("GPL"); -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) static int rt2800soc_probe(struct platform_device *pdev) { return rt2x00soc_probe(pdev, &rt2800pci_ops); @@ -1092,9 +1102,9 @@ static struct platform_driver rt2800soc_driver = { .suspend = rt2x00soc_suspend, .resume = rt2x00soc_resume, }; -#endif /* CONFIG_RT2800PCI_SOC */ +#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI static struct pci_driver rt2800pci_driver = { .name = KBUILD_MODNAME, .id_table = rt2800pci_device_table, @@ -1103,21 +1113,21 @@ static struct pci_driver rt2800pci_driver = { .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, }; -#endif /* CONFIG_RT2800PCI_PCI */ +#endif /* CONFIG_PCI */ static int __init rt2800pci_init(void) { int ret = 0; -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) ret = platform_driver_register(&rt2800soc_driver); if (ret) return ret; #endif -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI ret = pci_register_driver(&rt2800pci_driver); if (ret) { -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif return ret; @@ -1129,10 +1139,10 @@ static int __init rt2800pci_init(void) static void __exit rt2800pci_exit(void) { -#ifdef CONFIG_RT2800PCI_PCI +#ifdef CONFIG_PCI pci_unregister_driver(&rt2800pci_driver); #endif -#ifdef CONFIG_RT2800PCI_SOC +#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) platform_driver_unregister(&rt2800soc_driver); #endif } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index 5a8dda9b5b5a..70e050d904c8 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -38,10 +38,10 @@ * Queue register offset macros */ #define TX_QUEUE_REG_OFFSET 0x10 -#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) -#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) +#define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) /* * 8051 firmware image. @@ -52,8 +52,8 @@ /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) +#define TXD_DESC_SIZE (4 * sizeof(__le32)) +#define RXD_DESC_SIZE (4 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO and Beacon Ring. diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3dff56ec195a..b97a4a54ff4c 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -45,11 +45,60 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); /* + * Queue handlers. + */ +static void rt2800usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} + +static void rt2800usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); + rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + break; + case QID_BEACON: + rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); + rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); + rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); + rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -107,18 +156,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev, /* * Device state switch handlers. */ -static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); - rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -165,7 +202,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, - ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); + ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE) + / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); @@ -183,9 +221,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { if (state == STATE_AWAKE) - rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); + rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2); else - rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); return 0; } @@ -214,12 +252,6 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, rt2800usb_disable_radio(rt2x00dev); rt2800usb_set_state(rt2x00dev, STATE_SLEEP); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2800usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -245,6 +277,49 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, } /* + * Watchdog handlers + */ +static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + 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); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); + 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); + + for (i = 0; i < 10; i++) { + udelay(10); + if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) + break; + } + + rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); + } + + rt2x00usb_watchdog(rt2x00dev); +} + +/* * TX descriptor initialization */ static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) @@ -266,8 +341,14 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, * Initialize TXINFO descriptor */ rt2x00_desc_read(txi, 0, &word); + + /* + * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is + * TXWI + 802.11 header + L2 pad + payload + pad, + * so need to decrease size of TXINFO and USB end pad. + */ rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - entry->skb->len - TXINFO_DESC_SIZE); + entry->skb->len - TXINFO_DESC_SIZE - 4); rt2x00_set_field32(&word, TXINFO_W0_WIV, !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); @@ -285,22 +366,37 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry, skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; } -/* - * TX data initialization - */ -static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +static void rt2800usb_write_tx_data(struct queue_entry *entry, + struct txentry_desc *txdesc) { - int length; + unsigned int len; + int err; + + rt2800_write_tx_data(entry, txdesc); /* - * The length _must_ include 4 bytes padding, - * it should always be multiple of 4, - * but it must _not_ be a multiple of the USB packet size. + * pad(1~3 bytes) is added after each 802.11 payload. + * USB end pad(4 bytes) is added at each USB bulk out packet end. + * TX frame format is : + * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad | + * |<------------- tx_pkt_len ------------->| */ - length = roundup(entry->skb->len + 4, 4); - length += (4 * !(length % entry->queue->usb_maxpacket)); + len = roundup(entry->skb->len, 4) + 4; + err = skb_padto(entry->skb, len); + if (unlikely(err)) { + WARNING(entry->queue->rt2x00dev, "TX SKB padding error, out of memory\n"); + return; + } - return length; + entry->skb->len = len; +} + +/* + * TX data initialization + */ +static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +{ + return entry->skb->len; } /* @@ -335,14 +431,6 @@ static void rt2800usb_work_txdone(struct work_struct *work) } } -static void rt2800usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -507,6 +595,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, .ampdu_action = rt2800_ampdu_action, + .flush = rt2x00mac_flush, + .get_survey = rt2800_get_survey, }; static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -535,13 +625,15 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .link_stats = rt2800_link_stats, .reset_tuner = rt2800_reset_tuner, .link_tuner = rt2800_link_tuner, - .watchdog = rt2x00usb_watchdog, + .watchdog = rt2800usb_watchdog, + .start_queue = rt2800usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt2800usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt2800usb_write_tx_desc, - .write_tx_data = rt2800_write_tx_data, + .write_tx_data = rt2800usb_write_tx_data, .write_beacon = rt2800_write_beacon, .get_tx_data_len = rt2800usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt2800usb_kill_tx_queue, .fill_rxdone = rt2800usb_fill_rxdone, .config_shared_key = rt2800_config_shared_key, .config_pairwise_key = rt2800_config_pairwise_key, @@ -553,21 +645,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { }; static const struct data_queue_desc rt2800usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 128, .data_size = AGGREGATION_SIZE, .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 64, .data_size = AGGREGATION_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt2800usb_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, + .entry_num = 8, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), @@ -599,11 +691,19 @@ 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) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, /* 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) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ @@ -612,8 +712,13 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, /* 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) }, /* Belkin */ { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -624,6 +729,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, @@ -632,17 +738,36 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, /* 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) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, /* 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) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* 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) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Hawking */ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -651,6 +776,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, + /* 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) }, /* Linksys */ { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -658,17 +787,44 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, /* Motorola */ { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, /* 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) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Philips */ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, /* 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) }, /* Samsung */ { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Siemens */ @@ -681,13 +837,22 @@ static struct usb_device_id rt2800usb_device_table[] = { { 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) }, /* 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) }, /* Sparklan */ { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -701,101 +866,16 @@ static struct usb_device_id rt2800usb_device_table[] = { /* 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) }, /* Zyxel */ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, -#ifdef CONFIG_RT2800USB_RT30XX - /* Abocom */ - { 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) }, - /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Allwin */ - { 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) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AzureWave */ - { 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) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Corega */ - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* D-Link */ - { 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, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Draytek */ - { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Encore */ - { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* EnGenius */ - { 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) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* 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) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* 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, 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) }, - /* Para */ - { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Planex */ - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, +#ifdef CONFIG_RT2800USB_RT33XX /* Ralink */ - { USB_DEVICE(0x148f, 0x2070), 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, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x003e), 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) }, - /* SMC */ - { USB_DEVICE(0x083a, 0x7511), 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) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ @@ -809,12 +889,9 @@ static struct usb_device_id rt2800usb_device_table[] = { /* I-O DATA */ { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 0722badccf86..671ea3592610 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -40,8 +40,8 @@ /* * DMA descriptor defines. */ -#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define TXINFO_DESC_SIZE (1 * sizeof(__le32)) +#define RXINFO_DESC_SIZE (1 * sizeof(__le32)) /* * TX Info structure diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ab43e7ca2a23..84aaf393da43 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -66,7 +66,7 @@ #ifdef CONFIG_RT2X00_DEBUG #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); + DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args) #else #define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ do { } while (0) @@ -347,6 +347,10 @@ struct link { struct delayed_work watchdog_work; }; +enum rt2x00_delayed_flags { + DELAYED_UPDATE_BEACON, +}; + /* * Interface structure * Per interface configuration details, this structure @@ -354,22 +358,6 @@ struct link { */ struct rt2x00_intf { /* - * All fields within the rt2x00_intf structure - * must be protected with a spinlock. - */ - spinlock_t lock; - - /* - * MAC of the device. - */ - u8 mac[ETH_ALEN]; - - /* - * BBSID of the AP to associate with. - */ - u8 bssid[ETH_ALEN]; - - /* * beacon->skb must be protected with the mutex. */ struct mutex beacon_skb_mutex; @@ -384,8 +372,7 @@ struct rt2x00_intf { /* * Actions that needed rescheduling. */ - unsigned int delayed_flags; -#define DELAYED_UPDATE_BEACON 0x00000001 + unsigned long delayed_flags; /* * Software sequence counter, this is only required @@ -567,7 +554,15 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*link_tuner) (struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count); + + /* + * Data queue handlers. + */ void (*watchdog) (struct rt2x00_dev *rt2x00dev); + void (*start_queue) (struct data_queue *queue); + void (*kick_queue) (struct data_queue *queue); + void (*stop_queue) (struct data_queue *queue); + void (*flush_queue) (struct data_queue *queue); /* * TX control handlers @@ -579,8 +574,6 @@ struct rt2x00lib_ops { void (*write_beacon) (struct queue_entry *entry, struct txentry_desc *txdesc); int (*get_tx_data_len) (struct queue_entry *entry); - void (*kick_tx_queue) (struct data_queue *queue); - void (*kill_tx_queue) (struct data_queue *queue); /* * RX control handlers @@ -902,7 +895,7 @@ struct rt2x00_dev { /* * FIFO for storing tx status reports between isr and tasklet. */ - struct kfifo txstatus_fifo; + DECLARE_KFIFO_PTR(txstatus_fifo, u32); /* * Tasklet for processing tx status reports (rt2800pci). @@ -916,7 +909,7 @@ struct rt2x00_dev { * in those cases REGISTER_BUSY_COUNT attempts should be * taken with a REGISTER_BUSY_DELAY interval. */ -#define REGISTER_BUSY_COUNT 5 +#define REGISTER_BUSY_COUNT 100 #define REGISTER_BUSY_DELAY 100 /* @@ -1068,6 +1061,78 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_pause_queue - Pause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will pause the data queue locally, preventing + * new frames to be added to the queue (while the hardware is + * still allowed to run). + */ +void rt2x00queue_pause_queue(struct data_queue *queue); + +/** + * rt2x00queue_unpause_queue - unpause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will unpause the data queue locally, allowing + * new frames to be added to the queue again. + */ +void rt2x00queue_unpause_queue(struct data_queue *queue); + +/** + * rt2x00queue_start_queue - Start a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will start handling all pending frames in the queue. + */ +void rt2x00queue_start_queue(struct data_queue *queue); + +/** + * rt2x00queue_stop_queue - Halt a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will stop all pending frames in the queue. + */ +void rt2x00queue_stop_queue(struct data_queue *queue); + +/** + * rt2x00queue_flush_queue - Flush a data queue + * @queue: Pointer to &struct data_queue. + * @drop: True to drop all pending frames. + * + * This function will flush the queue. After this call + * the queue is guarenteed to be empty. + */ +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop); + +/** + * rt2x00queue_start_queues - Start all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to start them + */ +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_flush_queues - Flush all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @drop: True to drop all pending frames. + * + * This function will loop through all available queues to flush + * any pending frames. + */ +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop); + /* * Debugfs handlers. */ @@ -1093,6 +1158,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_dmastart(struct queue_entry *entry); void rt2x00lib_dmadone(struct queue_entry *entry); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); @@ -1134,6 +1200,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, 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); /* * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 54ffb5aeb34e..e7f67d5eda52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -62,13 +62,13 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, * This will prevent the device being confused when it wants * to ACK frames or consideres itself associated. */ - memset(&conf.mac, 0, sizeof(conf.mac)); + memset(conf.mac, 0, sizeof(conf.mac)); if (mac) - memcpy(&conf.mac, mac, ETH_ALEN); + memcpy(conf.mac, mac, ETH_ALEN); - memset(&conf.bssid, 0, sizeof(conf.bssid)); + memset(conf.bssid, 0, sizeof(conf.bssid)); if (bssid) - memcpy(&conf.bssid, bssid, ETH_ALEN); + memcpy(conf.bssid, bssid, ETH_ALEN); flags |= CONFIG_UPDATE_TYPE; if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) @@ -133,7 +133,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, */ if (!(ant->flags & ANTENNA_RX_DIVERSITY)) config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); - else if(config.rx == ANTENNA_SW_DIVERSITY) + else if (config.rx == ANTENNA_SW_DIVERSITY) config.rx = active->rx; if (!(ant->flags & ANTENNA_TX_DIVERSITY)) @@ -146,7 +146,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * else the changes will be ignored by the device. */ if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00queue_stop_queue(rt2x00dev->rx); /* * Write new antenna setup to device and reset the link tuner. @@ -160,7 +160,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, memcpy(active, &config, sizeof(config)); if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00queue_start_queue(rt2x00dev->rx); } void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index fcdb6b0dc40f..c92db3264741 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct timeval timestamp; u32 data_len; - do_gettimeofday(×tamp); - - if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) + if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))) return; + do_gettimeofday(×tamp); + if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); return; @@ -339,18 +339,19 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, return -ENOMEM; temp = data + - sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); + sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); queue_for_each(intf->rt2x00dev, queue) { - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); - temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, + temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n", + queue->qid, (unsigned int)queue->flags, queue->count, queue->limit, queue->length, queue->index[Q_INDEX], queue->index[Q_INDEX_DMA_DONE], queue->index[Q_INDEX_DONE]); - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } size = strlen(data); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d019830ca840..9597a03242cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -66,20 +66,16 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); /* - * Enable RX. + * Enable queues. */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + rt2x00queue_start_queues(rt2x00dev); + rt2x00link_start_tuner(rt2x00dev); /* * Start watchdog monitoring. */ rt2x00link_start_watchdog(rt2x00dev); - /* - * Start the TX queues. - */ - ieee80211_wake_queues(rt2x00dev->hw); - return 0; } @@ -89,20 +85,16 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) return; /* - * Stop the TX queues in mac80211. - */ - ieee80211_stop_queues(rt2x00dev->hw); - rt2x00queue_stop_queues(rt2x00dev); - - /* * Stop watchdog monitoring. */ rt2x00link_stop_watchdog(rt2x00dev); /* - * Disable RX. + * Stop all queues */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + rt2x00link_stop_tuner(rt2x00dev); + rt2x00queue_stop_queues(rt2x00dev); + rt2x00queue_flush_queues(rt2x00dev, true); /* * Disable radio. @@ -113,41 +105,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00leds_led_radio(rt2x00dev, false); } -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - /* - * When we are disabling the RX, we should also stop the link tuner. - */ - if (state == STATE_RADIO_RX_OFF) - rt2x00link_stop_tuner(rt2x00dev); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - /* - * When we are enabling the RX, we should also start the link tuner. - */ - if (state == STATE_RADIO_RX_ON) - rt2x00link_start_tuner(rt2x00dev); -} - static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); - int delayed_flags; - - /* - * Copy all data we need during this action under the protection - * of a spinlock. Otherwise race conditions might occur which results - * into an invalid configuration. - */ - spin_lock(&intf->lock); - - delayed_flags = intf->delayed_flags; - intf->delayed_flags = 0; - - spin_unlock(&intf->lock); /* * It is possible the radio was disabled while the work had been @@ -158,7 +120,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) return; - if (delayed_flags & DELAYED_UPDATE_BEACON) + if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) rt2x00queue_update_beacon(rt2x00dev, vif, true); } @@ -251,8 +213,16 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); +void rt2x00lib_dmastart(struct queue_entry *entry) +{ + set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + rt2x00queue_index_inc(entry->queue, Q_INDEX); +} +EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); + void rt2x00lib_dmadone(struct queue_entry *entry) { + set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags); clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); } @@ -264,11 +234,9 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + unsigned int header_length, i; u8 rate_idx, rate_flags, retry_rates; u8 skbdesc_flags = skbdesc->flags; - unsigned int i; bool success; /* @@ -287,6 +255,11 @@ void rt2x00lib_txdone(struct queue_entry *entry, skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; /* + * Determine the length of 802.11 header. + */ + header_length = ieee80211_get_hdrlen_from_skb(entry->skb); + + /* * Remove L2 padding which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) @@ -414,7 +387,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, * is reenabled when the txdone handler has finished. */ if (!rt2x00queue_threshold(entry->queue)) - ieee80211_wake_queue(rt2x00dev->hw, qid); + rt2x00queue_unpause_queue(entry->queue); } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); @@ -486,6 +459,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry) unsigned int header_length; int rate_idx; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || + !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + goto submit_entry; + if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) goto submit_entry; @@ -570,9 +547,11 @@ void rt2x00lib_rxdone(struct queue_entry *entry) entry->skb = skb; submit_entry: - rt2x00dev->ops->lib->clear_entry(entry); - rt2x00queue_index_inc(entry->queue, Q_INDEX); + entry->flags = 0; rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && + test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + rt2x00dev->ops->lib->clear_entry(entry); } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -681,7 +660,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, { entry->flags = 0; entry->bitrate = rate->bitrate; - entry->hw_value =index; + entry->hw_value = index; entry->hw_value_short = index; if (rate->flags & DEV_RATE_SHORT_PREAMBLE) @@ -821,8 +800,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate tx status FIFO for driver use. */ - if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) && - rt2x00dev->ops->lib->txstatus_tasklet) { + if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->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 @@ -836,9 +814,10 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) return status; /* tasklet for processing the tx status reports. */ - tasklet_init(&rt2x00dev->txstatus_tasklet, - rt2x00dev->ops->lib->txstatus_tasklet, - (unsigned long)rt2x00dev); + if (rt2x00dev->ops->lib->txstatus_tasklet) + tasklet_init(&rt2x00dev->txstatus_tasklet, + rt2x00dev->ops->lib->txstatus_tasklet, + (unsigned long)rt2x00dev); } diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c637bcaec5f8..b7ad46ecaa1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c @@ -40,8 +40,6 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, if (tx_info->control.sta) txdesc->mpdu_density = tx_info->control.sta->ht_cap.ampdu_density; - else - txdesc->mpdu_density = 0; txdesc->ba_size = 7; /* FIXME: What value is needed? */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 619da23b7b56..a105c500627b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -57,7 +57,7 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) } #define RATE_MCS(__mode, __mcs) \ - ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) + ((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff)) static inline int rt2x00_get_rate_mcs(const u16 mcs_value) { @@ -69,7 +69,6 @@ static inline int rt2x00_get_rate_mcs(const u16 mcs_value) */ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev); void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state); /* * Initialization handlers. @@ -179,15 +178,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); /** - * rt2x00queue_stop_queues - Halt all data queues - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * This function will loop through all available queues to stop - * any pending outgoing frames. - */ -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); - -/** * rt2x00queue_init_queues - Initialize all data queues * @rt2x00dev: Pointer to &struct rt2x00_dev. * diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index b971d8798ebf..bfda60eaf4ef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -67,7 +67,7 @@ (__avg).avg_weight ? \ ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ ((__val) * (AVG_FACTOR))) / \ - (AVG_SAMPLES) ) : \ + (AVG_SAMPLES)) : \ ((__val) * (AVG_FACTOR)); \ __new.avg = __new.avg_weight / (AVG_FACTOR); \ __new; \ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c3c206a97d54..658542d2efe1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -104,7 +104,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); enum data_queue_qid qid = skb_get_queue_mapping(skb); - struct data_queue *queue; + struct data_queue *queue = NULL; /* * Mac80211 might be calling this function while we are trying @@ -153,7 +153,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto exit_fail; if (rt2x00queue_threshold(queue)) - ieee80211_stop_queue(rt2x00dev->hw, qid); + rt2x00queue_pause_queue(queue); return NETDEV_TX_OK; @@ -268,7 +268,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; - spin_lock_init(&intf->lock); spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; @@ -282,15 +281,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * STA interfaces at this time, since this can cause * invalid behavior in the device. */ - memcpy(&intf->mac, vif->addr, ETH_ALEN); - if (vif->type == NL80211_IFTYPE_AP) { - memcpy(&intf->bssid, vif->addr, ETH_ALEN); - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, intf->bssid); - } else { - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, - intf->mac, NULL); - } + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, + vif->addr, NULL); /* * Some filters depend on the current working mode. We can force @@ -358,7 +350,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) * if for any reason the link tuner must be reset, this will be * handled by rt2x00lib_config(). */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); + rt2x00queue_stop_queue(rt2x00dev->rx); /* * When we've just turned on the radio, we want to reprogram @@ -376,7 +368,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); /* Turn RX back on */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); + rt2x00queue_start_queue(rt2x00dev->rx); return 0; } @@ -451,9 +443,7 @@ static void rt2x00mac_set_tim_iter(void *data, u8 *mac, vif->type != NL80211_IFTYPE_WDS) return; - spin_lock(&intf->lock); - intf->delayed_flags |= DELAYED_UPDATE_BEACON; - spin_unlock(&intf->lock); + set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags); } int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, @@ -478,17 +468,17 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) { if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) - memcpy(&crypto->key, + memcpy(crypto->key, &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY], sizeof(crypto->key)); if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) - memcpy(&crypto->tx_mic, + memcpy(crypto->tx_mic, &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], sizeof(crypto->tx_mic)); if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) - memcpy(&crypto->rx_mic, + memcpy(crypto->rx_mic, &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], sizeof(crypto->rx_mic)); } @@ -498,7 +488,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); int (*set_key) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); @@ -522,7 +511,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (rt2x00dev->intf_sta_count) crypto.bssidx = 0; else - crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); + crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1); crypto.cipher = rt2x00crypto_key_to_cipher(key); if (crypto.cipher == CIPHER_NONE) @@ -540,7 +529,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (crypto.cipher == CIPHER_TKIP) memcpy_tkip(&crypto, &key->key[0], key->keylen); else - memcpy(&crypto.key, &key->key[0], key->keylen); + memcpy(crypto.key, &key->key[0], key->keylen); /* * Each BSS has a maximum of 4 shared keys. * Shared key index values: @@ -620,22 +609,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return; - spin_lock(&intf->lock); - /* - * conf->bssid can be NULL if coming from the internal - * beacon update routine. - */ - if (changes & BSS_CHANGED_BSSID) - memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); - - spin_unlock(&intf->lock); - - /* - * Call rt2x00_config_intf() outside of the spinlock context since - * the call will sleep for USB drivers. By using the ieee80211_if_conf - * values as arguments we make keep access to rt2x00_intf thread safe - * even without the lock. + * Update the BSSID. */ if (changes & BSS_CHANGED_BSSID) rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, @@ -719,3 +694,13 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) wiphy_rfkill_set_hw_state(hw->wiphy, !active); } EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); + +void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_flush_queue(queue, drop); +} +EXPORT_SYMBOL_GPL(rt2x00mac_flush); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 2449d785cf8d..73631c6fbb30 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -82,6 +82,13 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) skbdesc->desc_len = entry->queue->desc_size; /* + * DMA is already done, notify rt2x00lib that + * it finished successfully. + */ + rt2x00lib_dmastart(entry); + rt2x00lib_dmadone(entry); + + /* * Send the frame to rt2x00lib for further processing. */ rt2x00lib_rxdone(entry); @@ -105,7 +112,7 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, */ addr = dma_alloc_coherent(rt2x00dev->dev, queue->limit * queue->desc_size, - &dma, GFP_KERNEL | GFP_DMA); + &dma, GFP_KERNEL); if (!addr) return -ENOMEM; @@ -279,7 +286,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00dev->irq = pci_dev->irq; rt2x00dev->name = pci_name(pci_dev); - if (pci_dev->is_pcie) + if (pci_is_pcie(pci_dev)) rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE); else rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index b854d62ff99b..746ce8fe8cf4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -64,7 +64,7 @@ static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, const void *value, const u32 length) { - memcpy_toio(rt2x00dev->csr.base + offset, value, length); + __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); } /** diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index e360d287defb..ca82b3a91697 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -199,7 +199,12 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) { - unsigned int l2pad = L2PAD_SIZE(header_length); + /* + * L2 padding is only present if the skb contains more than just the + * IEEE 802.11 header. + */ + unsigned int l2pad = (skb->len > header_length) ? + L2PAD_SIZE(header_length) : 0; if (!l2pad) return; @@ -311,14 +316,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, memset(txdesc, 0, sizeof(*txdesc)); /* - * Initialize information from queue - */ - txdesc->qid = entry->queue->qid; - txdesc->cw_min = entry->queue->cw_min; - txdesc->cw_max = entry->queue->cw_max; - txdesc->aifs = entry->queue->aifs; - - /* * Header and frame information. */ txdesc->length = entry->skb->len; @@ -460,12 +457,9 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, rt2x00debug_dump_frame(queue->rt2x00dev, DUMP_FRAME_TX, entry->skb); } -static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, +static void rt2x00queue_kick_tx_queue(struct data_queue *queue, struct txentry_desc *txdesc) { - struct data_queue *queue = entry->queue; - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - /* * Check if we need to kick the queue, there are however a few rules * 1) Don't kick unless this is the last in frame in a burst. @@ -477,7 +471,7 @@ static void rt2x00queue_kick_tx_queue(struct queue_entry *entry, */ if (rt2x00queue_threshold(queue) || !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) - rt2x00dev->ops->lib->kick_tx_queue(queue); + queue->rt2x00dev->ops->lib->kick_queue(queue); } int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, @@ -567,7 +561,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, rt2x00queue_index_inc(queue, Q_INDEX); rt2x00queue_write_tx_descriptor(entry, &txdesc); - rt2x00queue_kick_tx_queue(entry, &txdesc); + rt2x00queue_kick_tx_queue(queue, &txdesc); return 0; } @@ -591,7 +585,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, rt2x00queue_free_skb(intf->beacon); if (!enable_beacon) { - rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue); + rt2x00queue_stop_queue(intf->beacon->queue); mutex_unlock(&intf->beacon_skb_mutex); return 0; } @@ -649,10 +643,10 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, * it should not be kicked during this run, since it * is part of another TX operation. */ - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); index_start = queue->index[start]; index_end = queue->index[end]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); /* * Start from the TX done pointer, this guarentees that we will @@ -706,11 +700,11 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, return NULL; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); entry = &queue->entries[queue->index[index]]; - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); return entry; } @@ -726,7 +720,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) return; } - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->index[index]++; if (queue->index[index] >= queue->limit) @@ -741,15 +735,219 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) queue->count++; } - spin_unlock_irqrestore(&queue->lock, irqflags); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } +void rt2x00queue_pause_queue(struct data_queue *queue) +{ + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + !test_bit(QUEUE_STARTED, &queue->flags) || + test_and_set_bit(QUEUE_PAUSED, &queue->flags)) + return; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + /* + * For TX queues, we have to disable the queue + * inside mac80211. + */ + ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); + +void rt2x00queue_unpause_queue(struct data_queue *queue) +{ + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + !test_bit(QUEUE_STARTED, &queue->flags) || + !test_and_clear_bit(QUEUE_PAUSED, &queue->flags)) + return; + + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + /* + * For TX queues, we have to enable the queue + * inside mac80211. + */ + ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); + break; + case QID_RX: + /* + * For RX we need to kick the queue now in order to + * receive frames. + */ + queue->rt2x00dev->ops->lib->kick_queue(queue); + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue); + +void rt2x00queue_start_queue(struct data_queue *queue) +{ + mutex_lock(&queue->status_lock); + + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + test_and_set_bit(QUEUE_STARTED, &queue->flags)) { + mutex_unlock(&queue->status_lock); + return; + } + + set_bit(QUEUE_PAUSED, &queue->flags); + + queue->rt2x00dev->ops->lib->start_queue(queue); + + rt2x00queue_unpause_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queue); + +void rt2x00queue_stop_queue(struct data_queue *queue) +{ + mutex_lock(&queue->status_lock); + + if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) { + mutex_unlock(&queue->status_lock); + return; + } + + rt2x00queue_pause_queue(queue); + + queue->rt2x00dev->ops->lib->stop_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); + +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) +{ + unsigned int i; + bool started; + bool tx_queue = + (queue->qid == QID_AC_VO) || + (queue->qid == QID_AC_VI) || + (queue->qid == QID_AC_BE) || + (queue->qid == QID_AC_BK); + + mutex_lock(&queue->status_lock); + + /* + * If the queue has been started, we must stop it temporarily + * to prevent any new frames to be queued on the device. If + * we are not dropping the pending frames, the queue must + * only be stopped in the software and not the hardware, + * otherwise the queue will never become empty on its own. + */ + started = test_bit(QUEUE_STARTED, &queue->flags); + if (started) { + /* + * Pause the queue + */ + rt2x00queue_pause_queue(queue); + + /* + * If we are not supposed to drop any pending + * frames, this means we must force a start (=kick) + * to the queue to make sure the hardware will + * start transmitting. + */ + if (!drop && tx_queue) + queue->rt2x00dev->ops->lib->kick_queue(queue); + } + + /* + * Check if driver supports flushing, we can only guarentee + * 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. + */ + for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) + msleep(10); + + /* + * The queue flush has failed... + */ + if (unlikely(!rt2x00queue_empty(queue))) + WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid); + + /* + * Restore the queue to the previous status + */ + if (started) + rt2x00queue_unpause_queue(queue); + + mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); + +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + /* + * rt2x00queue_start_queue will call ieee80211_wake_queue + * for each queue after is has been properly initialized. + */ + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_start_queue(queue); + + rt2x00queue_start_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queues); + +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + /* + * rt2x00queue_stop_queue will call ieee80211_stop_queue + * as well, but we are completely shutting doing everything + * now, so it is much safer to stop all TX queues at once, + * and use rt2x00queue_stop_queue for cleaning up. + */ + ieee80211_stop_queues(rt2x00dev->hw); + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_stop_queue(queue); + + rt2x00queue_stop_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); + +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop) +{ + struct data_queue *queue; + + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_flush_queue(queue, drop); + + rt2x00queue_flush_queue(rt2x00dev->rx, drop); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues); + static void rt2x00queue_reset(struct data_queue *queue) { unsigned long irqflags; unsigned int i; - spin_lock_irqsave(&queue->lock, irqflags); + spin_lock_irqsave(&queue->index_lock, irqflags); queue->count = 0; queue->length = 0; @@ -759,15 +957,7 @@ static void rt2x00queue_reset(struct data_queue *queue) queue->last_action[i] = jiffies; } - spin_unlock_irqrestore(&queue->lock, irqflags); -} - -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - txall_queue_for_each(rt2x00dev, queue) - rt2x00dev->ops->lib->kill_tx_queue(queue); + spin_unlock_irqrestore(&queue->index_lock, irqflags); } void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) @@ -778,11 +968,8 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) queue_for_each(rt2x00dev, queue) { rt2x00queue_reset(queue); - for (i = 0; i < queue->limit; i++) { + for (i = 0; i < queue->limit; i++) rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); - if (queue->qid == QID_RX) - rt2x00queue_index_inc(queue, Q_INDEX); - } } } @@ -809,8 +996,8 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return -ENOMEM; #define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ - ( ((char *)(__base)) + ((__limit) * (__esize)) + \ - ((__index) * (__psize)) ) + (((char *)(__base)) + ((__limit) * (__esize)) + \ + ((__index) * (__psize))) for (i = 0; i < queue->limit; i++) { entries[i].flags = 0; @@ -911,7 +1098,8 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { - spin_lock_init(&queue->lock); + mutex_init(&queue->status_lock); + spin_lock_init(&queue->index_lock); queue->rt2x00dev = rt2x00dev; queue->qid = qid; @@ -953,7 +1141,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) /* * Initialize queue parameters. * RX: qid = QID_RX - * TX: qid = QID_AC_BE + index + * TX: qid = QID_AC_VO + index * TX: cw_min: 2^5 = 32. * TX: cw_max: 2^10 = 1024. * BCN: qid = QID_BEACON @@ -961,7 +1149,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) */ rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); - qid = QID_AC_BE; + qid = QID_AC_VO; tx_queue_for_each(rt2x00dev, queue) rt2x00queue_init(rt2x00dev, queue, qid++); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index d81d85f34866..fab8e2687f29 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -43,28 +43,12 @@ #define AGGREGATION_SIZE 3840 /** - * DOC: Number of entries per queue - * - * Under normal load without fragmentation, 12 entries are sufficient - * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code, we need to add some additional margins to - * make sure the queue will never (or only under extreme load) fill up - * completely. - * Since we don't use preallocated DMA, having a large number of queue entries - * will have minimal impact on the memory requirements for the queue. - */ -#define RX_ENTRIES 24 -#define TX_ENTRIES 24 -#define BEACON_ENTRIES 1 -#define ATIM_ENTRIES 8 - -/** * enum data_queue_qid: Queue identification * + * @QID_AC_VO: AC VO queue + * @QID_AC_VI: AC VI queue * @QID_AC_BE: AC BE queue * @QID_AC_BK: AC BK queue - * @QID_AC_VI: AC VI queue - * @QID_AC_VO: AC VO queue * @QID_HCCA: HCCA queue * @QID_MGMT: MGMT queue (prio queue) * @QID_RX: RX queue @@ -73,10 +57,10 @@ * @QID_ATIM: Atim queue (value unspeficied, don't send it to device) */ enum data_queue_qid { - QID_AC_BE = 0, - QID_AC_BK = 1, - QID_AC_VI = 2, - QID_AC_VO = 3, + QID_AC_VO = 0, + QID_AC_VI = 1, + QID_AC_BE = 2, + QID_AC_BK = 3, QID_HCCA = 4, QID_MGMT = 13, QID_RX = 14, @@ -296,7 +280,6 @@ enum txentry_desc_flags { * Summary of information for the frame descriptor before sending a TX frame. * * @flags: Descriptor flags (See &enum queue_entry_flags). - * @qid: Queue identification (See &enum data_queue_qid). * @length: Length of the entire frame. * @header_length: Length of 802.11 header. * @length_high: PLCP length high word. @@ -309,11 +292,8 @@ enum txentry_desc_flags { * @rate_mode: Rate mode (See @enum rate_modulation). * @mpdu_density: MDPU density. * @retry_limit: Max number of retries. - * @aifs: AIFS value. * @ifs: IFS value. * @txop: IFS value for 11n capable chips. - * @cw_min: cwmin value. - * @cw_max: cwmax value. * @cipher: Cipher type used for encryption. * @key_idx: Key index used for encryption. * @iv_offset: Position where IV should be inserted by hardware. @@ -322,8 +302,6 @@ enum txentry_desc_flags { struct txentry_desc { unsigned long flags; - enum data_queue_qid qid; - u16 length; u16 header_length; @@ -339,11 +317,8 @@ struct txentry_desc { u16 mpdu_density; short retry_limit; - short aifs; short ifs; short txop; - short cw_min; - short cw_max; enum cipher cipher; u16 key_idx; @@ -365,12 +340,16 @@ struct txentry_desc { * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured * while transfering the data to the hardware. No TX status report will * be expected from the hardware. + * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and + * returned. It is now waiting for the status reporting before the + * entry can be reused again. */ enum queue_entry_flags { ENTRY_BCN_ASSIGNED, ENTRY_OWNER_DEVICE_DATA, ENTRY_DATA_PENDING, - ENTRY_DATA_IO_FAILED + ENTRY_DATA_IO_FAILED, + ENTRY_DATA_STATUS_PENDING, }; /** @@ -417,13 +396,33 @@ enum queue_index { }; /** + * enum data_queue_flags: Status flags for data queues + * + * @QUEUE_STARTED: The queue has been started. Fox RX queues this means the + * device might be DMA'ing skbuffers. TX queues will accept skbuffers to + * be transmitted and beacon queues will start beaconing the configured + * beacons. + * @QUEUE_PAUSED: The queue has been started but is currently paused. + * When this bit is set, the queue has been stopped in mac80211, + * preventing new frames to be enqueued. However, a few frames + * might still appear shortly after the pausing... + */ +enum data_queue_flags { + QUEUE_STARTED, + QUEUE_PAUSED, +}; + +/** * struct data_queue: Data queue * * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to. * @entries: Base address of the &struct queue_entry which are * part of this queue. * @qid: The queue identification, see &enum data_queue_qid. - * @lock: Spinlock to protect index handling. Whenever @index, @index_done or + * @flags: Entry flags, see &enum queue_entry_flags. + * @status_lock: The mutex for protecting the start/stop/flush + * handling on this queue. + * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or * @index_crypt needs to be changed this lock should be grabbed to prevent * index corruption due to concurrency. * @count: Number of frames handled in the queue. @@ -446,8 +445,11 @@ struct data_queue { struct queue_entry *entries; enum data_queue_qid qid; + unsigned long flags; + + struct mutex status_lock; + spinlock_t index_lock; - spinlock_t lock; unsigned int count; unsigned short limit; unsigned short threshold; @@ -618,10 +620,10 @@ static inline int rt2x00queue_threshold(struct data_queue *queue) } /** - * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts + * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports * @queue: Queue to check. */ -static inline int rt2x00queue_timeout(struct data_queue *queue) +static inline int rt2x00queue_status_timeout(struct data_queue *queue) { return time_after(queue->last_action[Q_INDEX_DMA_DONE], queue->last_action[Q_INDEX_DONE] + (HZ / 10)); diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index cef94621cef7..e8259ae48ced 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -83,10 +83,6 @@ enum dev_state { */ STATE_RADIO_ON, STATE_RADIO_OFF, - STATE_RADIO_RX_ON, - STATE_RADIO_RX_OFF, - STATE_RADIO_RX_ON_LINK, - STATE_RADIO_RX_OFF_LINK, STATE_RADIO_IRQ_ON, STATE_RADIO_IRQ_OFF, STATE_RADIO_IRQ_ON_ISR, diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index fc98063de71d..2aa5c38022f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -40,6 +40,8 @@ static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev) kfree(rt2x00dev->eeprom); rt2x00dev->eeprom = NULL; + + iounmap(rt2x00dev->csr.base); } static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) @@ -51,9 +53,9 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) if (!res) return -ENODEV; - rt2x00dev->csr.base = (void __iomem *)KSEG1ADDR(res->start); + rt2x00dev->csr.base = ioremap(res->start, resource_size(res)); if (!rt2x00dev->csr.base) - goto exit; + return -ENOMEM; rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); if (!rt2x00dev->eeprom) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index b3317df7a7d4..1a9937d5aff6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -195,7 +195,8 @@ static void rt2x00usb_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)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; rt2x00usb_work_txdone_entry(entry); @@ -226,9 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Schedule the delayed work for reading the TX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); } static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) @@ -237,8 +236,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; u32 length; + int status; - if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) + if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || + test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) return; /* @@ -253,121 +254,15 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); - if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { + status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (status) { + if (status == -ENODEV) + clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } } -void rt2x00usb_kick_tx_queue(struct data_queue *queue) -{ - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, - rt2x00usb_kick_tx_entry); -} -EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); - -static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) -{ - 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; - - usb_kill_urb(entry_priv->urb); - - /* - * Kill guardian urb (if required by driver). - */ - if ((entry->queue->qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) - usb_kill_urb(bcn_priv->guardian_urb); -} - -void rt2x00usb_kill_tx_queue(struct data_queue *queue) -{ - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, - rt2x00usb_kill_tx_entry); -} -EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); - -static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - unsigned short threshold = queue->threshold; - - WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," - " invoke forced forced reset", queue->qid); - - /* - * Temporarily disable the TX queue, this will force mac80211 - * to use the other queues until this queue has been restored. - * - * Set the queue threshold to the queue limit. This prevents the - * queue from being enabled during the txdone handler. - */ - queue->threshold = queue->limit; - ieee80211_stop_queue(rt2x00dev->hw, queue->qid); - - /* - * Kill all entries in the queue, afterwards we need to - * wait a bit for all URBs to be cancelled. - */ - rt2x00usb_kill_tx_queue(queue); - - /* - * In case that a driver has overriden the txdone_work - * function, we invoke the TX done through there. - */ - rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); - - /* - * Security measure: if the driver did override the - * txdone_work function, and the hardware did arrive - * in a state which causes it to malfunction, it is - * possible that the driver couldn't handle the txdone - * event correctly. So after giving the driver the - * chance to cleanup, we now force a cleanup of any - * leftovers. - */ - if (!rt2x00queue_empty(queue)) { - WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," - " status handling failed, invoke hard reset", queue->qid); - rt2x00usb_work_txdone(&rt2x00dev->txdone_work); - } - - /* - * The queue has been reset, and mac80211 is allowed to use the - * queue again. - */ - queue->threshold = threshold; - ieee80211_wake_queue(rt2x00dev->hw, queue->qid); -} - -static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) -{ - WARNING(queue->rt2x00dev, "TX queue %d status timed out," - " invoke forced tx handler", queue->qid); - - ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); -} - -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)) - rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00queue_timeout(queue)) - rt2x00usb_watchdog_tx_status(queue); - } - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); - /* * RX data handlers. */ @@ -382,7 +277,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work) while (!rt2x00queue_empty(rt2x00dev->rx)) { entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); - if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; /* @@ -424,11 +320,157 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * Schedule the delayed work for reading the RX status * from the device. */ - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && - test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); + ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); } +static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) +{ + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + int status; + + if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || + test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) + return; + + rt2x00lib_dmastart(entry); + + usb_fill_bulk_urb(entry_priv->urb, usb_dev, + usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint), + entry->skb->data, entry->skb->len, + rt2x00usb_interrupt_rxdone, entry); + + status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (status) { + if (status == -ENODEV) + clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + rt2x00lib_dmadone(entry); + } +} + +void rt2x00usb_kick_queue(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + if (!rt2x00queue_empty(queue)) + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kick_tx_entry); + break; + case QID_RX: + if (!rt2x00queue_full(queue)) + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_kick_rx_entry); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); + +static void rt2x00usb_flush_entry(struct queue_entry *entry) +{ + 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; + + usb_kill_urb(entry_priv->urb); + + /* + * Kill guardian urb (if required by driver). + */ + if ((entry->queue->qid == QID_BEACON) && + (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) + usb_kill_urb(bcn_priv->guardian_urb); +} + +void rt2x00usb_flush_queue(struct data_queue *queue) +{ + struct work_struct *completion; + unsigned int i; + + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00usb_flush_entry); + + /* + * Obtain the queue completion handler + */ + switch (queue->qid) { + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + completion = &queue->rt2x00dev->txdone_work; + break; + case QID_RX: + completion = &queue->rt2x00dev->rxdone_work; + break; + default: + return; + } + + for (i = 0; i < 20; i++) { + /* + * Check if the driver is already done, otherwise we + * have to sleep a little while to give the driver/hw + * the oppurtunity to complete interrupt process itself. + */ + if (rt2x00queue_empty(queue)) + break; + + /* + * Schedule the completion handler manually, when this + * worker function runs, it should cleanup the queue. + */ + ieee80211_queue_work(queue->rt2x00dev->hw, completion); + + /* + * Wait for a little while to give the driver + * the oppurtunity to recover itself. + */ + msleep(10); + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue); + +static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," + " invoke forced forced reset\n", queue->qid); + + rt2x00queue_flush_queue(queue, true); +} + +static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d status timed out," + " invoke forced tx handler\n", queue->qid); + + ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); +} + +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)) + rt2x00usb_watchdog_tx_dma(queue); + if (rt2x00queue_status_timeout(queue)) + rt2x00usb_watchdog_tx_status(queue); + } + } +} +EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); + /* * Radio handlers */ @@ -436,12 +478,6 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, REGISTER_TIMEOUT); - - /* - * The USB version of kill_tx_queue also works - * on the RX queue. - */ - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx); } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); @@ -450,25 +486,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); */ void rt2x00usb_clear_entry(struct queue_entry *entry) { - struct usb_device *usb_dev = - to_usb_device_intf(entry->queue->rt2x00dev->dev); - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - int pipe; - entry->flags = 0; - if (entry->queue->qid == QID_RX) { - pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); - usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, - entry->skb->data, entry->skb->len, - rt2x00usb_interrupt_rxdone, entry); - - set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { - set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); - rt2x00lib_dmadone(entry); - } - } + if (entry->queue->qid == QID_RX) + rt2x00usb_kick_rx_entry(entry); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index c2d997f67b3e..6aaf51fc7ad8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -378,22 +378,22 @@ struct queue_entry_priv_usb_bcn { }; /** - * rt2x00usb_kick_tx_queue - Kick data queue + * rt2x00usb_kick_queue - Kick data queue * @queue: Data queue to kick * * This will walk through all entries of the queue and push all pending * frames to the hardware as a single burst. */ -void rt2x00usb_kick_tx_queue(struct data_queue *queue); +void rt2x00usb_kick_queue(struct data_queue *queue); /** - * rt2x00usb_kill_tx_queue - Kill data queue - * @queue: Data queue to kill + * rt2x00usb_flush_queue - Flush data queue + * @queue: Data queue to stop * * This will walk through all entries of the queue and kill all - * previously kicked frames before they can be send. + * URB's which were send to the device. */ -void rt2x00usb_kill_tx_queue(struct data_queue *queue); +void rt2x00usb_flush_queue(struct data_queue *queue); /** * rt2x00usb_watchdog - Watchdog for USB communication diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index af548c87f108..8de44dd401e0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1140,6 +1140,106 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt61pci_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +static void rt61pci_kick_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BE: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BK: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + default: + break; + } +} + +static void rt61pci_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_AC_VO: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_VI: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BE: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_AC_BK: + rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); + rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); + rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); + break; + case QID_RX: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1616,18 +1716,6 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, enum dev_state state) { @@ -1744,12 +1832,6 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt61pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt61pci_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1789,10 +1871,10 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -1820,7 +1902,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - if (txdesc->qid != QID_BEACON) { + if (entry->queue->qid != QID_BEACON) { rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, skbdesc->skb_dma); @@ -1866,8 +1948,8 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry, * Register descriptor details in skb frame descriptor. */ skbdesc->desc = txd; - skbdesc->desc_len = - (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE; + skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE : + TXD_DESC_SIZE; } /* @@ -1879,6 +1961,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -1900,13 +1983,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry, rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with descriptor to register. + * Write entire beacon with descriptor and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, entry_priv->desc, TXINFO_SIZE); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, - entry->skb->data, entry->skb->len); + entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -1928,37 +2014,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry, entry->skb = NULL; } -static void rt61pci_kick_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - -static void rt61pci_kill_tx_queue(struct data_queue *queue) -{ - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - u32 reg; - - if (queue->qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - return; - } - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - /* * RX control handlers */ @@ -2078,7 +2133,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < TX_ENTRIES; i++) { + for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; @@ -2824,6 +2879,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt61pci_conf_tx, .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -2842,10 +2898,11 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_stats = rt61pci_link_stats, .reset_tuner = rt61pci_reset_tuner, .link_tuner = rt61pci_link_tuner, + .start_queue = rt61pci_start_queue, + .kick_queue = rt61pci_kick_queue, + .stop_queue = rt61pci_stop_queue, .write_tx_desc = rt61pci_write_tx_desc, .write_beacon = rt61pci_write_beacon, - .kick_tx_queue = rt61pci_kick_tx_queue, - .kill_tx_queue = rt61pci_kill_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_shared_key = rt61pci_config_shared_key, .config_pairwise_key = rt61pci_config_pairwise_key, @@ -2857,21 +2914,21 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { }; static const struct data_queue_desc rt61pci_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = 0, /* No DMA required for beacons */ .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci), diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e2e728ab0b2e..e3cd6db76b0e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -412,7 +412,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) @@ -784,25 +784,25 @@ struct hw_pairwise_ta_entry { */ /* - * AC0_BASE_CSR: AC_BK base address. + * AC0_BASE_CSR: AC_VO base address. */ #define AC0_BASE_CSR 0x3400 #define AC0_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC1_BASE_CSR: AC_BE base address. + * AC1_BASE_CSR: AC_VI base address. */ #define AC1_BASE_CSR 0x3404 #define AC1_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC2_BASE_CSR: AC_VI base address. + * AC2_BASE_CSR: AC_BE base address. */ #define AC2_BASE_CSR 0x3408 #define AC2_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * AC3_BASE_CSR: AC_VO base address. + * AC3_BASE_CSR: AC_BK base address. */ #define AC3_BASE_CSR 0x340c #define AC3_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) @@ -814,7 +814,7 @@ struct hw_pairwise_ta_entry { #define MGMT_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) /* - * TX_RING_CSR0: TX Ring size for AC_BK, AC_BE, AC_VI, AC_VO. + * TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK. */ #define TX_RING_CSR0 0x3418 #define TX_RING_CSR0_AC0_RING_SIZE FIELD32(0x000000ff) @@ -833,10 +833,10 @@ struct hw_pairwise_ta_entry { /* * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK. */ #define AIFSN_CSR 0x3420 #define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) @@ -846,10 +846,10 @@ struct hw_pairwise_ta_entry { /* * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK. */ #define CWMIN_CSR 0x3424 #define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) @@ -859,10 +859,10 @@ struct hw_pairwise_ta_entry { /* * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK. */ #define CWMAX_CSR 0x3428 #define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) @@ -883,14 +883,14 @@ struct hw_pairwise_ta_entry { /* * TX_CNTL_CSR: KICK/Abort TX. - * KICK_TX_AC0: For AC_BK. - * KICK_TX_AC1: For AC_BE. - * KICK_TX_AC2: For AC_VI. - * KICK_TX_AC3: For AC_VO. - * ABORT_TX_AC0: For AC_BK. - * ABORT_TX_AC1: For AC_BE. - * ABORT_TX_AC2: For AC_VI. - * ABORT_TX_AC3: For AC_VO. + * KICK_TX_AC0: For AC_VO. + * KICK_TX_AC1: For AC_VI. + * KICK_TX_AC2: For AC_BE. + * KICK_TX_AC3: For AC_BK. + * ABORT_TX_AC0: For AC_VO. + * ABORT_TX_AC1: For AC_VI. + * ABORT_TX_AC2: For AC_BE. + * ABORT_TX_AC3: For AC_BK. */ #define TX_CNTL_CSR 0x3430 #define TX_CNTL_CSR_KICK_TX_AC0 FIELD32(0x00000001) @@ -1010,18 +1010,18 @@ struct hw_pairwise_ta_entry { #define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us. */ #define AC_TXOP_CSR0 0x3474 #define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) #define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us. */ #define AC_TXOP_CSR1 0x3478 #define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 9be8089317e4..0b4e8590cbb7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -40,7 +40,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 0; +static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -1031,6 +1031,55 @@ dynamic_cca_tune: } /* + * Queue handlers. + */ +static void rt73usb_start_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +static void rt73usb_stop_queue(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + u32 reg; + + switch (queue->qid) { + case QID_RX: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); + break; + case QID_BEACON: + rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + break; + default: + break; + } +} + +/* * Firmware functions */ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1324,18 +1373,6 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) /* * Device state switch handlers. */ -static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) { /* @@ -1402,12 +1439,6 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, case STATE_RADIO_OFF: rt73usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt73usb_toggle_rx(rt2x00dev, state); - break; case STATE_RADIO_IRQ_ON: case STATE_RADIO_IRQ_ON_ISR: case STATE_RADIO_IRQ_OFF: @@ -1472,10 +1503,10 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry, rt2x00_desc_write(txd, 0, word); rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid); + rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); @@ -1515,6 +1546,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; unsigned int beacon_base; + unsigned int padding_len; u32 reg; /* @@ -1542,11 +1574,13 @@ static void rt73usb_write_beacon(struct queue_entry *entry, rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); /* - * Write entire beacon with descriptor to register. + * Write entire beacon with descriptor and padding to register. */ + padding_len = roundup(entry->skb->len, 4) - entry->skb->len; + skb_pad(entry->skb, padding_len); beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, - entry->skb->data, entry->skb->len); + rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); /* * Enable beaconing again. @@ -1582,14 +1616,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry) return length; } -static void rt73usb_kill_tx_queue(struct data_queue *queue) -{ - if (queue->qid == QID_BEACON) - rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0); - - rt2x00usb_kill_tx_queue(queue); -} - /* * RX control handlers */ @@ -2264,6 +2290,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt73usb_conf_tx, .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .flush = rt2x00mac_flush, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2280,11 +2307,13 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, .watchdog = rt2x00usb_watchdog, + .start_queue = rt73usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt73usb_stop_queue, + .flush_queue = rt2x00usb_flush_queue, .write_tx_desc = rt73usb_write_tx_desc, .write_beacon = rt73usb_write_beacon, .get_tx_data_len = rt73usb_get_tx_data_len, - .kick_tx_queue = rt2x00usb_kick_tx_queue, - .kill_tx_queue = rt73usb_kill_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_shared_key = rt73usb_config_shared_key, .config_pairwise_key = rt73usb_config_pairwise_key, @@ -2296,21 +2325,21 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { }; static const struct data_queue_desc rt73usb_queue_rx = { - .entry_num = RX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = RXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_tx = { - .entry_num = TX_ENTRIES, + .entry_num = 32, .data_size = DATA_FRAME_SIZE, .desc_size = TXD_DESC_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, + .entry_num = 4, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb), diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 44d5b2bebd39..9f6b470414d3 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -322,7 +322,7 @@ struct hw_pairwise_ta_entry { * DROP_VERSION_ERROR: Drop version error frame. * DROP_MULTICAST: Drop multicast frames. * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. + * DROP_ACK_CTS: Drop received ACK and CTS. */ #define TXRX_CSR0 0x3040 #define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) @@ -689,10 +689,10 @@ struct hw_pairwise_ta_entry { /* * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK. */ #define AIFSN_CSR 0x0400 #define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) @@ -702,10 +702,10 @@ struct hw_pairwise_ta_entry { /* * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK. */ #define CWMIN_CSR 0x0404 #define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) @@ -715,10 +715,10 @@ struct hw_pairwise_ta_entry { /* * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK. */ #define CWMAX_CSR 0x0408 #define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) @@ -727,18 +727,18 @@ struct hw_pairwise_ta_entry { #define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000) /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us. */ #define AC_TXOP_CSR0 0x040c #define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) #define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us. */ #define AC_TXOP_CSR1 0x0410 #define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) |