aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h21
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c27
6 files changed, 59 insertions, 14 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 762f6b4e7afc..0ae942cb66df 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1070,6 +1070,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
1070 */ 1070 */
1071void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); 1071void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
1072void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); 1072void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
1073void rt2x00lib_dmadone(struct queue_entry *entry);
1073void rt2x00lib_txdone(struct queue_entry *entry, 1074void rt2x00lib_txdone(struct queue_entry *entry,
1074 struct txdone_entry_desc *txdesc); 1075 struct txdone_entry_desc *txdesc);
1075void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); 1076void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status);
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index daf7f950a28f..54dc44bb415c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -338,14 +338,15 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
338 return -ENOMEM; 338 return -ENOMEM;
339 339
340 temp = data + 340 temp = data +
341 sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\n"); 341 sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
342 342
343 queue_for_each(intf->rt2x00dev, queue) { 343 queue_for_each(intf->rt2x00dev, queue) {
344 spin_lock_irqsave(&queue->lock, irqflags); 344 spin_lock_irqsave(&queue->lock, irqflags);
345 345
346 temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, 346 temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
347 queue->count, queue->limit, queue->length, 347 queue->count, queue->limit, queue->length,
348 queue->index[Q_INDEX], 348 queue->index[Q_INDEX],
349 queue->index[Q_INDEX_DMA_DONE],
349 queue->index[Q_INDEX_DONE]); 350 queue->index[Q_INDEX_DONE]);
350 351
351 spin_unlock_irqrestore(&queue->lock, irqflags); 352 spin_unlock_irqrestore(&queue->lock, irqflags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 580595ba5683..053fdd3bd720 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -251,6 +251,12 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
251} 251}
252EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); 252EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
253 253
254void rt2x00lib_dmadone(struct queue_entry *entry)
255{
256 rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
257}
258EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
259
254void rt2x00lib_txdone(struct queue_entry *entry, 260void rt2x00lib_txdone(struct queue_entry *entry,
255 struct txdone_entry_desc *txdesc) 261 struct txdone_entry_desc *txdesc)
256{ 262{
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ecf57635ae51..6d41599a090c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -731,13 +731,13 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
731 if (queue->index[index] >= queue->limit) 731 if (queue->index[index] >= queue->limit)
732 queue->index[index] = 0; 732 queue->index[index] = 0;
733 733
734 queue->last_action[index] = jiffies;
735
734 if (index == Q_INDEX) { 736 if (index == Q_INDEX) {
735 queue->length++; 737 queue->length++;
736 queue->last_index = jiffies;
737 } else if (index == Q_INDEX_DONE) { 738 } else if (index == Q_INDEX_DONE) {
738 queue->length--; 739 queue->length--;
739 queue->count++; 740 queue->count++;
740 queue->last_index_done = jiffies;
741 } 741 }
742 742
743 spin_unlock_irqrestore(&queue->lock, irqflags); 743 spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -746,14 +746,17 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
746static void rt2x00queue_reset(struct data_queue *queue) 746static void rt2x00queue_reset(struct data_queue *queue)
747{ 747{
748 unsigned long irqflags; 748 unsigned long irqflags;
749 unsigned int i;
749 750
750 spin_lock_irqsave(&queue->lock, irqflags); 751 spin_lock_irqsave(&queue->lock, irqflags);
751 752
752 queue->count = 0; 753 queue->count = 0;
753 queue->length = 0; 754 queue->length = 0;
754 queue->last_index = jiffies; 755
755 queue->last_index_done = jiffies; 756 for (i = 0; i < Q_INDEX_MAX; i++) {
756 memset(queue->index, 0, sizeof(queue->index)); 757 queue->index[i] = 0;
758 queue->last_action[i] = jiffies;
759 }
757 760
758 spin_unlock_irqrestore(&queue->lock, irqflags); 761 spin_unlock_irqrestore(&queue->lock, irqflags);
759} 762}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 0e38a911195d..d81d85f34866 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -401,6 +401,8 @@ struct queue_entry {
401 * 401 *
402 * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is 402 * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
403 * owned by the hardware then the queue is considered to be full. 403 * owned by the hardware then the queue is considered to be full.
404 * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
405 * transfered to the hardware.
404 * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by 406 * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
405 * the hardware and for which we need to run the txdone handler. If this 407 * the hardware and for which we need to run the txdone handler. If this
406 * entry is not owned by the hardware the queue is considered to be empty. 408 * entry is not owned by the hardware the queue is considered to be empty.
@@ -409,6 +411,7 @@ struct queue_entry {
409 */ 411 */
410enum queue_index { 412enum queue_index {
411 Q_INDEX, 413 Q_INDEX,
414 Q_INDEX_DMA_DONE,
412 Q_INDEX_DONE, 415 Q_INDEX_DONE,
413 Q_INDEX_MAX, 416 Q_INDEX_MAX,
414}; 417};
@@ -445,13 +448,12 @@ struct data_queue {
445 enum data_queue_qid qid; 448 enum data_queue_qid qid;
446 449
447 spinlock_t lock; 450 spinlock_t lock;
448 unsigned long last_index;
449 unsigned long last_index_done;
450 unsigned int count; 451 unsigned int count;
451 unsigned short limit; 452 unsigned short limit;
452 unsigned short threshold; 453 unsigned short threshold;
453 unsigned short length; 454 unsigned short length;
454 unsigned short index[Q_INDEX_MAX]; 455 unsigned short index[Q_INDEX_MAX];
456 unsigned long last_action[Q_INDEX_MAX];
455 457
456 unsigned short txop; 458 unsigned short txop;
457 unsigned short aifs; 459 unsigned short aifs;
@@ -616,12 +618,23 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
616} 618}
617 619
618/** 620/**
619 * rt2x00queue_timeout - Check if a timeout occured for this queue 621 * rt2x00queue_timeout - Check if a timeout occured for STATUS reorts
620 * @queue: Queue to check. 622 * @queue: Queue to check.
621 */ 623 */
622static inline int rt2x00queue_timeout(struct data_queue *queue) 624static inline int rt2x00queue_timeout(struct data_queue *queue)
623{ 625{
624 return time_after(queue->last_index, queue->last_index_done + (HZ / 10)); 626 return time_after(queue->last_action[Q_INDEX_DMA_DONE],
627 queue->last_action[Q_INDEX_DONE] + (HZ / 10));
628}
629
630/**
631 * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
632 * @queue: Queue to check.
633 */
634static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
635{
636 return time_after(queue->last_action[Q_INDEX],
637 queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
625} 638}
626 639
627/** 640/**
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.