From 0262ab0df64a67d4c0ed7577a29b7d866819cc68 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 29 Aug 2008 21:04:26 +0200 Subject: rt2x00: Fix race conditions in flag handling Some of the flags should be accessed atomically to prevent race conditions. The flags that are most important are those that can change often and indicate the actual state of the device, queue or queue entry. The big flag rename was done to move all state flags to the same naming type as the other rt2x00dev flags and made sure all places where the flags were used were changed. ;) Thanks to Stephen for most of the queue flags updates, which fixes some of the most obvious consequences of the race conditions. Among those the notorious: rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0. rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0. rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the non-full queue 0. Signed-off-by: Stephen Blackheath Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 2050227ea53..2dd7c830c12 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -163,7 +163,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct txdone_entry_desc txdesc; - if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; @@ -232,7 +232,7 @@ static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) { struct queue_entry_priv_usb *entry_priv = entry->priv_data; - if (__test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) + if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) usb_submit_urb(entry_priv->urb, GFP_ATOMIC); } @@ -283,7 +283,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); u8 rxd[32]; - if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; @@ -293,7 +293,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * a problem. */ if (urb->actual_length < entry->queue->desc_size || urb->status) { - __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(urb, GFP_ATOMIC); return; } @@ -361,7 +361,7 @@ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, entry->skb->data, entry->skb->len, rt2x00usb_interrupt_rxdone, entry); - __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(entry_priv->urb, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); -- cgit v1.2.3-70-g09d2 From 1abc3656e961e62218257a85b3fe0a90ccd9036c Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Fri, 29 Aug 2008 21:07:20 +0200 Subject: rt2x00: skb->data pointer should not include TX descriptor Make sure the skb->data pointer points to the frame data, not the TX descriptor. The frame dumping code relies on that. Signed-off-by: Mattias Nissler Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 3 +-- drivers/net/wireless/rt2x00/rt2x00usb.c | 11 ++++++----- drivers/net/wireless/rt2x00/rt73usb.c | 3 +-- 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c5f49e36559..0e008b606f7 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1114,8 +1114,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, - skb->len - skbdesc->desc_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 2dd7c830c12..b73a7e0aeed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -167,11 +167,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; - /* - * Remove the descriptor data from the buffer. - */ - skb_pull(entry->skb, entry->queue->desc_size); - /* * Obtain the status about this packet. * Note that when the status is 0 it does not mean the @@ -224,6 +219,12 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); + /* + * Make sure the skb->data pointer points to the frame, not the + * descriptor. + */ + skb_pull(entry->skb, entry->queue->desc_size); + return 0; } EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index cf236ec533a..e698ae0efbc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1556,8 +1556,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, - skb->len - skbdesc->desc_len); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); rt2x00_set_field32(&word, TXD_W0_BURST2, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); -- cgit v1.2.3-70-g09d2