diff options
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00debug.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 27 |
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 | */ |
1071 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | 1071 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); |
1072 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | 1072 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); |
1073 | void rt2x00lib_dmadone(struct queue_entry *entry); | ||
1073 | void rt2x00lib_txdone(struct queue_entry *entry, | 1074 | void rt2x00lib_txdone(struct queue_entry *entry, |
1074 | struct txdone_entry_desc *txdesc); | 1075 | struct txdone_entry_desc *txdesc); |
1075 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); | 1076 | void 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 | } |
252 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | 252 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); |
253 | 253 | ||
254 | void rt2x00lib_dmadone(struct queue_entry *entry) | ||
255 | { | ||
256 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); | ||
257 | } | ||
258 | EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); | ||
259 | |||
254 | void rt2x00lib_txdone(struct queue_entry *entry, | 260 | void 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) | |||
746 | static void rt2x00queue_reset(struct data_queue *queue) | 746 | static 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 | */ |
410 | enum queue_index { | 412 | enum 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 | */ |
622 | static inline int rt2x00queue_timeout(struct data_queue *queue) | 624 | static 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 | */ | ||
634 | static 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 | } |
284 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | 289 | EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); |
285 | 290 | ||
286 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | 291 | static 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 | ||
340 | static 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 | |||
334 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | 348 | void 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 | } |
343 | EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | 359 | EXPORT_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. |