2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 0/9] rt2x00: Cleanups and fixes.

Some assorted cleanups and fixes for rt2x00.
First patch fixes the rt61pci security issues reported by Pavel Roskin.
The remaining patches clean up the code and work towards the final patch
which fixes beaconing on rt2800.

Gertjan van Wingerde (9):
rt2x00: Fix setting of txdesc->length field.
rt2x00: Clean up rt2800usb.h.
rt2x00: Don't check whether hardware crypto is enabled when reading
RXD.
rt2x00: Factor out TXWI writing to common rt2800 code.
rt2x00: Factor out RXWI processing to common rt2800 code.
rt2x00: Clean up generic procedures on descriptor writing.
rt2x00: Clean up all driver's kick_tx_queue callback functions.
rt2x00: provide beacon's txdesc to write_beacon callback function.
rt2x00: Fix beaconing on rt2800.

drivers/net/wireless/rt2x00/rt2400pci.c | 22 ++--
drivers/net/wireless/rt2x00/rt2500pci.c | 22 ++--
drivers/net/wireless/rt2x00/rt2500usb.c | 66 ++++------
drivers/net/wireless/rt2x00/rt2800lib.c | 98 +++++++++++++++
drivers/net/wireless/rt2x00/rt2800lib.h | 3 +
drivers/net/wireless/rt2x00/rt2800pci.c | 166 ++++++--------------------
drivers/net/wireless/rt2x00/rt2800usb.c | 180 +++++++---------------------
drivers/net/wireless/rt2x00/rt2800usb.h | 40 ------
drivers/net/wireless/rt2x00/rt2x00.h | 3 +-
drivers/net/wireless/rt2x00/rt2x00crypto.c | 1 +
drivers/net/wireless/rt2x00/rt2x00queue.c | 23 ++--
drivers/net/wireless/rt2x00/rt61pci.c | 41 +++----
drivers/net/wireless/rt2x00/rt73usb.c | 51 +++-----
13 files changed, 280 insertions(+), 436 deletions(-)



2010-05-09 09:21:36

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 9/9] rt2x00: Fix beaconing on rt2800.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> According to the Ralink vendor driver for rt2800 we don't need a full
> TXD for a beacon but just a TXWI in front of the actual beacon.
> Fix the rt2800pci and rt2800usb beaconing code accordingly.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>
> ---
> ?drivers/net/wireless/rt2x00/rt2800pci.c | ? 17 +++++++++--------
> ?drivers/net/wireless/rt2x00/rt2800usb.c | ? 14 ++++++--------
> ?2 files changed, 15 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 80c6768..7d4778d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -682,7 +682,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct txentry_desc *txdesc)
> ?{
> ? ? ? ?struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
> - ? ? ? struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
> ? ? ? ?unsigned int beacon_base;
> ? ? ? ?u32 reg;
>
> @@ -695,15 +694,17 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
> ? ? ? ?rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
>
> ? ? ? ?/*
> - ? ? ? ?* Write entire beacon with descriptor to register.
> + ? ? ? ?* Add the TXWI for the beacon to the skb.
> + ? ? ? ?*/
> + ? ? ? rt2800_write_txwi(entry->skb, txdesc);
> + ? ? ? skb_push(entry->skb, TXWI_DESC_SIZE);

This looks quite suspicious...
First writing into the SKB and only then making room for it?
Perhaps we should make sure rt2800_write_txwi demands the
room is already added (or it calls skb_push itself).

Ivo

2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 3/9] rt2x00: Don't check whether hardware crypto is enabled when reading RXD.

We should simply follow what the hardware told us it has done.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2500usb.c | 8 +++-----
drivers/net/wireless/rt2x00/rt2800pci.c | 17 +++++++----------
drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++------
drivers/net/wireless/rt2x00/rt61pci.c | 8 ++------
drivers/net/wireless/rt2x00/rt73usb.c | 8 ++------
5 files changed, 16 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index c6e6e7b..f90b308 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1213,11 +1213,9 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;

- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
- rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
- if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
- rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
- }
+ rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
+ if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
+ rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;

if (rxdesc->cipher != CIPHER_NONE) {
_rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index df2c3fb..b9ec081 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -840,16 +840,13 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
- /*
- * Unfortunately we don't know the cipher type used during
- * decryption. This prevents us from correct providing
- * correct statistics through debugfs.
- */
- rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
- rxdesc->cipher_status =
- rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR);
- }
+ /*
+ * Unfortunately we don't know the cipher type used during
+ * decryption. This prevents us from correct providing
+ * correct statistics through debugfs.
+ */
+ rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
+ rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR);

