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 2e9b9ebbeb78..ce7a074f2519 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -73,8 +73,9 @@ enum { | |||
73 | /* migration should happen before other stuff but after perf */ | 73 | /* migration should happen before other stuff but after perf */ |
74 | CPU_PRI_PERF = 20, | 74 | CPU_PRI_PERF = 20, |
75 | CPU_PRI_MIGRATION = 10, | 75 | CPU_PRI_MIGRATION = 10, |
76 | /* prepare workqueues for other notifiers */ | 76 | /* bring up workqueues before normal notifiers and down after */ |
77 | CPU_PRI_WORKQUEUE = 5, | 77 | CPU_PRI_WORKQUEUE_UP = 5, |
78 | CPU_PRI_WORKQUEUE_DOWN = -5, | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ | 81 | #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4fa9e3552f1e..f59b7fd26e26 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -3644,6 +3644,41 @@ err_destroy: | |||
3644 | return NOTIFY_BAD; | 3644 | return NOTIFY_BAD; |
3645 | } | 3645 | } |
3646 | 3646 | ||
3647 | /* | ||
3648 | * Workqueues should be brought up before normal priority CPU notifiers. | ||
3649 | * This will be registered high priority CPU notifier. | ||
3650 | */ | ||
3651 | static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, | ||
3652 | unsigned long action, | ||
3653 | void *hcpu) | ||
3654 | { | ||
3655 | switch (action & ~CPU_TASKS_FROZEN) { | ||
3656 | case CPU_UP_PREPARE: | ||
3657 | case CPU_UP_CANCELED: | ||
3658 | case CPU_DOWN_FAILED: | ||
3659 | case CPU_ONLINE: | ||
3660 | return workqueue_cpu_callback(nfb, action, hcpu); | ||
3661 | } | ||
3662 | return NOTIFY_OK; | ||
3663 | } | ||
3664 | |||
3665 | /* | ||
3666 | * Workqueues should be brought down after normal priority CPU notifiers. | ||
3667 | * This will be registered as low priority CPU notifier. | ||
3668 | */ | ||
3669 | static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, | ||
3670 | unsigned long action, | ||
3671 | void *hcpu) | ||
3672 | { | ||
3673 | switch (action & ~CPU_TASKS_FROZEN) { | ||
3674 | case CPU_DOWN_PREPARE: | ||
3675 | case CPU_DYING: | ||
3676 | case CPU_POST_DEAD: | ||
3677 | return workqueue_cpu_callback(nfb, action, hcpu); | ||
3678 | } | ||
3679 | return NOTIFY_OK; | ||
3680 | } | ||
3681 | |||
3647 | #ifdef CONFIG_SMP | 3682 | #ifdef CONFIG_SMP |
3648 | 3683 | ||
3649 | struct work_for_cpu { | 3684 | struct work_for_cpu { |
@@ -3839,7 +3874,8 @@ static int __init init_workqueues(void) | |||
3839 | unsigned int cpu; | 3874 | unsigned int cpu; |
3840 | int i; | 3875 | int i; |
3841 | 3876 | ||
3842 | cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); | 3877 | cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); |
3878 | cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); | ||
3843 | 3879 | ||
3844 | /* initialize gcwqs */ | 3880 | /* initialize gcwqs */ |
3845 | for_each_gcwq_cpu(cpu) { | 3881 | for_each_gcwq_cpu(cpu) { |