2011-04-18 13:35:32

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 01/23] Enable WLAN LED on Ralink SoC (rt305x) devices

From: Layne Edwards <[email protected]>

This patch adds WLAN LED support to the mac80211 rt2x00 driver for
Ralink SoC (rt305x) devices. The current WLAN LED drivers in
rt2800lib.c set the LED brightness via an MCU request, but do nothing
for SoC. This patch checks for SoC and sets the register to enable the
WLAN LED (instead of an MCU request). This enables the WLAN LED for
RT305x devices.

Signed-off-by: Layne Edwards <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 60 +++++++++++++++++++++---------
1 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 769c05c..13ccc1b 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -949,25 +949,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
unsigned int ledmode =
rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
EEPROM_FREQ_LED_MODE);
+ u32 reg;

- if (led->type == LED_TYPE_RADIO) {
- rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? 0x20 : 0);
- } else if (led->type == LED_TYPE_ASSOC) {
- rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
- } else if (led->type == LED_TYPE_QUALITY) {
- /*
- * The brightness is divided into 6 levels (0 - 5),
- * The specs tell us the following levels:
- * 0, 1 ,3, 7, 15, 31
- * to determine the level in a simple way we can simply
- * work with bitshifting:
- * (1 << level) - 1
- */
- rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
- (1 << brightness / (LED_FULL / 6)) - 1,
- polarity);
+ /* Check for SoC (SOC devices don't support MCU requests) */
+ if (rt2x00_is_soc(led->rt2x00dev)) {
+ rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+
+ /* Set LED Polarity */
+ rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
+
+ /* Set LED Mode */
+ if (led->type == LED_TYPE_RADIO) {
+ rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
+ enabled ? 3 : 0);
+ } else if (led->type == LED_TYPE_ASSOC) {
+ rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
+ enabled ? 3 : 0);
+ } else if (led->type == LED_TYPE_QUALITY) {
+ rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
+ enabled ? 3 : 0);
+ }
+
+ rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+ } else {
+ if (led->type == LED_TYPE_RADIO) {
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+ enabled ? 0x20 : 0);
+ } else if (led->type == LED_TYPE_ASSOC) {
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+ enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+ } else if (led->type == LED_TYPE_QUALITY) {
+ /*
+ * The brightness is divided into 6 levels (0 - 5),
+ * The specs tell us the following levels:
+ * 0, 1 ,3, 7, 15, 31
+ * to determine the level in a simple way we can simply
+ * work with bitshifting:
+ * (1 << level) - 1
+ */
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+ (1 << brightness / (LED_FULL / 6)) - 1,
+ polarity);
+ }
}
}

--
1.7.2.3



2011-04-28 03:02:37

by Yasushi SHOJI

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

At Mon, 18 Apr 2011 15:27:43 +0200,
Ivo van Doorn wrote:
>
> From: Helmut Schaa <helmut.schaa-gM/[email protected]>
>
> Allow passing a void pointer to rt2x00_queue_entry_for_each which in
> turn in provided to the callback function.
>
> Furthermore, allow the callback function to stop processing by returning
> true. And also notify the caller of rt2x00_queue_entry_for_each if the
> loop was canceled by the callback.

My colleague just tested this patch set and found out that the in
question makes our 400MHz ARM cpu board with ralink usb dongle non
functional due to high cpu consumption. it seems for us that exiting
from function every time it finds an entry is too expensive on systems
slower than PCs.

To verify our thought, we changed the source code as the patch below.
What we intended to do with this change is to continue processing all
entry without breaking semantics.

With the patch below our board seem to work fine again, but not sure
exactly why it takes so much time to check the list again. We are not
against the idea of the patch at all. We just want to ask you guys
how we should go to track this problem. it might be the slow usb?

Thanks,

> diff -urN compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c
> --- compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-04-27 04:04:26.000000000 +0900
> +++ compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-04-27 17:13:45.000000000 +0900
> @@ -740,6 +740,7 @@
> unsigned int index_start;
> unsigned int index_end;
> unsigned int i;
> + bool ret = false;
>
> if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
> ERROR(queue->rt2x00dev,
> @@ -766,21 +767,21 @@
> if (index_start < index_end) {
> for (i = index_start; i < index_end; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
> } else {
> for (i = index_start; i < queue->limit; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
>
> for (i = 0; i < index_end; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
> }
>
> - return false;
> + return ret;
> }
> EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
--
yashi

2011-04-18 14:14:14

by Rafał Miłecki

[permalink] [raw]
Subject: Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

W dniu 18 kwietnia 2011 16:06 użytkownik Ivo Van Doorn
<[email protected]> napisał:
> Hi,
>
>>> All register reads/writes in rt2800usb were previously done with
>>> rt2800_register_read/rt2800_register_write. These however indirectly
>>> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
>>> additional overhead of at least one call and several move instructions
>>> to each register access.
>>>
>>> Replacing the calls to rt2800_register_read/rt2800_register_write with
>>> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
>>> rid of quite a number of instructions in the drivers hotpaths (IRQ
>>> handling and txdone handling).
>>>
>>> For consistency replace all references to rt2800_register_read/write
>>> with the rt2x00usb_register_read/write variants.
>>
>> This way you loose abstraction of writes/reads for usb vs. pci. And
>> you still can not optimize rt2800lib code which is shared between usb
>> and pci.
>
> Well the rt2800lib code is not changed by this (or patch 20 of this series).
>
>> Wouldn't this be better to create two pointers in struct rt2x00_dev.
>> One for writing function and one for reading function? Am I right
>> thinking calling functions by pointers is quite fast? Or is this still
>> noticeably slower than using proper functions directly?
>
> We already have the pointer inside struct rt2x00_dev which references
> the register access functions for rt2800pci/usb. These pointers are used
> by rt2800lib to access the common registers. What this patch does, is
> optimize the case where we exactly know which function we need, because
> we are in the actual driver.

Ah, OK, I can see rt2800_register_read/write indeed are using pointers:
rt2800ops->register_read(rt2x00dev, offset, value);
So I believe it was still not fast enough for you.

It's OK then. I just though you were using
if (dev->usb)
rt2x00usb_register_read
else
...


> As for the performance, I'll let Helmut comment on that as he created patch 20,
> which introduced this change to rt2800pci. :)

--
Rafał

2011-04-18 13:36:18

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 20/23] rt2x00: Optimize register access in rt2800pci

From: Helmut Schaa <[email protected]>

All register reads/writes in rt2800pci were previously done with
rt2800_register_read/rt2800_register_write. These however indirectly
call rt2x00pci_register_read/rt2x00pci_register_write which adds an
additional overhead of at least one call and several move instructions
to each register access.

Replacing the calls to rt2800_register_read/rt2800_register_write with
direct calls to rt2x00pci_register_read/rt2x00pci_register_write gets
rid of quite a number of instructions in the drivers hotpaths (IRQ
handling and txdone handling).

For consistency replace all references to rt2800_register_read/write
with the rt2x00pci_register_read/write variants.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800pci.c | 158 ++++++++++++++++--------------
1 files changed, 84 insertions(+), 74 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6f91a9a..b0c729b 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
return;

for (i = 0; i < 200; i++) {
- rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);

if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
if (i == 200)
ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");

- rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}

#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
@@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;

- rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);

eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);

- rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
}

static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
struct eeprom_93cx6 eeprom;
u32 reg;

- rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);

eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
@@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue)

switch (queue->qid) {
case QID_RX:
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
/*
@@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue)
tasklet_enable(&rt2x00dev->tbtt_tasklet);
tasklet_enable(&rt2x00dev->pretbtt_tasklet);

- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);

- rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
- rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
break;
default:
break;
@@ -233,11 +233,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
case QID_AC_BE:
case QID_AC_BK:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+ entry->entry_idx);
break;
case QID_MGMT:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
+ entry->entry_idx);
break;
default:
break;
@@ -251,20 +253,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)

switch (queue->qid) {
case QID_RX:
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);

- rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
- rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);

/*
* Wait for tbtt tasklets to finish.
@@ -295,7 +297,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
reg = 0;
rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);

/*
* Write firmware to device.
@@ -303,11 +305,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
data, len);

- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);

- rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);

return 0;
}
@@ -351,7 +353,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
* Set RX IDX in register to inform hardware that we have
* handled this entry and it is available for reuse again.
*/
- rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+ rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
entry->entry_idx);
} else {
rt2x00_desc_read(entry_priv->desc, 1, &word);
@@ -369,45 +371,51 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
* Initialize registers.
*/
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
- rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0);
- rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
+ rt2x00dev->tx[0].limit);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);

entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
- rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0);
- rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
+ rt2x00dev->tx[1].limit);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);

entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
- rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0);
- rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
+ rt2x00dev->tx[2].limit);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);

entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
- rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
- rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0);
- rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
+ rt2x00dev->tx[3].limit);
+ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);

entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
- rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
- rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
- rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0);
+ rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
+ rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
+ rt2x00dev->rx[0].limit);
+ rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
+ rt2x00dev->rx[0].limit - 1);
+ rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);

/*
* Enable global DMA configuration
*/
- rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);

- rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+ rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);

return 0;
}
@@ -427,8 +435,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);

/*
* Enable tasklets. The beacon related tasklets are
@@ -440,7 +448,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}

spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
@@ -459,7 +467,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
- rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);

if (state == STATE_RADIO_IRQ_OFF) {
@@ -480,7 +488,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Reset DMA indexes
*/
- rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -488,26 +496,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);

- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);

if (rt2x00_rt(rt2x00dev, RT5390)) {
- rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+ rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
- rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+ rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
}

- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+ rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);

- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);

- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);

return 0;
}
@@ -525,8 +533,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00_is_soc(rt2x00dev)) {
rt2800_disable_radio(rt2x00dev);
- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
}
}

@@ -537,8 +545,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
} else if (state == STATE_SLEEP) {
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+ 0xffffffff);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
+ 0xffffffff);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
}

@@ -778,9 +788,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
* access needs locking.
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 1);
- rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}

@@ -851,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* need to lock the kfifo.
*/
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+ rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);

if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break;
@@ -873,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
u32 reg, mask;

/* Read status and ACK all interrupts */
- rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);

if (!reg)
return IRQ_NONE;
@@ -914,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
* the tasklet will reenable the appropriate interrupts.
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
reg &= mask;
- rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);

return IRQ_HANDLED;
--
1.7.2.3


2011-04-18 13:36:20

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

From: Ivo van Doorn <[email protected]>

All register reads/writes in rt2800usb were previously done with
rt2800_register_read/rt2800_register_write. These however indirectly
call rt2x00usb_register_read/rt2x00usb_register_write which adds an
additional overhead of at least one call and several move instructions
to each register access.

Replacing the calls to rt2800_register_read/rt2800_register_write with
direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
rid of quite a number of instructions in the drivers hotpaths (IRQ
handling and txdone handling).

For consistency replace all references to rt2800_register_read/write
with the rt2x00usb_register_read/write variants.

Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 56 +++++++++++++++---------------
1 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index fd8aa99..44ead75 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue)

switch (queue->qid) {
case QID_RX:
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
@@ -82,16 +82,16 @@ static void rt2800usb_stop_queue(struct data_queue *queue)

switch (queue->qid) {
case QID_RX:
- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
@@ -185,11 +185,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Write firmware to device.
*/
- rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data + offset, length);
+ rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data + offset, length);

- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);

/*
* Send firmware request to device to load firmware,
@@ -204,7 +204,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
}

msleep(10);
- rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);

return 0;
}
@@ -222,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2800_wait_csr_ready(rt2x00dev))
return -EBUSY;

- rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+ rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);

- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+ rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);

- rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);

- rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+ rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);

rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
USB_MODE_RESET, REGISTER_TIMEOUT);

- rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+ rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);

return 0;
}
@@ -249,7 +249,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
return -EIO;

- rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+ rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
@@ -262,7 +262,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
/ 1024) - 3);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
- rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
+ rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);

return rt2800_enable_radio(rt2x00dev);
}
@@ -338,12 +338,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
unsigned int i;
u32 reg;

- rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
WARNING(rt2x00dev, "TX HW queue 0 timed out,"
" invoke forced kick\n");

- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);

for (i = 0; i < 10; i++) {
udelay(10);
@@ -351,15 +351,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
break;
}

- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
}

- rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
WARNING(rt2x00dev, "TX HW queue 1 timed out,"
" invoke forced kick\n");

- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);

for (i = 0; i < 10; i++) {
udelay(10);
@@ -367,7 +367,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
break;
}

- rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+ rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
}

rt2x00usb_watchdog(rt2x00dev);
--
1.7.2.3


2011-04-18 13:36:01

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO

From: Johannes Stezenbach <[email protected]>

TX status is reported by the hardware when a packet has been
sent (or after TX failed after possible retries), which is some
time after the DMA completion. Since the rt2800usb hardware can
not signal interrupts we have to use a timer, otherwise the
TX status would only be read by the next packet's TX DMA
completion, or by the watchdog thread.

Signed-off-by: Johannes Stezenbach <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 41 ++++++++++++++++++++++++++++++-
drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++
drivers/net/wireless/rt2x00/rt2x00dev.c | 1 +
drivers/net/wireless/rt2x00/rt2x00usb.c | 5 +++-
4 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 69004b9..2005972 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -98,6 +98,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
}
}

+/*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+
+ tx_queue_for_each(rt2x00dev, queue) {
+ if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+ rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+ return true;
+ }
+ return false;
+}
+
static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
int urb_status, u32 tx_status)
{
@@ -115,8 +131,11 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
} else
rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
rt2800usb_tx_sta_fifo_read_completed);
- } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+ } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+ } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+ mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
+ }
}

static void rt2800usb_tx_dma_done(struct queue_entry *entry)
@@ -127,6 +146,14 @@ static void rt2800usb_tx_dma_done(struct queue_entry *entry)
rt2800usb_tx_sta_fifo_read_completed);
}

+static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+ rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+ rt2800usb_tx_sta_fifo_read_completed);
+}
+
/*
* Firmware functions
*/
@@ -459,6 +486,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
break;
}
}
+
+ /*
+ * The hw may delay sending the packet after DMA complete
+ * if the medium is busy, thus the TX_STA_FIFO entry is
+ * also delayed -> use a timer to retrieve it.
+ */
+ if (rt2800usb_txstatus_pending(rt2x00dev))
+ mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
}

/*
@@ -599,6 +634,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);

+ setup_timer(&rt2x00dev->txstatus_timer,
+ rt2800usb_tx_sta_fifo_timeout,
+ (unsigned long) rt2x00dev);
+
/*
* Set the rssi offset.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index e3b9b51..8f37121 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -37,6 +37,7 @@
#include <linux/etherdevice.h>
#include <linux/input-polldev.h>
#include <linux/kfifo.h>
+#include <linux/timer.h>

#include <net/mac80211.h>

@@ -924,6 +925,11 @@ struct rt2x00_dev {
DECLARE_KFIFO_PTR(txstatus_fifo, u32);

/*
+ * Timer to ensure tx status reports are read (rt2800usb).
+ */
+ struct timer_list txstatus_timer;
+
+ /*
* Tasklet for processing tx status reports (rt2800pci).
*/
struct tasklet_struct txstatus_tasklet;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2e490e0..7776d9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
/*
* Stop all work.
*/
+ del_timer_sync(&rt2x00dev->txstatus_timer);
cancel_work_sync(&rt2x00dev->intf_work);
if (rt2x00_is_usb(rt2x00dev)) {
cancel_work_sync(&rt2x00dev->rxdone_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 14736e2..34b8a88 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -280,7 +280,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
* Schedule the delayed work for reading the TX status
* from the device.
*/
- queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+ if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
+ !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
}

static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
@@ -816,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,

INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+ init_timer(&rt2x00dev->txstatus_timer);

retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
--
1.7.2.3


2011-04-18 13:56:14

by Rafał Miłecki

[permalink] [raw]
Subject: Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

Hello Ivo,

I don't develop rt2x00 and I'm not sure about my solution, so of
course decision is up to you, just wanted to suggest you sth.

2011/4/18 Ivo van Doorn <[email protected]>:
> From: Ivo van Doorn <[email protected]>
>
> All register reads/writes in rt2800usb were previously done with
> rt2800_register_read/rt2800_register_write. These however indirectly
> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
> additional overhead of at least one call and several move instructions
> to each register access.
>
> Replacing the calls to rt2800_register_read/rt2800_register_write with
> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
> rid of quite a number of instructions in the drivers hotpaths (IRQ
> handling and txdone handling).
>
> For consistency replace all references to rt2800_register_read/write
> with the rt2x00usb_register_read/write variants.

This way you loose abstraction of writes/reads for usb vs. pci. And
you still can not optimize rt2800lib code which is shared between usb
and pci.

Wouldn't this be better to create two pointers in struct rt2x00_dev.
One for writing function and one for reading function? Am I right
thinking calling functions by pointers is quite fast? Or is this still
noticeably slower than using proper functions directly?

--
Rafał

2011-04-18 13:35:44

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

From: Helmut Schaa <[email protected]>

Allow passing a void pointer to rt2x00_queue_entry_for_each which in
turn in provided to the callback function.

Furthermore, allow the callback function to stop processing by returning
true. And also notify the caller of rt2x00_queue_entry_for_each if the
loop was canceled by the callback.

No functional changes, just preparation for an upcoming patch.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00queue.c | 28 +++++++++++++++++--------
drivers/net/wireless/rt2x00/rt2x00queue.h | 10 +++++++-
drivers/net/wireless/rt2x00/rt2x00usb.c | 32 +++++++++++++++++++---------
3 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index d03eef2..458bb48 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -650,10 +650,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
return ret;
}

-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
enum queue_index start,
enum queue_index end,
- void (*fn)(struct queue_entry *entry))
+ void *data,
+ bool (*fn)(struct queue_entry *entry,
+ void *data))
{
unsigned long irqflags;
unsigned int index_start;
@@ -664,7 +666,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
ERROR(queue->rt2x00dev,
"Entry requested from invalid index range (%d - %d)\n",
start, end);
- return;
+ return true;
}

/*
@@ -683,15 +685,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
* send out all frames in the correct order.
*/
if (index_start < index_end) {
- for (i = index_start; i < index_end; i++)
- fn(&queue->entries[i]);
+ for (i = index_start; i < index_end; i++) {
+ if (fn(&queue->entries[i], data))
+ return true;
+ }
} else {
- for (i = index_start; i < queue->limit; i++)
- fn(&queue->entries[i]);
+ for (i = index_start; i < queue->limit; i++) {
+ if (fn(&queue->entries[i], data))
+ return true;
+ }

- for (i = 0; i < index_end; i++)
- fn(&queue->entries[i]);
+ for (i = 0; i < index_end; i++) {
+ if (fn(&queue->entries[i], data))
+ return true;
+ }
}
+
+ return false;
}
EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 6ae8200..6b66452 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -580,16 +580,22 @@ struct data_queue_desc {
* @queue: Pointer to @data_queue
* @start: &enum queue_index Pointer to start index
* @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
* @fn: The function to call for each &struct queue_entry
*
* This will walk through all entries in the queue, in chronological
* order. This means it will start at the current @start pointer
* and will walk through the queue until it reaches the @end pointer.
+ *
+ * If fn returns true for an entry rt2x00queue_for_each_entry will stop
+ * processing and return true as well.
*/
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
enum queue_index start,
enum queue_index end,
- void (*fn)(struct queue_entry *entry));
+ void *data,
+ bool (*fn)(struct queue_entry *entry,
+ void *data));