if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) {
/*
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 94b6812..df7ad98 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -549,7 +549,6 @@ static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2800usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxi = (__le32 *)entry->skb->data;
__le32 *rxwi;
@@ -595,11 +594,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
- rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
- rxdesc->cipher_status =
- rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
- }
+ rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
+ rxdesc->cipher_status = rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);

if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
/*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 8099eca..1b0c70d 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1968,12 +1968,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
- rxdesc->cipher =
- rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
- rxdesc->cipher_status =
- rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
- }
+ rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+ rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);

if (rxdesc->cipher != CIPHER_NONE) {
_rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 1399c18..6acba62 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1644,12 +1644,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

- if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
- rxdesc->cipher =
- rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
- rxdesc->cipher_status =
- rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
- }
+ rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+ rxdesc->cipher_status = rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);

if (rxdesc->cipher != CIPHER_NONE) {
_rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
--
1.7.1


2010-05-09 09:41:03

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [PATCH 9/9] rt2x00: Fix beaconing on rt2800.

On 05/09/10 11:21, Ivo Van Doorn wrote:
> On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
> <[email protected]> wrote:
>> According to the Ralink vendor driver for rt2800 we don't need a full
>> TXD for a beacon but just a TXWI in front of the actual beacon.
>> Fix the rt2800pci and rt2800usb beaconing code accordingly.
>>
>> Signed-off-by: Gertjan van Wingerde <[email protected]>
>> ---
>> drivers/net/wireless/rt2x00/rt2800pci.c | 17 +++++++++--------
>> drivers/net/wireless/rt2x00/rt2800usb.c | 14 ++++++--------
>> 2 files changed, 15 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
>> index 80c6768..7d4778d 100644
>> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
>> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
>> @@ -682,7 +682,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
>> struct txentry_desc *txdesc)
>> {
>> struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
>> - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
>> unsigned int beacon_base;
>> u32 reg;
>>
>> @@ -695,15 +694,17 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
>> rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
>>
>> /*
>> - * Write entire beacon with descriptor to register.
>> + * Add the TXWI for the beacon to the skb.
>> + */
>> + rt2800_write_txwi(entry->skb, txdesc);
>> + skb_push(entry->skb, TXWI_DESC_SIZE);
>
> This looks quite suspicious...
> First writing into the SKB and only then making room for it?
> Perhaps we should make sure rt2800_write_txwi demands the
> room is already added (or it calls skb_push itself).
>

Yep, I wasn't too happy with this as well. It's on my TODO-list to fix that up, but that
requires more restructuring of the common code.
For the sake of keeping this patch small I kept it this way, and I'm already working on
follow-up patches to clean the skb handling up, so that we don't have to fiddle around
with the skb->data pointer anymore when creating descriptors and TXWI's.

---
Gertjan.

2010-05-08 21:40:34

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 5/9] rt2x00: Factor out RXWI processing to common rt2800 code.

RXWI processing is exactly the same for rt2800pci and rt2800usb, so
make it common code.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 44 ++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800lib.h | 1 +
drivers/net/wireless/rt2x00/rt2800pci.c | 57 +++++-------------------
drivers/net/wireless/rt2x00/rt2800usb.c | 74 ++++++++++---------------------
4 files changed, 79 insertions(+), 97 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 28d82ce..7410ac1 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -335,6 +335,50 @@ void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc)
}
EXPORT_SYMBOL_GPL(rt2800_write_txwi);

+void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *rxdesc)
+{
+ __le32 *rxwi = (__le32 *) skb->data;
+ u32 word;
+
+ rt2x00_desc_read(rxwi, 0, &word);
+
+ rxdesc->cipher = rt2x00_get_field32(word, RXWI_W0_UDF);
+ rxdesc->size = rt2x00_get_field32(word, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+
+ rt2x00_desc_read(rxwi, 1, &word);
+
+ if (rt2x00_get_field32(word, RXWI_W1_SHORT_GI))
+ rxdesc->flags |= RX_FLAG_SHORT_GI;
+
+ if (rt2x00_get_field32(word, RXWI_W1_BW))
+ rxdesc->flags |= RX_FLAG_40MHZ;
+
+ /*
+ * Detect RX rate, always use MCS as signal type.
+ */
+ rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
+ rxdesc->signal = rt2x00_get_field32(word, RXWI_W1_MCS);
+ rxdesc->rate_mode = rt2x00_get_field32(word, RXWI_W1_PHYMODE);
+
+ /*
+ * Mask of 0x8 bit to remove the short preamble flag.
+ */
+ if (rxdesc->rate_mode == RATE_MODE_CCK)
+ rxdesc->signal &= ~0x8;
+
+ rt2x00_desc_read(rxwi, 2, &word);
+
+ rxdesc->rssi =
+ (rt2x00_get_field32(word, RXWI_W2_RSSI0) +
+ rt2x00_get_field32(word, RXWI_W2_RSSI1)) / 2;
+
+ /*
+ * Remove RXWI descriptor from start of buffer.
+ */
+ skb_pull(skb, RXWI_DESC_SIZE);
+}
+EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
+
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
const struct rt2x00debug rt2800_rt2x00debug = {
.owner = THIS_MODULE,
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index b805310..94de999 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -112,6 +112,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 arg0, const u8 arg1);

void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc);
+void rt2800_process_rxwi(struct sk_buff *skb, struct rxdone_entry_desc *txdesc);

extern const struct rt2x00debug rt2800_rt2x00debug;

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index bd56cd1..308842a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -770,20 +770,11 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
- __le32 *rxwi = (__le32 *)entry->skb->data;
- u32 rxd3;
- u32 rxwi0;
- u32 rxwi1;
- u32 rxwi2;
- u32 rxwi3;
-
- rt2x00_desc_read(rxd, 3, &rxd3);
- rt2x00_desc_read(rxwi, 0, &rxwi0);
- rt2x00_desc_read(rxwi, 1, &rxwi1);
- rt2x00_desc_read(rxwi, 2, &rxwi2);
- rt2x00_desc_read(rxwi, 3, &rxwi3);
-
- if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR))
+ u32 word;
+
+ rt2x00_desc_read(rxd, 3, &word);
+
+ if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

/*
@@ -791,10 +782,9 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* decryption. This prevents us from correct providing
* correct statistics through debugfs.
*/
- rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
- rxdesc->cipher_status = rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR);
+ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR);

- if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) {
+ if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) {
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
* decryption. Unfortunately the descriptor doesn't contain
@@ -809,47 +799,22 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
}

