2010-11-04 19:43:37

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 01/13] rt2x00: Add TXOP_CTRL_CFG register definition

From: Helmut Schaa <[email protected]>

Remove the magic value initialisation of the TXOP_CTRL_CFG register by
defining its fields and using them during intialisation. The field
RESERVED_TRUN_EN is referred to as reserved, however it is set to 1 by
the legacy drivers. Hence, do the same.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index eb8b6ca..6cfed06 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -960,8 +960,31 @@

/*
* TXOP_CTRL_CFG:
+ * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation
+ * AC_TRUN_EN: Enable/Disable truncation for AC change
+ * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change
+ * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode
+ * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS
+ * RESERVED_TRUN_EN: Reserved
+ * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection
+ * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz
+ * transmissions if extension CCA is clear).
+ * EXT_CCA_DLY: Extension CCA signal delay time (unit: us)
+ * EXT_CWMIN: CwMin for extension channel backoff
+ * 0: Disabled
+ *
*/
#define TXOP_CTRL_CFG 0x1340
+#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN FIELD32(0x00000001)
+#define TXOP_CTRL_CFG_AC_TRUN_EN FIELD32(0x00000002)
+#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN FIELD32(0x00000004)
+#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN FIELD32(0x00000008)
+#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN FIELD32(0x00000010)
+#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020)
+#define TXOP_CTRL_CFG_LSIG_TXOP_EN FIELD32(0x00000040)
+#define TXOP_CTRL_CFG_EXT_CCA_EN FIELD32(0x00000080)
+#define TXOP_CTRL_CFG_EXT_CCA_DLY FIELD32(0x0000ff00)
+#define TXOP_CTRL_CFG_EXT_CWMIN FIELD32(0x000f0000)

/*
* TX_RTS_CFG:
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 5f00e00..54bf085 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2097,7 +2097,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
}

- rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
+ /*
+ * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
+ * although it is reserved.
+ */
+ rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
+ rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
+ rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
+
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);

rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
--
1.7.2.3



2010-11-04 21:32:49

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH 05/13] rt2x00: Add unlikely to skb allocation failure check

On Thu, Nov 4, 2010 at 7:38 PM, Ivo van Doorn <[email protected]> wrote:
> From: Helmut Schaa <[email protected]>
>
> The skb allocation should really only fail under high memory pressure
> or other uncommon situations. Hence, mark the allocation failure check
> as unlikely.
>
> Signed-off-by: Helmut Schaa <[email protected]>
> Signed-off-by: Ivo van Doorn <[email protected]>
> ---
> ?drivers/net/wireless/rt2x00/rt2x00dev.c | ? ?2 +-
> ?1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index 5ba79b9..a5c7a4f 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -491,7 +491,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
> ? ? ? ? * received frame and reuse the existing buffer.
> ? ? ? ? */
> ? ? ? ?skb = rt2x00queue_alloc_rxskb(entry);
> - ? ? ? if (!skb)
> + ? ? ? if (unlikely(!skb))
> ? ? ? ? ? ? ? ?goto submit_entry;
>
> ? ? ? ?/*
> --
err, wait a sec, I've been looking for this mail for some time, but:

http://mail.linux.ie/pipermail/ilug/2004-December/075654.html

"Note tests for NULL (!something) don't need an unlikely as gcc does
that by default itself."

But there's more, according to http://gcc.gnu.org/news/profiledriven.html:
(static program profile) gcc expect pointers to be non-null

(therefore all !skb tests should be unlikely branches by default, or?)

Best regards,
Chr

2010-11-04 19:43:47

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 06/13] rt2x00: Optimize rt2x00debug_dump_frame when frame dumping is not active

From: Helmut Schaa <[email protected]>

When rt2x00 is compiled with debugging but frame dumping is currently
not active we can avoid the call to do_gettimeofday. Furthermore,
frame dumping is not the default case, mark it as unlikely.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index fcdb6b0..8296a9d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
struct timeval timestamp;
u32 data_len;

- do_gettimeofday(&timestamp);
-
- if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+ if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
return;

+ do_gettimeofday(&timestamp);
+
if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
return;
--
1.7.2.3


2010-11-04 23:22:08

by Julian Calaby

[permalink] [raw]
Subject: Re: [PATCH 11/13] rt2x00: Fix crash on USB unplug

Ivo,

A minor nit:

On Fri, Nov 5, 2010 at 06:41, Ivo van Doorn <[email protected]> wrote:
> By not scheduling the TX/RX completion worker threads
> when Radio is disabled, or hardware has been unplugged,
> the queues cannot be completely cleaned.
>
> This causes crashes when the hardware has been unplugged while
> the radio is still enabled.
>
> Signed-off-by: Ivo van Doorn <[email protected]>
> Acked-by: Gertjan van Wingerde <[email protected]>
> ---
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index a5c7a4f..b6822cd 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -483,6 +483,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
> ? ? ? ?unsigned int header_length;
> ? ? ? ?int rate_idx;
>
> + ? ? ? if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
> + ? ? ? ? ? !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
> + ? ? ? ? ? ? ? goto submit_entry;
> +
> ? ? ? ?if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
> ? ? ? ? ? ? ? ?goto submit_entry;
>

Could these two if statements be combined?

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/

2010-11-04 19:44:03

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 13/13] rt2x00: Fix comments in rt73usb.h and rt61pci.h

From: Lalith Suresh <[email protected]>

This patch fixes a few comments in rt73usb.h and rt61pci.h.

Signed-off-by: Lalith Suresh <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt61pci.h | 2 +-
drivers/net/wireless/rt2x00/rt73usb.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index e2e728a..afc803b 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -412,7 +412,7 @@ struct hw_pairwise_ta_entry {
* DROP_VERSION_ERROR: Drop version error frame.
* DROP_MULTICAST: Drop multicast frames.
* DROP_BORADCAST: Drop broadcast frames.
- * ROP_ACK_CTS: Drop received ACK and CTS.
+ * DROP_ACK_CTS: Drop received ACK and CTS.
*/
#define TXRX_CSR0 0x3040
#define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff)
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index 44d5b2b..1315ce5 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -322,7 +322,7 @@ struct hw_pairwise_ta_entry {
* DROP_VERSION_ERROR: Drop version error frame.
* DROP_MULTICAST: Drop multicast frames.
* DROP_BORADCAST: Drop broadcast frames.
- * ROP_ACK_CTS: Drop received ACK and CTS.
+ * DROP_ACK_CTS: Drop received ACK and CTS.
*/
#define TXRX_CSR0 0x3040
#define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff)
--
1.7.2.3


2010-11-06 12:51:33

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 11/13] rt2x00: Fix crash on USB unplug