/**
* rt2x00queue_empty - Check if the queue is empty.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 94047e9..0bc8dcc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -230,7 +230,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
}

-static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -240,7 +240,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)

if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- return;
+ return true;

/*
* USB devices cannot blindly pass the skb->len as the
@@ -261,6 +261,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
+
+ return false;
}

/*
@@ -323,7 +325,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
}

-static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -332,7 +334,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)

if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- return;
+ return true;

rt2x00lib_dmastart(entry);

@@ -348,6 +350,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
+
+ return false;
}

void rt2x00usb_kick_queue(struct data_queue *queue)
@@ -358,12 +362,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
case QID_AC_BE:
case QID_AC_BK:
if (!rt2x00queue_empty(queue))
- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+ rt2x00queue_for_each_entry(queue,
+ Q_INDEX_DONE,
+ Q_INDEX,
+ NULL,
rt2x00usb_kick_tx_entry);
break;
case QID_RX:
if (!rt2x00queue_full(queue))
- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+ rt2x00queue_for_each_entry(queue,
+ Q_INDEX_DONE,
+ Q_INDEX,
+ NULL,
rt2x00usb_kick_rx_entry);
break;
default:
@@ -372,14 +382,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
}
EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);

-static void rt2x00usb_flush_entry(struct queue_entry *entry)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;

if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return;
+ return true;

usb_kill_urb(entry_priv->urb);

@@ -389,6 +399,8 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
if ((entry->queue->qid == QID_BEACON) &&
(test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
usb_kill_urb(bcn_priv->guardian_urb);
+
+ return false;
}

void rt2x00usb_flush_queue(struct data_queue *queue)
@@ -396,7 +408,7 @@ 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,
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
rt2x00usb_flush_entry);

/*
@@ -489,7 +501,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
entry->flags = 0;

if (entry->queue->qid == QID_RX)
- rt2x00usb_kick_rx_entry(entry);
+ rt2x00usb_kick_rx_entry(entry, NULL);
}
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);

--
1.7.2.3


2011-04-18 13:36:13

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental.

From: Gertjan van Wingerde <[email protected]>

The rt33xx devices support for both PCI and USB devices has been in
the tree for a couple of months now, and seems to be functional and
not in a worse shape than the support for rt28xx and rt30xx devices.

No longer mark it as experimental and enable the support for these
devices by default.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/Kconfig | 16 ++++------------
1 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index f630552..e7e361e 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -74,17 +74,13 @@ config RT2800PCI
if RT2800PCI

config RT2800PCI_RT33XX
- bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- default n
+ bool "rt2800pci - Include support for rt33xx devices"
+ default y
---help---
This adds support for rt33xx wireless chipset family to the
rt2800pci driver.
Supported chips: RT3390

- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
config RT2800PCI_RT35XX
bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
@@ -153,17 +149,13 @@ config RT2800USB
if RT2800USB

config RT2800USB_RT33XX
- bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- default n
+ bool "rt2800usb - Include support for rt33xx devices"
+ default y
---help---
This adds support for rt33xx wireless chipset family to the
rt2800usb driver.
Supported chips: RT3370

- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
config RT2800USB_RT35XX
bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
--
1.7.2.3


2011-04-18 13:36:05

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt

From: Helmut Schaa <[email protected]>

This allows the compiler to perform the necessary bitfield calculations
during compile time instead of run time and thus reduces the number of
instructions to run during each tasklet invocation. This should improve
performance in the RX hotpath.

This comes at the cost of a slight increase in the module size (for
example rt2800pci):

Before:
text data bss dec hex filename
14133 832 4 14969 3a79 drivers/net/wireless/rt2x00/rt2800pci.ko

After:
text data bss dec hex filename
14149 832 4 14985 3a89 drivers/net/wireless/rt2x00/rt2800pci.ko

Signed-off-by: Helmut Schaa <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 4 ++--
drivers/net/wireless/rt2x00/rt2500pci.c | 4 ++--
drivers/net/wireless/rt2x00/rt2800pci.c | 4 ++--
drivers/net/wireless/rt2x00/rt61pci.c | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6b7206e..01e9517 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}

-static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
+static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
{
u32 reg;

diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 82e8012..c8deeeb 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}

-static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
+static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
{
u32 reg;

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index d2fe5fd..46c3e3c 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -768,8 +768,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
return !max_tx_done;
}

-static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
+static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
{
u32 reg;

diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 35c5d20..264508f 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}

-static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_field32 irq_field)
+static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_field32 irq_field)
{
u32 reg;

--
1.7.2.3


2011-04-18 14:06:07

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

Hi,

>> All register reads/writes in rt2800usb were previously done with
>> rt2800_register_read/rt2800_register_write. These however indirectly
>> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
>> additional overhead of at least one call and several move instructions
>> to each register access.
>>
>> Replacing the calls to rt2800_register_read/rt2800_register_write with
>> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
>> rid of quite a number of instructions in the drivers hotpaths (IRQ
>> handling and txdone handling).
>>
>> For consistency replace all references to rt2800_register_read/write
>> with the rt2x00usb_register_read/write variants.
>
> This way you loose abstraction of writes/reads for usb vs. pci. And
> you still can not optimize rt2800lib code which is shared between usb
> and pci.

Well the rt2800lib code is not changed by this (or patch 20 of this series).

> Wouldn't this be better to create two pointers in struct rt2x00_dev.
> One for writing function and one for reading function? Am I right
> thinking calling functions by pointers is quite fast? Or is this still
> noticeably slower than using proper functions directly?

We already have the pointer inside struct rt2x00_dev which references
the register access functions for rt2800pci/usb. These pointers are used
by rt2800lib to access the common registers. What this patch does, is
optimize the case where we exactly know which function we need, because
we are in the actual driver.

As for the performance, I'll let Helmut comment on that as he created patch 20,
which introduced this change to rt2800pci. :)

Ivo

2011-04-18 13:36:10

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs.

From: Gertjan van Wingerde <[email protected]>

Both USB and PCI drivers allow a system administrator to dynamically add
USB/PCI IDs to the device table that a driver supports via the
/sys/bus/{usb,pci,pci_express}/drivers/<driver-name>/new_id files.

However, for the rt2x00 drivers using this method currently crashes the
system with a NULL pointer failure.

This is due to the set-up of rt2x00 where the probe functions require a
rt2x00_ops structure in the driver_info field of the probed device. As
this field is empty for the dynamically added devices this fails for
these devices.

Fix this by introducing driver-specific probe wrappers that do nothing
but calling the bus-specific probe functions with the rt2x00_ops structure
as an argument, rather than depending on the driver_info field.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 11 +-
drivers/net/wireless/rt2x00/rt2500pci.c | 10 +-
drivers/net/wireless/rt2x00/rt2500usb.c | 70 +++---
drivers/net/wireless/rt2x00/rt2800pci.c | 58 +++--
drivers/net/wireless/rt2x00/rt2800usb.c | 440 ++++++++++++++++---------------
drivers/net/wireless/rt2x00/rt2x00pci.c | 3 +-
drivers/net/wireless/rt2x00/rt2x00pci.h | 2 +-
drivers/net/wireless/rt2x00/rt2x00usb.c | 3 +-
drivers/net/wireless/rt2x00/rt2x00usb.h | 8 +-
drivers/net/wireless/rt2x00/rt61pci.c | 14 +-
drivers/net/wireless/rt2x00/rt73usb.c | 154 ++++++-----
11 files changed, 404 insertions(+), 369 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 01e9517..d4acdde 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1802,10 +1802,11 @@ static const struct rt2x00_ops rt2400pci_ops = {
* RT2400pci module information.
*/
static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
- { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0101) },
{ 0, }
};

+
MODULE_AUTHOR(DRV_PROJECT);
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
@@ -1813,10 +1814,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
MODULE_LICENSE("GPL");

+static int rt2400pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
static struct pci_driver rt2400pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2400pci_device_table,
- .probe = rt2x00pci_probe,
+ .probe = rt2400pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c8deeeb..15f5649 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2095,7 +2095,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
* RT2500pci module information.
*/
static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
- { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0201) },
{ 0, }
};

@@ -2106,10 +2106,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
MODULE_LICENSE("GPL");

+static int rt2500pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
static struct pci_driver rt2500pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2500pci_device_table,
- .probe = rt2x00pci_probe,
+ .probe = rt2500pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index dbbd8bc..d88c367 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1904,54 +1904,54 @@ static const struct rt2x00_ops rt2500usb_ops = {
*/
static struct usb_device_id rt2500usb_device_table[] = {
/* ASUS */
- { USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1706) },
+ { USB_DEVICE(0x0b05, 0x1707) },
/* Belkin */
- { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x050d, 0x7050) },
+ { USB_DEVICE(0x050d, 0x7051) },
/* Cisco Systems */
- { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x13b1, 0x000d) },
+ { USB_DEVICE(0x13b1, 0x0011) },
+ { USB_DEVICE(0x13b1, 0x001a) },
/* Conceptronic */
- { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c02) },
/* D-LINK */
- { USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x2001, 0x3c00) },
/* Gigabyte */
- { USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x1044, 0x8001) },
+ { USB_DEVICE(0x1044, 0x8007) },
/* Hercules */
- { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x06f8, 0xe000) },
/* Melco */
- { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0411, 0x005e) },
+ { USB_DEVICE(0x0411, 0x0066) },
+ { USB_DEVICE(0x0411, 0x0067) },
+ { USB_DEVICE(0x0411, 0x008b) },
+ { USB_DEVICE(0x0411, 0x0097) },
/* MSI */
- { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0db0, 0x6861) },
+ { USB_DEVICE(0x0db0, 0x6865) },
+ { USB_DEVICE(0x0db0, 0x6869) },
/* Ralink */
- { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) },
- { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x148f, 0x1706) },
+ { USB_DEVICE(0x148f, 0x2570) },
+ { USB_DEVICE(0x148f, 0x9020) },
/* Sagem */
- { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x079b, 0x004b) },
/* Siemens */
- { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0681, 0x3c06) },
/* SMC */
- { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0707, 0xee13) },
/* Spairon */
- { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x114b, 0x0110) },
/* SURECOM */
- { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0769, 0x11f3) },
/* Trust */
- { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0eb0, 0x9020) },
/* VTech */
- { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x0f88, 0x3012) },
/* Zinwell */
- { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0260) },
{ 0, }
};

@@ -1962,10 +1962,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
MODULE_LICENSE("GPL");

+static int rt2500usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
static struct usb_driver rt2500usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2500usb_device_table,
- .probe = rt2x00usb_probe,
+ .probe = rt2500usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 46c3e3c..6f91a9a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1117,36 +1117,36 @@ static const struct rt2x00_ops rt2800pci_ops = {
*/
#ifdef CONFIG_PCI
static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
- { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0601) },
+ { PCI_DEVICE(0x1814, 0x0681) },
+ { PCI_DEVICE(0x1814, 0x0701) },
+ { PCI_DEVICE(0x1814, 0x0781) },
+ { PCI_DEVICE(0x1814, 0x3090) },
+ { PCI_DEVICE(0x1814, 0x3091) },
+ { PCI_DEVICE(0x1814, 0x3092) },
+ { PCI_DEVICE(0x1432, 0x7708) },
+ { PCI_DEVICE(0x1432, 0x7727) },
+ { PCI_DEVICE(0x1432, 0x7728) },
+ { PCI_DEVICE(0x1432, 0x7738) },
+ { PCI_DEVICE(0x1432, 0x7748) },
+ { PCI_DEVICE(0x1432, 0x7758) },
+ { PCI_DEVICE(0x1432, 0x7768) },
+ { PCI_DEVICE(0x1462, 0x891a) },
+ { PCI_DEVICE(0x1a3b, 0x1059) },
#ifdef CONFIG_RT2800PCI_RT33XX
- { PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x3390) },
#endif
#ifdef CONFIG_RT2800PCI_RT35XX
- { PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
- { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1432, 0x7711) },
+ { PCI_DEVICE(0x1432, 0x7722) },
+ { PCI_DEVICE(0x1814, 0x3060) },
+ { PCI_DEVICE(0x1814, 0x3062) },
+ { PCI_DEVICE(0x1814, 0x3562) },
+ { PCI_DEVICE(0x1814, 0x3592) },
+ { PCI_DEVICE(0x1814, 0x3593) },
#endif
#ifdef CONFIG_RT2800PCI_RT53XX
- { PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+ { PCI_DEVICE(0x1814, 0x5390) },
#endif
{ 0, }
};
@@ -1182,10 +1182,16 @@ static struct platform_driver rt2800soc_driver = {
#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */

#ifdef CONFIG_PCI
+static int rt2800pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
+}
+
static struct pci_driver rt2800pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2800pci_device_table,
- .probe = rt2x00pci_probe,
+ .probe = rt2800pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 1bb9a7d..6f7c161 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -768,230 +768,230 @@ static const struct rt2x00_ops rt2800usb_ops = {
*/
static struct usb_device_id rt2800usb_device_table[] = {
/* Abocom */
- { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07b8, 0x2870) },
+ { USB_DEVICE(0x07b8, 0x2770) },
+ { USB_DEVICE(0x07b8, 0x3070) },
+ { USB_DEVICE(0x07b8, 0x3071) },
+ { USB_DEVICE(0x07b8, 0x3072) },
+ { USB_DEVICE(0x1482, 0x3c09) },
/* AirTies */
- { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1eda, 0x2310) },
/* Allwin */
- { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x8516, 0x2070) },
+ { USB_DEVICE(0x8516, 0x2770) },
+ { USB_DEVICE(0x8516, 0x2870) },
+ { USB_DEVICE(0x8516, 0x3070) },
+ { USB_DEVICE(0x8516, 0x3071) },
+ { USB_DEVICE(0x8516, 0x3072) },
/* Alpha Networks */
- { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c2c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c06) },
+ { USB_DEVICE(0x14b2, 0x3c07) },
+ { USB_DEVICE(0x14b2, 0x3c09) },
+ { USB_DEVICE(0x14b2, 0x3c12) },
+ { USB_DEVICE(0x14b2, 0x3c23) },
+ { USB_DEVICE(0x14b2, 0x3c25) },
+ { USB_DEVICE(0x14b2, 0x3c27) },
+ { USB_DEVICE(0x14b2, 0x3c28) },
+ { USB_DEVICE(0x14b2, 0x3c2c) },
/* Amit */
- { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x15c5, 0x0008) },
/* Askey */
- { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1690, 0x0740) },
/* ASUS */
- { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1731) },
+ { USB_DEVICE(0x0b05, 0x1732) },
+ { USB_DEVICE(0x0b05, 0x1742) },
+ { USB_DEVICE(0x0b05, 0x1784) },
+ { USB_DEVICE(0x1761, 0x0b05) },
/* AzureWave */
- { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3247) },
+ { USB_DEVICE(0x13d3, 0x3273) },
+ { USB_DEVICE(0x13d3, 0x3305) },
+ { USB_DEVICE(0x13d3, 0x3307) },
+ { USB_DEVICE(0x13d3, 0x3321) },
/* Belkin */
- { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x050d, 0x8053) },
+ { USB_DEVICE(0x050d, 0x805c) },
+ { USB_DEVICE(0x050d, 0x815c) },
+ { USB_DEVICE(0x050d, 0x825b) },
+ { USB_DEVICE(0x050d, 0x935a) },
+ { USB_DEVICE(0x050d, 0x935b) },
/* Buffalo */
- { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x01a2), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0411, 0x00e8) },
+ { USB_DEVICE(0x0411, 0x016f) },
+ { USB_DEVICE(0x0411, 0x01a2) },
/* Corega */
- { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07aa, 0x002f) },
+ { USB_DEVICE(0x07aa, 0x003c) },
+ { USB_DEVICE(0x07aa, 0x003f) },
+ { USB_DEVICE(0x18c5, 0x0012) },
/* D-Link */
- { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c09) },
+ { USB_DEVICE(0x07d1, 0x3c0a) },
+ { USB_DEVICE(0x07d1, 0x3c0d) },
+ { USB_DEVICE(0x07d1, 0x3c0e) },
+ { USB_DEVICE(0x07d1, 0x3c0f) },
+ { USB_DEVICE(0x07d1, 0x3c11) },
+ { USB_DEVICE(0x07d1, 0x3c16) },
/* Draytek */
- { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07fa, 0x7712) },
/* Edimax */
- { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x7392, 0x7711) },
+ { USB_DEVICE(0x7392, 0x7717) },
+ { USB_DEVICE(0x7392, 0x7718) },
/* Encore */
- { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x203d, 0x1480) },
+ { USB_DEVICE(0x203d, 0x14a9) },
/* EnGenius */
- { USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1740, 0x9701) },
+ { USB_DEVICE(0x1740, 0x9702) },
+ { USB_DEVICE(0x1740, 0x9703) },
+ { USB_DEVICE(0x1740, 0x9705) },
+ { USB_DEVICE(0x1740, 0x9706) },
+ { USB_DEVICE(0x1740, 0x9707) },
+ { USB_DEVICE(0x1740, 0x9708) },
+ { USB_DEVICE(0x1740, 0x9709) },
/* Gemtek */
- { USB_DEVICE(0x15a9, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x15a9, 0x0012) },
/* Gigabyte */
- { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1044, 0x800b) },
+ { USB_DEVICE(0x1044, 0x800d) },
/* Hawking */
- { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0e66, 0x0001) },
+ { USB_DEVICE(0x0e66, 0x0003) },
+ { USB_DEVICE(0x0e66, 0x0009) },
+ { USB_DEVICE(0x0e66, 0x000b) },
+ { USB_DEVICE(0x0e66, 0x0013) },
+ { USB_DEVICE(0x0e66, 0x0017) },
+ { USB_DEVICE(0x0e66, 0x0018) },
/* I-O DATA */
- { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x04bb, 0x0945) },
+ { USB_DEVICE(0x04bb, 0x0947) },
+ { USB_DEVICE(0x04bb, 0x0948) },
/* Linksys */
- { USB_DEVICE(0x13b1, 0x0031), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13b1, 0x0031) },
+ { USB_DEVICE(0x1737, 0x0070) },
+ { USB_DEVICE(0x1737, 0x0071) },
/* Logitec */
- { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0789, 0x0162) },
+ { USB_DEVICE(0x0789, 0x0163) },
+ { USB_DEVICE(0x0789, 0x0164) },
+ { USB_DEVICE(0x0789, 0x0166) },
/* Motorola */
- { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x100d, 0x9031) },
/* MSI */
- { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0db0, 0x3820) },
+ { USB_DEVICE(0x0db0, 0x3821) },
+ { USB_DEVICE(0x0db0, 0x3822) },
+ { USB_DEVICE(0x0db0, 0x3870) },
+ { USB_DEVICE(0x0db0, 0x3871) },
+ { USB_DEVICE(0x0db0, 0x6899) },
+ { USB_DEVICE(0x0db0, 0x821a) },
+ { USB_DEVICE(0x0db0, 0x822a) },
+ { USB_DEVICE(0x0db0, 0x822b) },
+ { USB_DEVICE(0x0db0, 0x822c) },
+ { USB_DEVICE(0x0db0, 0x870a) },
+ { USB_DEVICE(0x0db0, 0x871a) },
+ { USB_DEVICE(0x0db0, 0x871b) },
+ { USB_DEVICE(0x0db0, 0x871c) },
+ { USB_DEVICE(0x0db0, 0x899a) },
/* Para */
- { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x20b8, 0x8888) },
/* Pegatron */
- { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1d4d, 0x000c) },
+ { USB_DEVICE(0x1d4d, 0x000e) },
+ { USB_DEVICE(0x1d4d, 0x0011) },
/* Philips */
- { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0471, 0x200f) },
/* Planex */
- { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x2019, 0xab25) },
+ { USB_DEVICE(0x2019, 0xed06) },
/* Quanta */
- { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1a32, 0x0304) },
/* Ralink */
- { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x2070) },
+ { USB_DEVICE(0x148f, 0x2770) },
+ { USB_DEVICE(0x148f, 0x2870) },
+ { USB_DEVICE(0x148f, 0x3070) },
+ { USB_DEVICE(0x148f, 0x3071) },
+ { USB_DEVICE(0x148f, 0x3072) },
/* Samsung */
- { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x04e8, 0x2018) },
/* Siemens */
- { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x129b, 0x1828) },
/* Sitecom */
- { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0017) },
+ { USB_DEVICE(0x0df6, 0x002b) },
+ { USB_DEVICE(0x0df6, 0x002c) },
+ { USB_DEVICE(0x0df6, 0x002d) },
+ { USB_DEVICE(0x0df6, 0x0039) },
+ { USB_DEVICE(0x0df6, 0x003b) },
+ { USB_DEVICE(0x0df6, 0x003d) },
+ { USB_DEVICE(0x0df6, 0x003e) },
+ { USB_DEVICE(0x0df6, 0x003f) },
+ { USB_DEVICE(0x0df6, 0x0040) },
+ { USB_DEVICE(0x0df6, 0x0042) },
+ { USB_DEVICE(0x0df6, 0x0047) },
+ { USB_DEVICE(0x0df6, 0x0048) },
/* SMC */
- { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0x6618) },
+ { USB_DEVICE(0x083a, 0x7511) },
+ { USB_DEVICE(0x083a, 0x7512) },
+ { USB_DEVICE(0x083a, 0x7522) },
+ { USB_DEVICE(0x083a, 0x8522) },
+ { USB_DEVICE(0x083a, 0xa618) },
+ { USB_DEVICE(0x083a, 0xa701) },
+ { USB_DEVICE(0x083a, 0xa702) },
+ { USB_DEVICE(0x083a, 0xa703) },
+ { USB_DEVICE(0x083a, 0xb522) },
/* Sparklan */
- { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x15a9, 0x0006) },
/* Sweex */
- { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x177f, 0x0302) },
/* U-Media */
- { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x157e, 0x3013), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x157e, 0x300e) },
+ { USB_DEVICE(0x157e, 0x3013) },
/* ZCOM */
- { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0cde, 0x0022) },
+ { USB_DEVICE(0x0cde, 0x0025) },
/* Zinwell */
- { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0280) },
+ { USB_DEVICE(0x5a57, 0x0282) },
+ { USB_DEVICE(0x5a57, 0x0283) },
+ { USB_DEVICE(0x5a57, 0x5257) },
/* Zyxel */
- { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0586, 0x341e), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0586, 0x3416) },
+ { USB_DEVICE(0x0586, 0x3418) },
+ { USB_DEVICE(0x0586, 0x341e) },
#ifdef CONFIG_RT2800USB_RT33XX
/* Ralink */
- { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3370) },
+ { USB_DEVICE(0x148f, 0x8070) },
/* Sitecom */
- { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0050) },
#endif
#ifdef CONFIG_RT2800USB_RT35XX
/* Allwin */
- { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x8516, 0x3572) },
/* Askey */
- { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1690, 0x0744) },
/* Cisco */
- { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x167b, 0x4001) },
/* EnGenius */
- { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1740, 0x9801) },
/* I-O DATA */
- { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x04bb, 0x0944) },
/* Linksys */
- { USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13b1, 0x002f) },
+ { USB_DEVICE(0x1737, 0x0079) },
/* Ralink */
- { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x148f, 0x3572) },
/* Sitecom */
- { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0041) },
/* Toshiba */
- { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0930, 0x0a07) },
/* Zinwell */
- { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x5a57, 0x0284) },
#endif
#ifdef CONFIG_RT2800USB_UNKNOWN
/*
@@ -999,73 +999,73 @@ static struct usb_device_id rt2800usb_device_table[] = {
* vendor linux driver).
*/
/* Alpha Networks */
- { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c08) },
+ { USB_DEVICE(0x14b2, 0x3c11) },
/* Amigo */
- { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0e0b, 0x9031) },
+ { USB_DEVICE(0x0e0b, 0x9041) },
/* ASUS */
- { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1760) },
+ { USB_DEVICE(0x0b05, 0x1761) },
+ { USB_DEVICE(0x0b05, 0x1790) },
/* AzureWave */
- { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x13d3, 0x3262) },
+ { USB_DEVICE(0x13d3, 0x3284) },
+ { USB_DEVICE(0x13d3, 0x3322) },
/* Belkin */
- { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x050d, 0x825a) },
/* Buffalo */
- { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0411, 0x012e) },
+ { USB_DEVICE(0x0411, 0x0148) },
+ { USB_DEVICE(0x0411, 0x0150) },
+ { USB_DEVICE(0x0411, 0x015d) },
/* Corega */
- { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07aa, 0x0041) },
+ { USB_DEVICE(0x07aa, 0x0042) },
+ { USB_DEVICE(0x18c5, 0x0008) },
/* D-Link */
- { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c0b) },
+ { USB_DEVICE(0x07d1, 0x3c13) },
+ { USB_DEVICE(0x07d1, 0x3c15) },
+ { USB_DEVICE(0x07d1, 0x3c17) },
/* Edimax */
- { USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x7392, 0x4085) },
/* Encore */
- { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x203d, 0x14a1) },
/* Gemtek */
- { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x15a9, 0x0010) },
/* Gigabyte */
- { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1044, 0x800c) },
/* LevelOne */
- { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1740, 0x0605) },
+ { USB_DEVICE(0x1740, 0x0615) },
/* Linksys */
- { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1737, 0x0077) },
+ { USB_DEVICE(0x1737, 0x0078) },
/* Motorola */
- { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x100d, 0x9032) },
/* Ovislink */
- { USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1b75, 0x3071) },
+ { USB_DEVICE(0x1b75, 0x3072) },
/* Pegatron */
- { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x05a6, 0x0101) },
+ { USB_DEVICE(0x1d4d, 0x0002) },
+ { USB_DEVICE(0x1d4d, 0x0010) },
/* Planex */
- { USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x2019, 0x5201) },
+ { USB_DEVICE(0x2019, 0xab24) },
/* Qcom */
- { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x18e8, 0x6259) },
/* SMC */
- { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x083a, 0xa512) },
+ { USB_DEVICE(0x083a, 0xc522) },
+ { USB_DEVICE(0x083a, 0xd522) },
+ { USB_DEVICE(0x083a, 0xf511) },
/* Sweex */
- { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x177f, 0x0153) },
+ { USB_DEVICE(0x177f, 0x0313) },
/* Zyxel */
- { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x0586, 0x341a) },
#endif
{ 0, }
};
@@ -1078,10 +1078,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2870);
MODULE_LICENSE("GPL");

