aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00usb.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2010-08-30 15:15:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-31 14:22:25 -0400
commit652a9dd2a0c07251e328519cc23f1316ab13ed51 (patch)
tree836afb7f5062716ce7391ad242786c1d2b3d2bd9 /drivers/net/wireless/rt2x00/rt2x00usb.c
parent0e3afe5b20c4ccdeff5178c62b557a917945a828 (diff)
rt2x00: Split watchdog check into a DMA and STATUS timeout
The watchdog for rt2800usb triggers frequently causing all URB's to be canceled often enough to interrupt the normal TX flow. More research indicated that not the URB upload to the USB host were hanging, but instead the TX status reports. To correctly detect what is going on, we introduce Q_INDEX_DMA_DONE which is an index counter between Q_INDEX_DONE and Q_INDEX and indicates if the frame has been transfered to the device. This also requires the rt2x00queue timeout functions to be updated to differentiate between a DMA timeout (time between Q_INDEX and Q_INDEX_DMA_DONE timeout) and a STATUS timeout (time between Q_INDEX_DMA_DONE and Q_INDEX_DONE timeout) All Q_INDEX_DMA_DONE code was taken from the RFC from Helmut Schaa <helmut.schaa@googlemail.com> for the implementation for watchdog for rt2800pci. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Acked-by: Gertjan van Wingerde <gwingerde@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00usb.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 6cc7aa418d87..aec6440d364a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -213,6 +213,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
213 return; 213 return;
214 214
215 /* 215 /*
216 * Report the frame as DMA done
217 */
218 rt2x00lib_dmadone(entry);
219
220 /*
216 * Check if the frame was correctly uploaded 221 * Check if the frame was correctly uploaded
217 */ 222 */
218 if (urb->status) 223 if (urb->status)
@@ -283,13 +288,14 @@ void rt2x00usb_kill_tx_queue(struct data_queue *queue)
283} 288}
284EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); 289EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
285 290
286static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) 291static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
287{ 292{
288 struct queue_entry *entry; 293 struct queue_entry *entry;
289 struct queue_entry_priv_usb *entry_priv; 294 struct queue_entry_priv_usb *entry_priv;
290 unsigned short threshold = queue->threshold; 295 unsigned short threshold = queue->threshold;
291 296
292 WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid); 297 WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
298 " invoke forced forced reset", queue->qid);
293 299
294 /* 300 /*
295 * Temporarily disable the TX queue, this will force mac80211 301 * Temporarily disable the TX queue, this will force mac80211
@@ -331,13 +337,23 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
331 ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); 337 ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
332} 338}
333 339
340static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
341{
342 WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
343 " invoke forced tx handler", queue->qid);
344
345 ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
346}
347
334void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) 348void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
335{ 349{
336 struct data_queue *queue; 350 struct data_queue *queue;
337 351
338 tx_queue_for_each(rt2x00dev, queue) { 352 tx_queue_for_each(rt2x00dev, queue) {
353 if (rt2x00queue_dma_timeout(queue))
354 rt2x00usb_watchdog_tx_dma(queue);
339 if (rt2x00queue_timeout(queue)) 355 if (rt2x00queue_timeout(queue))
340 rt2x00usb_watchdog_reset_tx(queue); 356 rt2x00usb_watchdog_tx_status(queue);
341 } 357 }
342} 358}
343EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); 359EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
@@ -383,6 +399,11 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
383 return; 399 return;
384 400
385 /* 401 /*
402 * Report the frame as DMA done
403 */
404 rt2x00lib_dmadone(entry);
405
406 /*
386 * Check if the received data is simply too small 407 * Check if the received data is simply too small
387 * to be actually valid, or if the urb is signaling 408 * to be actually valid, or if the urb is signaling
388 * a problem. 409 * a problem.