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) { |
