aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2010-12-13 06:35:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-13 15:23:35 -0500
commit5be65609fec2e331c7d804471be3d59089a30d98 (patch)
tree6c6967c7835d6ec3a8ce79c2c9b84bf95aefca31 /drivers/net/wireless/rt2x00/rt2x00queue.c
parent0b7fde54f94979edc67bbf86b5adba702ebfefe8 (diff)
rt2x00: Add "flush" queue command
Add a new command to the queue handlers: "flush", this moves the flush() callback from mac80211 into rt2x00queue and adds support for flushing the RX queue as well. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Acked-by: Helmut Schaa <helmut.schaa@googlemail.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.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 558965fb41b3..313a8faa5fa4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -780,6 +780,12 @@ void rt2x00queue_unpause_queue(struct data_queue *queue)
780 */ 780 */
781 ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); 781 ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
782 break; 782 break;
783 case QID_RX:
784 /*
785 * For RX we need to kick the queue now in order to
786 * receive frames.
787 */
788 queue->rt2x00dev->ops->lib->kick_queue(queue);
783 default: 789 default:
784 break; 790 break;
785 } 791 }
@@ -823,6 +829,74 @@ void rt2x00queue_stop_queue(struct data_queue *queue)
823} 829}
824EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); 830EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
825 831
832void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
833{
834 unsigned int i;
835 bool started;
836 bool tx_queue =
837 (queue->qid == QID_AC_BE) ||
838 (queue->qid == QID_AC_BK) ||
839 (queue->qid == QID_AC_VI) ||
840 (queue->qid == QID_AC_VO);
841
842 mutex_lock(&queue->status_lock);
843
844 /*
845 * If the queue has been started, we must stop it temporarily
846 * to prevent any new frames to be queued on the device. If
847 * we are not dropping the pending frames, the queue must
848 * only be stopped in the software and not the hardware,
849 * otherwise the queue will never become empty on its own.
850 */
851 started = test_bit(QUEUE_STARTED, &queue->flags);
852 if (started) {
853 /*
854 * Pause the queue
855 */
856 rt2x00queue_pause_queue(queue);
857
858 /*
859 * If we are not supposed to drop any pending
860 * frames, this means we must force a start (=kick)
861 * to the queue to make sure the hardware will
862 * start transmitting.
863 */
864 if (!drop && tx_queue)
865 queue->rt2x00dev->ops->lib->kick_queue(queue);
866 }
867
868 /*
869 * Check if driver supports flushing, we can only guarentee
870 * full support for flushing if the driver is able
871 * to cancel all pending frames (drop = true).
872 */
873 if (drop && queue->rt2x00dev->ops->lib->flush_queue)
874 queue->rt2x00dev->ops->lib->flush_queue(queue);
875
876 /*
877 * When we don't want to drop any frames, or when
878 * the driver doesn't fully flush the queue correcly,
879 * we must wait for the queue to become empty.
880 */
881 for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
882 msleep(10);
883
884 /*
885 * The queue flush has failed...
886 */
887 if (unlikely(!rt2x00queue_empty(queue)))
888 WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid);
889
890 /*
891 * Restore the queue to the previous status
892 */
893 if (started)
894 rt2x00queue_unpause_queue(queue);
895
896 mutex_unlock(&queue->status_lock);
897}
898EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue);
899
826void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) 900void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev)
827{ 901{
828 struct data_queue *queue; 902 struct data_queue *queue;
@@ -857,6 +931,17 @@ void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
857} 931}
858EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); 932EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues);
859 933
934void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop)
935{
936 struct data_queue *queue;
937
938 tx_queue_for_each(rt2x00dev, queue)
939 rt2x00queue_flush_queue(queue, drop);
940
941 rt2x00queue_flush_queue(rt2x00dev->rx, drop);
942}
943EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues);
944
860static void rt2x00queue_reset(struct data_queue *queue) 945static void rt2x00queue_reset(struct data_queue *queue)
861{ 946{
862 unsigned long irqflags; 947 unsigned long irqflags;