Commit 152a5992 authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville

rt2x00: Decrease association time for USB devices

When powersaving is enabled, assocaition times are very high
(for WPA2 networks, the time can easily be around the 3 seconds).

This is caused, because the flushing of the queues takes
too much time. Without the flushing callback mac80211 assumes
a timeout of 100ms while scanning. Limit all flush waiting
loops to the same maximum.

We can apply this maximum by passing the drop status to the
driver, which makes sure the driver performs extra actions
during the waiting for the queue to become empty.

After these changes, association times fall within the
healthy range of ~0.6 seconds with powersaving enabled.
The difference between association time between powersaving
enabled and disabled is now only ~0.1 second (which can also
be due to the measuring method).
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Acked-by: default avatarGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f0187a19
...@@ -1740,6 +1740,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { ...@@ -1740,6 +1740,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.start_queue = rt2400pci_start_queue, .start_queue = rt2400pci_start_queue,
.kick_queue = rt2400pci_kick_queue, .kick_queue = rt2400pci_kick_queue,
.stop_queue = rt2400pci_stop_queue, .stop_queue = rt2400pci_stop_queue,
.flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2400pci_write_tx_desc, .write_tx_desc = rt2400pci_write_tx_desc,
.write_beacon = rt2400pci_write_beacon, .write_beacon = rt2400pci_write_beacon,
.fill_rxdone = rt2400pci_fill_rxdone, .fill_rxdone = rt2400pci_fill_rxdone,
......
...@@ -2033,6 +2033,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { ...@@ -2033,6 +2033,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.start_queue = rt2500pci_start_queue, .start_queue = rt2500pci_start_queue,
.kick_queue = rt2500pci_kick_queue, .kick_queue = rt2500pci_kick_queue,
.stop_queue = rt2500pci_stop_queue, .stop_queue = rt2500pci_stop_queue,
.flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2500pci_write_tx_desc, .write_tx_desc = rt2500pci_write_tx_desc,
.write_beacon = rt2500pci_write_beacon, .write_beacon = rt2500pci_write_beacon,
.fill_rxdone = rt2500pci_fill_rxdone, .fill_rxdone = rt2500pci_fill_rxdone,
......
...@@ -1057,6 +1057,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { ...@@ -1057,6 +1057,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.start_queue = rt2800pci_start_queue, .start_queue = rt2800pci_start_queue,
.kick_queue = rt2800pci_kick_queue, .kick_queue = rt2800pci_kick_queue,
.stop_queue = rt2800pci_stop_queue, .stop_queue = rt2800pci_stop_queue,
.flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt2800pci_write_tx_desc, .write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2800_write_tx_data, .write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon, .write_beacon = rt2800_write_beacon,
......
...@@ -571,7 +571,7 @@ struct rt2x00lib_ops { ...@@ -571,7 +571,7 @@ struct rt2x00lib_ops {
void (*start_queue) (struct data_queue *queue); void (*start_queue) (struct data_queue *queue);
void (*kick_queue) (struct data_queue *queue); void (*kick_queue) (struct data_queue *queue);
void (*stop_queue) (struct data_queue *queue); void (*stop_queue) (struct data_queue *queue);
void (*flush_queue) (struct data_queue *queue); void (*flush_queue) (struct data_queue *queue, bool drop);
void (*tx_dma_done) (struct queue_entry *entry); void (*tx_dma_done) (struct queue_entry *entry);
/* /*
......
...@@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) ...@@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
} }
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
{
unsigned int i;
for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
msleep(10);
}
EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
/* /*
* Device initialization handlers. * Device initialization handlers.
*/ */
......
...@@ -107,6 +107,16 @@ struct queue_entry_priv_pci { ...@@ -107,6 +107,16 @@ struct queue_entry_priv_pci {
*/ */
bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00pci_flush_queue - Flush data queue
* @queue: Data queue to stop
* @drop: True to drop all pending frames.
*
* This will wait for a maximum of 100ms, waiting for the queues
* to become empty.
*/
void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
/* /*
* Device initialization handlers. * Device initialization handlers.
*/ */
......
...@@ -849,7 +849,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); ...@@ -849,7 +849,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
{ {
unsigned int i;
bool started; bool started;
bool tx_queue = bool tx_queue =
(queue->qid == QID_AC_VO) || (queue->qid == QID_AC_VO) ||
...@@ -884,20 +883,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) ...@@ -884,20 +883,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
} }
/* /*
* Check if driver supports flushing, we can only guarentee * Check if driver supports flushing, if that is the case we can
* full support for flushing if the driver is able * defer the flushing to the driver. Otherwise we must use the
* to cancel all pending frames (drop = true). * alternative which just waits for the queue to become empty.
*/
if (drop && queue->rt2x00dev->ops->lib->flush_queue)
queue->rt2x00dev->ops->lib->flush_queue(queue);
/*
* When we don't want to drop any frames, or when
* the driver doesn't fully flush the queue correcly,
* we must wait for the queue to become empty.
*/ */
for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) if (likely(queue->rt2x00dev->ops->lib->flush_queue))
msleep(10); queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
/* /*
* The queue flush has failed... * The queue flush has failed...
......
...@@ -458,13 +458,14 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) ...@@ -458,13 +458,14 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
return false; return false;
} }
void rt2x00usb_flush_queue(struct data_queue *queue) void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
{ {
struct work_struct *completion; struct work_struct *completion;
unsigned int i; unsigned int i;
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, if (drop)
rt2x00usb_flush_entry); rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
rt2x00usb_flush_entry);
/* /*
* Obtain the queue completion handler * Obtain the queue completion handler
...@@ -483,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) ...@@ -483,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
return; return;
} }
for (i = 0; i < 20; i++) { for (i = 0; i < 10; i++) {
/* /*
* Check if the driver is already done, otherwise we * Check if the driver is already done, otherwise we
* have to sleep a little while to give the driver/hw * have to sleep a little while to give the driver/hw
......
...@@ -404,11 +404,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue); ...@@ -404,11 +404,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue);
/** /**
* rt2x00usb_flush_queue - Flush data queue * rt2x00usb_flush_queue - Flush data queue
* @queue: Data queue to stop * @queue: Data queue to stop
* @drop: True to drop all pending frames.
* *
* This will walk through all entries of the queue and kill all * This will walk through all entries of the queue and will optionally
* URB's which were send to the device. * kill all URB's which were send to the device, or at least wait until
* they have been returned from the device..
*/ */
void rt2x00usb_flush_queue(struct data_queue *queue); void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
/** /**
* rt2x00usb_watchdog - Watchdog for USB communication * rt2x00usb_watchdog - Watchdog for USB communication
......
...@@ -3003,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { ...@@ -3003,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.start_queue = rt61pci_start_queue, .start_queue = rt61pci_start_queue,
.kick_queue = rt61pci_kick_queue, .kick_queue = rt61pci_kick_queue,
.stop_queue = rt61pci_stop_queue, .stop_queue = rt61pci_stop_queue,
.flush_queue = rt2x00pci_flush_queue,
.write_tx_desc = rt61pci_write_tx_desc, .write_tx_desc = rt61pci_write_tx_desc,
.write_beacon = rt61pci_write_beacon, .write_beacon = rt61pci_write_beacon,
.clear_beacon = rt61pci_clear_beacon, .clear_beacon = rt61pci_clear_beacon,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment