diff options
-rw-r--r-- | include/linux/cpu.h | 5 | ||||
-rw-r--r-- | kernel/workqueue.c | 38 |
2 files changed, 40 insertions, 3 deletions
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 5f09323ee88..42af2eae880 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -66,8 +66,9 @@ enum { | |||
66 | /* migration should happen before other stuff but after perf */ | 66 | /* migration should happen before other stuff but after perf */ |
67 | CPU_PRI_PERF = 20, | 67 | CPU_PRI_PERF = 20, |
68 | CPU_PRI_MIGRATION = 10, | 68 | CPU_PRI_MIGRATION = 10, |
69 | /* prepare workqueues for other notifiers */ | 69 | /* bring up workqueues before normal notifiers and down after */ |
70 | CPU_PRI_WORKQUEUE = 5, | 70 | CPU_PRI_WORKQUEUE_UP = 5, |
71 | CPU_PRI_WORKQUEUE_DOWN = -5, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | #ifdef CONFIG_SMP | 74 | #ifdef CONFIG_SMP |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index ee1845b8d69..e88c924fc6b 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -3561,6 +3561,41 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, | |||
3561 | return notifier_from_errno(0); | 3561 | return notifier_from_errno(0); |
3562 | } | 3562 | } |
3563 | 3563 | ||
3564 | /* | ||
3565 | * Workqueues should be brought up before normal priority CPU notifiers. | ||
3566 | * This will be registered high priority CPU notifier. | ||
3567 | */ | ||
3568 | static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, | ||
3569 | unsigned long action, | ||
3570 | void *hcpu) | ||
3571 | { | ||
3572 | switch (action & ~CPU_TASKS_FROZEN) { | ||
3573 | case CPU_UP_PREPARE: | ||
3574 | case CPU_UP_CANCELED: | ||
3575 | case CPU_DOWN_FAILED: | ||
3576 | case CPU_ONLINE: | ||
3577 | return workqueue_cpu_callback(nfb, action, hcpu); | ||
3578 | } | ||
3579 | return NOTIFY_OK; | ||
3580 | } | ||
3581 | |||
3582 | /* | ||
3583 | * Workqueues should be brought down after normal priority CPU notifiers. | ||
3584 | * This will be registered as low priority CPU notifier. | ||
3585 | */ | ||
3586 | static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, | ||
3587 | unsigned long action, | ||
3588 | void *hcpu) | ||
3589 | { | ||
3590 | switch (action & ~CPU_TASKS_FROZEN) { | ||
3591 | case CPU_DOWN_PREPARE: | ||
3592 | case CPU_DYING: | ||
3593 | case CPU_POST_DEAD: | ||
3594 | return workqueue_cpu_callback(nfb, action, hcpu); | ||
3595 | } | ||
3596 | return NOTIFY_OK; | ||
3597 | } | ||
3598 | |||
3564 | #ifdef CONFIG_SMP | 3599 | #ifdef CONFIG_SMP |
3565 | 3600 | ||
3566 | struct work_for_cpu { | 3601 | struct work_for_cpu { |
@@ -3754,7 +3789,8 @@ static int __init init_workqueues(void) | |||
3754 | unsigned int cpu; | 3789 | unsigned int cpu; |
3755 | int i; | 3790 | int i; |
3756 | 3791 | ||
3757 | cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); | 3792 | cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); |
3793 | cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); | ||
3758 | 3794 | ||
3759 | /* initialize gcwqs */ | 3795 | /* initialize gcwqs */ |
3760 | for_each_gcwq_cpu(cpu) { | 3796 | for_each_gcwq_cpu(cpu) { |