- if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS))
+ if (rt2x00_get_field32(word, RXD_W3_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;

- if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD))
+ if (rt2x00_get_field32(word, RXD_W3_L2PAD))
rxdesc->dev_flags |= RXDONE_L2PAD;

- if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
- rxdesc->flags |= RX_FLAG_SHORT_GI;
-
- if (rt2x00_get_field32(rxwi1, RXWI_W1_BW))
- rxdesc->flags |= RX_FLAG_40MHZ;
-
/*
- * Detect RX rate, always use MCS as signal type.
+ * Process the RXWI structure that is at the start of the buffer.
*/
- rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
- rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE);
- rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS);
-
- /*
- * Mask of 0x8 bit to remove the short preamble flag.
- */
- if (rxdesc->rate_mode == RATE_MODE_CCK)
- rxdesc->signal &= ~0x8;
-
- rxdesc->rssi =
- (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
- rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
-
- rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+ rt2800_process_rxwi(entry->skb, rxdesc);

/*
* 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, entry->entry_idx);
-
- /*
- * Remove TXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, RXWI_DESC_SIZE);
}

/*
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index b39b858..db37119 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -507,53 +507,45 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxi = (__le32 *)entry->skb->data;
- __le32 *rxwi;
__le32 *rxd;
- u32 rxi0;
- u32 rxwi0;
- u32 rxwi1;
- u32 rxwi2;
- u32 rxwi3;
- u32 rxd0;
+ u32 word;
int rx_pkt_len;

/*
+ * Copy descriptor to the skbdesc->desc buffer, making it safe from
+ * moving of frame data in rt2x00usb.
+ */
+ memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
+
+ /*
* RX frame format is :
* | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad |
* |<------------ rx_pkt_len -------------->|
*/
- rt2x00_desc_read(rxi, 0, &rxi0);
- rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN);
-
- rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE);
+ rt2x00_desc_read(rxi, 0, &word);
+ rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);

/*
- * FIXME : we need to check for rx_pkt_len validity
+ * Remove the RXINFO structure from the sbk.
*/
- rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len);
+ skb_pull(entry->skb, RXINFO_DESC_SIZE);

/*
- * Copy descriptor to the skbdesc->desc buffer, making it safe from
- * moving of frame data in rt2x00usb.
+ * FIXME: we need to check for rx_pkt_len validity
*/
- memcpy(skbdesc->desc, rxi, skbdesc->desc_len);
+ rxd = (__le32 *)(entry->skb->data + rx_pkt_len);

/*
* It is now safe to read the descriptor on all architectures.
*/
- rt2x00_desc_read(rxwi, 0, &rxwi0);
- rt2x00_desc_read(rxwi, 1, &rxwi1);
- rt2x00_desc_read(rxwi, 2, &rxwi2);
- rt2x00_desc_read(rxwi, 3, &rxwi3);
- rt2x00_desc_read(rxd, 0, &rxd0);
+ rt2x00_desc_read(rxd, 0, &word);

- if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
+ if (rt2x00_get_field32(word, RXD_W0_CRC_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;

- rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
- rxdesc->cipher_status = rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
+ rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W0_CIPHER_ERROR);

- if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
+ if (rt2x00_get_field32(word, RXD_W0_DECRYPTED)) {
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
* decryption. Unfortunately the descriptor doesn't contain
@@ -568,41 +560,21 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
rxdesc->flags |= RX_FLAG_MMIC_ERROR;
}

- if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
+ if (rt2x00_get_field32(word, RXD_W0_MY_BSS))
rxdesc->dev_flags |= RXDONE_MY_BSS;

- if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD))
+ if (rt2x00_get_field32(word, RXD_W0_L2PAD))
rxdesc->dev_flags |= RXDONE_L2PAD;

- if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI))
- rxdesc->flags |= RX_FLAG_SHORT_GI;
-
- if (rt2x00_get_field32(rxwi1, RXWI_W1_BW))
- rxdesc->flags |= RX_FLAG_40MHZ;
-
/*
- * Detect RX rate, always use MCS as signal type.
+ * Remove RXD descriptor from end of buffer.
*/
- rxdesc->dev_flags |= RXDONE_SIGNAL_MCS;
- rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE);
- rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS);
-
- /*
- * Mask of 0x8 bit to remove the short preamble flag.
- */
- if (rxdesc->rate_mode == RATE_MODE_CCK)
- rxdesc->signal &= ~0x8;
-
- rxdesc->rssi =
- (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
- rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
-
- rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
+ skb_trim(entry->skb, rx_pkt_len);

/*
- * Remove RXWI descriptor from start of buffer.
+ * Process the RXWI structure.
*/
- skb_pull(entry->skb, skbdesc->desc_len);
+ rt2800_process_rxwi(entry->skb, rxdesc);
}