+static int rt2800usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
static struct usb_driver rt2800usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt2800usb_device_table,
- .probe = rt2x00usb_probe,
+ .probe = rt2800usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 695aecf..17148bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -251,9 +251,8 @@ exit:
return -ENOMEM;
}

-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
{
- struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 5d58874..e2c99f2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -126,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
/*
* PCI driver handlers.
*/
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
void rt2x00pci_remove(struct pci_dev *pci_dev);
#ifdef CONFIG_PM
int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 9957579..570184e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -791,10 +791,9 @@ exit:
}

int rt2x00usb_probe(struct usb_interface *usb_intf,
- const struct usb_device_id *id)
+ const struct rt2x00_ops *ops)
{
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
- struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 6aeba71..52b09d2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -35,12 +35,6 @@
})

/*
- * This variable should be used with the
- * usb_driver structure initialization.
- */
-#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
-
-/*
* For USB vendor requests we need to pass a timeout
* time in ms, for this we use the REGISTER_TIMEOUT,
* however when loading firmware a higher value is
@@ -433,7 +427,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
* USB driver handlers.
*/
int rt2x00usb_probe(struct usb_interface *usb_intf,
- const struct usb_device_id *id);
+ const struct rt2x00_ops *ops);
void rt2x00usb_disconnect(struct usb_interface *usb_intf);
#ifdef CONFIG_PM
int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 264508f..c5dccdb 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3061,11 +3061,11 @@ static const struct rt2x00_ops rt61pci_ops = {
*/
static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
/* RT2561s */
- { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0301) },
/* RT2561 v2 */
- { PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0302) },
/* RT2661 */
- { PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) },
+ { PCI_DEVICE(0x1814, 0x0401) },
{ 0, }
};

@@ -3080,10 +3080,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);
MODULE_FIRMWARE(FIRMWARE_RT2661);
MODULE_LICENSE("GPL");

+static int rt61pci_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
static struct pci_driver rt61pci_driver = {
.name = KBUILD_MODNAME,
.id_table = rt61pci_device_table,
- .probe = rt2x00pci_probe,
+ .probe = rt61pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
.suspend = rt2x00pci_suspend,
.resume = rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index cdb026d..be3eb5e 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2388,113 +2388,113 @@ static const struct rt2x00_ops rt73usb_ops = {
*/
static struct usb_device_id rt73usb_device_table[] = {
/* AboCom */
- { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x07b8, 0xb21b) },
+ { USB_DEVICE(0x07b8, 0xb21c) },
+ { USB_DEVICE(0x07b8, 0xb21d) },
+ { USB_DEVICE(0x07b8, 0xb21e) },
+ { USB_DEVICE(0x07b8, 0xb21f) },
/* AL */
- { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c10) },
/* Amigo */
- { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x148f, 0x9021) },
+ { USB_DEVICE(0x0eb0, 0x9021) },
/* AMIT */
- { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x18c5, 0x0002) },
/* Askey */
- { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1690, 0x0722) },
/* ASUS */
- { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0b05, 0x1723) },
+ { USB_DEVICE(0x0b05, 0x1724) },
/* Belkin */
- { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x050d, 0x705a) },
+ { USB_DEVICE(0x050d, 0x905b) },
+ { USB_DEVICE(0x050d, 0x905c) },
/* Billionton */
- { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1631, 0xc019) },
+ { USB_DEVICE(0x08dd, 0x0120) },
/* Buffalo */
- { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0411, 0x00d8) },
+ { USB_DEVICE(0x0411, 0x00d9) },
+ { USB_DEVICE(0x0411, 0x00f4) },
+ { USB_DEVICE(0x0411, 0x0116) },
+ { USB_DEVICE(0x0411, 0x0119) },
+ { USB_DEVICE(0x0411, 0x0137) },
/* CEIVA */
- { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x178d, 0x02be) },
/* CNet */
- { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1371, 0x9022) },
+ { USB_DEVICE(0x1371, 0x9032) },
/* Conceptronic */
- { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x14b2, 0x3c22) },
/* Corega */
- { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x07aa, 0x002e) },
/* D-Link */
- { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c03) },
+ { USB_DEVICE(0x07d1, 0x3c04) },
+ { USB_DEVICE(0x07d1, 0x3c06) },
+ { USB_DEVICE(0x07d1, 0x3c07) },
/* Edimax */
- { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x7392, 0x7318) },
+ { USB_DEVICE(0x7392, 0x7618) },
/* EnGenius */
- { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1740, 0x3701) },
/* Gemtek */
- { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x15a9, 0x0004) },
/* Gigabyte */
- { USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1044, 0x8008) },
+ { USB_DEVICE(0x1044, 0x800a) },
/* Huawei-3Com */
- { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1472, 0x0009) },
/* Hercules */
- { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x06f8, 0xe002) },
+ { USB_DEVICE(0x06f8, 0xe010) },
+ { USB_DEVICE(0x06f8, 0xe020) },
/* Linksys */
- { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x13b1, 0x0020) },
+ { USB_DEVICE(0x13b1, 0x0023) },
+ { USB_DEVICE(0x13b1, 0x0028) },
/* MSI */
- { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0db0, 0x4600) },
+ { USB_DEVICE(0x0db0, 0x6877) },
+ { USB_DEVICE(0x0db0, 0x6874) },
+ { USB_DEVICE(0x0db0, 0xa861) },
+ { USB_DEVICE(0x0db0, 0xa874) },
/* Ovislink */
- { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1b75, 0x7318) },
/* Ralink */
- { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x04bb, 0x093d) },
+ { USB_DEVICE(0x148f, 0x2573) },
+ { USB_DEVICE(0x148f, 0x2671) },
+ { USB_DEVICE(0x0812, 0x3101) },
/* Qcom */
- { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x18e8, 0x6196) },
+ { USB_DEVICE(0x18e8, 0x6229) },
+ { USB_DEVICE(0x18e8, 0x6238) },
/* Samsung */
- { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x04e8, 0x4471) },
/* Senao */
- { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x1740, 0x7100) },
/* Sitecom */
- { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0df6, 0x0024) },
+ { USB_DEVICE(0x0df6, 0x0027) },
+ { USB_DEVICE(0x0df6, 0x002f) },
+ { USB_DEVICE(0x0df6, 0x90ac) },
+ { USB_DEVICE(0x0df6, 0x9712) },
/* Surecom */
- { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0769, 0x31f3) },
/* Tilgin */
- { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x6933, 0x5001) },
/* Philips */
- { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0471, 0x200a) },
/* Planex */
- { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
- { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x2019, 0xab01) },
+ { USB_DEVICE(0x2019, 0xab50) },
/* WideTell */
- { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x7167, 0x3840) },
/* Zcom */
- { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0cde, 0x001c) },
/* ZyXEL */
- { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x0586, 0x3415) },
{ 0, }
};

@@ -2506,10 +2506,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
MODULE_FIRMWARE(FIRMWARE_RT2571);
MODULE_LICENSE("GPL");

+static int rt73usb_probe(struct usb_interface *usb_intf,
+ const struct usb_device_id *id)
+{
+ return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
static struct usb_driver rt73usb_driver = {
.name = KBUILD_MODNAME,
.id_table = rt73usb_device_table,
- .probe = rt2x00usb_probe,
+ .probe = rt73usb_probe,
.disconnect = rt2x00usb_disconnect,
.suspend = rt2x00usb_suspend,
.resume = rt2x00usb_resume,
--
1.7.2.3


2011-04-18 13:35:52

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons

From: Helmut Schaa <[email protected]>

Use TXOP_HTTXOP for beacons to stay in sync with the legacy drivers.

Signed-off-by: Helmut Schaa <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00ht.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index e8c0c3e..a30f68c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -92,14 +92,15 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,

/*
* Determine IFS values
- * - Use TXOP_BACKOFF for management frames
+ * - Use TXOP_BACKOFF for management frames except beacons
* - Use TXOP_SIFS for fragment bursts
* - Use TXOP_HTTXOP for everything else
*
* Note: rt2800 devices won't use CTS protection (if used)
* for frames not transmitted with TXOP_HTTXOP
*/
- if (ieee80211_is_mgmt(hdr->frame_control))
+ if (ieee80211_is_mgmt(hdr->frame_control) &&
+ !ieee80211_is_beacon(hdr->frame_control))
txdesc->u.ht.txop = TXOP_BACKOFF;
else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
txdesc->u.ht.txop = TXOP_SIFS;
--
1.7.2.3


2011-04-28 18:55:21

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

> My colleague just tested this patch set and found out that the in
> question makes our 400MHz ARM cpu board with ralink usb dongle non
> functional due to high cpu consumption. ?it seems for us that exiting
> from function every time it finds an entry is too expensive on systems
> slower than PCs.

Interesting, I would suspected the patch to reduce the CPU consumption
rather then increasing it. I can do some testing regarding this looping
during the weekend, but I haven't seen high CPU consumption on my
system during my last test. However I wasn't testing on an embedded system...

> To verify our thought, we changed the source code as the patch below.
> What we intended to do with this change is to continue processing all
> entry without breaking semantics.
>
> With the patch below our board seem to work fine again, but not sure
> exactly why it takes so much time to check the list again. ?We are not
> against the idea of the patch at all. ?We just want to ask you guys
> how we should go to track this problem. it might be the slow usb?

Could you try use debugfs and see if some queue and packet counters
of mac80211/rt2x00 show excessive values?

Have you been running the test with powersaving enabled or disabled?

Ivo

2011-04-18 13:35:55

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously

From: Johannes Stezenbach <[email protected]>

Trying to fix the "TX status report missed" warnings
by reading the TX_STA_FIFO entries as quickly as possible.
The TX_STA_FIFO is too small in hardware, thus reading
it only from the workqueue is too slow and entries get lost.

Start an asynchronous read of the TX_STA_FIFO directly from
the TX URB completion callback (atomic context, thus it cannot
use the blocking rt2800_register_read()). If the async
read returns a valid FIFO entry, it is pushed into a larger
FIFO inside struct rt2x00_dev, until rt2800_txdone() picks
it up.

A .tx_dma_done callback is added to struct rt2x00lib_ops
to trigger the async read from the URB completion callback.

Signed-off-by: Johannes Stezenbach <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 34 ++++++--------------
drivers/net/wireless/rt2x00/rt2800usb.c | 31 ++++++++++++++++++
drivers/net/wireless/rt2x00/rt2x00.h | 1 +
drivers/net/wireless/rt2x00/rt2x00usb.c | 53 +++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2x00usb.h | 15 +++++++++
5 files changed, 110 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 0e2c006..d79c8fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
struct queue_entry *entry;
u32 reg;
- u8 pid;
- int i;
+ u8 qid;

- /*
- * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
- * at most X times and also stop processing once the TX_STA_FIFO_VALID
- * flag is not set anymore.
- *
- * The legacy drivers use X=TX_RING_SIZE but state in a comment
- * that the TX_STA_FIFO stack has a size of 16. We stick to our
- * tx ring size for now.
- */
- for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
- if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
- break;
+ while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {

- /*
- * Skip this entry when it contains an invalid
- * queue identication number.
+ /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+ * qid is guaranteed to be one of the TX QIDs
*/
- pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
- if (pid >= QID_RX)
- continue;
-
- queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
- if (unlikely(!queue))
+ qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+ queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+ if (unlikely(!queue)) {
+ WARNING(rt2x00dev, "Got TX status for an unavailable "
+ "queue %u, dropping\n", qid);
continue;
+ }

/*
* Inside each queue, we process each entry in a chronological
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f3ce5e8..862430e 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -98,6 +98,35 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
}
}

+static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+ int urb_status, u32 tx_status)
+{
+ if (urb_status) {
+ WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
+ return;
+ }
+
+ /* try to read all TX_STA_FIFO entries before scheduling txdone_work */
+ if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
+ if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
+ WARNING(rt2x00dev, "TX status FIFO overrun, "
+ "drop tx status report.\n");
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+ } else
+ rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+ rt2800usb_tx_sta_fifo_read_completed);
+ } else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+}
+
+static void rt2800usb_tx_dma_done(struct queue_entry *entry)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+ rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+ rt2800usb_tx_sta_fifo_read_completed);
+}
+
/*
* Firmware functions
*/
@@ -565,6 +594,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
@@ -635,6 +665,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt2800usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
+ .tx_dma_done = rt2800usb_tx_dma_done,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2800usb_write_tx_data,
.write_beacon = rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 79c385a..e3b9b51 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -571,6 +571,7 @@ struct rt2x00lib_ops {
void (*kick_queue) (struct data_queue *queue);
void (*stop_queue) (struct data_queue *queue);
void (*flush_queue) (struct data_queue *queue);
+ void (*tx_dma_done) (struct queue_entry *entry);

/*
* TX control handlers
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 0bc8dcc..5fbab6f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);

+
+struct rt2x00_async_read_data {
+ __le32 reg;
+ struct usb_ctrlrequest cr;
+ struct rt2x00_dev *rt2x00dev;
+ void (*callback)(struct rt2x00_dev *,int,u32);
+};
+
+static void rt2x00usb_register_read_async_cb(struct urb *urb)
+{
+ struct rt2x00_async_read_data *rd = urb->context;
+ rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg));
+ kfree(urb->context);
+}
+
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void (*callback)(struct rt2x00_dev*,int,u32))
+{
+ struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+ struct urb *urb;
+ struct rt2x00_async_read_data *rd;
+
+ rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+ if (!rd)
+ return;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ kfree(rd);
+ return;
+ }
+
+ rd->rt2x00dev = rt2x00dev;
+ rd->callback = callback;
+ rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
+ rd->cr.bRequest = USB_MULTI_READ;
+ rd->cr.wValue = 0;
+ rd->cr.wIndex = cpu_to_le16(offset);
+ rd->cr.wLength = cpu_to_le16(sizeof(u32));
+
+ usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+ (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
+ rt2x00usb_register_read_async_cb, rd);
+ if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+ kfree(rd);
+ usb_free_urb(urb);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
+
/*
* TX data handlers.
*/
@@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;

+ if (rt2x00dev->ops->lib->tx_dma_done)
+ rt2x00dev->ops->lib->tx_dma_done(entry);
+
/*
* Report the frame as DMA done
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 6aaf51f..e3faca6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -345,6 +345,21 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
const struct rt2x00_field32 field,
u32 *reg);

+/**
+ * rt2x00usb_register_read_async - Asynchronously read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @callback: Functon to call when read completes.
+ *
+ * Submit a control URB to read a 32bit register. This safe to
+ * be called from atomic context. The callback will be called
+ * when the URB completes. Otherwise the function is similar
+ * to rt2x00usb_register_read().
+ */
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void (*callback)(struct rt2x00_dev*,int,u32));
+
/*
* Radio handlers
*/
--
1.7.2.3