Hi,

On Fri, Nov 5, 2010 at 1:07 AM, Blaise Gassend <[email protected]> wrote:
>>> Signed-off-by: Ivo van Doorn <[email protected]>
>>> Acked-by: Gertjan van Wingerde <[email protected]>
>>> ---
>>> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> index a5c7a4f..b6822cd 100644
>>> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
>>> @@ -483,6 +483,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
>>> ? ? ? ?unsigned int header_length;
>>> ? ? ? ?int rate_idx;
>>>
>>> + ? ? ? if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
>>> + ? ? ? ? ? !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
>>> + ? ? ? ? ? ? ? goto submit_entry;
>>> +
>>> ? ? ? ?if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
>>> ? ? ? ? ? ? ? ?goto submit_entry;
>>>
>>
>> Could these two if statements be combined?

They can, but I wanted the separation for clarity, the first
if-statement checks the
device state, while the second if-statement is for the frame itself.

> I'm also worried that the crash may still happen when the second if
> causes a jump. So far I am still getting crashes with this patch in.

I don't see how this could cause a crash, I know there are still issues
around this function, but how can the usage of 2 if-statement cause a crash?

Ivo

2010-11-08 19:13:25

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 11/13] rt2x00: Fix crash on USB unplug

Hi,

On Mon, Nov 8, 2010 at 8:08 PM, Blaise Gassend <[email protected]> wrote:
>>>>> + ? ? ? if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
>>>>> + ? ? ? ? ? !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
>>>>> + ? ? ? ? ? ? ? goto submit_entry;
>>>>> +
>>>>> ? ? ? ?if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
>>>>> ? ? ? ? ? ? ? ?goto submit_entry;
>> I don't see how this could cause a crash, I know there are still issues
>> around this function, but how can the usage of 2 if-statement cause a crash?
>
> What I meant here is that submit_entry does not kill the queue entry
> if data IO failed, which could result in an infinite loop if a
> disconnected device is causing the data IO case to be hit rather than
> one of the two previous ones.

The case that IO failure continuously occurs, while the device is still plugged,
isn't covered by this patch. However if the device was unplugged then
DEVICE_STATE_PRESENT would be cleared either on the first return of
the URB, or on the second in case of a race condition. In either case,
it will not pass the first if-statement when the device was unplugged,
so it doesn't
matter anymore what the entry->flags indicate.

Ivo

2010-11-04 19:43:44

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 04/13] rt2x00: Reduce tx descriptor size

From: Helmut Schaa <[email protected]>

The tx descriptor values qid, cw_min, cw_max and aifs are directly
accessible through the tx entry struct. So there's no need to copy
them into the tx descriptor and passing them to the indiviual drivers.
Instead we can just get the correct value from the tx entry.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2500pci.c | 6 +++---
drivers/net/wireless/rt2x00/rt2500usb.c | 6 +++---
drivers/net/wireless/rt2x00/rt2800lib.c | 2 +-
drivers/net/wireless/rt2x00/rt2x00queue.c | 8 --------
drivers/net/wireless/rt2x00/rt2x00queue.h | 9 ---------
drivers/net/wireless/rt2x00/rt61pci.c | 14 +++++++-------
drivers/net/wireless/rt2x00/rt73usb.c | 8 ++++----
7 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ab6c9ec..b69e55f 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1193,9 +1193,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,

rt2x00_desc_read(txd, 2, &word);
rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
- rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
- rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
+ rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
+ rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
rt2x00_desc_write(txd, 2, word);

rt2x00_desc_read(txd, 3, &word);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 725ae34..f20ab79 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1081,9 +1081,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,

rt2x00_desc_read(txd, 1, &word);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
- rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
- rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
- rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
+ rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+ rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
rt2x00_desc_write(txd, 1, word);

rt2x00_desc_read(txd, 2, &word);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index dcd3a89..6fa6549 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -487,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
txdesc->key_idx : 0xff);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid);
+ rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
rt2x00_desc_write(txwi, 1, word);

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index e360d28..4e2a8c2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -311,14 +311,6 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
memset(txdesc, 0, sizeof(*txdesc));