/*
--
1.7.1


2010-05-09 09:18:34

by Pavel Roskin

[permalink] [raw]
Subject: Re: [PATCH 1/9] rt2x00: Fix setting of txdesc->length field.

On Sun, 2010-05-09 at 11:03 +0200, Ivo Van Doorn wrote:
> On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
> <[email protected]> wrote:
> > We should take the stripping of the IV into account for the txdesc->length
> > field.
> >
> > Signed-off-by: Gertjan van Wingerde <[email protected]>
>
> Acked-by: Ivo van Doorn <[email protected]>

Tested-by: Pavel Roskin <[email protected]>

It's working. Thank you!

--
Regards,
Pavel Roskin

2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 6/9] rt2x00: Clean up generic procedures on descriptor writing.

With a little bit of restructuring it isn't necessary to have special
cases in rt2x00queue_write_tx_descriptor for writing the descriptor
for beacons.
Simply split off the kicking of the TX queue to a separate function
with is only called for non-beacons.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2x00queue.c | 16 ++++++++++------
1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 59d9459..8768c6f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -428,20 +428,23 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
* it is now ready to be dumped to userspace through debugfs.
*/
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb);
+}
+
+static void rt2x00queue_kick_tx_queue(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
+{
+ struct data_queue *queue = entry->queue;
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;

/*
* Check if we need to kick the queue, there are however a few rules
- * 1) Don't kick beacon queue
- * 2) Don't kick unless this is the last in frame in a burst.
+ * 1) Don't kick unless this is the last in frame in a burst.
* When the burst flag is set, this frame is always followed
* by another frame which in some way are related to eachother.
* This is true for fragments, RTS or CTS-to-self frames.
- * 3) Rule 2 can be broken when the available entries
+ * 2) Rule 2 can be broken when the available entries
* in the queue are less then a certain threshold.
*/
- if (entry->queue->qid == QID_BEACON)
- return;
-
if (rt2x00queue_threshold(queue) ||
!test_bit(ENTRY_TXD_BURST, &txdesc->flags))
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
@@ -537,6 +540,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,

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

return 0;
}
--
1.7.1


2010-05-09 09:09:04

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 4/9] rt2x00: Factor out TXWI writing to common rt2800 code.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> TXWI writing is exactly the same for rt2800pci and rt2800usb, so
> make it common code.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-09 09:08:07

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 3/9] rt2x00: Don't check whether hardware crypto is enabled when reading RXD.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> We should simply follow what the hardware told us it has done.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-09 18:54:58

by Adam Baker

[permalink] [raw]
Subject: Re: [PATCH 6/9] rt2x00: Clean up generic procedures on descriptor writing.

Gertjan van Wingerde <gwingerde@...> writes:

> - * 3) Rule 2 can be broken when the available entries
> + * 2) Rule 2 can be broken when the available entries
> * in the queue are less then a certain threshold.
> */

shouldn't this say Rule 1 can be broken now?

Adam


2010-05-09 09:17:32

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 8/9] rt2x00: provide beacon's txdesc to write_beacon callback function.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> Preparation to fix rt2800 beaconing.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-09 09:10:14

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 5/9] rt2x00: Factor out RXWI processing to common rt2800 code.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> RXWI processing is exactly the same for rt2800pci and rt2800usb, so
> make it common code.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 1/9] rt2x00: Fix setting of txdesc->length field.

We should take the stripping of the IV into account for the txdesc->length
field.

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

diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index d291c78..583dacd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -128,6 +128,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)

/* Pull buffer to correct size */
skb_pull(skb, txdesc->iv_len);
+ txdesc->length -= txdesc->iv_len;

/* IV/EIV data has officially been stripped */
skbdesc->flags |= SKBDESC_IV_STRIPPED;
--
1.7.1


2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 2/9] rt2x00: Clean up rt2800usb.h.

Remove unused RXD_DESC_SIZE define and remove duplicated RXWI definitions
from rt2800.h.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h
index d1d8ae9..2bca6a7 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.h
+++ b/drivers/net/wireless/rt2x00/rt2800usb.h
@@ -79,8 +79,6 @@
*/
#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
-#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
-#define RXD_DESC_SIZE ( 1 * sizeof(__le32) )

/*
* TX Info structure
@@ -113,44 +111,6 @@
#define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff)

/*
- * RX WI structure
- */
-
-/*
- * Word0
- */
-#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff)
-#define RXWI_W0_KEY_INDEX FIELD32(0x00000300)
-#define RXWI_W0_BSSID FIELD32(0x00001c00)
-#define RXWI_W0_UDF FIELD32(0x0000e000)
-#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define RXWI_W0_TID FIELD32(0xf0000000)
-
-/*
- * Word1
- */
-#define RXWI_W1_FRAG FIELD32(0x0000000f)
-#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0)
-#define RXWI_W1_MCS FIELD32(0x007f0000)
-#define RXWI_W1_BW FIELD32(0x00800000)
-#define RXWI_W1_SHORT_GI FIELD32(0x01000000)
-#define RXWI_W1_STBC FIELD32(0x06000000)
-#define RXWI_W1_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define RXWI_W2_RSSI0 FIELD32(0x000000ff)
-#define RXWI_W2_RSSI1 FIELD32(0x0000ff00)
-#define RXWI_W2_RSSI2 FIELD32(0x00ff0000)
-
-/*
- * Word3
- */
-#define RXWI_W3_SNR0 FIELD32(0x000000ff)
-#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
-
-/*
* RX descriptor format for RX Ring.
*/

--
1.7.1


2010-05-09 09:42:20

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 9/9] rt2x00: Fix beaconing on rt2800.