2011-04-18 13:36:22

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 22/23] rt2x00: Implement get_ringparam callback function

From: Ivo van Doorn <[email protected]>

With the get_ringparam callback function we can export ring parameters
to ethtool through the mac80211 interface.

Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 1 +
drivers/net/wireless/rt2x00/rt2500pci.c | 1 +
drivers/net/wireless/rt2x00/rt2500usb.c | 1 +
drivers/net/wireless/rt2x00/rt2800pci.c | 1 +
drivers/net/wireless/rt2x00/rt2800usb.c | 1 +
drivers/net/wireless/rt2x00/rt2x00.h | 2 ++
drivers/net/wireless/rt2x00/rt2x00mac.c | 16 ++++++++++++++++
drivers/net/wireless/rt2x00/rt61pci.c | 1 +
drivers/net/wireless/rt2x00/rt73usb.c | 1 +
9 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index d4acdde..bbe76f7 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1720,6 +1720,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.tx_last_beacon = rt2400pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 15f5649..6f48996 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2013,6 +2013,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.tx_last_beacon = rt2500pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index d88c367..5ef3386 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1823,6 +1823,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.conf_tx = rt2x00mac_conf_tx,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index b0c729b..08d3947 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1028,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.ampdu_action = rt2800_ampdu_action,
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2800_ops rt2800pci_rt2800_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 44ead75..0d4e8fa 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -673,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.ampdu_action = rt2800_ampdu_action,
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2800_ops rt2800usb_rt2800_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index dcdc50d..f1d8f55 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1254,6 +1254,8 @@ 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);
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+ u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);

/*
* Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4770156..6d1d383 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -737,3 +737,19 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
rt2x00queue_flush_queue(queue, drop);
}
EXPORT_SYMBOL_GPL(rt2x00mac_flush);
+
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+ u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+
+ tx_queue_for_each(rt2x00dev, queue) {
+ *tx += queue->length;
+ *tx_max += queue->limit;
+ }
+
+ *rx = rt2x00dev->rx->length;
+ *rx_max = rt2x00dev->rx->limit;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c5dccdb..eb54031 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2979,6 +2979,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.get_tsf = rt61pci_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index be3eb5e..bf7fea4 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2310,6 +2310,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.get_tsf = rt73usb_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .get_ringparam = rt2x00mac_get_ringparam,
};

static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
--
1.7.2.3


2011-04-18 14:50:42

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

Hi,

Am Montag, 18. April 2011 schrieb Ivo Van Doorn:
> > Wouldn't this be better to create two pointers in struct rt2x00_dev.
> > One for writing function and one for reading function? Am I right
> > thinking calling functions by pointers is quite fast? Or is this still
> > noticeably slower than using proper functions directly?
>
> We already have the pointer inside struct rt2x00_dev which references
> the register access functions for rt2800pci/usb. These pointers are used
> by rt2800lib to access the common registers. What this patch does, is
> optimize the case where we exactly know which function we need, because
> we are in the actual driver.
>
> As for the performance, I'll let Helmut comment on that as he created patch 20,
> which introduced this change to rt2800pci. :)

Sure, I was comparing some assembly in the rt2800pci hotpaths (on a 380Mhz
MIPS CPU btw). A register read/write on PCI is just a readl or writel,
nothing more but using the indirect wrappers we get something like this
(This is x86_64 as I didn't want to cross compile right now). For example
the register read + write in rt2800pci_enable_interrupt (which is called
in every tasklet invocation, which can happen for every rx'ed frame and
every tx'ed frame).

movq 8(%rbx), %rax # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
leaq -36(%rbp), %rdx #, tmp82
movq %rbx, %rdi # rt2x00dev,
movq 72(%rax), %rax # D.47612_27->drv, D.47612_27->drv
movl $516, %esi #,
call *(%rax) # rt2800ops_29->register_read
movb %r14b, %cl #,
movq 8(%rbx), %rax # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
movq %rbx, %rdi # rt2x00dev,
movq 72(%rax), %rax # D.47619_31->drv, D.47619_31->drv
movl $516, %esi #,
movl $1, %edx #, reg.119
sall %cl, %edx #, reg.119
andl %r13d, %edx # irq_field$bit_mask, reg.119
notl %r13d # tmp89
andl -36(%rbp), %r13d # reg, tmp89
orl %r13d, %edx # tmp89, reg.119
movl %edx, -36(%rbp) # reg.119, reg
call *16(%rax) # rt2800ops_33->register_write

Also, this will trigger rt2x00pci_register_read

pushq %rbp #
mov %esi, %esi # offset, addr.27
movq %rsp, %rbp #,
addq 1056(%rdi), %rsi # rt2x00dev_1(D)->csr.base, addr.27
movl %eax, (%rdx) # ret,* value

And rt2x00pci_register_write:

pushq %rbp #
mov %esi, %esi # offset, addr.26
movq %rsp, %rbp #,
addq 1056(%rdi), %rsi # rt2x00dev_1(D)->csr.base, addr.26
movl %edx,(%rsi) # value,* addr.26

And here the same when using rt2x00pci_register_read/write directly:

movq 1056(%rbx), %rax # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
movl 516(%rax),%eax #, reg.119
movl %r13d, %edx # irq_field$bit_mask, tmp80
movb %r14b, %cl #,
notl %edx # tmp80
andl %edx, %eax # tmp80, reg.119
movl $1, %edx #, tmp85
sall %cl, %edx #, tmp85
andl %r13d, %edx # irq_field$bit_mask, tmp85
orl %edx, %eax # tmp85, reg.119
movq 1056(%rbx), %rdx # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
movl %eax,516(%rdx) # reg.119,

As you can see we save more then just one indirect function call:

17 movs -> 7 movs
2 calls -> 0 calls
1 add -> 0 adds

This happens because the compiler is able to apply a number of optimizations
that are only possible by inlining rt2x00pci_register_read/write. When using
the indirect function call the compiler is not able to inline them.

So, I first thought about using direct calls only in the interrupt handler
and the RX/TX hotpaths but since using rt2800_register_read and
rt2x00pci_register_read in different locations in rt2800pci would be even
more confusing I just replaced every rt2800_register_read with
rt2x00pci_register_read in rt2800pci.

One way to keep the abstraction and still improve the register_read/write
operations would be to introduce a inlined rt2800pci_register_read/write
which directly calls rt2x00pci_register_read/write and provide that via
rt2800_ops to rt2800lib. That way all calls in rt2800pci can directly
inline rt2x00_register_read/write while rt2800lib will still use indirect
calls to do the same.

However, I didn't see any need for this.

Helmut

2011-04-18 13:35:49

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value

From: Helmut Schaa <[email protected]>

Bring the TX_SW_CFG2 initialisation for rt305x devices in sync with the
ralink legacy drivers.

Signed-off-by: Helmut Schaa <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e0fa559..0e2c006 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2427,7 +2427,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
} else if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
} else if (rt2x00_rt(rt2x00dev, RT5390)) {
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
--
1.7.2.3


2011-04-18 13:35:42

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 03/23] rt2x00: Split rt2x00dev->flags

From: Ivo van Doorn <[email protected]>

The number of flags defined for the rt2x00dev->flags field,
has been growing over the years. Currently we are approaching
the maximum number of bits which are available in the field.

A secondary problem, is that one part of the field are initialized only
during boot, because the driver requirements are initialized or device
requirements are loaded from the EEPROM. In both cases, the flags are
fixed and will not change during device operation. The other flags are
the device state, and will change frequently. So far this resulted in the fact
that for some flags, the atomic bit accessors are used, while for the others
the non-atomic variants are used.

By splitting the flags up into a "flags" and "cap_flags" we can put all flags
which are fixed inside "cap_flags". This field can then be read non-atomically.
In the "flags" field we keep the device state, which is going to be read atomically.

This adds more room for more flags in the future, and sanitizes the field access methods.

Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Helmut Schaa <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 10 ++--
drivers/net/wireless/rt2x00/rt2500pci.c | 10 ++--
drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++--
drivers/net/wireless/rt2x00/rt2800lib.c | 20 +++---
drivers/net/wireless/rt2x00/rt2800pci.c | 22 ++++----
drivers/net/wireless/rt2x00/rt2800usb.c | 14 ++--
drivers/net/wireless/rt2x00/rt2x00.h | 84 +++++++++++++++-----------
drivers/net/wireless/rt2x00/rt2x00config.c | 4 +-
drivers/net/wireless/rt2x00/rt2x00crypto.c | 4 +-
drivers/net/wireless/rt2x00/rt2x00debug.c | 42 ++++++++++++-
drivers/net/wireless/rt2x00/rt2x00dev.c | 14 ++--
drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +-
drivers/net/wireless/rt2x00/rt2x00lib.h | 4 +-
drivers/net/wireless/rt2x00/rt2x00link.c | 2 +-
drivers/net/wireless/rt2x00/rt2x00mac.c | 12 ++--
drivers/net/wireless/rt2x00/rt2x00queue.c | 20 +++---
drivers/net/wireless/rt2x00/rt2x00usb.c | 6 +-
drivers/net/wireless/rt2x00/rt61pci.c | 42 +++++++-------
drivers/net/wireless/rt2x00/rt73usb.c | 32 +++++-----
19 files changed, 203 insertions(+), 153 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 137a24e..5d1654a 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1536,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Check if the BBP tuning should be enabled.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);

return 0;
}
@@ -1640,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* This device requires the atim queue and DMA-mapped skbs.
*/
- __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+ __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 198fc0a..3da954e 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1687,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Check if the BBP tuning should be enabled.
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);

/*
* Read the RSSI <-> dBm offset information.
@@ -1958,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* This device requires the atim queue and DMA-mapped skbs.
*/
- __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+ __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index eac7881..dbbd8bc 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Read the RSSI <-> dBm offset information.
@@ -1790,13 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* This device requires the atim queue
*/
- __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+ __set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt) {
- __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
}
- __set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+ __set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 13ccc1b..c6f5584 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1763,8 +1763,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,

if (rf->channel <= 14) {
if (!rt2x00_rt(rt2x00dev, RT5390)) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG,
- &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+ &rt2x00dev->cap_flags)) {
rt2800_bbp_write(rt2x00dev, 82, 0x62);
rt2800_bbp_write(rt2x00dev, 75, 0x46);
} else {
@@ -1775,7 +1775,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
} else {
rt2800_bbp_write(rt2x00dev, 82, 0xf2);

- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
rt2800_bbp_write(rt2x00dev, 75, 0x46);
else
rt2800_bbp_write(rt2x00dev, 75, 0x50);
@@ -2008,7 +2008,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
return txpower;

- if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
/*
* Check if eirp txpower exceed txpower_limit.
* We use OFDM 6M as criterion and its eirp txpower
@@ -3309,8 +3309,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
- if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
- &rt2x00dev->flags))
+ if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+ &rt2x00dev->cap_flags))
rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
@@ -3733,15 +3733,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);

if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
- __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
- __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);

/*
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Store led settings, for correct led behaviour.
@@ -3761,7 +3761,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)

if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
EIRP_MAX_TX_POWER_LIMIT)
- __set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);

return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index adc3534..4241f19 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -966,28 +966,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
*/
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);

/*
* This device has a pre tbtt interrupt and thus fetches
* a new beacon directly prior to transmission.
*/
- __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);

/*
* This device requires firmware.
*/
if (!rt2x00_is_soc(rt2x00dev))
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
+ __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
- __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index d2f5c87..f3ce5e8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -553,18 +553,18 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* This device has multiple filters for control frames
* and has a separate filter for PS Poll frames.
*/
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);

/*
* This device requires firmware.
*/
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+ __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
- __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index dd0f66a..79c385a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -643,11 +643,11 @@ struct rt2x00_ops {
};

/*
- * rt2x00 device flags
+ * rt2x00 state flags
*/
-enum rt2x00_flags {
+enum rt2x00_state_flags {
/*
- * Device state flags
+ * Device flags
*/
DEVICE_STATE_PRESENT,
DEVICE_STATE_REGISTERED_HW,
@@ -657,42 +657,47 @@ enum rt2x00_flags {
DEVICE_STATE_SCANNING,

/*
- * Driver requirements
- */
- DRIVER_REQUIRE_FIRMWARE,
- DRIVER_REQUIRE_BEACON_GUARD,
- DRIVER_REQUIRE_ATIM_QUEUE,
- DRIVER_REQUIRE_DMA,
- DRIVER_REQUIRE_COPY_IV,
- DRIVER_REQUIRE_L2PAD,
- DRIVER_REQUIRE_TXSTATUS_FIFO,
- DRIVER_REQUIRE_TASKLET_CONTEXT,
- DRIVER_REQUIRE_SW_SEQNO,
- DRIVER_REQUIRE_HT_TX_DESC,
-
- /*
- * Driver features
- */
- CONFIG_SUPPORT_HW_BUTTON,
- CONFIG_SUPPORT_HW_CRYPTO,
- CONFIG_SUPPORT_POWER_LIMIT,
- DRIVER_SUPPORT_CONTROL_FILTERS,
- DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
- DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
- DRIVER_SUPPORT_LINK_TUNING,
-
- /*
* Driver configuration
*/
- CONFIG_FRAME_TYPE,
- CONFIG_RF_SEQUENCE,
- CONFIG_EXTERNAL_LNA_A,
- CONFIG_EXTERNAL_LNA_BG,
- CONFIG_DOUBLE_ANTENNA,
CONFIG_CHANNEL_HT40,
};

/*
+ * rt2x00 capability flags
+ */
+enum rt2x00_capability_flags {
+ /*
+ * Requirements
+ */
+ REQUIRE_FIRMWARE,
+ REQUIRE_BEACON_GUARD,
+ REQUIRE_ATIM_QUEUE,
+ REQUIRE_DMA,
+ REQUIRE_COPY_IV,
+ REQUIRE_L2PAD,
+ REQUIRE_TXSTATUS_FIFO,
+ REQUIRE_TASKLET_CONTEXT,
+ REQUIRE_SW_SEQNO,
+ REQUIRE_HT_TX_DESC,
+
+ /*
+ * Capabilities
+ */
+ CAPABILITY_HW_BUTTON,
+ CAPABILITY_HW_CRYPTO,
+ CAPABILITY_POWER_LIMIT,
+ CAPABILITY_CONTROL_FILTERS,
+ CAPABILITY_CONTROL_FILTER_PSPOLL,
+ CAPABILITY_PRE_TBTT_INTERRUPT,
+ CAPABILITY_LINK_TUNING,
+ CAPABILITY_FRAME_TYPE,
+ CAPABILITY_RF_SEQUENCE,
+ CAPABILITY_EXTERNAL_LNA_A,
+ CAPABILITY_EXTERNAL_LNA_BG,
+ CAPABILITY_DOUBLE_ANTENNA,
+};
+
+/*
* rt2x00 device structure.
*/
struct rt2x00_dev {
@@ -738,13 +743,20 @@ struct rt2x00_dev {
#endif /* CONFIG_RT2X00_LIB_LEDS */

/*
- * Device flags.
- * In these flags the current status and some
- * of the device capabilities are stored.
+ * Device state flags.
+ * In these flags the current status is stored.
+ * Access to these flags should occur atomically.
*/
unsigned long flags;

/*
+ * Device capabiltiy flags.
+ * In these flags the device/driver capabilities are stored.
+ * Access to these flags should occur non-atomically.
+ */
+ unsigned long cap_flags;
+
+ /*
* Device information, Bus IRQ and name (PCI, SoC)
*/
int irq;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index e7f67d5..e225a66 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -176,10 +176,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,

if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
if (conf_is_ht40(conf)) {
- __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+ set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
} else {
- __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+ clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
hw_value = conf->channel->hw_value;
}

diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 5e9074b..e1e0c51 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;

- if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key)
+ if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
return;

__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
@@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
struct ieee80211_key_conf *key = tx_info->control.hw_key;
unsigned int overhead = 0;

- if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key)
+ if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key)
return overhead;

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 66166ef..78787fc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -63,7 +63,8 @@ struct rt2x00debug_intf {
* - driver folder
* - driver file
* - chipset file
- * - device flags file
+ * - device state flags file
+ * - device capability flags file
* - register folder
* - csr offset/value files
* - eeprom offset/value files
@@ -78,6 +79,7 @@ struct rt2x00debug_intf {
struct dentry *driver_entry;
struct dentry *chipset_entry;
struct dentry *dev_flags;
+ struct dentry *cap_flags;
struct dentry *register_folder;
struct dentry *csr_off_entry;
struct dentry *csr_val_entry;
@@ -553,6 +555,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
.llseek = default_llseek,
};

+static ssize_t rt2x00debug_read_cap_flags(struct file *file,
+ char __user *buf,
+ size_t length,
+ loff_t *offset)
+{
+ struct rt2x00debug_intf *intf = file->private_data;
+ char line[16];
+ size_t size;
+
+ if (*offset)
+ return 0;
+
+ size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
+
+ if (copy_to_user(buf, line, size))
+ return -EFAULT;
+
+ *offset += size;
+ return size;
+}
+
+static const struct file_operations rt2x00debug_fop_cap_flags = {
+ .owner = THIS_MODULE,
+ .read = rt2x00debug_read_cap_flags,
+ .open = rt2x00debug_file_open,
+ .release = rt2x00debug_file_release,
+ .llseek = default_llseek,
+};
+
static struct dentry *rt2x00debug_create_file_driver(const char *name,
struct rt2x00debug_intf
*intf,
@@ -652,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
goto exit;

+ intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
+ intf->driver_folder, intf,
+ &rt2x00debug_fop_cap_flags);
+ if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
+ goto exit;
+
intf->register_folder =
debugfs_create_dir("register", intf->driver_folder);
if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -705,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf, &rt2x00debug_fop_queue_stats);

#ifdef CONFIG_RT2X00_LIB_CRYPTO
- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
intf->crypto_stats_entry =
debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
intf, &rt2x00debug_fop_crypto_stats);
@@ -743,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
debugfs_remove(intf->csr_off_entry);
debugfs_remove(intf->register_folder);
debugfs_remove(intf->dev_flags);
+ debugfs_remove(intf->cap_flags);
debugfs_remove(intf->chipset_entry);
debugfs_remove(intf->driver_entry);
debugfs_remove(intf->driver_folder);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9bffe84..af25b01 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -200,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
* here as they will fetch the next beacon directly prior to
* transmission.
*/
- if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags))
return;

/* fetch next beacon */
@@ -271,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
/*
* Remove L2 padding which was added during
*/
- if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+ if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
rt2x00queue_remove_l2pad(entry->skb, header_length);