/*
- * Initialize information from queue
- */
- txdesc->qid = entry->queue->qid;
- txdesc->cw_min = entry->queue->cw_min;
- txdesc->cw_max = entry->queue->cw_max;
- txdesc->aifs = entry->queue->aifs;
-
- /*
* Header and frame information.
*/
txdesc->length = entry->skb->len;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 64acfb6..8a36ef3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -280,7 +280,6 @@ enum txentry_desc_flags {
* Summary of information for the frame descriptor before sending a TX frame.
*
* @flags: Descriptor flags (See &enum queue_entry_flags).
- * @qid: Queue identification (See &enum data_queue_qid).
* @length: Length of the entire frame.
* @header_length: Length of 802.11 header.
* @length_high: PLCP length high word.
@@ -293,11 +292,8 @@ enum txentry_desc_flags {
* @rate_mode: Rate mode (See @enum rate_modulation).
* @mpdu_density: MDPU density.
* @retry_limit: Max number of retries.
- * @aifs: AIFS value.
* @ifs: IFS value.
* @txop: IFS value for 11n capable chips.
- * @cw_min: cwmin value.
- * @cw_max: cwmax value.
* @cipher: Cipher type used for encryption.
* @key_idx: Key index used for encryption.
* @iv_offset: Position where IV should be inserted by hardware.
@@ -306,8 +302,6 @@ enum txentry_desc_flags {
struct txentry_desc {
unsigned long flags;

- enum data_queue_qid qid;
-
u16 length;
u16 header_length;

@@ -323,11 +317,8 @@ struct txentry_desc {
u16 mpdu_density;

short retry_limit;
- short aifs;
short ifs;
short txop;
- short cw_min;
- short cw_max;

enum cipher cipher;
u16 key_idx;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 3232336..fba9ee1 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1789,10 +1789,10 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
- rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
- rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
- rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
+ rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
+ rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+ rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
@@ -1820,7 +1820,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
rt2x00_desc_write(txd, 5, word);

- if (txdesc->qid != QID_BEACON) {
+ if (entry->queue->qid != QID_BEACON) {
rt2x00_desc_read(txd, 6, &word);
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
skbdesc->skb_dma);
@@ -1866,8 +1866,8 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
* Register descriptor details in skb frame descriptor.
*/
skbdesc->desc = txd;
- skbdesc->desc_len =
- (txdesc->qid == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE;
+ skbdesc->desc_len = (entry->queue->qid == QID_BEACON) ? TXINFO_SIZE :
+ TXD_DESC_SIZE;
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 67447ec..3c86f00 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1472,10 +1472,10 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
rt2x00_desc_write(txd, 0, word);

rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->qid);
- rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
- rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
- rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, entry->queue->qid);
+ rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->queue->aifs);
+ rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+ rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
--
1.7.2.3


2010-11-13 12:56:19

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

On Wed, Nov 10, 2010 at 8:40 PM, John W. Linville
<[email protected]> wrote:
> On Fri, Nov 05, 2010 at 11:07:22AM +0100, Ivo Van Doorn wrote:
>> Hi,
>>
>> >> On Fri, Nov 5, 2010 at 10:44 AM, Helmut Schaa
>> >> <[email protected]> wrote:
>> >> > Hi,
>> >> >
>> >> > Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
>> >> >> From: Helmut Schaa <[email protected]>
>> >> >>
>> >> >> At least some devices need such a long time to inititalize WPDMA. This
>> >> >> only increases the maximum wait time and shouldn't affect devices that
>> >> >> have been working before.
>> >> >>
>> >> >> Reported-by: Joshua Smith <[email protected]>
>> >> >> Signed-off-by: Helmut Schaa <[email protected]>
>> >> >> Signed-off-by: Ivo van Doorn <[email protected]>
>> >> >> ---
>> >> >
>> >> > Ivo, the patch context looks different then in the version I've send to you.
>> >> >
>> >> > The
>> >> > ? ? ? ?for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
>> >> > should be
>> >> > ? ? ? ?for (i = 0; i < 100; i++) {
>> >> >
>> >> > Otherwise we don't wait up to one second as in the comment but just 50ms :P
>> >> >
>> >> > However, that change was part of a previous patch that was already merged into
>> >> > the rt2x00 git tree. Seems like that change got lost during the merge ...
>> >>
>> >> I'll try to find the patch which changed the REGISTER_BUSY_COUNT behavior.
>> >
>> > I'm not sure but I guess I haven't sent that one as separate [PATCH] but it
>> > was inlined in the mail traffic with Joshua ("Question about starting up an
>> > AP").
>>
>> Ah ok, that explains why I missed it. I'll dig it up, and send it to
>> wireless-testing
>> as soon as possible (John, do you want it as separate patch, or should
>> it be merged
>> into this patch?).
>
> Separate patch, please (if you haven't already sent it).

Ok, patch will follow today.

ivo

2010-11-04 19:43:42

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

From: Helmut Schaa <[email protected]>

At least some devices need such a long time to inititalize WPDMA. This
only increases the maximum wait time and shouldn't affect devices that
have been working before.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b1738bb..dcd3a89 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
unsigned int i;
u32 reg;

+ /*
+ * Some devices are really slow to respond here. Wait a whole second
+ * before timing out.
+ */
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
!rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
return 0;

- msleep(1);
+ msleep(10);
}

ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
--
1.7.2.3


2010-11-04 19:43:54

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 08/13] rt2x00: Remove failsave from rt2x00usb_watchdog_tx_dma

From: Ivo van Doorn <[email protected]>

When the TX status handler failed to clear the queue
in rt2x00usb_watchdog_tx_dma() we shouldn't use a failsave
to use the rt2x00usb txdone handler.

If a driver has overriden the txdone handler it must make
sure the txdone handler is capable of cleaning up the queue itself.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 88995d5..6dd9619 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -323,21 +323,6 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);

/*
- * Security measure: if the driver did override the
- * txdone_work function, and the hardware did arrive
- * in a state which causes it to malfunction, it is
- * possible that the driver couldn't handle the txdone
- * event correctly. So after giving the driver the
- * chance to cleanup, we now force a cleanup of any
- * leftovers.
- */
- if (!rt2x00queue_empty(queue)) {
- WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
- " status handling failed, invoke hard reset", queue->qid);
- rt2x00usb_work_txdone(&rt2x00dev->txdone_work);
- }
-
- /*
* The queue has been reset, and mac80211 is allowed to use the
* queue again.
*/
--
1.7.2.3


2010-11-05 09:56:57

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

Am Freitag 05 November 2010 schrieb Ivo Van Doorn:
> Hi,
>
> On Fri, Nov 5, 2010 at 10:44 AM, Helmut Schaa
> <[email protected]> wrote:
> > Hi,
> >
> > Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
> >> From: Helmut Schaa <[email protected]>
> >>
> >> At least some devices need such a long time to inititalize WPDMA. This
> >> only increases the maximum wait time and shouldn't affect devices that
> >> have been working before.
> >>
> >> Reported-by: Joshua Smith <[email protected]>
> >> Signed-off-by: Helmut Schaa <[email protected]>
> >> Signed-off-by: Ivo van Doorn <[email protected]>
> >> ---
> >
> > Ivo, the patch context looks different then in the version I've send to you.
> >
> > The
> > for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> > should be
> > for (i = 0; i < 100; i++) {
> >
> > Otherwise we don't wait up to one second as in the comment but just 50ms :P
> >
> > However, that change was part of a previous patch that was already merged into
> > the rt2x00 git tree. Seems like that change got lost during the merge ...
>
> I'll try to find the patch which changed the REGISTER_BUSY_COUNT behavior.

I'm not sure but I guess I haven't sent that one as separate [PATCH] but it
was inlined in the mail traffic with Joshua ("Question about starting up an
AP").

> I'm almost worried that more patches have somehow gotten lost (I already noticed
> that there were a bunch of patches which were send upstream had disappeared
> from rt2x00.git, but those fortunately reappeared during the last
> update from wireless-testing).

I haven't noticed any other missing patches till now.

> Ivo
>
> Ivo

So, you finally decided to clone yourself?

Thanks,
Helmut

2010-11-04 19:43:49

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 07/13] rt2x00: Rename rt2x00queue_timeout

Rename rt2x00queue_timeout to rt2x00queue_status_timeout to
better describe what is actually timing out (note that
we already have a rt2x00queue_dma_timeout).

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 8a36ef3..64c00e2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -593,10 +593,10 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
}

/**
- * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts
+ * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports
* @queue: Queue to check.
*/
-static inline int rt2x00queue_timeout(struct data_queue *queue)
+static inline int rt2x00queue_status_timeout(struct data_queue *queue)
{
return time_after(queue->last_action[Q_INDEX_DMA_DONE],
queue->last_action[Q_INDEX_DONE] + (HZ / 10));
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index b3317df..88995d5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -361,7 +361,7 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
if (!rt2x00queue_empty(queue)) {
if (rt2x00queue_dma_timeout(queue))
rt2x00usb_watchdog_tx_dma(queue);
- if (rt2x00queue_timeout(queue))
+ if (rt2x00queue_status_timeout(queue))
rt2x00usb_watchdog_tx_status(queue);
}
}
--
1.7.2.3


2010-11-05 08:02:53

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH 05/13] rt2x00: Add unlikely to skb allocation failure check

Am Freitag 05 November 2010 schrieb Rafał Miłecki:
> 2010/11/5 Helmut Schaa <[email protected]>:
> > Interesting, didn't know that. I've just given it a try and the MIPS assembly
> > indeed stays the same with and without the unlikely. Nevertheless, I've found
> > quite a number of unlikely(!x) checks throughout the net stack ...
>
> What do you mean by x? AFAIU gcc optimization is only for pointers. If
> x is some int (bool), it still has affect.

I meant x to be a pointer, yes.

Helmut

2010-11-05 09:52:41

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

Hi,

On Fri, Nov 5, 2010 at 10:44 AM, Helmut Schaa
<[email protected]> wrote:
> Hi,
>
> Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
>> From: Helmut Schaa <[email protected]>
>>
>> At least some devices need such a long time to inititalize WPDMA. This
>> only increases the maximum wait time and shouldn't affect devices that
>> have been working before.
>>
>> Reported-by: Joshua Smith <[email protected]>
>> Signed-off-by: Helmut Schaa <[email protected]>
>> Signed-off-by: Ivo van Doorn <[email protected]>
>> ---
>
> Ivo, the patch context looks different then in the version I've send to you.
>
> The
> ? ? ? ?for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> should be
> ? ? ? ?for (i = 0; i < 100; i++) {
>
> Otherwise we don't wait up to one second as in the comment but just 50ms :P
>
> However, that change was part of a previous patch that was already merged into
> the rt2x00 git tree. Seems like that change got lost during the merge ...

I'll try to find the patch which changed the REGISTER_BUSY_COUNT behavior.
I'm almost worried that more patches have somehow gotten lost (I already noticed
that there were a bunch of patches which were send upstream had disappeared
from rt2x00.git, but those fortunately reappeared during the last
update from wireless-testing).

Ivo

Ivo

2010-11-05 09:45:31

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

Hi,

Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
> From: Helmut Schaa <[email protected]>
>
> At least some devices need such a long time to inititalize WPDMA. This
> only increases the maximum wait time and shouldn't affect devices that
> have been working before.
>
> Reported-by: Joshua Smith <[email protected]>
> Signed-off-by: Helmut Schaa <[email protected]>
> Signed-off-by: Ivo van Doorn <[email protected]>
> ---

Ivo, the patch context looks different then in the version I've send to you.

The
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
should be
for (i = 0; i < 100; i++) {

Otherwise we don't wait up to one second as in the comment but just 50ms :P

However, that change was part of a previous patch that was already merged into
the rt2x00 git tree. Seems like that change got lost during the merge ...

Helmut

> drivers/net/wireless/rt2x00/rt2800lib.c | 6 +++++-
> 1 files changed, 5 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index b1738bb..dcd3a89 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
> unsigned int i;
> u32 reg;
>
> + /*
> + * Some devices are really slow to respond here. Wait a whole second
> + * before timing out.
> + */
> for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
> if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
> !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
> return 0;
>
> - msleep(1);
> + msleep(10);
> }
>
> ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
>


2010-11-10 19:44:56

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

On Fri, Nov 05, 2010 at 11:07:22AM +0100, Ivo Van Doorn wrote:
> Hi,
>
> >> On Fri, Nov 5, 2010 at 10:44 AM, Helmut Schaa
> >> <[email protected]> wrote:
> >> > Hi,
> >> >
> >> > Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
> >> >> From: Helmut Schaa <[email protected]>
> >> >>
> >> >> At least some devices need such a long time to inititalize WPDMA. This
> >> >> only increases the maximum wait time and shouldn't affect devices that
> >> >> have been working before.
> >> >>
> >> >> Reported-by: Joshua Smith <[email protected]>
> >> >> Signed-off-by: Helmut Schaa <[email protected]>
> >> >> Signed-off-by: Ivo van Doorn <[email protected]>
> >> >> ---
> >> >
> >> > Ivo, the patch context looks different then in the version I've send to you.
> >> >
> >> > The
> >> > ? ? ? ?for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> >> > should be
> >> > ? ? ? ?for (i = 0; i < 100; i++) {
> >> >
> >> > Otherwise we don't wait up to one second as in the comment but just 50ms :P
> >> >
> >> > However, that change was part of a previous patch that was already merged into
> >> > the rt2x00 git tree. Seems like that change got lost during the merge ...
> >>
> >> I'll try to find the patch which changed the REGISTER_BUSY_COUNT behavior.
> >
> > I'm not sure but I guess I haven't sent that one as separate [PATCH] but it
> > was inlined in the mail traffic with Joshua ("Question about starting up an
> > AP").
>
> Ah ok, that explains why I missed it. I'll dig it up, and send it to
> wireless-testing
> as soon as possible (John, do you want it as separate patch, or should
> it be merged
> into this patch?).

Separate patch, please (if you haven't already sent it).

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2010-11-04 19:43:52

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 09/13] rt2x00: Implement flush callback

Implement a basic flush callback function, which simply loops
over all TX queues and waits until all frames have been transmitted
and the status reports have been gathered.

At this moment we don't support dropping any frames during the
flush, but mac80211 will only send 'false' for this argument anyway,
so this is not important at this time.

Signed-off-by: Ivo van Doorn <[email protected]>
Acked-by: Helmut Schaa <[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 | 1 +
drivers/net/wireless/rt2x00/rt2x00mac.c | 38 +++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt61pci.c | 1 +
drivers/net/wireless/rt2x00/rt73usb.c | 1 +
9 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index c94aa1e..bc1ae1e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1612,6 +1612,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.get_tsf = rt2400pci_get_tsf,
.tx_last_beacon = rt2400pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
+ .flush = rt2x00mac_flush,
};

static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index b69e55f..5475415 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1909,6 +1909,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.get_tsf = rt2500pci_get_tsf,
.tx_last_beacon = rt2500pci_tx_last_beacon,
.rfkill_poll = rt2x00mac_rfkill_poll,
+ .flush = rt2x00mac_flush,
};

static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index f20ab79..478c4f1 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1801,6 +1801,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.rfkill_poll = rt2x00mac_rfkill_poll,
+ .flush = rt2x00mac_flush,
};

static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 2c12b59..6dc61b7 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -943,6 +943,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
+ .flush = rt2x00mac_flush,
};

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 3f44131..04dfedc 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -508,6 +508,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
+ .flush = rt2x00mac_flush,
};

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 94fe589..42bd3a9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1133,6 +1133,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params);
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
+void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);