On Sun, May 9, 2010 at 11:41 AM, Gertjan van Wingerde
<[email protected]> wrote:
> On 05/09/10 11:21, Ivo Van Doorn wrote:
>> On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
>> <[email protected]> wrote:
>>> According to the Ralink vendor driver for rt2800 we don't need a full
>>> TXD for a beacon but just a TXWI in front of the actual beacon.
>>> Fix the rt2800pci and rt2800usb beaconing code accordingly.
>>>
>>> Signed-off-by: Gertjan van Wingerde <[email protected]>
>>> ---
>>> ?drivers/net/wireless/rt2x00/rt2800pci.c | ? 17 +++++++++--------
>>> ?drivers/net/wireless/rt2x00/rt2800usb.c | ? 14 ++++++--------
>>> ?2 files changed, 15 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
>>> index 80c6768..7d4778d 100644
>>> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
>>> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
>>> @@ -682,7 +682,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
>>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct txentry_desc *txdesc)
>>> ?{
>>> ? ? ? ?struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
>>> - ? ? ? struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
>>> ? ? ? ?unsigned int beacon_base;
>>> ? ? ? ?u32 reg;
>>>
>>> @@ -695,15 +694,17 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
>>> ? ? ? ?rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
>>>
>>> ? ? ? ?/*
>>> - ? ? ? ?* Write entire beacon with descriptor to register.
>>> + ? ? ? ?* Add the TXWI for the beacon to the skb.
>>> + ? ? ? ?*/
>>> + ? ? ? rt2800_write_txwi(entry->skb, txdesc);
>>> + ? ? ? skb_push(entry->skb, TXWI_DESC_SIZE);
>>
>> This looks quite suspicious...
>> First writing into the SKB and only then making room for it?
>> Perhaps we should make sure rt2800_write_txwi demands the
>> room is already added (or it calls skb_push itself).
>>
>
> Yep, I wasn't too happy with this as well. It's on my TODO-list to fix that up, but that
> requires more restructuring of the common code.
> For the sake of keeping this patch small I kept it this way, and I'm already working on
> follow-up patches to clean the skb handling up, so that we don't have to fiddle around
> with the skb->data pointer anymore when creating descriptors and TXWI's.

Ok. In that case:

Acked-by: Ivo van Doorn <[email protected]>

2010-05-08 21:40:33

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 7/9] rt2x00: Clean up all driver's kick_tx_queue callback functions.

All of the driver's kick_tx_queue callback functions treat the TX queue
for beacons in a special manner.
Clean this up by integrating the kicking of the beacon queue into the
write_beacon callback function, and let the generic code no longer call
the kick_tx_queue callback function when updating the beacon.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 19 ++++------
drivers/net/wireless/rt2x00/rt2500pci.c | 19 ++++------
drivers/net/wireless/rt2x00/rt2500usb.c | 55 +++++++++++-----------------
drivers/net/wireless/rt2x00/rt2800pci.c | 20 ++++------
drivers/net/wireless/rt2x00/rt2800usb.c | 29 +++++----------
drivers/net/wireless/rt2x00/rt2x00queue.c | 5 +--
drivers/net/wireless/rt2x00/rt61pci.c | 30 +++++++---------
drivers/net/wireless/rt2x00/rt73usb.c | 40 +++++++-------------
8 files changed, 83 insertions(+), 134 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6f89891..9c13a4e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1089,6 +1089,14 @@ static void rt2400pci_write_beacon(struct queue_entry *entry)
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 1, word);
+
+ /*
+ * Enable beaconing again.
+ */
+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}

static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
@@ -1096,17 +1104,6 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
{
u32 reg;

- if (queue == QID_BEACON) {
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- }
- return;
- }
-
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d9b6304..84ab56e 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1246,6 +1246,14 @@ static void rt2500pci_write_beacon(struct queue_entry *entry)
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 1, word);
+
+ /*
+ * Enable beaconing again.
+ */
+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}

static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
@@ -1253,17 +1261,6 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
{
u32 reg;

- if (queue == QID_BEACON) {
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- }
- return;
- }
-
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue == QID_AC_BE));
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue == QID_AC_BK));
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index f90b308..5ee9b9f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1090,7 +1090,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
int length;
- u16 reg;
+ u16 reg, reg0;

/*
* Add the descriptor in front of the skb.
@@ -1132,6 +1132,26 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
* Send out the guardian byte.
*/
usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
+
+ /*
+ * Enable beaconing again.
+ */
+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+ reg0 = reg;
+ rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
+ /*
+ * Beacon generation will fail initially.
+ * To prevent this we need to change the TXRX_CSR19
+ * register several times (reg0 is the same as reg
+ * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
+ * and 1 in reg).
+ */
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
}

static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
@@ -1148,37 +1168,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
return length;
}

-static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
-{
- u16 reg, reg0;
-
- if (queue != QID_BEACON) {
- rt2x00usb_kick_tx_queue(rt2x00dev, queue);
- return;
- }
-
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
- if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
- rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
- rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
- reg0 = reg;
- rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
- /*
- * Beacon generation will fail initially.
- * To prevent this we need to change the TXRX_CSR19
- * register several times (reg0 is the same as reg
- * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
- * and 1 in reg).
- */
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
- }
-}
-
/*
* RX control handlers
*/
@@ -1777,7 +1766,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt2500usb_write_beacon,
.get_tx_data_len = rt2500usb_get_tx_data_len,
- .kick_tx_queue = rt2500usb_kick_tx_queue,
+ .kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt2x00usb_kill_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
.config_shared_key = rt2500usb_config_key,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 308842a..6d56460 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -705,6 +705,14 @@ static void rt2800pci_write_beacon(struct queue_entry *entry)
entry->skb->data, entry->skb->len);

/*
+ * Enable beaconing again.
+ */
+ 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);
+
+ /*
* Clean up beacon skb.
*/
dev_kfree_skb_any(entry->skb);
@@ -716,18 +724,6 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
{
struct data_queue *queue;
unsigned int idx, qidx = 0;
- u32 reg;
-
- if (queue_idx == QID_BEACON) {
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
- 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);
- }
- return;
- }