/*
@@ -280,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* mac80211 will expect the same data to be present it the
* frame as it was passed to us.
*/
- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
rt2x00crypto_tx_insert_iv(entry->skb, header_length);

/*
@@ -377,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* send the status report back.
*/
if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
- if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+ if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags))
ieee80211_tx_status(rt2x00dev->hw, entry->skb);
else
ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
@@ -806,15 +806,15 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Take TX headroom required for alignment into account.
*/
- if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+ if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
- else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+ else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;

/*
* Allocate tx status FIFO for driver use.
*/
- if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
+ if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
/*
* Allocate the txstatus fifo. In the worst case the tx
* status fifo has to hold the tx status of all entries
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index be0ff78..f316aad 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
{
int retval;

- if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
+ if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))
return 0;

if (!rt2x00dev->fw) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 88f2f92..bbee2cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -416,13 +416,13 @@ static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
*/
static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
{
- if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
}

static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
{
- if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
}

diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 128b361..ba0bb76 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -383,7 +383,7 @@ static void rt2x00link_tuner(struct work_struct *work)
* do not support link tuning at all, while other devices can disable
* the feature from the EEPROM.
*/
- if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))
rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4a1c41b..4770156 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* Use the ATIM queue if appropriate and present.
*/
if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
- test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
+ test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))
qid = QID_ATIM;

queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
@@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
* of different types, but has no a separate filter for PS Poll frames,
* FIF_CONTROL flag implies FIF_PSPOLL.
*/
- if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
+ if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) {
if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
*total_flags |= FIF_CONTROL | FIF_PSPOLL;
}
- if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
+ if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) {
if (*total_flags & FIF_CONTROL)
*total_flags |= FIF_PSPOLL;
}
@@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return 0;
- else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
return -EOPNOTSUPP;
else if (key->keylen > 32)
return -ENOSPC;
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- __set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+ set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
rt2x00link_stop_tuner(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
@@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- __clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+ clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
rt2x00link_start_tuner(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 9fc4a1e..d03eef2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
* at least 8 bytes bytes available in headroom for IV/EIV
* and 8 bytes for ICV data as tailroon.
*/
- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {
head_size += 8;
tail_size += 8;
}
@@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->entry = entry;

- if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) {
+ if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
skb->data,
skb->len,
@@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,

__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);

- if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
+ if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
return;

/*
@@ -396,7 +396,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
rt2x00crypto_create_tx_descriptor(entry, txdesc);
rt2x00queue_create_tx_descriptor_seq(entry, txdesc);

- if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
+ if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
else
rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
@@ -436,7 +436,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
/*
* Map the skb to DMA.
*/
- if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+ if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
rt2x00queue_map_txskb(entry);

return 0;
@@ -529,7 +529,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
*/
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
- if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
+ if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))
rt2x00crypto_tx_copy_iv(skb, &txdesc);
else
rt2x00crypto_tx_remove_iv(skb, &txdesc);
@@ -543,9 +543,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
* PCI and USB devices, while header alignment only is valid
* for PCI devices.
*/
- if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+ if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
- else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
+ else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
rt2x00queue_align_frame(entry->skb);

/*
@@ -1069,7 +1069,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
if (status)
goto exit;

- if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
+ if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {
status = rt2x00queue_alloc_entries(rt2x00dev->atim,
rt2x00dev->ops->atim);
if (status)
@@ -1121,7 +1121,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
enum data_queue_qid qid;
unsigned int req_atim =
- !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+ !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);

/*
* We need the following queues:
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index fbe735f..94047e9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -387,7 +387,7 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
* Kill guardian urb (if required by driver).
*/
if ((entry->queue->qid == QID_BEACON) &&
- (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+ (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
usb_kill_urb(bcn_priv->guardian_urb);
}

@@ -583,7 +583,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)
* then we are done.
*/
if (queue->qid != QID_BEACON ||
- !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+ !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
return 0;

for (i = 0; i < queue->limit; i++) {
@@ -618,7 +618,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue)
* then we are done.
*/
if (queue->qid != QID_BEACON ||
- !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+ !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
return;

for (i = 0; i < queue->limit; i++) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 8ee1514..c16c150 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,

rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+ !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));

/*
* Configure the RX antenna.
@@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,

if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
sel = antenna_sel_a;
- lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
} else {
sel = antenna_sel_bg;
- lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+ lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
}

for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
else if (rt2x00_rf(rt2x00dev, RF2527))
rt61pci_config_antenna_2x(rt2x00dev, ant);
else if (rt2x00_rf(rt2x00dev, RF2529)) {
- if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags))
rt61pci_config_antenna_2x(rt2x00dev, ant);
else
rt61pci_config_antenna_2529(rt2x00dev, ant);
@@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
short lna_gain = 0;

if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;

rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
} else {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
lna_gain += 14;

rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
@@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
low_bound = 0x28;
up_bound = 0x48;
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
low_bound += 0x10;
up_bound += 0x10;
}
} else {
low_bound = 0x20;
up_bound = 0x40;
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
low_bound += 0x10;
up_bound += 0x10;
}
@@ -2537,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Determine number of antennas.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
- __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);

/*
* Identify default antenna configuration.
@@ -2551,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Read the Frame type.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
- __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);

/*
* Detect if this device has a hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Read frequency offset and RF programming sequence.
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
- __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);

rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);

@@ -2574,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);

if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
- __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
- __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);

/*
* When working with a RF2529 chip without double antenna,
@@ -2584,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* eeprom word.
*/
if (rt2x00_rf(rt2x00dev, RF2529) &&
- !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+ !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) {
rt2x00dev->default_ant.rx =
ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
rt2x00dev->default_ant.tx =
@@ -2799,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->supported_bands = SUPPORT_BAND_2GHZ;
spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;

- if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) {
+ if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) {
spec->num_channels = 14;
spec->channels = rf_vals_noseq;
} else {
@@ -2869,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* This device has multiple filters for control frames,
* but has no a separate filter for PS Poll frames.
*/
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);

/*
* This device requires firmware and DMA mapped skbs.
*/
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
- __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+ __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+ __set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
- __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 6593059..cdb026d 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
- temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+ temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)
&& (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
break;
@@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,

rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+ !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));

/*
* Configure the RX antenna.
@@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,

if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
sel = antenna_sel_a;
- lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+ lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
} else {
sel = antenna_sel_bg;
- lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+ lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
}

for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
short lna_gain = 0;

if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;

rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
@@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
low_bound = 0x28;
up_bound = 0x48;

- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
low_bound += 0x10;
up_bound += 0x10;
}
@@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
up_bound = 0x1c;
}

- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
low_bound += 0x14;
up_bound += 0x10;
}
@@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
}

if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+ if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
if (lna == 3 || lna == 2)
offset += 10;
} else {
@@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Read the Frame type.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
- __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);

/*
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
- __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);

/*
* Read frequency offset.
@@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);

if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
- __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
- __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
}

/*
@@ -2200,15 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
* This device has multiple filters for control frames,
* but has no a separate filter for PS Poll frames.
*/
- __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);

/*
* This device requires firmware.
*/
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+ __set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
if (!modparam_nohwcrypt)
- __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
- __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+ __set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+ __set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);

/*
* Set the rssi offset.
--
1.7.2.3


2011-04-18 13:35:57

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 09/23] rt2x00: fix queue timeout checks

From: Johannes Stezenbach <[email protected]>

Add a timestamp to each queue entry which is updated whenever
the status of the entry changes, and remove the per-queue
timestamps. The previous check was incorrect and caused both
false positives and false negatives.

With the corrected check it comes apparent that the TX status
usually times out on rt2800usb unless there is sufficient traffic
(i.e. the next TX will complete the previous TX status).

Signed-off-by: Johannes Stezenbach <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00dev.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2x00lib.h | 6 +++---
drivers/net/wireless/rt2x00/rt2x00queue.c | 11 +++++------
drivers/net/wireless/rt2x00/rt2x00queue.h | 23 +++++++++++++----------
drivers/net/wireless/rt2x00/rt2x00usb.c | 20 ++++++++++++++++++--
5 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index af25b01..2e490e0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -225,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
void rt2x00lib_dmastart(struct queue_entry *entry)
{
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ rt2x00queue_index_inc(entry, Q_INDEX);
}
EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);

@@ -233,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry)
{
set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+ rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
}
EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);

@@ -392,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,

rt2x00dev->ops->lib->clear_entry(entry);

- rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ rt2x00queue_index_inc(entry, Q_INDEX_DONE);

/*
* If the data queue was below the threshold before the txdone
@@ -559,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)

submit_entry:
entry->flags = 0;
- rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ rt2x00queue_index_inc(entry, Q_INDEX_DONE);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00dev->ops->lib->clear_entry(entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index bbee2cd..57ede6c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -175,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,

/**
* rt2x00queue_index_inc - Index incrementation function
- * @queue: Queue (&struct data_queue) to perform the action on.
+ * @entry: Queue entry (&struct queue_entry) to perform the action on.
* @index: Index type (&enum queue_index) to perform the action on.
*
- * This function will increase the requested index on the queue,
+ * This function will increase the requested index on the entry's queue,
* it will grab the appropriate locks and handle queue overflow events by
* resetting the index to the start of the queue.
*/
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);

/**
* rt2x00queue_init_queues - Initialize all data queues
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 458bb48..df8817f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -561,7 +561,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,

set_bit(ENTRY_DATA_PENDING, &entry->flags);

- rt2x00queue_index_inc(queue, Q_INDEX);
+ rt2x00queue_index_inc(entry, Q_INDEX);
rt2x00queue_write_tx_descriptor(entry, &txdesc);
rt2x00queue_kick_tx_queue(queue, &txdesc);

@@ -727,8 +727,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
}
EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);

-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
{
+ struct data_queue *queue = entry->queue;
unsigned long irqflags;

if (unlikely(index >= Q_INDEX_MAX)) {
@@ -743,7 +744,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
if (queue->index[index] >= queue->limit)
queue->index[index] = 0;

- queue->last_action[index] = jiffies;
+ entry->last_action = jiffies;

if (index == Q_INDEX) {
queue->length++;
@@ -969,10 +970,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
queue->count = 0;
queue->length = 0;

- for (i = 0; i < Q_INDEX_MAX; i++) {
+ for (i = 0; i < Q_INDEX_MAX; i++)
queue->index[i] = 0;
- queue->last_action[i] = jiffies;
- }

spin_unlock_irqrestore(&queue->index_lock, irqflags);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 6b66452..36f4d03 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -364,6 +364,7 @@ enum queue_entry_flags {
* struct queue_entry: Entry inside the &struct data_queue
*
* @flags: Entry flags, see &enum queue_entry_flags.
+ * @last_action: Timestamp of last change.
* @queue: The data queue (&struct data_queue) to which this entry belongs.
* @skb: The buffer which is currently being transmitted (for TX queue),
* or used to directly recieve data in (for RX queue).
@@ -373,6 +374,7 @@ enum queue_entry_flags {
*/
struct queue_entry {
unsigned long flags;
+ unsigned long last_action;

struct data_queue *queue;

@@ -463,7 +465,6 @@ struct data_queue {
unsigned short threshold;
unsigned short length;
unsigned short index[Q_INDEX_MAX];
- unsigned long last_action[Q_INDEX_MAX];

unsigned short txop;
unsigned short aifs;
@@ -635,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)

/**
* rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports
- * @queue: Queue to check.
+ * @entry: Queue entry to check.
*/
-static inline int rt2x00queue_status_timeout(struct data_queue *queue)
+static inline int rt2x00queue_status_timeout(struct queue_entry *entry)
{
- return time_after(queue->last_action[Q_INDEX_DMA_DONE],
- queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+ if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+ return false;
+ return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
}

/**
- * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
- * @queue: Queue to check.
+ * rt2x00queuedma__timeout - Check if a timeout occured for DMA transfers
+ * @entry: Queue entry to check.
*/
-static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
{
- return time_after(queue->last_action[Q_INDEX],
- queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
+ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ return false;
+ return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
}

/**
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 5fbab6f..14736e2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -521,15 +521,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
}

+static int rt2x00usb_status_timeout(struct data_queue *queue)
+{
+ struct queue_entry *entry;
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+ return rt2x00queue_status_timeout(entry);
+}
+
+static int rt2x00usb_dma_timeout(struct data_queue *queue)
+{
+ struct queue_entry *entry;
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+ return rt2x00queue_dma_timeout(entry);
+}
+
void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;

tx_queue_for_each(rt2x00dev, queue) {
if (!rt2x00queue_empty(queue)) {
- if (rt2x00queue_dma_timeout(queue))
+ if (rt2x00usb_dma_timeout(queue))
rt2x00usb_watchdog_tx_dma(queue);
- if (rt2x00queue_status_timeout(queue))
+ if (rt2x00usb_status_timeout(queue))
rt2x00usb_watchdog_tx_status(queue);
}
}
--
1.7.2.3


2011-04-18 13:36:24

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 23/23] rt2x00: Implement get_antenna and set_antenna callback functions

From: Ivo van Doorn <[email protected]>

Implement the get_antenna and set_antenna callback functions, which will
allow clients to control the antenna for all non-11n hardware (Antenna handling
in rt2800 is still a bit magical, so we can't use the set_antenna for those drivers
yet).

To best support the set_antenna callback some modifications are needed in the
diversity handling. We should never look at the default antenna settings to determine
if software diversity is enabled. Instead we should set the diversity flag when
possible, which will allow the link_tuner to automatically pick up the tuning.

Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 2 +
drivers/net/wireless/rt2x00/rt2500pci.c | 2 +
drivers/net/wireless/rt2x00/rt2500usb.c | 2 +
drivers/net/wireless/rt2x00/rt2x00.h | 2 +
drivers/net/wireless/rt2x00/rt2x00config.c | 45 +++++++++++--------
drivers/net/wireless/rt2x00/rt2x00link.c | 10 ----
drivers/net/wireless/rt2x00/rt2x00mac.c | 65 ++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt61pci.c | 2 +
drivers/net/wireless/rt2x00/rt73usb.c | 2 +
9 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index bbe76f7..937f9e8 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1720,6 +1720,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.tx_last_beacon = rt2400pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .set_antenna = rt2x00mac_set_antenna,
+ .get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
};

diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 6f48996..d27d7b8 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2013,6 +2013,8 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.tx_last_beacon = rt2500pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .set_antenna = rt2x00mac_set_antenna,
+ .get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
};

diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 5ef3386..b21f812 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1823,6 +1823,8 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.conf_tx = rt2x00mac_conf_tx,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .set_antenna = rt2x00mac_set_antenna,
+ .get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
};

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index f1d8f55..acf561f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1254,6 +1254,8 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);

diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index f70a2b4..2a313b6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
}

-static inline
-enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
- enum antenna default_ant)
-{
- if (current_ant != ANTENNA_SW_DIVERSITY)
- return current_ant;
- return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
-}
-
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
struct antenna_setup config)
{
@@ -126,19 +117,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
struct antenna_setup *active = &rt2x00dev->link.ant.active;

/*
- * Failsafe: Make sure we are not sending the
- * ANTENNA_SW_DIVERSITY state to the driver.
- * If that happens, fallback to hardware defaults,
- * or our own default.
+ * When the caller tries to send the SW diversity,
+ * we must update the ANTENNA_RX_DIVERSITY flag to
+ * enable the antenna diversity in the link tuner.
+ *
+ * Secondly, we must guarentee we never send the
+ * software antenna diversity command to the driver.
*/
- if (!(ant->flags & ANTENNA_RX_DIVERSITY))
- config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
- else if (config.rx == ANTENNA_SW_DIVERSITY)
+ if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
+ if (config.rx == ANTENNA_SW_DIVERSITY) {
+ ant->flags |= ANTENNA_RX_DIVERSITY;
+
+ if (def->rx == ANTENNA_SW_DIVERSITY)
+ config.rx = ANTENNA_B;
+ else
+ config.rx = def->rx;
+ }
+ } else if (config.rx == ANTENNA_SW_DIVERSITY)
config.rx = active->rx;

- if (!(ant->flags & ANTENNA_TX_DIVERSITY))
- config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
- else if (config.tx == ANTENNA_SW_DIVERSITY)
+ if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
+ if (config.tx == ANTENNA_SW_DIVERSITY) {
+ ant->flags |= ANTENNA_TX_DIVERSITY;
+
+ if (def->tx == ANTENNA_SW_DIVERSITY)
+ config.tx = ANTENNA_B;
+ else
+ config.tx = def->tx;
+ }
+ } else if (config.tx == ANTENNA_SW_DIVERSITY)
config.tx = active->tx;

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index ba0bb76..fa55399 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
/*
* Determine if software diversity is enabled for
* either the TX or RX antenna (or both).
- * Always perform this check since within the link
- * tuner interval the configuration might have changed.
*/
- ant->flags &= ~ANTENNA_RX_DIVERSITY;
- ant->flags &= ~ANTENNA_TX_DIVERSITY;
-
- if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
- ant->flags |= ANTENNA_RX_DIVERSITY;
- if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
- ant->flags |= ANTENNA_TX_DIVERSITY;
-
if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
!(ant->flags & ANTENNA_TX_DIVERSITY)) {
ant->flags = 0;
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 6d1d383..93bec14 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -738,6 +738,71 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
}
EXPORT_SYMBOL_GPL(rt2x00mac_flush);

+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct link_ant *ant = &rt2x00dev->link.ant;
+ struct antenna_setup *def = &rt2x00dev->default_ant;
+ struct antenna_setup setup;
+
+ // The antenna value is not supposed to be 0,
+ // or exceed the maximum number of antenna's.
+ if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
+ return -EINVAL;
+
+ // When the client tried to configure the antenna to or from
+ // diversity mode, we must reset the default antenna as well
+ // as that controls the diversity switch.
+ if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
+ ant->flags &= ~ANTENNA_TX_DIVERSITY;
+ if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
+ ant->flags &= ~ANTENNA_RX_DIVERSITY;
+
+ // If diversity is being enabled, check if we need hardware
+ // or software diversity. In the latter case, reset the value,
+ // and make sure we update the antenna flags to have the
+ // link tuner pick up the diversity tuning.
+ if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
+ tx_ant = ANTENNA_SW_DIVERSITY;
+ ant->flags |= ANTENNA_TX_DIVERSITY;
+ }
+
+ if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
+ rx_ant = ANTENNA_SW_DIVERSITY;
+ ant->flags |= ANTENNA_RX_DIVERSITY;
+ }
+
+ setup.tx = tx_ant;
+ setup.rx = rx_ant;
+
+ rt2x00lib_config_antenna(rt2x00dev, setup);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
+
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct link_ant *ant = &rt2x00dev->link.ant;
+ struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+ // When software diversity is active, we must report this to the
+ // client and not the current active antenna state.
+ if (ant->flags & ANTENNA_TX_DIVERSITY)
+ *tx_ant = ANTENNA_HW_DIVERSITY;
+ else
+ *tx_ant = active->tx;
+
+ if (ant->flags & ANTENNA_RX_DIVERSITY)
+ *rx_ant = ANTENNA_HW_DIVERSITY;
+ else
+ *rx_ant = active->rx;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
+
void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
{
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index eb54031..9d35ec1 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2979,6 +2979,8 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.get_tsf = rt61pci_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .set_antenna = rt2x00mac_set_antenna,
+ .get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
};

diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index bf7fea4..a6ce7d6 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2310,6 +2310,8 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.get_tsf = rt73usb_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.flush = rt2x00mac_flush,
+ .set_antenna = rt2x00mac_set_antenna,
+ .get_antenna = rt2x00mac_get_antenna,
.get_ringparam = rt2x00mac_get_ringparam,
};

--
1.7.2.3


2011-04-28 03:02:37

by Yasushi SHOJI

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