/*
* Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index c3c206a..283a8d9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -719,3 +719,41 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)
wiphy_rfkill_set_hw_state(hw->wiphy, !active);
}
EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll);
+
+void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+ unsigned int i = 0;
+
+ ieee80211_stop_queues(hw);
+
+ /*
+ * Run over all queues to kick them, this will force
+ * any pending frames to be transmitted.
+ */
+ tx_queue_for_each(rt2x00dev, queue) {
+ rt2x00dev->ops->lib->kick_tx_queue(queue);
+ }
+
+ /**
+ * All queues have been kicked, now wait for each queue
+ * to become empty. With a bit of luck, we only have to wait
+ * for the first queue to become empty, because while waiting
+ * for the that queue, the other queues will have transmitted
+ * all their frames as well (since they were already kicked).
+ */
+ tx_queue_for_each(rt2x00dev, queue) {
+ for (i = 0; i < 10; i++) {
+ if (rt2x00queue_empty(queue))
+ break;
+ msleep(100);
+ }
+
+ if (!rt2x00queue_empty(queue))
+ WARNING(rt2x00dev, "Failed to flush queue %d", queue->qid);
+ }
+
+ ieee80211_wake_queues(hw);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_flush);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index fba9ee1..f01bff7 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2824,6 +2824,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.conf_tx = rt61pci_conf_tx,
.get_tsf = rt61pci_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
+ .flush = rt2x00mac_flush,
};

