diff options
author | Stanislaw Gruszka <stf_xl@wp.pl> | 2013-10-05 12:15:33 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-10-10 13:49:28 -0400 |
commit | fdbdd25c47ac1db04a161308dfb1060869eba982 (patch) | |
tree | 6dc88a9b1c9e4fbca723c822d99a40339f9cffee | |
parent | 733aec6a5bd39ba34ddd0568b7f7394aec2541fb (diff) |
rt2x00: do not pause queue on flush
Pausing queue on flush make no sense since txdone procedure un-pause
queue. Before flush procedure we have to assure queue is stopped,
i.e. on receive path h/w RX is disabled, on transmit path queue is
disabled in mac80211. That conditions are true except one function:
rt2x00usb_watchdog_tx_dma(), so add stop/start queue there.
Note stop/start queue can be racy if we do this from multiple paths,
but currently we stop TX queues only on rt2x00lib_disable_radio(),
which also stop/sync watchdog, hance we have no race condition.
Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 37 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 2 |
2 files changed, 8 insertions, 31 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6c8a33b6ee22..218e3206ce1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -1033,38 +1033,21 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); | |||
1033 | 1033 | ||
1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | 1034 | void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) |
1035 | { | 1035 | { |
1036 | bool started; | ||
1037 | bool tx_queue = | 1036 | bool tx_queue = |
1038 | (queue->qid == QID_AC_VO) || | 1037 | (queue->qid == QID_AC_VO) || |
1039 | (queue->qid == QID_AC_VI) || | 1038 | (queue->qid == QID_AC_VI) || |
1040 | (queue->qid == QID_AC_BE) || | 1039 | (queue->qid == QID_AC_BE) || |
1041 | (queue->qid == QID_AC_BK); | 1040 | (queue->qid == QID_AC_BK); |
1042 | 1041 | ||
1043 | mutex_lock(&queue->status_lock); | ||
1044 | 1042 | ||
1045 | /* | 1043 | /* |
1046 | * If the queue has been started, we must stop it temporarily | 1044 | * If we are not supposed to drop any pending |
1047 | * to prevent any new frames to be queued on the device. If | 1045 | * frames, this means we must force a start (=kick) |
1048 | * we are not dropping the pending frames, the queue must | 1046 | * to the queue to make sure the hardware will |
1049 | * only be stopped in the software and not the hardware, | 1047 | * start transmitting. |
1050 | * otherwise the queue will never become empty on its own. | ||
1051 | */ | 1048 | */ |
1052 | started = test_bit(QUEUE_STARTED, &queue->flags); | 1049 | if (!drop && tx_queue) |
1053 | if (started) { | 1050 | queue->rt2x00dev->ops->lib->kick_queue(queue); |
1054 | /* | ||
1055 | * Pause the queue | ||
1056 | */ | ||
1057 | rt2x00queue_pause_queue(queue); | ||
1058 | |||
1059 | /* | ||
1060 | * If we are not supposed to drop any pending | ||
1061 | * frames, this means we must force a start (=kick) | ||
1062 | * to the queue to make sure the hardware will | ||
1063 | * start transmitting. | ||
1064 | */ | ||
1065 | if (!drop && tx_queue) | ||
1066 | queue->rt2x00dev->ops->lib->kick_queue(queue); | ||
1067 | } | ||
1068 | 1051 | ||
1069 | /* | 1052 | /* |
1070 | * Check if driver supports flushing, if that is the case we can | 1053 | * Check if driver supports flushing, if that is the case we can |
@@ -1080,14 +1063,6 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | |||
1080 | if (unlikely(!rt2x00queue_empty(queue))) | 1063 | if (unlikely(!rt2x00queue_empty(queue))) |
1081 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", | 1064 | rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", |
1082 | queue->qid); | 1065 | queue->qid); |
1083 | |||
1084 | /* | ||
1085 | * Restore the queue to the previous status | ||
1086 | */ | ||
1087 | if (started) | ||
1088 | rt2x00queue_unpause_queue(queue); | ||
1089 | |||
1090 | mutex_unlock(&queue->status_lock); | ||
1091 | } | 1066 | } |
1092 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); | 1067 | EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); |
1093 | 1068 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 88289873c0cf..4e121627925d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -523,7 +523,9 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | |||
523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", | 523 | rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", |
524 | queue->qid); | 524 | queue->qid); |
525 | 525 | ||
526 | rt2x00queue_stop_queue(queue); | ||
526 | rt2x00queue_flush_queue(queue, true); | 527 | rt2x00queue_flush_queue(queue, true); |
528 | rt2x00queue_start_queue(queue); | ||
527 | } | 529 | } |
528 | 530 | ||
529 | static int rt2x00usb_dma_timeout(struct data_queue *queue) | 531 | static int rt2x00usb_dma_timeout(struct data_queue *queue) |