if (queue_idx > QID_HCCA && queue_idx != QID_MGMT)
return;
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index db37119..dbec718 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -459,6 +459,14 @@ static void rt2800usb_write_beacon(struct queue_entry *entry)
REGISTER_TIMEOUT32(entry->skb->len));

/*
+ * Enable beaconing again.
+ */
+ 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);
+
+ /*
* Clean up the beacon skb.
*/
dev_kfree_skb(entry->skb);
@@ -480,25 +488,6 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
return length;
}

-static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
-{
- u32 reg;
-
- if (queue != QID_BEACON) {
- rt2x00usb_kick_tx_queue(rt2x00dev, queue);
- return;
- }
-
- rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
- 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);
- }
-}
-
/*
* RX control handlers
*/
@@ -667,7 +656,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt2800usb_write_beacon,
.get_tx_data_len = rt2800usb_get_tx_data_len,
- .kick_tx_queue = rt2800usb_kick_tx_queue,
+ .kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt2x00usb_kill_tx_queue,
.fill_rxdone = rt2800usb_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 8768c6f..7ab4fbb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -606,12 +606,9 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);

/*
- * Send beacon to hardware.
- * Also enable beacon generation, which might have been disabled
- * by the driver during the config_beacon() callback function.
+ * Send beacon to hardware and enable beacon genaration..
*/
rt2x00dev->ops->lib->write_beacon(intf->beacon);
- rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);

mutex_unlock(&intf->beacon_skb_mutex);

diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 1b0c70d..9e3a1ee 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1869,6 +1869,19 @@ static void rt61pci_write_beacon(struct queue_entry *entry)
entry->skb->data, entry->skb->len);

/*
+ * Enable beaconing again.
+ *
+ * For Wi-Fi faily generated beacons between participating
+ * stations. Set TBTT phase adaptive adjustment step to 8us.
+ */
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+ /*
* Clean up beacon skb.
*/
dev_kfree_skb_any(entry->skb);
@@ -1880,23 +1893,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
{
u32 reg;

- if (queue == QID_BEACON) {
- /*
- * For Wi-Fi faily generated beacons between participating
- * stations. Set TBTT phase adaptive adjustment step to 8us.
- */
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
-
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
- }
- return;
- }
-
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE));
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK));
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 6acba62..ca3707a 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1536,6 +1536,19 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
REGISTER_TIMEOUT32(entry->skb->len));

/*
+ * Enable beaconing again.
+ *
+ * For Wi-Fi faily generated beacons between participating stations.
+ * Set TBTT phase adaptive adjustment step to 8us (default 16us)
+ */
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+ /*
* Clean up the beacon skb.
*/
dev_kfree_skb(entry->skb);
@@ -1556,31 +1569,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry)
return length;
}

-static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
-{
- u32 reg;
-
- if (queue != QID_BEACON) {
- rt2x00usb_kick_tx_queue(rt2x00dev, queue);
- return;
- }
-
- /*
- * For Wi-Fi faily generated beacons between participating stations.
- * Set TBTT phase adaptive adjustment step to 8us (default 16us)
- */
- rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
-
- rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
- }
-}
-
/*
* RX control handlers
*/
@@ -2261,7 +2249,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt73usb_write_beacon,
.get_tx_data_len = rt73usb_get_tx_data_len,
- .kick_tx_queue = rt73usb_kick_tx_queue,
+ .kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt2x00usb_kill_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
.config_shared_key = rt73usb_config_shared_key,
--
1.7.1


2010-05-08 21:40:34

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 9/9] rt2x00: Fix beaconing on rt2800.

According to the Ralink vendor driver for rt2800 we don't need a full
TXD for a beacon but just a TXWI in front of the actual beacon.
Fix the rt2800pci and rt2800usb beaconing code accordingly.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 80c6768..7d4778d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -682,7 +682,6 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
unsigned int beacon_base;
u32 reg;

@@ -695,15 +694,17 @@ static void rt2800pci_write_beacon(struct queue_entry *entry,
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);

/*
- * Write entire beacon with descriptor to register.
+ * Add the TXWI for the beacon to the skb.
+ */
+ rt2800_write_txwi(entry->skb, txdesc);
+ skb_push(entry->skb, TXWI_DESC_SIZE);
+
+ /*
+ * Write entire beacon with TXWI to register.
*/
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
- rt2800_register_multiwrite(rt2x00dev,
- beacon_base,
- skbdesc->desc, skbdesc->desc_len);
- rt2800_register_multiwrite(rt2x00dev,
- beacon_base + skbdesc->desc_len,
- entry->skb->data, entry->skb->len);
+ rt2800_register_multiwrite(rt2x00dev, beacon_base,
+ entry->skb->data, entry->skb->len);

/*
* Enable beaconing again.
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index d992a93..00e7906 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -431,18 +431,10 @@ static void rt2800usb_write_beacon(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
unsigned int beacon_base;
u32 reg;

/*
- * Add the descriptor in front of the skb.
- */
- skb_push(entry->skb, entry->queue->desc_size);
- memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
- skbdesc->desc = entry->skb->data;
-
- /*
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
@@ -451,6 +443,12 @@ static void rt2800usb_write_beacon(struct queue_entry *entry,
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);

/*
+ * Add the TXWI for the beacon to the skb.
+ */
+ rt2800_write_txwi(entry->skb, txdesc);
+ skb_push(entry->skb, TXWI_DESC_SIZE);
+
+ /*
* Write entire beacon with descriptor to register.
*/
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
--
1.7.1