static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 3c86f00..dcb9211 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2264,6 +2264,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.conf_tx = rt73usb_conf_tx,
.get_tsf = rt73usb_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll,
+ .flush = rt2x00mac_flush,
};

static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
--
1.7.2.3


2010-11-08 19:08:48

by Blaise Gassend

[permalink] [raw]
Subject: Re: [PATCH 11/13] rt2x00: Fix crash on USB unplug

>>>> + ? ? ? if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
>>>> + ? ? ? ? ? !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
>>>> + ? ? ? ? ? ? ? goto submit_entry;
>>>> +
>>>> ? ? ? ?if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
>>>> ? ? ? ? ? ? ? ?goto submit_entry;
> I don't see how this could cause a crash, I know there are still issues
> around this function, but how can the usage of 2 if-statement cause a crash?

What I meant here is that submit_entry does not kill the queue entry
if data IO failed, which could result in an infinite loop if a
disconnected device is causing the data IO case to be hit rather than
one of the two previous ones.

Blaise

2010-11-04 19:43:58

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 11/13] rt2x00: Fix crash on USB unplug

By not scheduling the TX/RX completion worker threads
when Radio is disabled, or hardware has been unplugged,
the queues cannot be completely cleaned.

This causes crashes when the hardware has been unplugged while
the radio is still enabled.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a5c7a4f..b6822cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -483,6 +483,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
unsigned int header_length;
int rate_idx;

