diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2010-08-30 21:15:19 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-08-31 20:22:25 +0200 |
commit | 652a9dd2a0c07251e328519cc23f1316ab13ed51 (patch) | |
tree | 836afb7f5062716ce7391ad242786c1d2b3d2bd9 /drivers/net/wireless/rt2x00/rt2x00usb.c | |
parent | rt2x00: Correctly kill beacon queue (diff) | |
download | linux-652a9dd2a0c07251e328519cc23f1316ab13ed51.tar.xz linux-652a9dd2a0c07251e328519cc23f1316ab13ed51.zip |
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.c | 27 |
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) return; /* + * Report the frame as DMA done + */ + rt2x00lib_dmadone(entry); + + /* * Check if the frame was correctly uploaded */ if (urb->status) @@ -283,13 +288,14 @@ void rt2x00usb_kill_tx_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); -static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) +static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) { struct queue_entry *entry; struct queue_entry_priv_usb *entry_priv; unsigned short threshold = queue->threshold; - WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid); + WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," + " invoke forced forced reset", queue->qid); /* * Temporarily disable the TX queue, this will force mac80211 @@ -331,13 +337,23 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); } +static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) +{ + WARNING(queue->rt2x00dev, "TX queue %d status timed out," + " invoke forced tx handler", queue->qid); + + ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); +} + void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; tx_queue_for_each(rt2x00dev, queue) { + if (rt2x00queue_dma_timeout(queue)) + rt2x00usb_watchdog_tx_dma(queue); if (rt2x00queue_timeout(queue)) - rt2x00usb_watchdog_reset_tx(queue); + rt2x00usb_watchdog_tx_status(queue); } } EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); @@ -383,6 +399,11 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) return; /* + * Report the frame as DMA done + */ + rt2x00lib_dmadone(entry); + + /* * Check if the received data is simply too small * to be actually valid, or if the urb is signaling * a problem. |