diff options
author | Ivo van Doorn <IvDoorn@gmail.com> | 2011-01-30 07:24:05 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-01-31 15:06:25 -0500 |
commit | 0439f5367c8d8bb2ebaca8d7329f51f3148b2fb2 (patch) | |
tree | dee1b60792da49cd903266ec8daf90516c604c49 /drivers/net | |
parent | e1f4e808bb7a884d6563553c2c94cbdd901a16c7 (diff) |
rt2x00: Move TX/RX work into dedicated workqueue
The TX/RX work structures must be able to run independently
of other workqueues. This is because mac80211 might use
the flush() callback function from various context, which depends
on the TX/RX work to complete while the main thread is blocked
(until the the TX queues are empty).
This should reduce the number of 'Queue %d failed to flush' warnings.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00link.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 8 |
4 files changed, 25 insertions, 7 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7661e4f60ddc..39bc2faf1793 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -860,6 +860,13 @@ struct rt2x00_dev { | |||
860 | */ | 860 | */ |
861 | struct ieee80211_low_level_stats low_level_stats; | 861 | struct ieee80211_low_level_stats low_level_stats; |
862 | 862 | ||
863 | /** | ||
864 | * Work queue for all work which should not be placed | ||
865 | * on the mac80211 workqueue (because of dependencies | ||
866 | * between various work structures). | ||
867 | */ | ||
868 | struct workqueue_struct *workqueue; | ||
869 | |||
863 | /* | 870 | /* |
864 | * Scheduled work. | 871 | * Scheduled work. |
865 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 872 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e7162852ec34..9de9dbe94399 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -997,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
997 | BIT(NL80211_IFTYPE_WDS); | 997 | BIT(NL80211_IFTYPE_WDS); |
998 | 998 | ||
999 | /* | 999 | /* |
1000 | * Initialize configuration work. | 1000 | * Initialize work. |
1001 | */ | 1001 | */ |
1002 | rt2x00dev->workqueue = | ||
1003 | alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0); | ||
1004 | if (!rt2x00dev->workqueue) { | ||
1005 | retval = -ENOMEM; | ||
1006 | goto exit; | ||
1007 | } | ||
1008 | |||
1002 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 1009 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
1003 | 1010 | ||
1004 | /* | 1011 | /* |
@@ -1057,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1057 | cancel_work_sync(&rt2x00dev->intf_work); | 1064 | cancel_work_sync(&rt2x00dev->intf_work); |
1058 | cancel_work_sync(&rt2x00dev->rxdone_work); | 1065 | cancel_work_sync(&rt2x00dev->rxdone_work); |
1059 | cancel_work_sync(&rt2x00dev->txdone_work); | 1066 | cancel_work_sync(&rt2x00dev->txdone_work); |
1067 | destroy_workqueue(rt2x00dev->workqueue); | ||
1060 | 1068 | ||
1061 | /* | 1069 | /* |
1062 | * Free the tx status fifo. | 1070 | * Free the tx status fifo. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index bfda60eaf4ef..c975b0a12e95 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -417,7 +417,8 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) | |||
417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) | 417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) |
418 | return; | 418 | return; |
419 | 419 | ||
420 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 420 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
421 | &link->watchdog_work, WATCHDOG_INTERVAL); | ||
421 | } | 422 | } |
422 | 423 | ||
423 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) | 424 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) |
@@ -441,7 +442,9 @@ static void rt2x00link_watchdog(struct work_struct *work) | |||
441 | rt2x00dev->ops->lib->watchdog(rt2x00dev); | 442 | rt2x00dev->ops->lib->watchdog(rt2x00dev); |
442 | 443 | ||
443 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 444 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
444 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 445 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
446 | &link->watchdog_work, | ||
447 | WATCHDOG_INTERVAL); | ||
445 | } | 448 | } |
446 | 449 | ||
447 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 450 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 1a9937d5aff6..fbe735f5b352 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -227,7 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
227 | * Schedule the delayed work for reading the TX status | 227 | * Schedule the delayed work for reading the TX status |
228 | * from the device. | 228 | * from the device. |
229 | */ | 229 | */ |
230 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | 230 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
231 | } | 231 | } |
232 | 232 | ||
233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -320,7 +320,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
320 | * Schedule the delayed work for reading the RX status | 320 | * Schedule the delayed work for reading the RX status |
321 | * from the device. | 321 | * from the device. |
322 | */ | 322 | */ |
323 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); | 323 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
324 | } | 324 | } |
325 | 325 | ||
326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) |
@@ -429,7 +429,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) | |||
429 | * Schedule the completion handler manually, when this | 429 | * Schedule the completion handler manually, when this |
430 | * worker function runs, it should cleanup the queue. | 430 | * worker function runs, it should cleanup the queue. |
431 | */ | 431 | */ |
432 | ieee80211_queue_work(queue->rt2x00dev->hw, completion); | 432 | queue_work(queue->rt2x00dev->workqueue, completion); |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * Wait for a little while to give the driver | 435 | * Wait for a little while to give the driver |
@@ -453,7 +453,7 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | |||
453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," | 453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," |
454 | " invoke forced tx handler\n", queue->qid); | 454 | " invoke forced tx handler\n", queue->qid); |
455 | 455 | ||
456 | ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); | 456 | queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); |
457 | } | 457 | } |
458 | 458 | ||
459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | 459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) |