__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
                __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
        }
+       __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
        .rfkill_poll            = rt2500usb_rfkill_poll,
        .link_stats             = rt2500usb_link_stats,
        .reset_tuner            = rt2500usb_reset_tuner,
+       .watchdog               = rt2x00usb_watchdog,
        .write_tx_desc          = rt2500usb_write_tx_desc,
        .write_beacon           = rt2500usb_write_beacon,
        .get_tx_data_len        = rt2500usb_get_tx_data_len,
 
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+       __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
        .link_stats             = rt2800_link_stats,
        .reset_tuner            = rt2800_reset_tuner,
        .link_tuner             = rt2800_link_tuner,
+       .watchdog               = rt2x00usb_watchdog,
        .write_tx_desc          = rt2800usb_write_tx_desc,
        .write_tx_data          = rt2800usb_write_tx_data,
        .write_beacon           = rt2800_write_beacon,
 
         * Work structure for scheduling periodic link tuning.
         */
        struct delayed_work work;
+
+       /*
+        * Work structure for scheduling periodic watchdog monitoring.
+        */
+       struct delayed_work watchdog_work;
 };
 
 /*
                             struct link_qual *qual);
        void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
                            struct link_qual *qual, const u32 count);
+       void (*watchdog) (struct rt2x00_dev *rt2x00dev);
 
        /*
         * TX control handlers
        DRIVER_SUPPORT_CONTROL_FILTERS,
        DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
        DRIVER_SUPPORT_LINK_TUNING,
+       DRIVER_SUPPORT_WATCHDOG,
 
        /*
         * Driver configuration
 
         */
        rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 
+       /*
+        * Start watchdog monitoring.
+        */
+       rt2x00link_start_watchdog(rt2x00dev);
+
        /*
         * Start the TX queues.
         */
        ieee80211_stop_queues(rt2x00dev->hw);
        rt2x00queue_stop_queues(rt2x00dev);
 
+       /*
+        * Stop watchdog monitoring.
+        */
+       rt2x00link_stop_watchdog(rt2x00dev);
+
        /*
         * Disable RX.
         */
 
 /*
  * Interval defines
  */
+#define WATCHDOG_INTERVAL      round_jiffies_relative(HZ)
 #define LINK_TUNE_INTERVAL     round_jiffies_relative(HZ)
 
 /*
 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
 
 /**
- * rt2x00link_register - Initialize link tuning functionality
+ * rt2x00link_start_watchdog - Start periodic watchdog monitoring
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  *
- * Initialize work structure and all link tuning related
- * parameters. This will not start the link tuning process itself.
+ * This start the watchdog periodic work, this work will
+ *be executed periodically until &rt2x00link_stop_watchdog has
+ * been called.
+ */
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * After this function completed the watchdog monitoring will not
+ * be running until &rt2x00link_start_watchdog is called.
+ */
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_register - Initialize link tuning & watchdog functionality
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * Initialize work structure and all link tuning and watchdog related
+ * parameters. This will not start the periodic work itself.
  */
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
 
 
                                             &link->work, LINK_TUNE_INTERVAL);
 }
 
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       struct link *link = &rt2x00dev->link;
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+           !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
+               return;
+
+       ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                    &link->watchdog_work, WATCHDOG_INTERVAL);
+}
+
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
+}
+
+static void rt2x00link_watchdog(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, link.watchdog_work.work);
+       struct link *link = &rt2x00dev->link;
+
+       /*
+        * When the radio is shutting down we should
+        * immediately cease the watchdog monitoring.
+        */
+       if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
+       rt2x00dev->ops->lib->watchdog(rt2x00dev);
+
+       if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               ieee80211_queue_delayed_work(rt2x00dev->hw,
+                                            &link->watchdog_work, WATCHDOG_INTERVAL);
+}
+
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
 {
+       INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
        INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
 }
 
 
        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);
 
        queue->count = 0;
        queue->length = 0;
+       queue->last_index = jiffies;
+       queue->last_index_done = jiffies;
        memset(queue->index, 0, sizeof(queue->index));
 
        spin_unlock_irqrestore(&queue->lock, irqflags);
 
        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;
        return rt2x00queue_available(queue) < queue->threshold;
 }
 
+/**
+ * rt2x00queue_timeout - Check if a timeout occured for this queue
+ * @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));
+}
+
 /**
  * _rt2x00_desc_read - Read a word from the hardware descriptor.
  * @desc: Base descriptor address
 
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
 
+static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+{
+       struct queue_entry_priv_usb *entry_priv;
+       unsigned short threshold = queue->threshold;
+
+       WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+
+       /*
+        * Temporarily disable the TX queue, this will force mac80211
+        * to use the other queues until this queue has been restored.
+        *
+        * Set the queue threshold to the queue limit. This prevents the
+        * queue from being enabled during the txdone handler.
+        */
+       queue->threshold = queue->limit;
+       ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+
+       /*
+        * Reset all currently uploaded TX frames.
+        */
+       while (!rt2x00queue_empty(queue)) {
+               entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
+               usb_kill_urb(entry_priv->urb);
+
+               /*
+                * We need a short delay here to wait for
+                * the URB to be canceled and invoked the tx_done handler.
+                */
+               udelay(200);
+       }
+
+       /*
+        * The queue has been reset, and mac80211 is allowed to use the
+        * queue again.
+        */
+       queue->threshold = threshold;
+       ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+}
+
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_queue *queue;
+
+       tx_queue_for_each(rt2x00dev, queue) {
+               if (rt2x00queue_timeout(queue))
+                       rt2x00usb_watchdog_reset_tx(queue);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
+
 /*
  * RX data handlers.
  */
 
 void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
                              const enum data_queue_qid qid);
 
+/**
+ * rt2x00usb_watchdog - Watchdog for USB communication
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ *
+ * Check the health of the USB communication and determine
+ * if timeouts have occured. If this is the case, this function
+ * will reset all communication to restore functionality again.
+ */
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
+
 /*
  * Device initialization handlers.
  */
 
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+       __set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
        /*
         * Set the rssi offset.
        .link_stats             = rt73usb_link_stats,
        .reset_tuner            = rt73usb_reset_tuner,
        .link_tuner             = rt73usb_link_tuner,
+       .watchdog               = rt2x00usb_watchdog,
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_beacon           = rt73usb_write_beacon,
        .get_tx_data_len        = rt73usb_get_tx_data_len,