diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2010-12-13 06:35:40 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-13 15:23:35 -0500 |
commit | 5be65609fec2e331c7d804471be3d59089a30d98 (patch) | |
tree | 6c6967c7835d6ec3a8ce79c2c9b84bf95aefca31 /drivers/net/wireless/rt2x00/rt2x00queue.c | |
parent | 0b7fde54f94979edc67bbf86b5adba702ebfefe8 (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.c | 85 |
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 | } |
824 | EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); | 830 | EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); |
825 | 831 | ||
832 | void 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 | } | ||
898 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); | ||
899 | |||
826 | void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) | 900 | void 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 | } |
858 | EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); | 932 | EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); |
859 | 933 | ||
934 | void 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 | } | ||
943 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues); | ||
944 | |||
860 | static void rt2x00queue_reset(struct data_queue *queue) | 945 | static void rt2x00queue_reset(struct data_queue *queue) |
861 | { | 946 | { |
862 | unsigned long irqflags; | 947 | unsigned long irqflags; |