+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+ !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ goto submit_entry;
+
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
goto submit_entry;

@@ -567,9 +571,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
entry->skb = skb;

submit_entry:
- rt2x00dev->ops->lib->clear_entry(entry);
- rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ entry->flags = 0;
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+ rt2x00dev->ops->lib->clear_entry(entry);
+ rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ }
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);

diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 6dd9619..9ac1459 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -226,9 +226,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
* Schedule the delayed work for reading the TX status
* from the device.
*/
- if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
- test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
}

static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
@@ -409,9 +407,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
* Schedule the delayed work for reading the RX status
* from the device.
*/
- if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
- test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
- ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
+ ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
}

/*
--
1.7.2.3


2010-11-04 19:43:45

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 05/13] rt2x00: Add unlikely to skb allocation failure check

From: Helmut Schaa <[email protected]>

The skb allocation should really only fail under high memory pressure
or other uncommon situations. Hence, mark the allocation failure check
as unlikely.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 5ba79b9..a5c7a4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -491,7 +491,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
* received frame and reuse the existing buffer.
*/
skb = rt2x00queue_alloc_rxskb(entry);
- if (!skb)
+ if (unlikely(!skb))
goto submit_entry;

/*
--
1.7.2.3


2010-11-05 00:07:23

by Blaise Gassend

[permalink] [raw]
Subject: Re: [PATCH 11/13] rt2x00: Fix crash on USB unplug

>> Signed-off-by: Ivo van Doorn <[email protected]>
>> Acked-by: Gertjan van Wingerde <[email protected]>
>> ---
>> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
>> index a5c7a4f..b6822cd 100644
>> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
>> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
>> @@ -483,6 +483,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
>> ? ? ? ?unsigned int header_length;
>> ? ? ? ?int rate_idx;
>>
>> + ? ? ? if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
>> + ? ? ? ? ? !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
>> + ? ? ? ? ? ? ? goto submit_entry;
>> +
>> ? ? ? ?if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
>> ? ? ? ? ? ? ? ?goto submit_entry;
>>
>
> Could these two if statements be combined?

I'm also worried that the crash may still happen when the second if
causes a jump. So far I am still getting crashes with this patch in.

2010-11-05 07:24:46

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH 05/13] rt2x00: Add unlikely to skb allocation failure check

Am Donnerstag 04 November 2010 schrieb Christian Lamparter:
> On Thu, Nov 4, 2010 at 7:38 PM, Ivo van Doorn <[email protected]> wrote:
> > From: Helmut Schaa <[email protected]>
> >
> > The skb allocation should really only fail under high memory pressure
> > or other uncommon situations. Hence, mark the allocation failure check
> > as unlikely.
> >
> > Signed-off-by: Helmut Schaa <[email protected]>
> > Signed-off-by: Ivo van Doorn <[email protected]>
> > ---
> > drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> > index 5ba79b9..a5c7a4f 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> > @@ -491,7 +491,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
> > * received frame and reuse the existing buffer.
> > */
> > skb = rt2x00queue_alloc_rxskb(entry);
> > - if (!skb)
> > + if (unlikely(!skb))
> > goto submit_entry;
> >
> > /*
> > --
> err, wait a sec, I've been looking for this mail for some time, but:
>
> http://mail.linux.ie/pipermail/ilug/2004-December/075654.html
>
> "Note tests for NULL (!something) don't need an unlikely as gcc does
> that by default itself."
>
> But there's more, according to http://gcc.gnu.org/news/profiledriven.html:
> (static program profile) gcc expect pointers to be non-null
>
> (therefore all !skb tests should be unlikely branches by default, or?)

Interesting, didn't know that. I've just given it a try and the MIPS assembly
indeed stays the same with and without the unlikely. Nevertheless, I've found
quite a number of unlikely(!x) checks throughout the net stack ...

But still, this seems unnecessary. John, please drop this patch.

Thanks Christian,
Helmut

2010-11-05 07:52:02

by Rafał Miłecki

[permalink] [raw]
Subject: Re: [PATCH 05/13] rt2x00: Add unlikely to skb allocation failure check

2010/11/5 Helmut Schaa <[email protected]>:
> Interesting, didn't know that. I've just given it a try and the MIPS assembly
> indeed stays the same with and without the unlikely. Nevertheless, I've found
> quite a number of unlikely(!x) checks throughout the net stack ...

What do you mean by x? AFAIU gcc optimization is only for pointers. If
x is some int (bool), it still has affect.

--
Rafał

2010-11-04 19:44:01

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 12/13] rt2x00: Fix hw crypto in AP mode for some devices

From: Helmut Schaa <[email protected]>

The BSSID register shouldn't be set in AP mode on some older devices (like
rt73usb) as it breaks hw crypto on these. However, rt2800 devices explicitly
need the BSSID register set to the same value as our own MAC address (only
in AP mode).

Hence, don't set the BSSID from rt2x00lib but move it down into rt2800 to
avoid problems on older devices.

This fixes a regression (at least for rt73usb) and avoids a new regression
for rt2800 devices in 2.6.36.

Reported-by: Johannes Stezenbach <[email protected]>
Reported-by: Lee <[email protected]>
Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 13 ++++++++++++-
drivers/net/wireless/rt2x00/rt2x00mac.c | 10 ++--------
2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 6fa6549..a53536d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1148,6 +1148,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf, const unsigned int flags)
{
u32 reg;
+ bool update_bssid = false;

if (flags & CONFIG_UPDATE_TYPE) {
/*
@@ -1177,6 +1178,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
}

if (flags & CONFIG_UPDATE_MAC) {
+ if (flags & CONFIG_UPDATE_TYPE &&
+ conf->sync == TSF_SYNC_AP_NONE) {
+ /*
+ * The BSSID register has to be set to our own mac
+ * address in AP mode.
+ */
+ memcpy(conf->bssid, conf->mac, sizeof(conf->mac));
+ update_bssid = true;
+ }
+
if (!is_zero_ether_addr((const u8 *)conf->mac)) {
reg = le32_to_cpu(conf->mac[1]);
rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
@@ -1187,7 +1198,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
conf->mac, sizeof(conf->mac));
}

