| From 4d5c9ea3313e410686855496f556d90e589ed2e2 Mon Sep 17 00:00:00 2001 |
| From: Viresh Kumar <viresh.kumar@linaro.org> |
| Date: Wed, 24 Apr 2013 17:12:56 +0530 |
| Subject: block: queue work on power efficient wq |
| |
| Block layer uses workqueues for multiple purposes. There is no real dependency |
| of scheduling these on the cpu which scheduled them. |
| |
| On a idle system, it is observed that and idle cpu wakes up many times just to |
| service this work. It would be better if we can schedule it on a cpu which the |
| scheduler believes to be the most appropriate one. |
| |
| This patch replaces normal workqueues with power efficient versions. |
| |
| Cc: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| (cherry picked from commit 695588f9454bdbc7c1a2fbb8a6bfdcfba6183348) |
| Signed-off-by: Mark Brown <broonie@linaro.org> |
| --- |
| block/blk-core.c | 3 ++- |
| block/blk-ioc.c | 3 ++- |
| block/genhd.c | 12 ++++++++---- |
| 3 files changed, 12 insertions(+), 6 deletions(-) |
| |
| --- a/block/blk-core.c |
| +++ b/block/blk-core.c |
| @@ -3191,7 +3191,8 @@ int __init blk_dev_init(void) |
| |
| /* used for unplugging and affects IO latency/throughput - HIGHPRI */ |
| kblockd_workqueue = alloc_workqueue("kblockd", |
| - WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); |
| + WQ_MEM_RECLAIM | WQ_HIGHPRI | |
| + WQ_POWER_EFFICIENT, 0); |
| if (!kblockd_workqueue) |
| panic("Failed to create kblockd\n"); |
| |
| --- a/block/blk-ioc.c |
| +++ b/block/blk-ioc.c |
| @@ -144,7 +144,8 @@ void put_io_context(struct io_context *i |
| if (atomic_long_dec_and_test(&ioc->refcount)) { |
| spin_lock_irqsave(&ioc->lock, flags); |
| if (!hlist_empty(&ioc->icq_list)) |
| - schedule_work(&ioc->release_work); |
| + queue_work(system_power_efficient_wq, |
| + &ioc->release_work); |
| else |
| free_ioc = true; |
| spin_unlock_irqrestore(&ioc->lock, flags); |
| --- a/block/genhd.c |
| +++ b/block/genhd.c |
| @@ -1489,9 +1489,11 @@ static void __disk_unblock_events(struct |
| intv = disk_events_poll_jiffies(disk); |
| set_timer_slack(&ev->dwork.timer, intv / 4); |
| if (check_now) |
| - queue_delayed_work(system_freezable_wq, &ev->dwork, 0); |
| + queue_delayed_work(system_freezable_power_efficient_wq, |
| + &ev->dwork, 0); |
| else if (intv) |
| - queue_delayed_work(system_freezable_wq, &ev->dwork, intv); |
| + queue_delayed_work(system_freezable_power_efficient_wq, |
| + &ev->dwork, intv); |
| out_unlock: |
| spin_unlock_irqrestore(&ev->lock, flags); |
| } |
| @@ -1534,7 +1536,8 @@ void disk_flush_events(struct gendisk *d |
| spin_lock_irq(&ev->lock); |
| ev->clearing |= mask; |
| if (!ev->block) |
| - mod_delayed_work(system_freezable_wq, &ev->dwork, 0); |
| + mod_delayed_work(system_freezable_power_efficient_wq, |
| + &ev->dwork, 0); |
| spin_unlock_irq(&ev->lock); |
| } |
| |
| @@ -1627,7 +1630,8 @@ static void disk_check_events(struct dis |
| |
| intv = disk_events_poll_jiffies(disk); |
| if (!ev->block && intv) |
| - queue_delayed_work(system_freezable_wq, &ev->dwork, intv); |
| + queue_delayed_work(system_freezable_power_efficient_wq, |
| + &ev->dwork, intv); |
| |
| spin_unlock_irq(&ev->lock); |
| |