At Mon, 18 Apr 2011 15:27:43 +0200,
Ivo van Doorn wrote:
>
> From: Helmut Schaa <helmut.schaa-gM/[email protected]>
>
> Allow passing a void pointer to rt2x00_queue_entry_for_each which in
> turn in provided to the callback function.
>
> Furthermore, allow the callback function to stop processing by returning
> true. And also notify the caller of rt2x00_queue_entry_for_each if the
> loop was canceled by the callback.

My colleague just tested this patch set and found out that the in
question makes our 400MHz ARM cpu board with ralink usb dongle non
functional due to high cpu consumption. it seems for us that exiting
from function every time it finds an entry is too expensive on systems
slower than PCs.

To verify our thought, we changed the source code as the patch below.
What we intended to do with this change is to continue processing all
entry without breaking semantics.

With the patch below our board seem to work fine again, but not sure
exactly why it takes so much time to check the list again. We are not
against the idea of the patch at all. We just want to ask you guys
how we should go to track this problem. it might be the slow usb?

Thanks,

> diff -urN compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c
> --- compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-04-27 04:04:26.000000000 +0900
> +++ compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c 2011-04-27 17:13:45.000000000 +0900
> @@ -740,6 +740,7 @@
> unsigned int index_start;
> unsigned int index_end;
> unsigned int i;
> + bool ret = false;
>
> if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
> ERROR(queue->rt2x00dev,
> @@ -766,21 +767,21 @@
> if (index_start < index_end) {
> for (i = index_start; i < index_end; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
> } else {
> for (i = index_start; i < queue->limit; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
>
> for (i = 0; i < index_end; i++) {
> if (fn(&queue->entries[i], data))
> - return true;
> + ret = true;
> }
> }
>
> - return false;
> + return ret;
> }
> EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
--
yashi

2011-04-18 13:35:47

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode

From: Helmut Schaa <[email protected]>

This seems to fix problems with some powersaving clients since a
positive value in TBTT_SYNC_CFG_TBTT_ADJUST introduces beacon skew,
which is not wanted in AP mode.

Also update the rest of the TBTT_SYNC config according to the
legacy drivers in AP mode.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index c6f5584..e0fa559 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1245,6 +1245,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+ if (conf->sync == TSF_SYNC_AP_NONE) {
+ /*
+ * Tune beacon queue transmit parameters for AP mode
+ */
+ rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
+ rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+ } else {
+ rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+ rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
+ rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+ }
}

if (flags & CONFIG_UPDATE_MAC) {
--
1.7.2.3


2011-04-18 15:02:49

by Rafał Miłecki

[permalink] [raw]
Subject: Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb

W dniu 18 kwietnia 2011 16:48 użytkownik Helmut Schaa
<[email protected]> napisał:
> Hi,
>
> Am Montag, 18. April 2011 schrieb Ivo Van Doorn:
>> > Wouldn't this be better to create two pointers in struct rt2x00_dev.
>> > One for writing function and one for reading function? Am I right
>> > thinking calling functions by pointers is quite fast? Or is this still
>> > noticeably slower than using proper functions directly?
>>
>> We already have the pointer inside struct rt2x00_dev which references
>> the register access functions for rt2800pci/usb. These pointers are used
>> by rt2800lib to access the common registers. What this patch does, is
>> optimize the case where we exactly know which function we need, because
>> we are in the actual driver.
>>
>> As for the performance, I'll let Helmut comment on that as he created patch 20,
>> which introduced this change to rt2800pci. :)
>
> Sure, I was comparing some assembly in the rt2800pci hotpaths (on a 380Mhz
> MIPS CPU btw). A register read/write on PCI is just a readl or writel,
> nothing more but using the indirect wrappers we get something like this
> (This is x86_64 as I didn't want to cross compile right now). For example
> the register read + write in rt2800pci_enable_interrupt (which is called
> in every tasklet invocation, which can happen for every rx'ed frame and
> every tx'ed frame).
>
> movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
> leaq    -36(%rbp), %rdx #, tmp82
> movq    %rbx, %rdi      # rt2x00dev,
> movq    72(%rax), %rax  # D.47612_27->drv, D.47612_27->drv
> movl    $516, %esi      #,
> call    *(%rax) # rt2800ops_29->register_read
> movb    %r14b, %cl      #,
> movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
> movq    %rbx, %rdi      # rt2x00dev,
> movq    72(%rax), %rax  # D.47619_31->drv, D.47619_31->drv
> movl    $516, %esi      #,
> movl    $1, %edx        #, reg.119
> sall    %cl, %edx       #, reg.119
> andl    %r13d, %edx     # irq_field$bit_mask, reg.119
> notl    %r13d   # tmp89
> andl    -36(%rbp), %r13d        # reg, tmp89
> orl     %r13d, %edx     # tmp89, reg.119
> movl    %edx, -36(%rbp) # reg.119, reg
> call    *16(%rax)       # rt2800ops_33->register_write
>
> Also, this will trigger rt2x00pci_register_read
>
> pushq   %rbp    #
> mov     %esi, %esi      # offset, addr.27
> movq    %rsp, %rbp      #,
> addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.27
> movl    %eax, (%rdx)    # ret,* value
>
> And rt2x00pci_register_write:
>
> pushq   %rbp    #
> mov     %esi, %esi      # offset, addr.26
> movq    %rsp, %rbp      #,
> addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.26
> movl    %edx,(%rsi)        # value,* addr.26
>
> And here the same when using rt2x00pci_register_read/write directly:
>
> movq    1056(%rbx), %rax        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
> movl    516(%rax),%eax     #, reg.119
> movl    %r13d, %edx     # irq_field$bit_mask, tmp80
> movb    %r14b, %cl      #,
> notl    %edx    # tmp80
> andl    %edx, %eax      # tmp80, reg.119
> movl    $1, %edx        #, tmp85
> sall    %cl, %edx       #, tmp85
> andl    %r13d, %edx     # irq_field$bit_mask, tmp85
> orl     %edx, %eax      # tmp85, reg.119
> movq    1056(%rbx), %rdx        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
> movl    %eax,516(%rdx)     # reg.119,
>
> As you can see we save more then just one indirect function call:
>
> 17 movs -> 7 movs
> 2 calls -> 0 calls
> 1 add -> 0 adds
>
> This happens because the compiler is able to apply a number of optimizations
> that are only possible by inlining rt2x00pci_register_read/write. When using
> the indirect function call the compiler is not able to inline them.
>
> So, I first thought about using direct calls only in the interrupt handler
> and the RX/TX hotpaths but since using rt2800_register_read and
> rt2x00pci_register_read in different locations in rt2800pci would be even
> more confusing I just replaced every rt2800_register_read with
> rt2x00pci_register_read in rt2800pci.
>
> One way to keep the abstraction and still improve the register_read/write
> operations would be to introduce a inlined rt2800pci_register_read/write
> which directly calls rt2x00pci_register_read/write and provide that via
> rt2800_ops to rt2800lib. That way all calls in rt2800pci can directly
> inline rt2x00_register_read/write while rt2800lib will still use indirect
> calls to do the same.
>
> However, I didn't see any need for this.

Huh, thanks a lot for great explanation :)

--
Rafał

2011-04-18 13:36:16

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files.

From: Gertjan van Wingerde <[email protected]>

The two functions that are in rt2x00ht.c can be much better placed
closer to the places where the call-sites of these functions are (one
in rt2x00config.c and one in rt2x00queue.c) allowing us to make these
functions static.
Also, conditional compilations doesn't seem to be necessary anymore as
802.11n support is quite common nowadays.

This makes the code a bit easier readable and searchable.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/Kconfig | 5 -
drivers/net/wireless/rt2x00/Makefile | 1 -
drivers/net/wireless/rt2x00/rt2x00config.c | 28 ++++++
drivers/net/wireless/rt2x00/rt2x00ht.c | 137 ----------------------------
drivers/net/wireless/rt2x00/rt2x00lib.h | 24 -----
drivers/net/wireless/rt2x00/rt2x00queue.c | 81 ++++++++++++++++-
6 files changed, 108 insertions(+), 168 deletions(-)
delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ht.c

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index d7e27b3..c457731 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -59,7 +59,6 @@ config RT2800PCI
select RT2800_LIB
select RT2X00_LIB_PCI if PCI
select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
- select RT2X00_LIB_HT
select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO
select CRC_CCITT
@@ -133,7 +132,6 @@ config RT2800USB
depends on USB
select RT2800_LIB
select RT2X00_LIB_USB
- select RT2X00_LIB_HT
select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO
select CRC_CCITT
@@ -196,9 +194,6 @@ config RT2X00_LIB_USB
config RT2X00_LIB
tristate

-config RT2X00_LIB_HT
- boolean
-
config RT2X00_LIB_FIRMWARE
boolean
select FW_LOADER
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 9713398..349d5b8 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o

obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index e225a66..f70a2b4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -163,6 +163,34 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
rt2x00queue_start_queue(rt2x00dev->rx);
}

+static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf)
+{
+ struct hw_mode_spec *spec = &rt2x00dev->spec;
+ int center_channel;
+ u16 i;
+
+ /*
+ * Initialize center channel to current channel.
+ */
+ center_channel = spec->channels[conf->channel->hw_value].channel;
+
+ /*
+ * Adjust center channel to HT40+ and HT40- operation.
+ */
+ if (conf_is_ht40_plus(conf))
+ center_channel += 2;
+ else if (conf_is_ht40_minus(conf))
+ center_channel -= (center_channel == 14) ? 1 : 2;
+
+ for (i = 0; i < spec->num_channels; i++)
+ if (spec->channels[i].channel == center_channel)
+ return i;
+
+ WARN_ON(1);
+ return conf->channel->hw_value;
+}
+
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
unsigned int ieee80211_flags)
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
deleted file mode 100644
index a30f68c..0000000
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- Copyright (C) 2004 - 2009 Ivo van Doorn <[email protected]>
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the
- Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- Module: rt2x00lib
- Abstract: rt2x00 HT specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
- struct txentry_desc *txdesc,
- const struct rt2x00_rate *hwrate)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-
- if (tx_info->control.sta)
- txdesc->u.ht.mpdu_density =
- tx_info->control.sta->ht_cap.ampdu_density;
-
- txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
-
- /*
- * Only one STBC stream is supported for now.
- */
- if (tx_info->flags & IEEE80211_TX_CTL_STBC)
- txdesc->u.ht.stbc = 1;
-
- /*
- * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
- * mcs rate to be used
- */
- if (txrate->flags & IEEE80211_TX_RC_MCS) {
- txdesc->u.ht.mcs = txrate->idx;
-
- /*
- * MIMO PS should be set to 1 for STA's using dynamic SM PS
- * when using more then one tx stream (>MCS7).
- */
- if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
- ((tx_info->control.sta->ht_cap.cap &
- IEEE80211_HT_CAP_SM_PS) >>
- IEEE80211_HT_CAP_SM_PS_SHIFT) ==
- WLAN_HT_CAP_SM_PS_DYNAMIC)
- __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
- } else {
- txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
- if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
- txdesc->u.ht.mcs |= 0x08;
- }
-
- /*
- * This frame is eligible for an AMPDU, however, don't aggregate
- * frames that are intended to probe a specific tx rate.
- */
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
- !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
- __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
-
- /*
- * Set 40Mhz mode if necessary (for legacy rates this will
- * duplicate the frame to both channels).
- */
- if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
- txrate->flags & IEEE80211_TX_RC_DUP_DATA)
- __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
- if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
- __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
-
- /*
- * Determine IFS values
- * - Use TXOP_BACKOFF for management frames except beacons
- * - Use TXOP_SIFS for fragment bursts
- * - Use TXOP_HTTXOP for everything else
- *
- * Note: rt2800 devices won't use CTS protection (if used)
- * for frames not transmitted with TXOP_HTTXOP
- */
- if (ieee80211_is_mgmt(hdr->frame_control) &&
- !ieee80211_is_beacon(hdr->frame_control))
- txdesc->u.ht.txop = TXOP_BACKOFF;
- else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
- txdesc->u.ht.txop = TXOP_SIFS;
- else
- txdesc->u.ht.txop = TXOP_HTTXOP;
-}
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf)
-{
- struct hw_mode_spec *spec = &rt2x00dev->spec;
- int center_channel;
- u16 i;
-
- /*
- * Initialize center channel to current channel.
- */
- center_channel = spec->channels[conf->channel->hw_value].channel;
-
- /*
- * Adjust center channel to HT40+ and HT40- operation.
- */
- if (conf_is_ht40_plus(conf))
- center_channel += 2;
- else if (conf_is_ht40_minus(conf))
- center_channel -= (center_channel == 14) ? 1 : 2;
-
- for (i = 0; i < spec->num_channels; i++)
- if (spec->channels[i].channel == center_channel)
- return i;
-
- WARN_ON(1);
- return conf->channel->hw_value;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 57ede6c..322cc4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -388,30 +388,6 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
#endif /* CONFIG_RT2X00_LIB_CRYPTO */

/*
- * HT handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_HT
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
- struct txentry_desc *txdesc,
- const struct rt2x00_rate *hwrate);
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf);
-#else
-static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
- struct txentry_desc *txdesc,
- const struct rt2x00_rate *hwrate)
-{
-}
-
-static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf)
-{
- return conf->channel->hw_value;
-}
-#endif /* CONFIG_RT2X00_LIB_HT */
-
-/*
* RFkill handlers.
*/
static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 0d79278..56f9d0d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
}
}

+static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+ struct txentry_desc *txdesc,
+ const struct rt2x00_rate *hwrate)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+
+ if (tx_info->control.sta)
+ txdesc->u.ht.mpdu_density =
+ tx_info->control.sta->ht_cap.ampdu_density;
+
+ txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
+
+ /*
+ * Only one STBC stream is supported for now.
+ */
+ if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+ txdesc->u.ht.stbc = 1;
+
+ /*
+ * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
+ * mcs rate to be used
+ */
+ if (txrate->flags & IEEE80211_TX_RC_MCS) {
+ txdesc->u.ht.mcs = txrate->idx;
+
+ /*
+ * MIMO PS should be set to 1 for STA's using dynamic SM PS
+ * when using more then one tx stream (>MCS7).
+ */
+ if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
+ ((tx_info->control.sta->ht_cap.cap &
+ IEEE80211_HT_CAP_SM_PS) >>
+ IEEE80211_HT_CAP_SM_PS_SHIFT) ==
+ WLAN_HT_CAP_SM_PS_DYNAMIC)
+ __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
+ } else {
+ txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+ if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+ txdesc->u.ht.mcs |= 0x08;
+ }
+
+ /*
+ * This frame is eligible for an AMPDU, however, don't aggregate
+ * frames that are intended to probe a specific tx rate.
+ */
+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+ !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+ __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+ /*
+ * Set 40Mhz mode if necessary (for legacy rates this will
+ * duplicate the frame to both channels).
+ */
+ if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+ txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+ __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+ if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+ __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+
+ /*
+ * Determine IFS values
+ * - Use TXOP_BACKOFF for management frames except beacons
+ * - Use TXOP_SIFS for fragment bursts
+ * - Use TXOP_HTTXOP for everything else
+ *
+ * Note: rt2800 devices won't use CTS protection (if used)
+ * for frames not transmitted with TXOP_HTTXOP
+ */
+ if (ieee80211_is_mgmt(hdr->frame_control) &&
+ !ieee80211_is_beacon(hdr->frame_control))
+ txdesc->u.ht.txop = TXOP_BACKOFF;
+ else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+ txdesc->u.ht.txop = TXOP_SIFS;
+ else
+ txdesc->u.ht.txop = TXOP_HTTXOP;
+}
+
static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
@@ -397,7 +476,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
rt2x00queue_create_tx_descriptor_seq(entry, txdesc);

if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
- rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+ rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
else
rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
}
--
1.7.2.3


2011-04-18 13:36:11

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 16/23] rt2x00: Add USB IDs.

From: Gertjan van Wingerde <[email protected]>

Add USB IDs that are listed in the latest Ralink Windows and/or Linux drivers.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6f7c161..fd8aa99 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -775,6 +775,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07b8, 0x3072) },
{ USB_DEVICE(0x1482, 0x3c09) },
/* AirTies */
+ { USB_DEVICE(0x1eda, 0x2012) },
{ USB_DEVICE(0x1eda, 0x2310) },
/* Allwin */
{ USB_DEVICE(0x8516, 0x2070) },
@@ -933,6 +934,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x0042) },
{ USB_DEVICE(0x0df6, 0x0047) },
{ USB_DEVICE(0x0df6, 0x0048) },
+ { USB_DEVICE(0x0df6, 0x0051) },
+ { USB_DEVICE(0x0df6, 0x005f) },
/* SMC */
{ USB_DEVICE(0x083a, 0x6618) },
{ USB_DEVICE(0x083a, 0x7511) },
@@ -963,6 +966,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0586, 0x3416) },
{ USB_DEVICE(0x0586, 0x3418) },
{ USB_DEVICE(0x0586, 0x341e) },
+ { USB_DEVICE(0x0586, 0x343e) },
#ifdef CONFIG_RT2800USB_RT33XX
/* Ralink */
{ USB_DEVICE(0x148f, 0x3370) },
@@ -998,6 +1002,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
* Unclear what kind of devices these are (they aren't supported by the
* vendor linux driver).
*/
+ /* Abocom */
+ { USB_DEVICE(0x07b8, 0x3073) },
+ { USB_DEVICE(0x07b8, 0x3074) },
/* Alpha Networks */
{ USB_DEVICE(0x14b2, 0x3c08) },
{ USB_DEVICE(0x14b2, 0x3c11) },
@@ -1005,14 +1012,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0e0b, 0x9031) },
{ USB_DEVICE(0x0e0b, 0x9041) },
/* ASUS */
+ { USB_DEVICE(0x0b05, 0x166a) },
{ USB_DEVICE(0x0b05, 0x1760) },
{ USB_DEVICE(0x0b05, 0x1761) },
{ USB_DEVICE(0x0b05, 0x1790) },
+ { USB_DEVICE(0x0b05, 0x179d) },
/* AzureWave */
{ USB_DEVICE(0x13d3, 0x3262) },
{ USB_DEVICE(0x13d3, 0x3284) },
{ USB_DEVICE(0x13d3, 0x3322) },
/* Belkin */
+ { USB_DEVICE(0x050d, 0x1003) },
{ USB_DEVICE(0x050d, 0x825a) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x012e) },
@@ -1028,20 +1038,29 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07d1, 0x3c13) },
{ USB_DEVICE(0x07d1, 0x3c15) },
{ USB_DEVICE(0x07d1, 0x3c17) },
+ { USB_DEVICE(0x2001, 0x3c17) },
/* Edimax */
{ USB_DEVICE(0x7392, 0x4085) },
+ { USB_DEVICE(0x7392, 0x7722) },
/* Encore */
{ USB_DEVICE(0x203d, 0x14a1) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0010) },
/* Gigabyte */
{ USB_DEVICE(0x1044, 0x800c) },
+ /* Huawei */
+ { USB_DEVICE(0x148f, 0xf101) },
+ /* I-O DATA */
+ { USB_DEVICE(0x04bb, 0x094b) },
/* LevelOne */
{ USB_DEVICE(0x1740, 0x0605) },
{ USB_DEVICE(0x1740, 0x0615) },
/* Linksys */
{ USB_DEVICE(0x1737, 0x0077) },
{ USB_DEVICE(0x1737, 0x0078) },
+ /* Logitec */
+ { USB_DEVICE(0x0789, 0x0168) },
+ { USB_DEVICE(0x0789, 0x0169) },
/* Motorola */
{ USB_DEVICE(0x100d, 0x9032) },
/* Ovislink */
@@ -1056,6 +1075,15 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x2019, 0xab24) },
/* Qcom */
{ USB_DEVICE(0x18e8, 0x6259) },
+ /* RadioShack */
+ { USB_DEVICE(0x08b9, 0x1197) },
+ /* Sitecom */
+ { USB_DEVICE(0x0df6, 0x003c) },
+ { USB_DEVICE(0x0df6, 0x004a) },
+ { USB_DEVICE(0x0df6, 0x004d) },
+ { USB_DEVICE(0x0df6, 0x0053) },
+ { USB_DEVICE(0x0df6, 0x0060) },
+ { USB_DEVICE(0x0df6, 0x0062) },
/* SMC */
{ USB_DEVICE(0x083a, 0xa512) },
{ USB_DEVICE(0x083a, 0xc522) },
--
1.7.2.3


