OSDN Git Service

rt2x00: Sequence counter should be protected in irqsave
authorIvo van Doorn <ivdoorn@gmail.com>
Mon, 28 Jul 2008 08:21:16 +0000 (10:21 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 1 Aug 2008 19:31:34 +0000 (15:31 -0400)
The sequence counter can be accessed in IRQ context,
which means the lock protecting the counter should
be irqsave. To prevent making the entire intf->lock irqsave
without reason, create a new lock which only protects
the sequence counter.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00queue.c

index db2dc97..8b10ea4 100644 (file)
@@ -368,6 +368,12 @@ struct rt2x00_intf {
 #define DELAYED_CONFIG_ERP             0x00000002
 #define DELAYED_LED_ASSOC              0x00000004
 
+       /*
+        * Software sequence counter, this is only required
+        * for hardware which doesn't support hardware
+        * sequence counting.
+        */
+       spinlock_t seqlock;
        u16 seqno;
 };
 
index c3ee4ec..bd422fd 100644 (file)
@@ -247,6 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
                rt2x00dev->intf_sta_count++;
 
        spin_lock_init(&intf->lock);
+       spin_lock_init(&intf->seqlock);
        intf->beacon = entry;
 
        if (conf->type == IEEE80211_IF_TYPE_AP)
index 3b27f6a..898cdd7 100644 (file)
@@ -128,6 +128,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
        unsigned int data_length;
        unsigned int duration;
        unsigned int residual;
+       unsigned long irqflags;
 
        memset(txdesc, 0, sizeof(*txdesc));
 
@@ -213,14 +214,14 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
         * sequence counter given by mac80211.
         */
        if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-               spin_lock(&intf->lock);
+               spin_lock_irqsave(&intf->seqlock, irqflags);
 
                if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
                        intf->seqno += 0x10;
                hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
                hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
 
-               spin_unlock(&intf->lock);
+               spin_unlock_irqrestore(&intf->seqlock, irqflags);
 
                __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
        }