aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2010-08-23 13:54:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-25 14:34:54 -0400
commit5eb7efe8a4807d98a277280e1317e5094eedfb6b (patch)
tree124a1a599ff718cfd84bb441202fe251f65bda19 /drivers/net/wireless/rt2x00/rt2x00queue.c
parentee1e755f84dfd5d482076c642fac830aafdc482b (diff)
rt2x00: Move direct access to queue->entries to rt2x00queue.c
All access to queue->entries through the Q_INDEX/Q_INDEX_DONE variables must be done using spinlock protection. It is best to manage this completely from rt2x00queue.c. For safely looping through all entries in the queue, the function rt2x00queue_for_each_entry is added which will walk from from a index range in a safe manner. This also fixes rt2x00usb which walked the entries list from 0 to length to kill each entry (killing entries must be done from Q_INDEX_DONE to Q_INDEX to enforce TX status reporting to occur in the correct order. 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/rt2x00queue.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 189eaf72967e..7fb9b6179af1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -625,6 +625,51 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
625 return 0; 625 return 0;
626} 626}
627 627
628void rt2x00queue_for_each_entry(struct data_queue *queue,
629 enum queue_index start,
630 enum queue_index end,
631 void (*fn)(struct queue_entry *entry))
632{
633 unsigned long irqflags;
634 unsigned int index_start;
635 unsigned int index_end;
636 unsigned int i;
637
638 if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
639 ERROR(queue->rt2x00dev,
640 "Entry requested from invalid index range (%d - %d)\n",
641 start, end);
642 return;
643 }
644
645 /*
646 * Only protect the range we are going to loop over,
647 * if during our loop a extra entry is set to pending
648 * it should not be kicked during this run, since it
649 * is part of another TX operation.
650 */
651 spin_lock_irqsave(&queue->lock, irqflags);
652 index_start = queue->index[start];
653 index_end = queue->index[end];
654 spin_unlock_irqrestore(&queue->lock, irqflags);
655
656 /*
657 * Start from the TX done pointer, this guarentees that we will
658 * send out all frames in the correct order.
659 */
660 if (index_start < index_end) {
661 for (i = index_start; i < index_end; i++)
662 fn(&queue->entries[i]);
663 } else {
664 for (i = index_start; i < queue->limit; i++)
665 fn(&queue->entries[i]);
666
667 for (i = 0; i < index_end; i++)
668 fn(&queue->entries[i]);
669 }
670}
671EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
672
628struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, 673struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
629 const enum data_queue_qid queue) 674 const enum data_queue_qid queue)
630{ 675{