*/
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_dmadone(struct queue_entry *entry);
 void rt2x00lib_txdone(struct queue_entry *entry,
                      struct txdone_entry_desc *txdesc);
 void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
 
                return -ENOMEM;
 
        temp = data +
-           sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\n");
+           sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 
        queue_for_each(intf->rt2x00dev, queue) {
                spin_lock_irqsave(&queue->lock, irqflags);
 
-               temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
+               temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
                                queue->count, queue->limit, queue->length,
                                queue->index[Q_INDEX],
+                               queue->index[Q_INDEX_DMA_DONE],
                                queue->index[Q_INDEX_DONE]);
 
                spin_unlock_irqrestore(&queue->lock, irqflags);
 
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
+void rt2x00lib_dmadone(struct queue_entry *entry)
+{
+       rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
+
 void rt2x00lib_txdone(struct queue_entry *entry,
                      struct txdone_entry_desc *txdesc)
 {
 
        if (queue->index[index] >= queue->limit)
                queue->index[index] = 0;
 
+       queue->last_action[index] = jiffies;
+
        if (index == Q_INDEX) {
                queue->length++;
-               queue->last_index = jiffies;
        } else if (index == Q_INDEX_DONE) {
                queue->length--;
                queue->count++;
-               queue->last_index_done = jiffies;
        }
 
        spin_unlock_irqrestore(&queue->lock, irqflags);
 static void rt2x00queue_reset(struct data_queue *queue)
 {
        unsigned long irqflags;
+       unsigned int i;
 
        spin_lock_irqsave(&queue->lock, irqflags);
 
        queue->count = 0;
        queue->length = 0;
-       queue->last_index = jiffies;
-       queue->last_index_done = jiffies;
-       memset(queue->index, 0, sizeof(queue->index));
+
+       for (i = 0; i < Q_INDEX_MAX; i++) {
+               queue->index[i] = 0;
+               queue->last_action[i] = jiffies;
+       }
 
        spin_unlock_irqrestore(&queue->lock, irqflags);
 }
 
  *
  * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
  *     owned by the hardware then the queue is considered to be full.
+ * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
+ *     transfered to the hardware.
  * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
  *     the hardware and for which we need to run the txdone handler. If this
  *     entry is not owned by the hardware the queue is considered to be empty.
  */
 enum queue_index {
        Q_INDEX,
+       Q_INDEX_DMA_DONE,
        Q_INDEX_DONE,
        Q_INDEX_MAX,
 };
        enum data_queue_qid qid;
 
        spinlock_t lock;
-       unsigned long last_index;
-       unsigned long last_index_done;
        unsigned int count;
        unsigned short limit;
        unsigned short threshold;
        unsigned short length;
        unsigned short index[Q_INDEX_MAX];
+       unsigned long last_action[Q_INDEX_MAX];
 
        unsigned short txop;
        unsigned short aifs;
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occured for this queue
+ * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts
  * @queue: Queue to check.
  */
 static inline int rt2x00queue_timeout(struct data_queue *queue)
 {
-       return time_after(queue->last_index, queue->last_index_done + (HZ / 10));
+       return time_after(queue->last_action[Q_INDEX_DMA_DONE],
+                         queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+}
+
+/**
+ * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+{
+       return time_after(queue->last_action[Q_INDEX],
+                         queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
 }
 
 /**
 
            !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
 
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
+
        /*
         * Check if the frame was correctly uploaded
         */
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
 
-static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
 {
        struct queue_entry *entry;
        struct queue_entry_priv_usb *entry_priv;
        unsigned short threshold = queue->threshold;
 
-       WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+       WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
+               " invoke forced forced reset", queue->qid);
 
        /*
         * Temporarily disable the TX queue, this will force mac80211
        ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
 }
 
+static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
+{
+       WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
+               " invoke forced tx handler", queue->qid);
+
+       ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
+}
+
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
 {
        struct data_queue *queue;
 
        tx_queue_for_each(rt2x00dev, queue) {
+               if (rt2x00queue_dma_timeout(queue))
+                       rt2x00usb_watchdog_tx_dma(queue);
                if (rt2x00queue_timeout(queue))
-                       rt2x00usb_watchdog_reset_tx(queue);
+                       rt2x00usb_watchdog_tx_status(queue);
        }
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
            !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
                return;
 
+       /*
+        * Report the frame as DMA done
+        */
+       rt2x00lib_dmadone(entry);
+
        /*
         * Check if the received data is simply too small
         * to be actually valid, or if the urb is signaling