- if (flags & CONFIG_UPDATE_BSSID) {
+ if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {
if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
reg = le32_to_cpu(conf->bssid[1]);
rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 283a8d9..36ddee8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -283,14 +283,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
* invalid behavior in the device.
*/
memcpy(&intf->mac, vif->addr, ETH_ALEN);
- if (vif->type == NL80211_IFTYPE_AP) {
- memcpy(&intf->bssid, vif->addr, ETH_ALEN);
- rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
- intf->mac, intf->bssid);
- } else {
- rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
- intf->mac, NULL);
- }
+ rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
+ intf->mac, NULL);

/*
* Some filters depend on the current working mode. We can force
--
1.7.2.3


2010-11-04 19:43:40

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 02/13] rt2x00: Sync Tx and RX ring sizes with legacy drivers

From: Helmut Schaa <[email protected]>

All rt2x00 devices used the same Tx and Rx ring size (24 entries) till
now. Newer devices (like rt2800) can however make use of a larger TX and
RX ring due to 11n capabilities (AMPDUs of size 64 for example).

Hence, bring rt2x00 in sync with the legacy drivers and use the same TX
and RX ring sizes. Also remove the global defines RX_ENTRIES, TX_ENTRIES,
BEACON_ENTRIES and ATIM_ENTRIES and use per driver values.

That is 24 entries for rt2400pci, 32 entries for rt2500pci, rt2500usb,
rt61pci and rt73usb and 128 (RX) and 64 (TX) for rt2800pci and rt2800usb.

Signed-off-by: Helmut Schaa <[email protected]>
Signed-off-by: Ivo van Doorn <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2500pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2500usb.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2800lib.c | 2 +-
drivers/net/wireless/rt2x00/rt2800pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt2800usb.c | 9 +++++----
drivers/net/wireless/rt2x00/rt2x00queue.h | 16 ----------------
drivers/net/wireless/rt2x00/rt61pci.c | 8 ++++----
drivers/net/wireless/rt2x00/rt73usb.c | 6 +++---
9 files changed, 29 insertions(+), 44 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 4f420a9..c94aa1e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1640,28 +1640,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
};

static const struct data_queue_desc rt2400pci_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2400pci_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2400pci_queue_bcn = {
- .entry_num = BEACON_ENTRIES,
+ .entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2400pci_queue_atim = {
- .entry_num = ATIM_ENTRIES,
+ .entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 97feb7a..ab6c9ec 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1937,28 +1937,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
};

static const struct data_queue_desc rt2500pci_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2500pci_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2500pci_queue_bcn = {
- .entry_num = BEACON_ENTRIES,
+ .entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2500pci_queue_atim = {
- .entry_num = ATIM_ENTRIES,
+ .entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 93e44c7..725ae34 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1829,28 +1829,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
};

static const struct data_queue_desc rt2500usb_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt2500usb_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt2500usb_queue_bcn = {
- .entry_num = BEACON_ENTRIES,
+ .entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb_bcn),
};

static const struct data_queue_desc rt2500usb_queue_atim = {
- .entry_num = ATIM_ENTRIES,
+ .entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 54bf085..b1738bb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -727,7 +727,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
* that the TX_STA_FIFO stack has a size of 16. We stick to our
* tx ring size for now.
*/
- for (i = 0; i < TX_ENTRIES; i++) {
+ for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
break;
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index b267395..2c12b59 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -777,7 +777,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* Since we have only one producer and one consumer we don't
* need to lock the kfifo.
*/
- for (i = 0; i < TX_ENTRIES; i++) {
+ for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);

if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
@@ -991,21 +991,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
};

