rt2x00: Introduce extra queue entry sanity flag
authorIvo van Doorn <ivdoorn@gmail.com>
Mon, 13 Dec 2010 11:36:18 +0000 (12:36 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 13 Dec 2010 20:23:36 +0000 (15:23 -0500)
Add a queue entry flag ENTRY_DATA_STATUS_PENDING,
which can be used to indicate a queue entry has
returned from the hardware and is waiting for
status processing. Using this flag we can add
some extra sanity checks to prevent queue corruption.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00usb.c

index 3d4c61fcf06f447ed3d75307ee8cfdc3d0504f23..fa74acdd271ff399a9cb8438ea8aadcce370536b 100644 (file)
@@ -235,6 +235,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
 
 void rt2x00lib_dmadone(struct queue_entry *entry)
 {
+       set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
        clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
        rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
 }
index baa39b75430c97e8c94056d9d6587a6610218125..47659346070bd68c7a287dbc699e3e3f00ba43d7 100644 (file)
@@ -340,12 +340,16 @@ struct txentry_desc {
  * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
  *     while transfering the data to the hardware. No TX status report will
  *     be expected from the hardware.
+ * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
+ *     returned. It is now waiting for the status reporting before the
+ *     entry can be reused again.
  */
 enum queue_entry_flags {
        ENTRY_BCN_ASSIGNED,
        ENTRY_OWNER_DEVICE_DATA,
        ENTRY_DATA_PENDING,
-       ENTRY_DATA_IO_FAILED
+       ENTRY_DATA_IO_FAILED,
+       ENTRY_DATA_STATUS_PENDING,
 };
 
 /**
index cd29ebc8a37b70fc71edc0a407c4c0e8707a6a04..8a16b5106a33a215e536026b7806167302a7dbb4 100644 (file)
@@ -195,7 +195,8 @@ static void rt2x00usb_work_txdone(struct work_struct *work)
                while (!rt2x00queue_empty(queue)) {
                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                                break;
 
                        rt2x00usb_work_txdone_entry(entry);
@@ -237,7 +238,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
        u32 length;
        int status;
 
-       if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
+       if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
+           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                return;
 
        /*
@@ -275,7 +277,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)
        while (!rt2x00queue_empty(rt2x00dev->rx)) {
                entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
 
-               if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+               if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+                   !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                        break;
 
                /*
@@ -327,7 +330,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
        struct queue_entry_priv_usb *entry_priv = entry->priv_data;
        int status;
 
-       if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+       if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+           test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
                return;
 
        rt2x00lib_dmastart(entry);