2010-05-09 09:03:44

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 1/9] rt2x00: Fix setting of txdesc->length field.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> We should take the stripping of the IV into account for the txdesc->length
> field.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

> ---
> ?drivers/net/wireless/rt2x00/rt2x00crypto.c | ? ?1 +
> ?1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
> index d291c78..583dacd 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
> @@ -128,6 +128,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
>
> ? ? ? ?/* Pull buffer to correct size */
> ? ? ? ?skb_pull(skb, txdesc->iv_len);
> + ? ? ? txdesc->length -= txdesc->iv_len;
>
> ? ? ? ?/* IV/EIV data has officially been stripped */
> ? ? ? ?skbdesc->flags |= SKBDESC_IV_STRIPPED;
> --
> 1.7.1
>
>

2010-05-09 09:16:26

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 7/9] rt2x00: Clean up all driver's kick_tx_queue callback functions.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> All of the driver's kick_tx_queue callback functions treat the TX queue
> for beacons in a special manner.
> Clean this up by integrating the kicking of the beacon queue into the
> write_beacon callback function, and let the generic code no longer call
> the kick_tx_queue callback function when updating the beacon.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-08 21:40:32

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 8/9] rt2x00: provide beacon's txdesc to write_beacon callback function.

Preparation to fix rt2800 beaconing.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2400pci.c | 3 ++-
drivers/net/wireless/rt2x00/rt2500pci.c | 3 ++-
drivers/net/wireless/rt2x00/rt2500usb.c | 3 ++-
drivers/net/wireless/rt2x00/rt2800pci.c | 3 ++-
drivers/net/wireless/rt2x00/rt2800usb.c | 3 ++-
drivers/net/wireless/rt2x00/rt2x00.h | 3 ++-
drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +-
drivers/net/wireless/rt2x00/rt61pci.c | 3 ++-
drivers/net/wireless/rt2x00/rt73usb.c | 3 ++-
9 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 9c13a4e..4b38451 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1059,7 +1059,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt2400pci_write_beacon(struct queue_entry *entry)
+static void rt2400pci_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 84ab56e..d876c6d 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1216,7 +1216,8 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt2500pci_write_beacon(struct queue_entry *entry)
+static void rt2500pci_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 5ee9b9f..30c0544 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1082,7 +1082,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
*/
static void rt2500usb_beacondone(struct urb *urb);

-static void rt2500usb_write_beacon(struct queue_entry *entry)
+static void rt2500usb_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6d56460..80c6768 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -678,7 +678,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt2800pci_write_beacon(struct queue_entry *entry)
+static void rt2800pci_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index dbec718..d992a93 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -427,7 +427,8 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt2800usb_write_beacon(struct queue_entry *entry)
+static void rt2800usb_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 4f9b666..6c1ff4c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -551,7 +551,8 @@ struct rt2x00lib_ops {
struct txentry_desc *txdesc);
int (*write_tx_data) (struct queue_entry *entry,
struct txentry_desc *txdesc);
- void (*write_beacon) (struct queue_entry *entry);
+ void (*write_beacon) (struct queue_entry *entry,
+ struct txentry_desc *txdesc);
int (*get_tx_data_len) (struct queue_entry *entry);
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 7ab4fbb..47f127c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -608,7 +608,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
/*
* Send beacon to hardware and enable beacon genaration..
*/
- rt2x00dev->ops->lib->write_beacon(intf->beacon);
+ rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);

mutex_unlock(&intf->beacon_skb_mutex);

diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9e3a1ee..2436363 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1842,7 +1842,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt61pci_write_beacon(struct queue_entry *entry)
+static void rt61pci_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ca3707a..81f6db1 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1504,7 +1504,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* TX data initialization
*/
-static void rt73usb_write_beacon(struct queue_entry *entry)
+static void rt73usb_write_beacon(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
--
1.7.1


2010-05-09 19:23:12

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [PATCH 6/9] rt2x00: Clean up generic procedures on descriptor writing.

On 05/09/10 20:54, Adam Baker wrote:
> Gertjan van Wingerde <gwingerde@...> writes:
>
>> - * 3) Rule 2 can be broken when the available entries
>> + * 2) Rule 2 can be broken when the available entries
>> * in the queue are less then a certain threshold.
>> */
>
> shouldn't this say Rule 1 can be broken now?
>

Yes, you're right. Update of the patch is on its way.

---
Gertjan

2010-05-09 09:04:45

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 2/9] rt2x00: Clean up rt2800usb.h.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> Remove unused RXD_DESC_SIZE define and remove duplicated RXWI definitions
> from rt2800.h.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-09 09:11:43

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [PATCH 6/9] rt2x00: Clean up generic procedures on descriptor writing.

On Sat, May 8, 2010 at 11:40 PM, Gertjan van Wingerde
<[email protected]> wrote:
> With a little bit of restructuring it isn't necessary to have special
> cases in rt2x00queue_write_tx_descriptor for writing the descriptor
> for beacons.
> Simply split off the kicking of the TX queue to a separate function
> with is only called for non-beacons.
>
> Signed-off-by: Gertjan van Wingerde <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

2010-05-08 21:40:35

by Gertjan van Wingerde

[permalink] [raw]
Subject: [PATCH 4/9] rt2x00: Factor out TXWI writing to common rt2800 code.

TXWI writing is exactly the same for rt2800pci and rt2800usb, so
make it common code.

