diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index a22837c560f..ff3a36622d1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -292,6 +292,56 @@ void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
292 | } | 292 | } |
293 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | 293 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); |
294 | 294 | ||
295 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | ||
296 | { | ||
297 | struct queue_entry_priv_usb *entry_priv; | ||
298 | unsigned short threshold = queue->threshold; | ||
299 | |||
300 | WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid); | ||
301 | |||
302 | /* | ||
303 | * Temporarily disable the TX queue, this will force mac80211 | ||
304 | * to use the other queues until this queue has been restored. | ||
305 | * | ||
306 | * Set the queue threshold to the queue limit. This prevents the | ||
307 | * queue from being enabled during the txdone handler. | ||
308 | */ | ||
309 | queue->threshold = queue->limit; | ||
310 | ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); | ||
311 | |||
312 | /* | ||
313 | * Reset all currently uploaded TX frames. | ||
314 | */ | ||
315 | while (!rt2x00queue_empty(queue)) { | ||
316 | entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; | ||
317 | usb_kill_urb(entry_priv->urb); | ||
318 | |||
319 | /* | ||
320 | * We need a short delay here to wait for | ||
321 | * the URB to be canceled and invoked the tx_done handler. | ||
322 | */ | ||
323 | udelay(200); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * The queue has been reset, and mac80211 is allowed to use the | ||
328 | * queue again. | ||
329 | */ | ||
330 | queue->threshold = threshold; | ||
331 | ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); | ||
332 | } | ||
333 | |||
334 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | ||
335 | { | ||
336 | struct data_queue *queue; | ||
337 | |||
338 | tx_queue_for_each(rt2x00dev, queue) { | ||
339 | if (rt2x00queue_timeout(queue)) | ||
340 | rt2x00usb_watchdog_reset_tx(queue); | ||
341 | } | ||
342 | } | ||
343 | EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | ||
344 | |||
295 | /* | 345 | /* |
296 | * RX data handlers. | 346 | * RX data handlers. |
297 | */ | 347 | */ |