/*
                 * Obtain the status about this packet.
                 */
-               txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
+               case 0: /* Success */
+               case 1: /* Success with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 2: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
                txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
 
                rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 
                /*
                 * Obtain the status about this packet.
                 */
-               txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
+               case 0: /* Success */
+               case 1: /* Success with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 2: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
                txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
 
                rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
 
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct skb_frame_desc *skbdesc;
        struct ieee80211_tx_status tx_status;
-       int success = !!(txdesc->status == TX_SUCCESS ||
-                        txdesc->status == TX_SUCCESS_RETRY);
-       int fail = !!(txdesc->status == TX_FAIL_RETRY ||
-                     txdesc->status == TX_FAIL_INVALID ||
-                     txdesc->status == TX_FAIL_OTHER);
 
        /*
         * Update TX statistics.
         */
-       rt2x00dev->link.qual.tx_success += success;
-       rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
+       rt2x00dev->link.qual.tx_success +=
+           test_bit(TXDONE_SUCCESS, &txdesc->flags);
+       rt2x00dev->link.qual.tx_failed +=
+           txdesc->retry + !!test_bit(TXDONE_FAILURE, &txdesc->flags);
 
        /*
         * Initialize TX status
         */
        tx_status.flags = 0;
        tx_status.ack_signal = 0;
-       tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
+       tx_status.excessive_retries =
+           test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags);
        tx_status.retry_count = txdesc->retry;
        memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
 
        if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
-               if (success)
+               if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
                        tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-               else
+               else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
                        rt2x00dev->low_level_stats.dot11ACKFailureCount++;
        }
 
        if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
-               if (success)
+               if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
                        rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
-               else
+               else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
                        rt2x00dev->low_level_stats.dot11RTSFailureCount++;
        }
 
                ieee80211_tx_status_irqsafe(rt2x00dev->hw,
                                            entry->skb, &tx_status);
        else
-               dev_kfree_skb(entry->skb);
+               dev_kfree_skb_irq(entry->skb);
        entry->skb = NULL;
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
 
        int dev_flags;
 };
 
+/**
+ * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc
+ *
+ * @TXDONE_UNKNOWN: Hardware could not determine success of transmission.
+ * @TXDONE_SUCCESS: Frame was successfully send
+ * @TXDONE_FAILURE: Frame was not successfully send
+ * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
+ *     frame transmission failed due to excessive retries.
+ */
+enum txdone_entry_desc_flags {
+       TXDONE_UNKNOWN = 1 << 0,
+       TXDONE_SUCCESS = 1 << 1,
+       TXDONE_FAILURE = 1 << 2,
+       TXDONE_EXCESSIVE_RETRY = 1 << 3,
+};
+
 /**
  * struct txdone_entry_desc: TX done entry descriptor
  *
  * after the device is done with transmission.
  *
  * @control: Control structure which was used to transmit the frame.
- * @status: TX status (See &enum tx_status).
+ * @flags: TX done flags (See &enum txdone_entry_desc_flags).
  * @retry: Retry count.
  */
 struct txdone_entry_desc {
        struct ieee80211_tx_control *control;
-       int status;
+       unsigned long flags;
        int retry;
 };
 
 
 #ifndef RT2X00REG_H
 #define RT2X00REG_H
 
-/*
- * TX result flags.
- */
-enum tx_status {
-       TX_SUCCESS = 0,
-       TX_SUCCESS_RETRY = 1,
-       TX_FAIL_RETRY = 2,
-       TX_FAIL_INVALID = 3,
-       TX_FAIL_OTHER = 4,
-};
-
 /*
  * Antenna values
  */
 
 
        /*
         * Obtain the status about this packet.
+        * Note that when the status is 0 it does not mean the
+        * frame was send out correctly. It only means the frame
+        * was succesfully pushed to the hardware, we have no
+        * way to determine the transmission status right now.
+        * (Only indirectly by looking at the failed TX counters
+        * in the register).
         */
-       txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
+       if (!urb->status)
+               __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
+       else
+               __set_bit(TXDONE_FAILURE, &txdesc.flags);
        txdesc.retry = 0;
        txdesc.control = &priv_tx->control;
 
 
                                "TX status report missed for entry %d\n",
                                entry_done->entry_idx);
 
-                       txdesc.status = TX_FAIL_OTHER;
+                       txdesc.flags = 0;
+                       __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
                        txdesc.retry = 0;
 
                        rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
                /*
                 * Obtain the status about this packet.
                 */
-               txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
+               txdesc.flags = 0;
+               switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
+               case 0: /* Success, maybe with retry */
+                       __set_bit(TXDONE_SUCCESS, &txdesc.flags);
+                       break;
+               case 6: /* Failure, excessive retries */
+                       __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
+                       /* Don't break, this is a failed frame! */
+               default: /* Failure */
+                       __set_bit(TXDONE_FAILURE, &txdesc.flags);
+               }
                txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
 
                rt2x00pci_txdone(rt2x00dev, entry, &txdesc);