aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--kernel/time/tick-sched.c54
2 files changed, 17 insertions, 41 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82365dde00a8..887b29708447 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1916,8 +1916,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1916 nohz_full= [KNL,BOOT] 1916 nohz_full= [KNL,BOOT]
1917 In kernels built with CONFIG_NO_HZ_FULL=y, set 1917 In kernels built with CONFIG_NO_HZ_FULL=y, set
1918 the specified list of CPUs whose tick will be stopped 1918 the specified list of CPUs whose tick will be stopped
1919 whenever possible. You need to keep at least one online 1919 whenever possible. The boot CPU will be forced outside
1920 CPU outside the range to maintain the timekeeping. 1920 the range to maintain the timekeeping.
1921 1921
1922 noiotrap [SH] Disables trapped I/O port accesses. 1922 noiotrap [SH] Disables trapped I/O port accesses.
1923 1923
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 369b5769fc97..2bac5ea2c9af 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -158,11 +158,21 @@ int tick_nohz_full_cpu(int cpu)
158/* Parse the boot-time nohz CPU list from the kernel parameters. */ 158/* Parse the boot-time nohz CPU list from the kernel parameters. */
159static int __init tick_nohz_full_setup(char *str) 159static int __init tick_nohz_full_setup(char *str)
160{ 160{
161 int cpu;
162
161 alloc_bootmem_cpumask_var(&nohz_full_mask); 163 alloc_bootmem_cpumask_var(&nohz_full_mask);
162 if (cpulist_parse(str, nohz_full_mask) < 0) 164 if (cpulist_parse(str, nohz_full_mask) < 0) {
163 pr_warning("NOHZ: Incorrect nohz_full cpumask\n"); 165 pr_warning("NOHZ: Incorrect nohz_full cpumask\n");
164 else 166 return 1;
165 have_nohz_full_mask = true; 167 }
168
169 cpu = smp_processor_id();
170 if (cpumask_test_cpu(cpu, nohz_full_mask)) {
171 pr_warning("NO_HZ: Clearing %d from nohz_full range for timekeeping\n", cpu);
172 cpumask_clear_cpu(cpu, nohz_full_mask);
173 }
174 have_nohz_full_mask = true;
175
166 return 1; 176 return 1;
167} 177}
168__setup("nohz_full=", tick_nohz_full_setup); 178__setup("nohz_full=", tick_nohz_full_setup);
@@ -195,42 +205,8 @@ static char __initdata nohz_full_buf[NR_CPUS + 1];
195 205
196static int __init init_tick_nohz_full(void) 206static int __init init_tick_nohz_full(void)
197{ 207{
198 cpumask_var_t online_nohz; 208 if (have_nohz_full_mask)
199 int cpu; 209 cpu_notifier(tick_nohz_cpu_down_callback, 0);
200
201 if (!have_nohz_full_mask)
202 return 0;
203
204 cpu_notifier(tick_nohz_cpu_down_callback, 0);
205
206 if (!zalloc_cpumask_var(&online_nohz, GFP_KERNEL)) {
207 pr_warning("NO_HZ: Not enough memory to check full nohz mask\n");
208 return -ENOMEM;
209 }
210
211 /*
212 * CPUs can probably not be concurrently offlined on initcall time.
213 * But we are paranoid, aren't we?
214 */
215 get_online_cpus();
216
217 /* Ensure we keep a CPU outside the dynticks range for timekeeping */
218 cpumask_and(online_nohz, cpu_online_mask, nohz_full_mask);
219 if (cpumask_equal(online_nohz, cpu_online_mask)) {
220 pr_warning("NO_HZ: Must keep at least one online CPU "
221 "out of nohz_full range\n");
222 /*
223 * We know the current CPU doesn't have its tick stopped.
224 * Let's use it for the timekeeping duty.
225 */
226 preempt_disable();
227 cpu = smp_processor_id();
228 pr_warning("NO_HZ: Clearing %d from nohz_full range\n", cpu);
229 cpumask_clear_cpu(cpu, nohz_full_mask);
230 preempt_enable();
231 }
232 put_online_cpus();
233 free_cpumask_var(online_nohz);
234 210
235 cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), nohz_full_mask); 211 cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), nohz_full_mask);
236 pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf); 212 pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf);