}
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota)
 {
        struct data_queue *queue;
        struct queue_entry *entry;
        u8 qid;
        bool match;
 
-       while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
+       while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
                /*
                 * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
                 * guaranteed to be one of the TX QIDs .
 
 
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
                         bool match);
-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
 void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
 bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
 
 
 }
 EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
 
-static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
-{
-       bool timeout = false;
-
-       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
-              (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
-
-               rt2800_txdone(rt2x00dev);
-
-               if (timeout)
-                       rt2800_txdone_nostatus(rt2x00dev);
-       }
-}
-
 static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
 {
        u32 status;
 {
        struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 
-       do {
-               rt2800mmio_txdone(rt2x00dev);
+       rt2800_txdone(rt2x00dev, 16);
 
-       } while (rt2800mmio_fetch_txstatus(rt2x00dev));
+       if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
 
-       if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2800mmio_enable_interrupt(rt2x00dev,
-                                           INT_SOURCE_CSR_TX_FIFO_STATUS);
 }
 EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
 
        mask = ~reg;
 
        if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+               rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
                rt2800mmio_fetch_txstatus(rt2x00dev);
-               tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+               if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+                       tasklet_schedule(&rt2x00dev->txstatus_tasklet);
        }
 
        if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
                 */
                if (tx_queue) {
                        tasklet_disable(&rt2x00dev->txstatus_tasklet);
-                       rt2800mmio_txdone(rt2x00dev);
+                       rt2800_txdone(rt2x00dev, UINT_MAX);
+                       rt2800_txdone_nostatus(rt2x00dev);
                        tasklet_enable(&rt2x00dev->txstatus_tasklet);
                }