Signed-off-by: Gertjan van Wingerde <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800lib.c | 54 +++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800lib.h | 2 +
drivers/net/wireless/rt2x00/rt2800pci.c | 56 +------------------------------
drivers/net/wireless/rt2x00/rt2800usb.c | 50 ++--------------------------
4 files changed, 60 insertions(+), 102 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 525267d..28d82ce 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -281,6 +281,60 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);

+void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc)
+{
+ __le32 *txwi = (__le32 *)(skb->data - TXWI_DESC_SIZE);
+ u32 word;
+
+ /*
+ * Initialize TX Info descriptor
+ */
+ rt2x00_desc_read(txwi, 0, &word);
+ rt2x00_set_field32(&word, TXWI_W0_FRAG,
+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
+ rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
+ rt2x00_set_field32(&word, TXWI_W0_TS,
+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W0_AMPDU,
+ test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
+ rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
+ rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
+ rt2x00_set_field32(&word, TXWI_W0_BW,
+ test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
+ test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
+ rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
+ rt2x00_desc_write(txwi, 0, word);
+
+ rt2x00_desc_read(txwi, 1, &word);
+ rt2x00_set_field32(&word, TXWI_W1_ACK,
+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W1_NSEQ,
+ test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
+ rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
+ rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
+ test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
+ txdesc->key_idx : 0xff);
+ rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
+ txdesc->length);
+ rt2x00_set_field32(&word, TXWI_W1_PACKETID, txdesc->queue + 1);
+ rt2x00_desc_write(txwi, 1, word);
+
+ /*
+ * Always write 0 to IV/EIV fields, hardware will insert the IV
+ * from the IVEIV register when TXD_W3_WIV is set to 0.
+ * When TXD_W3_WIV is set to 1 it will use the IV data
+ * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
+ * crypto entry in the registers should be used to encrypt the frame.
+ */
+ _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
+ _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
+}
+EXPORT_SYMBOL_GPL(rt2800_write_txwi);
+
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
const struct rt2x00debug rt2800_rt2x00debug = {
.owner = THIS_MODULE,
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index ebabeae..b805310 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -111,6 +111,8 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1);

+void rt2800_write_txwi(struct sk_buff *skb, struct txentry_desc *txdesc);
+
extern const struct rt2x00debug rt2800_rt2x00debug;

int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index b9ec081..bd56cd1 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -616,67 +616,13 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
static int rt2800pci_write_tx_data(struct queue_entry* entry,
struct txentry_desc *txdesc)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct sk_buff *skb = entry->skb;
- struct skb_frame_desc *skbdesc;
int ret;
- __le32 *txwi;
- u32 word;

ret = rt2x00pci_write_tx_data(entry, txdesc);
if (ret)
return ret;

- skbdesc = get_skb_frame_desc(skb);
- txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom);
-
- /*
- * Initialize TX Info descriptor
- */
- rt2x00_desc_read(txwi, 0, &word);
- rt2x00_set_field32(&word, TXWI_W0_FRAG,
- test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
- rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
- rt2x00_set_field32(&word, TXWI_W0_TS,
- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_AMPDU,
- test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
- rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
- rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
- rt2x00_set_field32(&word, TXWI_W0_BW,
- test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
- test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
- rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
- rt2x00_desc_write(txwi, 0, word);
-
- rt2x00_desc_read(txwi, 1, &word);
- rt2x00_set_field32(&word, TXWI_W1_ACK,
- test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W1_NSEQ,
- test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
- rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
- test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- txdesc->key_idx : 0xff);
- rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
- txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID,
- skbdesc->entry->queue->qid + 1);
- rt2x00_desc_write(txwi, 1, word);
-
- /*
- * Always write 0 to IV/EIV fields, hardware will insert the IV
- * from the IVEIV register when TXD_W3_WIV is set to 0.
- * When TXD_W3_WIV is set to 1 it will use the IV data
- * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
- * crypto entry in the registers should be used to encrypt the frame.
- */
- _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
- _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
+ rt2800_write_txwi(entry->skb, txdesc);

return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index df7ad98..b39b858 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -401,59 +401,15 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
__le32 *txi = skbdesc->desc;
- __le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)];
u32 word;

/*
- * Initialize TX Info descriptor
+ * Initialize TXWI descriptor
*/
- rt2x00_desc_read(txwi, 0, &word);
- rt2x00_set_field32(&word, TXWI_W0_FRAG,
- test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0);
- rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0);
- rt2x00_set_field32(&word, TXWI_W0_TS,
- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_AMPDU,
- test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
- rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
- rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
- rt2x00_set_field32(&word, TXWI_W0_BW,
- test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
- test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
- rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
- rt2x00_desc_write(txwi, 0, word);
-
- rt2x00_desc_read(txwi, 1, &word);
- rt2x00_set_field32(&word, TXWI_W1_ACK,
- test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W1_NSEQ,
- test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
- rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
- rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
- test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- txdesc->key_idx : 0xff);
- rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
- txdesc->length);
- rt2x00_set_field32(&word, TXWI_W1_PACKETID,
- skbdesc->entry->queue->qid + 1);
- rt2x00_desc_write(txwi, 1, word);
+ rt2800_write_txwi(skb, txdesc);

/*
- * Always write 0 to IV/EIV fields, hardware will insert the IV
- * from the IVEIV register when TXINFO_W0_WIV is set to 0.
- * When TXINFO_W0_WIV is set to 1 it will use the IV data
- * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
- * crypto entry in the registers should be used to encrypt the frame.
- */
- _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
- _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
-
- /*
- * Initialize TX descriptor
+ * Initialize TXINFO descriptor
*/
rt2x00_desc_read(txi, 0, &word);
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
--
1.7.1