static const struct data_queue_desc rt2800pci_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 128,
.data_size = AGGREGATION_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2800pci_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 64,
.data_size = AGGREGATION_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt2800pci_queue_bcn = {
- .entry_num = 8 * BEACON_ENTRIES,
+ .entry_num = 8,
.data_size = 0, /* No DMA required for beacons */
.desc_size = TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 3dff56e..3f44131 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -165,7 +165,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
* this limit so reduce the number to prevent errors.
*/
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
- ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3);
+ ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE)
+ / 1024) - 3);
rt2x00_set_field32(&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);
@@ -553,21 +554,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
};

static const struct data_queue_desc rt2800usb_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 128,
.data_size = AGGREGATION_SIZE,
.desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt2800usb_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 64,
.data_size = AGGREGATION_SIZE,
.desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt2800usb_queue_bcn = {
- .entry_num = 8 * BEACON_ENTRIES,
+ .entry_num = 8,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index d81d85f..64acfb6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -43,22 +43,6 @@
#define AGGREGATION_SIZE 3840

/**
- * DOC: Number of entries per queue
- *
- * Under normal load without fragmentation, 12 entries are sufficient
- * without the queue being filled up to the maximum. When using fragmentation
- * and the queue threshold code, we need to add some additional margins to
- * make sure the queue will never (or only under extreme load) fill up
- * completely.
- * Since we don't use preallocated DMA, having a large number of queue entries
- * will have minimal impact on the memory requirements for the queue.
- */
-#define RX_ENTRIES 24
-#define TX_ENTRIES 24
-#define BEACON_ENTRIES 1
-#define ATIM_ENTRIES 8
-
-/**
* enum data_queue_qid: Queue identification
*
* @QID_AC_BE: AC BE queue
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index af548c8..3232336 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2078,7 +2078,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
* that the TX_STA_FIFO stack has a size of 16. We stick to our
* tx ring size for now.
*/
- for (i = 0; i < TX_ENTRIES; i++) {
+ for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
rt2x00pci_register_read(rt2x00dev, STA_CSR4, &reg);
if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
break;
@@ -2857,21 +2857,21 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
};

static const struct data_queue_desc rt61pci_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt61pci_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
};

static const struct data_queue_desc rt61pci_queue_bcn = {
- .entry_num = 4 * BEACON_ENTRIES,
+ .entry_num = 4,
.data_size = 0, /* No DMA required for beacons */
.desc_size = TXINFO_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci),
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9be8089..67447ec 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2296,21 +2296,21 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
};

static const struct data_queue_desc rt73usb_queue_rx = {
- .entry_num = RX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt73usb_queue_tx = {
- .entry_num = TX_ENTRIES,
+ .entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};

static const struct data_queue_desc rt73usb_queue_bcn = {
- .entry_num = 4 * BEACON_ENTRIES,
+ .entry_num = 4,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXINFO_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
--
1.7.2.3


2010-11-04 19:43:56

by Ivo Van Doorn

[permalink] [raw]
Subject: [PATCH 10/13] rt2x00: Fix MCU_SLEEP arguments

Legacy driver uses 0xff as the second argument for the MCU_SLEEP
command. It is still unknown what the values actually mean, but
this will at least keep the command in-sync with the original
driver.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6dc61b7..1db0c3b 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -442,7 +442,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
* if the device is booting and wasn't asleep it will return
* failure when attempting to wakeup.
*/
- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);

if (state == STATE_AWAKE) {
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 04dfedc..5c31e33 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -184,9 +184,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
if (state == STATE_AWAKE)
- rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
else
- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);

return 0;
}
--
1.7.2.3


2010-11-05 10:07:23

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 03/13] rt2x00: Wait up to one second on rt2800 for WPDMA to be ready

Hi,

>> On Fri, Nov 5, 2010 at 10:44 AM, Helmut Schaa
>> <[email protected]> wrote:
>> > Hi,
>> >
>> > Am Donnerstag 04 November 2010 schrieb Ivo van Doorn:
>> >> From: Helmut Schaa <[email protected]>
>> >>
>> >> At least some devices need such a long time to inititalize WPDMA. This
>> >> only increases the maximum wait time and shouldn't affect devices that
>> >> have been working before.
>> >>
>> >> Reported-by: Joshua Smith <[email protected]>
>> >> Signed-off-by: Helmut Schaa <[email protected]>
>> >> Signed-off-by: Ivo van Doorn <[email protected]>
>> >> ---
>> >
>> > Ivo, the patch context looks different then in the version I've send to you.
>> >
>> > The
>> > ? ? ? ?for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
>> > should be
>> > ? ? ? ?for (i = 0; i < 100; i++) {
>> >
>> > Otherwise we don't wait up to one second as in the comment but just 50ms :P
>> >
>> > However, that change was part of a previous patch that was already merged into
>> > the rt2x00 git tree. Seems like that change got lost during the merge ...
>>
>> I'll try to find the patch which changed the REGISTER_BUSY_COUNT behavior.
>
> I'm not sure but I guess I haven't sent that one as separate [PATCH] but it
> was inlined in the mail traffic with Joshua ("Question about starting up an
> AP").

Ah ok, that explains why I missed it. I'll dig it up, and send it to
wireless-testing
as soon as possible (John, do you want it as separate patch, or should
it be merged
into this patch?).

>> I'm almost worried that more patches have somehow gotten lost (I already noticed
>> that there were a bunch of patches which were send upstream had disappeared
>> from rt2x00.git, but those fortunately reappeared during the last
>> update from wireless-testing).
>
> I haven't noticed any other missing patches till now.

Good.

>> Ivo
>>
>> Ivo
>
> So, you finally decided to clone yourself?

Yes that was a long-lived dream I had. An army of clones of myself... :)

Ivo