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/rt2x00usb.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/rt2x00usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index fca29ae57e71..cd80eec5ff51 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -366,7 +366,7 @@ void rt2x00usb_kick_queue(struct data_queue *queue) | |||
366 | } | 366 | } |
367 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); | 367 | EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); |
368 | 368 | ||
369 | static void rt2x00usb_kill_entry(struct queue_entry *entry) | 369 | static void rt2x00usb_flush_entry(struct queue_entry *entry) |
370 | { | 370 | { |
371 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 371 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
372 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 372 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
@@ -385,37 +385,61 @@ static void rt2x00usb_kill_entry(struct queue_entry *entry) | |||
385 | usb_kill_urb(bcn_priv->guardian_urb); | 385 | usb_kill_urb(bcn_priv->guardian_urb); |
386 | } | 386 | } |
387 | 387 | ||
388 | void rt2x00usb_stop_queue(struct data_queue *queue) | 388 | void rt2x00usb_flush_queue(struct data_queue *queue) |
389 | { | 389 | { |
390 | struct work_struct *completion; | ||
391 | unsigned int i; | ||
392 | |||
390 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, | 393 | rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, |
391 | rt2x00usb_kill_entry); | 394 | rt2x00usb_flush_entry); |
395 | |||
396 | /* | ||
397 | * Obtain the queue completion handler | ||
398 | */ | ||
399 | switch (queue->qid) { | ||
400 | case QID_AC_BE: | ||
401 | case QID_AC_BK: | ||
402 | case QID_AC_VI: | ||
403 | case QID_AC_VO: | ||
404 | completion = &queue->rt2x00dev->txdone_work; | ||
405 | break; | ||
406 | case QID_RX: | ||
407 | completion = &queue->rt2x00dev->rxdone_work; | ||
408 | break; | ||
409 | default: | ||
410 | return; | ||
411 | } | ||
412 | |||
413 | for (i = 0; i < 20; i++) { | ||
414 | /* | ||
415 | * Check if the driver is already done, otherwise we | ||
416 | * have to sleep a little while to give the driver/hw | ||
417 | * the oppurtunity to complete interrupt process itself. | ||
418 | */ | ||
419 | if (rt2x00queue_empty(queue)) | ||
420 | break; | ||
421 | |||
422 | /* | ||
423 | * Schedule the completion handler manually, when this | ||
424 | * worker function runs, it should cleanup the queue. | ||
425 | */ | ||
426 | ieee80211_queue_work(queue->rt2x00dev->hw, completion); | ||
427 | |||
428 | /* | ||
429 | * Wait for a little while to give the driver | ||
430 | * the oppurtunity to recover itself. | ||
431 | */ | ||
432 | msleep(10); | ||
433 | } | ||
392 | } | 434 | } |
393 | EXPORT_SYMBOL_GPL(rt2x00usb_stop_queue); | 435 | EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue); |
394 | 436 | ||
395 | static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) | 437 | static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) |
396 | { | 438 | { |
397 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | ||
398 | |||
399 | WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," | 439 | WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," |
400 | " invoke forced forced reset\n", queue->qid); | 440 | " invoke forced forced reset\n", queue->qid); |
401 | 441 | ||
402 | /* | 442 | rt2x00queue_flush_queue(queue, true); |
403 | * Temporarily disable the TX queue, this will force mac80211 | ||
404 | * to use the other queues until this queue has been restored. | ||
405 | */ | ||
406 | rt2x00queue_stop_queue(queue); | ||
407 | |||
408 | /* | ||
409 | * In case that a driver has overriden the txdone_work | ||
410 | * function, we invoke the TX done through there. | ||
411 | */ | ||
412 | rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); | ||
413 | |||
414 | /* | ||
415 | * The queue has been reset, and mac80211 is allowed to use the | ||
416 | * queue again. | ||
417 | */ | ||
418 | rt2x00queue_start_queue(queue); | ||
419 | } | 443 | } |
420 | 444 | ||
421 | static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | 445 | static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) |