2011-04-18 13:35:59

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 10/23] rt2800usb: handle TX status timeouts

From: Johannes Stezenbach <[email protected]>

The watchdog just triggers rt2800usb_work_txdone() when it
detects a TX status timeout, thus rt2800usb_work_txdone() needs to
handle this case.

Signed-off-by: Johannes Stezenbach <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 862430e..69004b9 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -449,11 +449,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);

- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+ break;
+ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ else if (rt2x00queue_status_timeout(entry))
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ else
break;
-
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
}
}
}
--
1.7.2.3


2011-04-18 13:36:04

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 12/23] Decrease association time for USB devices

From: Ivo van Doorn <[email protected]>

When powersaving is enabled, assocaition times are very high
(for WPA2 networks, the time can easily be around the 3 seconds).

This is caused, because the flushing of the queues takes
too much time. Without the flushing callback mac80211 assumes
a timeout of 100ms while scanning. Limit all flush waiting
loops to the same maximum.

We can apply this maximum by passing the drop status to the
driver, which makes sure the driver performs extra actions
during the waiting for the queue to become empty.

After these changes, association times fall within the
healthy range of ~0.6 seconds with powersaving enabled.
The difference between association time between powersaving
enabled and disabled is now only ~0.1 second (which can also
be due to the measuring method).

Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 1 +
drivers/net/wireless/rt2x00/rt2500pci.c | 1 +
drivers/net/wireless/rt2x00/rt2800pci.c | 1 +
drivers/net/wireless/rt2x00/rt2x00.h | 2 +-
drivers/net/wireless/rt2x00/rt2x00pci.c | 9 +++++++++
drivers/net/wireless/rt2x00/rt2x00pci.h | 10 ++++++++++
drivers/net/wireless/rt2x00/rt2x00queue.c | 19 +++++--------------
drivers/net/wireless/rt2x00/rt2x00usb.c | 9 +++++----
drivers/net/wireless/rt2x00/rt2x00usb.h | 8 +++++---
drivers/net/wireless/rt2x00/rt61pci.c | 1 +
10 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 5d1654a..6b7206e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1740,6 +1740,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.start_queue = rt2400pci_start_queue,
.kick_queue = rt2400pci_kick_queue,
.stop_queue = rt2400pci_stop_queue,
+ .flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_beacon = rt2400pci_write_beacon,
.fill_rxdone = rt2400pci_fill_rxdone,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 3da954e..82e8012 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2033,6 +2033,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.start_queue = rt2500pci_start_queue,
.kick_queue = rt2500pci_kick_queue,
.stop_queue = rt2500pci_stop_queue,
+ .flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_beacon = rt2500pci_write_beacon,
.fill_rxdone = rt2500pci_fill_rxdone,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 4241f19..d2fe5fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1057,6 +1057,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.start_queue = rt2800pci_start_queue,
.kick_queue = rt2800pci_kick_queue,
.stop_queue = rt2800pci_stop_queue,
+ .flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 8f37121..dcdc50d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -571,7 +571,7 @@ struct rt2x00lib_ops {
void (*start_queue) (struct data_queue *queue);
void (*kick_queue) (struct data_queue *queue);
void (*stop_queue) (struct data_queue *queue);
- void (*flush_queue) (struct data_queue *queue);
+ void (*flush_queue) (struct data_queue *queue, bool drop);
void (*tx_dma_done) (struct queue_entry *entry);

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 9649bd0..695aecf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);

+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+ unsigned int i;
+
+ for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+ msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
/*
* Device initialization handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 07961b8..5d58874 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -107,6 +107,16 @@ struct queue_entry_priv_pci {
*/
bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);

+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
/*
* Device initialization handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index df8817f..0d79278 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -849,7 +849,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);

void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
{
- unsigned int i;
bool started;
bool tx_queue =
(queue->qid == QID_AC_VO) ||
@@ -884,20 +883,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
}

/*
- * 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.
+ * Check if driver supports flushing, if that is the case we can
+ * defer the flushing to the driver. Otherwise we must use the
+ * alternative which just waits for the queue to become empty.
*/
- for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
- msleep(10);
+ if (likely(queue->rt2x00dev->ops->lib->flush_queue))
+ queue->rt2x00dev->ops->lib->flush_queue(queue, drop);

/*
* The queue flush has failed...
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 34b8a88..9957579 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -458,13 +458,14 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
return false;
}

-void rt2x00usb_flush_queue(struct data_queue *queue)
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
{
struct work_struct *completion;
unsigned int i;

- rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
- rt2x00usb_flush_entry);
+ if (drop)
+ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+ rt2x00usb_flush_entry);

/*
* Obtain the queue completion handler
@@ -483,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
return;
}

- for (i = 0; i < 20; i++) {
+ for (i = 0; i < 10; i++) {
/*
* Check if the driver is already done, otherwise we
* have to sleep a little while to give the driver/hw
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index e3faca6..6aeba71 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -404,11 +404,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue);
/**
* rt2x00usb_flush_queue - Flush data queue
* @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
*
- * This will walk through all entries of the queue and kill all
- * URB's which were send to the device.
+ * This will walk through all entries of the queue and will optionally
+ * kill all URB's which were send to the device, or at least wait until
+ * they have been returned from the device..
*/
-void rt2x00usb_flush_queue(struct data_queue *queue);
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);

/**
* rt2x00usb_watchdog - Watchdog for USB communication
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c16c150..35c5d20 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3003,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.start_queue = rt61pci_start_queue,
.kick_queue = rt61pci_kick_queue,
.stop_queue = rt61pci_stop_queue,
+ .flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt61pci_write_tx_desc,
.write_beacon = rt61pci_write_beacon,
.clear_beacon = rt61pci_clear_beacon,
--
1.7.2.3


2011-04-18 13:36:07

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device.

From: Gertjan van Wingerde <[email protected]>

Move the USB ID entry from the unknown devices to the list of RT35xx based
devices.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 2005972..1bb9a7d 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -983,6 +983,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Linksys */
{ USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
+ { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Sitecom */
@@ -1041,7 +1042,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Linksys */
{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
- { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Motorola */
{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
/* Ovislink */
--
1.7.2.3


2011-04-29 06:06:40

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

On 04/28/11 20:55, Ivo Van Doorn wrote:
> Hi,
>
>> My colleague just tested this patch set and found out that the in
>> question makes our 400MHz ARM cpu board with ralink usb dongle non
>> functional due to high cpu consumption. it seems for us that exiting
>> from function every time it finds an entry is too expensive on systems
>> slower than PCs.
>
> Interesting, I would suspected the patch to reduce the CPU consumption
> rather then increasing it. I can do some testing regarding this looping
> during the weekend, but I haven't seen high CPU consumption on my
> system during my last test. However I wasn't testing on an embedded system...
>
>> To verify our thought, we changed the source code as the patch below.
>> What we intended to do with this change is to continue processing all
>> entry without breaking semantics.
>>
>> With the patch below our board seem to work fine again, but not sure
>> exactly why it takes so much time to check the list again. We are not
>> against the idea of the patch at all. We just want to ask you guys
>> how we should go to track this problem. it might be the slow usb?
>
> Could you try use debugfs and see if some queue and packet counters
> of mac80211/rt2x00 show excessive values?
>
> Have you been running the test with powersaving enabled or disabled?
>

Yeah, I had the same impression as Ivo, that it should save CPU cycles,
especially since the patch was submitted by Helmut, who is very keen
on saving CPU cycles, as he tests on an embedded (PCI-based) platform as
well.

But, if this proves to not be useful for now, then we should revert the
entire patch, as the patch proposed simply negates the intended behavior
and leaves a mess.

I believe the offending patch was preparation for another patch which so
far has not materialized in a usable form, so there should be no harm in
reverting the offending patch.

---
Gertjan

2011-04-30 14:01:21

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

> >> My colleague just tested this patch set and found out that the in
> >> question makes our 400MHz ARM cpu board with ralink usb dongle non
> >> functional due to high cpu consumption. it seems for us that exiting
> >> from function every time it finds an entry is too expensive on systems
> >> slower than PCs.
> >
> > Interesting, I would suspected the patch to reduce the CPU consumption
> > rather then increasing it. I can do some testing regarding this looping
> > during the weekend, but I haven't seen high CPU consumption on my
> > system during my last test. However I wasn't testing on an embedded system...
> >
> >> To verify our thought, we changed the source code as the patch below.
> >> What we intended to do with this change is to continue processing all
> >> entry without breaking semantics.
> >>
> >> With the patch below our board seem to work fine again, but not sure
> >> exactly why it takes so much time to check the list again. We are not
> >> against the idea of the patch at all. We just want to ask you guys
> >> how we should go to track this problem. it might be the slow usb?
> >
> > Could you try use debugfs and see if some queue and packet counters
> > of mac80211/rt2x00 show excessive values?
> >
> > Have you been running the test with powersaving enabled or disabled?
> >
>
> Yeah, I had the same impression as Ivo, that it should save CPU cycles,
> especially since the patch was submitted by Helmut, who is very keen
> on saving CPU cycles, as he tests on an embedded (PCI-based) platform as
> well.
>
> But, if this proves to not be useful for now, then we should revert the
> entire patch, as the patch proposed simply negates the intended behavior
> and leaves a mess.
>
> I believe the offending patch was preparation for another patch which so
> far has not materialized in a usable form, so there should be no harm in
> reverting the offending patch.

I've have a different idea, after a discussion with Helmut, I had changed his
original patch. But I think below patch should resolve the issue as well.

Yasushi, can you please test this patch.

Thanks,

Ivo
--
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index bfbb446..6b0ca7e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)

if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- return true;
+ return false;

rt2x00lib_dmastart(entry);

@@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;

if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return true;
+ return false;

usb_kill_urb(entry_priv->urb);


2011-04-18 13:36:14

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default.

From: Gertjan van Wingerde <[email protected]>

Code seems to be feature-complete, so no reason to not enable
these devices by default.

Also, remove the sentence about the support for these devices being
non-functional.

Signed-off-by: Gertjan van Wingerde <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/Kconfig | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index e7e361e..d7e27b3 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -96,15 +96,12 @@ config RT2800PCI_RT35XX
config RT2800PCI_RT53XX
bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
- default n
+ default y
---help---
This adds support for rt53xx wireless chipset family to the
rt2800pci driver.
Supported chips: RT5390

- Support for these devices is non-functional at the moment and is
- intended for testers and developers.
-
endif

config RT2500USB
--
1.7.2.3


2011-04-18 13:35:38

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case

From: Helmut Schaa <[email protected]>

Since commit 0b7fde54f94979edc67bbf86b5adba702ebfefe8 "rt2x00: Protect
queue control with mutex" rt2x00 used rt2x00queue_pause_queue for
stopping a tx queue in mac80211. But in case of a failure in the tx
path rt2x00 still called ieee80211_stop_queue which stopped the queue
but prevented rt2x00queue_unpause_queue to wake the queue up again
resulting in a stuck tx queue.

Fix this by also using rt2x00queue_pause_queue in case of tx failures.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 661c6ba..4a1c41b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return;

exit_fail:
- ieee80211_stop_queue(rt2x00dev->hw, qid);
+ rt2x00queue_pause_queue(queue);
dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL_GPL(rt2x00mac_tx);
--
1.7.2.3


2011-05-02 13:33:47

by Yasushi SHOJI

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi Ivo,

At Sat, 30 Apr 2011 16:01:14 +0200,
Ivo van Doorn wrote:
>
> I've have a different idea, after a discussion with Helmut, I had changed his
> original patch. But I think below patch should resolve the issue as well.
>
> Yasushi, can you please test this patch.

We've tried your patch and the result is not as good as the original.
before we go into our test description, let me correct and add to my
previous comment:

- CPU consumption was not an issue (sorry for wrong info. my bad)
-- but network throughput performance is bad
- USB controller on the CPU is not fast
-- max throughput for USB memory read is about 50 Mbps on our test
-- max client mode transfer rate is about 20 Mbps (at best)

all test is done on our Freescale i.MX25[1] ARM based board,
Armadillo-440[2], a440 for short, and using HostAP[3] and netpipe[4].
As you can see, we are using the board as an access point instead of
client mode. this might have some impacts.

here is the summary of the test result we did:

|ping pc -> a440 |netpipe
-----------+-------------------+--------------------------------------
original |a few ms |starts at a few Mbps to 18 Mbps
flexible |fast for small, |error and exit on large packets
|not work for large |
ours |a few ms |starts at a few Mbps to 18 Mbps (same as orig)
ivo's |tens of ms |works but less than 1.0 Mbps throughput

here "original" means 7dab73b37[5], just before flexible patch.
flexible is 10e11568ca[6]. ours is the patch I sent in the previous
mail[7], ivo's is s/true/false/ on rt2x00usb.c[8].

detailed test result is at the end of this email.

BTW, we are in the big holiday week[10] right now. so please bear
with us. we might not reply promptly.

[1]:http://www.freescale.com/webapp/sps/site/overview.jsp?code=IMX25_FAMILY
[2]:http://www.atmark-techno.com/products/armadillo/a440/specs
[3]:http://hostap.epitest.fi/
[4]:http://www.scl.ameslab.gov/netpipe/

[5]:http://git.kernel.org/?p=linux/kernel/git/ivd/rt2x00.git;a=commit;h=7dab73b37f5e8885cb73efd25e73861f9b4f0246
[6]:http://git.kernel.org/?p=linux/kernel/git/ivd/rt2x00.git;a=commit;h=10e11568ca8b8a15f7478f6a4ceebabcbdba1018
[7]:http://article.gmane.org/gmane.linux.kernel.wireless.general/68843
[8]:http://article.gmane.org/gmane.linux.kernel.wireless.general/68987

[10]:http://en.wikipedia.org/wiki/Golden_Week_%28Japan%29

-------- detailed test results --------

flexible
========

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 61 128 128 61 61 61
0 0x00000001 49 64 1 50 49 49
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 226 128 128 98 98 98
0 0x00000001 201 64 0 9 9 9
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

NetPIPE
-------
$ NPtcp -h 192.168.40.101
0: 1 bytes 3 times --> 0.01 Mbps in 814.67 usec
1: 2 bytes 122 times --> 0.00 Mbps in 10791.37 usec
2: 3 bytes 9 times --> 0.03 Mbps in 729.17 usec
3: 4 bytes 91 times -->
(stopped...)



flexible + ivo patch
====================

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 83 128 128 83 83 83
0 0x00000001 57 64 1 58 57 57
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 173 128 128 45 45 45
0 0x00000001 148 64 1 21 20 20
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

NetPIPE
-------
$ NPtcp -h 192.168.40.101
0: 1 bytes 3 times --> 0.00 Mbps in 83008.00 usec
1: 2 bytes 3 times --> 0.00 Mbps in 33693.33 usec
2: 3 bytes 3 times --> 0.00 Mbps in 240411.83 usec
3: 4 bytes 3 times --> 0.00 Mbps in 47299.17 usec
4: 6 bytes 3 times --> 0.00 Mbps in 179131.50 usec
5: 8 bytes 3 times --> 0.04 Mbps in 1588.50 usec
6: 12 bytes 39 times --> 0.02 Mbps in 3682.92 usec
7: 13 bytes 11 times --> 0.14 Mbps in 719.14 usec
8: 16 bytes 64 times --> 0.02 Mbps in 7699.98 usec
9: 19 bytes 7 times --> 0.20 Mbps in 735.07 usec
10: 21 bytes 85 times --> 0.02 Mbps in 6706.57 usec
11: 24 bytes 9 times --> 0.00 Mbps in 141140.44 usec
12: 27 bytes 3 times --> 0.00 Mbps in 166763.17 usec
13: 29 bytes 3 times --> 0.29 Mbps in 764.00 usec
14: 32 bytes 63 times --> 0.32 Mbps in 772.13 usec
15: 35 bytes 68 times --> 0.06 Mbps in 4222.35 usec
16: 45 bytes 13 times --> 0.48 Mbps in 721.85 usec
17: 48 bytes 92 times --> 0.03 Mbps in 11973.77 usec
18: 51 bytes 5 times --> 0.51 Mbps in 764.70 usec
19: 61 bytes 51 times --> 0.01 Mbps in 42452.69 usec
20: 64 bytes 3 times --> 0.57 Mbps in 852.17 usec
21: 67 bytes 60 times --> 0.02 Mbps in 20637.03 usec
22: 93 bytes 3 times --> 0.00 Mbps in 1000327.83 usec
23: 96 bytes 3 times --> 0.00 Mbps in 961784.50 usec
24: 99 bytes 3 times --> 0.00 Mbps in 497735.83 usec
25: 125 bytes 3 times --> 0.00 Mbps in 832843.50 usec
26: 128 bytes 3 times --> 0.00 Mbps in 204765.50 usec
27: 131 bytes 3 times --> 0.01 Mbps in 126846.00 usec
28: 189 bytes 3 times --> 0.05 Mbps in 27758.17 usec
29: 192 bytes 3 times --> 1.79 Mbps in 817.83 usec
30: 195 bytes 82 times -->
(stopped...)



flexible + ours
===============

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 55 128 128 55 55 55
0 0x00000001 41 64 0 41 41 41
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue
qid flags count limit length index dma done done
14 0x00000001 154 128 128 26 26 26
0 0x00000001 140 64 0 12 12 12
1 0x00000001 0 64 0 0 0 0
2 0x00000001 0 64 0 0 0 0
3 0x00000001 0 64 0 0 0 0
16 0x00000001 0 8 0 0 0 0

NetPIPE
-------
$ NPtcp -h 192.168.40.101
0: 1 bytes 120 times --> 0.01 Mbps in 750.40 usec
1: 2 bytes 133 times --> 0.02 Mbps in 748.81 usec
2: 3 bytes 133 times --> 0.03 Mbps in 728.36 usec
3: 4 bytes 91 times --> 0.04 Mbps in 754.80 usec
4: 6 bytes 99 times --> 0.06 Mbps in 723.39 usec
5: 8 bytes 69 times --> 0.08 Mbps in 737.79 usec
6: 12 bytes 84 times --> 0.12 Mbps in 740.74 usec
7: 13 bytes 56 times --> 0.13 Mbps in 752.49 usec
8: 16 bytes 61 times --> 0.17 Mbps in 700.23 usec
9: 19 bytes 80 times --> 0.19 Mbps in 751.41 usec
10: 21 bytes 84 times --> 0.22 Mbps in 739.90 usec
11: 24 bytes 90 times --> 0.25 Mbps in 742.70 usec
12: 27 bytes 95 times --> 0.28 Mbps in 728.53 usec
13: 29 bytes 61 times --> 0.30 Mbps in 736.39 usec
14: 32 bytes 65 times --> 0.34 Mbps in 718.62 usec
15: 35 bytes 73 times --> 0.35 Mbps in 757.30 usec
16: 45 bytes 75 times --> 0.46 Mbps in 740.49 usec
17: 48 bytes 90 times --> 0.51 Mbps in 722.49 usec
18: 51 bytes 95 times --> 0.53 Mbps in 736.47 usec
19: 61 bytes 53 times --> 0.62 Mbps in 748.58 usec
20: 64 bytes 65 times --> 0.65 Mbps in 754.20 usec
21: 67 bytes 68 times --> 0.70 Mbps in 732.01 usec
22: 93 bytes 73 times --> 0.95 Mbps in 747.98 usec
23: 96 bytes 89 times --> 0.98 Mbps in 745.40 usec
24: 99 bytes 90 times --> 1.02 Mbps in 743.47 usec
25: 125 bytes 48 times --> 1.30 Mbps in 734.55 usec
26: 128 bytes 67 times --> 1.31 Mbps in 744.35 usec
27: 131 bytes 68 times --> 1.34 Mbps in 745.50 usec
28: 189 bytes 69 times --> 1.86 Mbps in 775.32 usec
29: 192 bytes 85 times --> 1.85 Mbps in 792.12 usec
30: 195 bytes 84 times --> 1.92 Mbps in 774.57 usec
31: 253 bytes 45 times --> 2.41 Mbps in 802.03 usec
32: 256 bytes 62 times --> 2.48 Mbps in 788.34 usec
33: 259 bytes 63 times --> 2.48 Mbps in 795.95 usec
34: 381 bytes 64 times --> 3.64 Mbps in 798.36 usec
35: 384 bytes 83 times --> 3.67 Mbps in 797.61 usec
36: 387 bytes 83 times --> 3.67 Mbps in 804.17 usec
37: 509 bytes 42 times --> 4.49 Mbps in 865.31 usec
38: 512 bytes 57 times --> 4.57 Mbps in 854.59 usec
39: 515 bytes 58 times --> 4.58 Mbps in 857.14 usec
40: 765 bytes 58 times --> 6.61 Mbps in 883.34 usec
41: 768 bytes 75 times --> 6.77 Mbps in 865.93 usec
42: 771 bytes 77 times --> 6.62 Mbps in 888.43 usec
43: 1021 bytes 37 times --> 8.30 Mbps in 939.04 usec
44: 1024 bytes 53 times --> 8.17 Mbps in 955.88 usec
45: 1027 bytes 52 times --> 8.06 Mbps in 972.20 usec
46: 1533 bytes 51 times --> 7.66 Mbps in 1525.97 usec
47: 1536 bytes 43 times --> 7.46 Mbps in 1570.44 usec
48: 1539 bytes 42 times --> 7.60 Mbps in 1545.51 usec
49: 2045 bytes 21 times --> 10.09 Mbps in 1546.31 usec
50: 2048 bytes 32 times --> 9.75 Mbps in 1601.77 usec
51: 2051 bytes 31 times --> 9.83 Mbps in 1592.16 usec
52: 3069 bytes 31 times --> 12.37 Mbps in 1892.11 usec
53: 3072 bytes 35 times --> 12.31 Mbps in 1904.36 usec
54: 3075 bytes 35 times --> 12.02 Mbps in 1952.34 usec
55: 4093 bytes 17 times --> 15.79 Mbps in 1977.85 usec
56: 4096 bytes 25 times --> 15.37 Mbps in 2032.76 usec
57: 4099 bytes 24 times --> 15.10 Mbps in 2070.98 usec
58: 6141 bytes 24 times --> 13.74 Mbps in 3410.75 usec
59: 6144 bytes 19 times --> 13.72 Mbps in 3417.03 usec
60: 6147 bytes 19 times --> 13.80 Mbps in 3397.32 usec
61: 8189 bytes 9 times --> 15.29 Mbps in 4086.61 usec
62: 8192 bytes 12 times --> 14.93 Mbps in 4185.71 usec
63: 8195 bytes 11 times --> 14.99 Mbps in 4170.91 usec
64: 12285 bytes 11 times --> 15.38 Mbps in 6095.45 usec
65: 12288 bytes 10 times --> 16.12 Mbps in 5814.15 usec
66: 12291 bytes 11 times --> 16.20 Mbps in 5790.18 usec
67: 16381 bytes 5 times --> 16.05 Mbps in 7787.10 usec
68: 16384 bytes 6 times --> 15.27 Mbps in 8187.83 usec
69: 16387 bytes 6 times --> 16.26 Mbps in 7686.83 usec
70: 24573 bytes 6 times --> 16.59 Mbps in 11301.75 usec
71: 24576 bytes 5 times --> 17.07 Mbps in 10982.60 usec
72: 24579 bytes 6 times --> 17.46 Mbps in 10737.75 usec
73: 32765 bytes 3 times --> 17.40 Mbps in 14369.67 usec
74: 32768 bytes 3 times --> 17.83 Mbps in 14019.67 usec
75: 32771 bytes 3 times --> 17.34 Mbps in 14418.17 usec
76: 49149 bytes 3 times --> 17.16 Mbps in 21856.33 usec
77: 49152 bytes 3 times --> 17.06 Mbps in 21987.50 usec
78: 49155 bytes 3 times --> 17.27 Mbps in 21715.00 usec
79: 65533 bytes 3 times --> 17.92 Mbps in 27894.50 usec
80: 65536 bytes 3 times --> 17.52 Mbps in 28542.00 usec
81: 65539 bytes 3 times --> 17.55 Mbps in 28490.00 usec
82: 98301 bytes 3 times --> 17.94 Mbps in 41802.83 usec
83: 98304 bytes 3 times --> 16.13 Mbps in 46505.17 usec
84: 98307 bytes 3 times --> 17.44 Mbps in 43001.00 usec
85: 131069 bytes 3 times --> 17.74 Mbps in 56360.50 usec
86: 131072 bytes 3 times --> 18.14 Mbps in 55120.33 usec
87: 131075 bytes 3 times --> 18.08 Mbps in 55323.17 usec
88: 196605 bytes 3 times --> 17.87 Mbps in 83919.67 usec
89: 196608 bytes 3 times --> 16.90 Mbps in 88738.67 usec
90: 196611 bytes 3 times --> 17.73 Mbps in 84627.00 usec
91: 262141 bytes 3 times --> 17.84 Mbps in 112088.50 usec
92: 262144 bytes 3 times --> 17.58 Mbps in 113748.67 usec
93: 262147 bytes 3 times --> 17.88 Mbps in 111867.67 usec
94: 393213 bytes 3 times --> 17.27 Mbps in 173754.83 usec
95: 393216 bytes 3 times --> 17.55 Mbps in 170984.50 usec
96: 393219 bytes 3 times --> 17.86 Mbps in 167983.67 usec
97: 524285 bytes 3 times --> 17.47 Mbps in 228930.00 usec
98: 524288 bytes 3 times --> 16.85 Mbps in 237405.00 usec
99: 524291 bytes 3 times --> 16.75 Mbps in 238756.33 usec
100: 786429 bytes 3 times --> 17.27 Mbps in 347394.50 usec
101: 786432 bytes 3 times --> 17.11 Mbps in 350626.17 usec
102: 786435 bytes 3 times --> 16.84 Mbps in 356215.50 usec
103: 1048573 bytes 3 times --> 17.57 Mbps in 455389.83 usec
104: 1048576 bytes 3 times --> 17.07 Mbps in 468556.83 usec
105: 1048579 bytes 3 times --> 17.47 Mbps in 457837.50 usec
106: 1572861 bytes 3 times --> 16.99 Mbps in 706165.00 usec
107: 1572864 bytes 3 times --> 17.47 Mbps in 686900.50 usec
108: 1572867 bytes 3 times --> 17.91 Mbps in 670021.00 usec
109: 2097149 bytes 3 times --> 16.74 Mbps in 955773.67 usec
110: 2097152 bytes 3 times --> 16.97 Mbps in 942824.67 usec
111: 2097155 bytes 3 times --> 17.30 Mbps in 925022.67 usec
112: 3145725 bytes 3 times --> 17.39 Mbps in 1379715.33 usec
113: 3145728 bytes 3 times --> 17.06 Mbps in 1406779.83 usec
114: 3145731 bytes 3 times --> 17.30 Mbps in 1387511.17 usec
(done successfully)
--
Yashi

2011-05-09 08:51:00

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

> At Mon, 2 May 2011 21:24:09 +0200,
> Ivo van Doorn wrote:
>>
>> > ?- CPU consumption was not an issue (sorry for wrong info. my bad)
>> > ?-- but network throughput performance is bad
>> > ?- USB controller on the CPU is not fast
>> > ?-- max throughput for USB memory read is about 50 Mbps on our test
>> > ?-- max client mode transfer rate is about 20 Mbps (at best)
>>
>> Ah ok, as CPU consumption is not the problem, then I better understand the problem.
>> My previous patch missed one fix for a return value. Could you try this one.
>
> it works like a charm! ?you can put a tested-by tag on this patch. :-)

Good news. :)
The patch has been sent upstream, it has already been picked up in
wireless-testing.git
and wireless-next-2.6.git a few days ago but hasn't yet by the
compat-wireless package.
So if all goes correct, the compat-wireless package which will be
generated today will
contain the fix.

Ivo

2011-05-02 19:24:17

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

> - CPU consumption was not an issue (sorry for wrong info. my bad)
> -- but network throughput performance is bad
> - USB controller on the CPU is not fast
> -- max throughput for USB memory read is about 50 Mbps on our test
> -- max client mode transfer rate is about 20 Mbps (at best)

Ah ok, as CPU consumption is not the problem, then I better understand the problem.
My previous patch missed one fix for a return value. Could you try this one.

> BTW, we are in the big holiday week[10] right now. so please bear
> with us. we might not reply promptly.

Not a problem. Have fun this week. :)

Thanks,

Ivo
---
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index e027ebd..dc6b662 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -298,7 +298,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)

if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- return true;
+ return false;

/*
* USB devices cannot blindly pass the skb->len as the
@@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)

if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
- return true;
+ return false;

rt2x00lib_dmastart(entry);

@@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;

if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return true;
+ return false;

usb_kill_urb(entry_priv->urb);


2011-05-09 08:08:43

by Yasushi SHOJI

[permalink] [raw]
Subject: Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible

Hi,

At Mon, 2 May 2011 21:24:09 +0200,
Ivo van Doorn wrote:
>
> > - CPU consumption was not an issue (sorry for wrong info. my bad)
> > -- but network throughput performance is bad
> > - USB controller on the CPU is not fast
> > -- max throughput for USB memory read is about 50 Mbps on our test
> > -- max client mode transfer rate is about 20 Mbps (at best)
>
> Ah ok, as CPU consumption is not the problem, then I better understand the problem.
> My previous patch missed one fix for a return value. Could you try this one.

it works like a charm! you can put a tested-by tag on this patch. :-)

here is the log, just in case.

0: 1 bytes 152 times --> 0.01 Mbps in 636.50 usec
1: 2 bytes 157 times --> 0.02 Mbps in 623.46 usec
2: 3 bytes 160 times --> 0.04 Mbps in 635.17 usec
3: 4 bytes 104 times --> 0.05 Mbps in 630.07 usec
4: 6 bytes 119 times --> 0.07 Mbps in 627.37 usec
5: 8 bytes 79 times --> 0.10 Mbps in 638.94 usec
6: 12 bytes 97 times --> 0.14 Mbps in 632.43 usec
7: 13 bytes 65 times --> 0.15 Mbps in 642.17 usec
8: 16 bytes 71 times --> 0.19 Mbps in 644.30 usec
9: 19 bytes 87 times --> 0.23 Mbps in 638.12 usec
10: 21 bytes 98 times --> 0.26 Mbps in 628.27 usec
11: 24 bytes 106 times --> 0.29 Mbps in 640.48 usec
12: 27 bytes 110 times --> 0.32 Mbps in 640.86 usec
13: 29 bytes 69 times --> 0.34 Mbps in 652.47 usec
14: 32 bytes 73 times --> 0.38 Mbps in 636.44 usec
15: 35 bytes 83 times --> 0.41 Mbps in 643.99 usec
16: 45 bytes 88 times --> 0.53 Mbps in 652.65 usec
17: 48 bytes 102 times --> 0.57 Mbps in 640.93 usec
18: 51 bytes 107 times --> 0.61 Mbps in 636.09 usec
19: 61 bytes 61 times --> 0.71 Mbps in 656.20 usec
20: 64 bytes 74 times --> 0.76 Mbps in 645.27 usec
21: 67 bytes 79 times --> 0.80 Mbps in 638.46 usec
22: 93 bytes 84 times --> 1.08 Mbps in 654.99 usec
23: 96 bytes 101 times --> 1.11 Mbps in 660.91 usec
24: 99 bytes 102 times --> 1.14 Mbps in 661.90 usec
25: 125 bytes 54 times --> 1.47 Mbps in 648.71 usec
26: 128 bytes 76 times --> 1.47 Mbps in 662.16 usec
27: 131 bytes 76 times --> 1.48 Mbps in 674.74 usec
28: 189 bytes 76 times --> 2.12 Mbps in 679.56 usec
29: 192 bytes 98 times --> 2.18 Mbps in 671.52 usec
30: 195 bytes 100 times --> 2.25 Mbps in 660.97 usec
31: 253 bytes 52 times --> 2.65 Mbps in 728.64 usec
32: 256 bytes 68 times --> 2.80 Mbps in 696.39 usec
33: 259 bytes 72 times --> 2.79 Mbps in 707.86 usec
34: 381 bytes 71 times --> 4.02 Mbps in 722.25 usec
35: 384 bytes 92 times --> 4.03 Mbps in 726.59 usec
36: 387 bytes 92 times --> 4.07 Mbps in 725.15 usec
37: 509 bytes 47 times --> 5.34 Mbps in 726.62 usec
38: 512 bytes 68 times --> 5.11 Mbps in 764.62 usec
39: 515 bytes 65 times --> 5.31 Mbps in 739.70 usec
40: 765 bytes 68 times --> 7.25 Mbps in 804.85 usec
41: 768 bytes 82 times --> 7.43 Mbps in 788.91 usec
42: 771 bytes 84 times --> 7.35 Mbps in 800.44 usec
43: 1021 bytes 42 times --> 9.23 Mbps in 844.04 usec
44: 1024 bytes 59 times --> 9.09 Mbps in 859.82 usec
45: 1027 bytes 58 times --> 9.08 Mbps in 862.79 usec
46: 1533 bytes 58 times --> 8.38 Mbps in 1395.98 usec
47: 1536 bytes 47 times --> 8.51 Mbps in 1377.14 usec
48: 1539 bytes 48 times --> 8.35 Mbps in 1405.50 usec
49: 2045 bytes 23 times --> 11.05 Mbps in 1411.89 usec
50: 2048 bytes 35 times --> 10.68 Mbps in 1463.26 usec
51: 2051 bytes 34 times --> 10.59 Mbps in 1477.41 usec
52: 3069 bytes 33 times --> 12.50 Mbps in 1873.76 usec
53: 3072 bytes 35 times --> 12.46 Mbps in 1881.50 usec
54: 3075 bytes 35 times --> 12.82 Mbps in 1829.67 usec
55: 4093 bytes 18 times --> 15.42 Mbps in 2025.56 usec
56: 4096 bytes 24 times --> 15.19 Mbps in 2056.62 usec
57: 4099 bytes 24 times --> 15.14 Mbps in 2065.52 usec
58: 6141 bytes 24 times --> 14.95 Mbps in 3133.44 usec
59: 6144 bytes 21 times --> 14.77 Mbps in 3174.33 usec
60: 6147 bytes 21 times --> 15.32 Mbps in 3061.95 usec
61: 8189 bytes 10 times --> 15.69 Mbps in 3981.60 usec
62: 8192 bytes 12 times --> 15.60 Mbps in 4005.46 usec
63: 8195 bytes 12 times --> 15.23 Mbps in 4104.79 usec
64: 12285 bytes 12 times --> 16.35 Mbps in 5731.54 usec
65: 12288 bytes 11 times --> 15.95 Mbps in 5877.59 usec
66: 12291 bytes 11 times --> 16.70 Mbps in 5615.00 usec
67: 16381 bytes 5 times --> 16.08 Mbps in 7770.10 usec
68: 16384 bytes 6 times --> 16.31 Mbps in 7662.92 usec
69: 16387 bytes 6 times --> 16.35 Mbps in 7645.50 usec
70: 24573 bytes 6 times --> 17.68 Mbps in 10605.92 usec
71: 24576 bytes 6 times --> 17.15 Mbps in 10930.00 usec
72: 24579 bytes 6 times --> 17.19 Mbps in 10907.83 usec
73: 32765 bytes 3 times --> 17.30 Mbps in 14453.17 usec
74: 32768 bytes 3 times --> 17.91 Mbps in 13956.67 usec
75: 32771 bytes 3 times --> 17.83 Mbps in 14023.33 usec
76: 49149 bytes 3 times --> 17.47 Mbps in 21468.17 usec
77: 49152 bytes 3 times --> 17.82 Mbps in 21048.17 usec
78: 49155 bytes 3 times --> 17.54 Mbps in 21384.67 usec
79: 65533 bytes 3 times --> 17.86 Mbps in 27996.33 usec
80: 65536 bytes 3 times --> 17.58 Mbps in 28433.50 usec
81: 65539 bytes 3 times --> 17.63 Mbps in 28366.50 usec
82: 98301 bytes 3 times --> 17.87 Mbps in 41966.67 usec
83: 98304 bytes 3 times --> 16.70 Mbps in 44917.83 usec
84: 98307 bytes 3 times --> 17.90 Mbps in 41894.33 usec
85: 131069 bytes 3 times --> 17.60 Mbps in 56809.17 usec
86: 131072 bytes 3 times --> 17.90 Mbps in 55871.83 usec
87: 131075 bytes 3 times --> 17.91 Mbps in 55821.17 usec
88: 196605 bytes 3 times --> 17.53 Mbps in 85542.50 usec
89: 196608 bytes 3 times --> 17.76 Mbps in 84443.33 usec
90: 196611 bytes 3 times --> 17.70 Mbps in 84745.83 usec
91: 262141 bytes 3 times --> 17.50 Mbps in 114315.50 usec
92: 262144 bytes 3 times --> 17.30 Mbps in 115606.00 usec
93: 262147 bytes 3 times --> 17.53 Mbps in 114096.50 usec
94: 393213 bytes 3 times --> 17.09 Mbps in 175546.83 usec
95: 393216 bytes 3 times --> 17.68 Mbps in 169663.67 usec
96: 393219 bytes 3 times --> 17.36 Mbps in 172796.83 usec
97: 524285 bytes 3 times --> 17.73 Mbps in 225642.83 usec
98: 524288 bytes 3 times --> 17.24 Mbps in 232031.17 usec
99: 524291 bytes 3 times --> 17.50 Mbps in 228568.83 usec
100: 786429 bytes 3 times --> 17.31 Mbps in 346536.33 usec
101: 786432 bytes 3 times --> 17.46 Mbps in 343555.00 usec
102: 786435 bytes 3 times --> 17.47 Mbps in 343362.00 usec
103: 1048573 bytes 3 times --> 17.50 Mbps in 457247.83 usec
104: 1048576 bytes 3 times --> 17.37 Mbps in 460508.33 usec
105: 1048579 bytes 3 times --> 17.58 Mbps in 455134.50 usec
106: 1572861 bytes 3 times --> 16.59 Mbps in 723288.00 usec
107: 1572864 bytes 3 times --> 17.55 Mbps in 683682.50 usec
108: 1572867 bytes 3 times --> 17.43 Mbps in 688538.00 usec
109: 2097149 bytes 3 times --> 17.32 Mbps in 923881.67 usec
110: 2097152 bytes 3 times --> 17.26 Mbps in 926999.17 usec
111: 2097155 bytes 3 times --> 17.10 Mbps in 935760.17 usec
112: 3145725 bytes 3 times --> 17.35 Mbps in 1383678.83 usec
113: 3145728 bytes 3 times --> 17.22 Mbps in 1393693.17 usec
114: 3145731 bytes 3 times --> 17.29 Mbps in 1387717.67 usec

Thanks,
--
yashi