aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLan Tianyu <tianyu.lan@intel.com>2014-08-26 03:43:45 -0400
committerIngo Molnar <mingo@kernel.org>2014-09-24 09:02:06 -0400
commit2ed53c0d6cc99fc712f7c037e41d9ec4eb8d6b08 (patch)
tree228355b0039e02165301c4e97360140b05d5e2b1
parentf3670394c29ff3730638762c1760fd2f624e6d7b (diff)
x86/smpboot: Speed up suspend/resume by avoiding 100ms sleep for CPU offline during S3
With certain kernel configurations, CPU offline consumes more than 100ms during S3. It's a timing related issue: native_cpu_die() would occasionally fall into a 100ms sleep when the CPU idle loop thread marked the CPU state to DEAD too slowly. What native_cpu_die() does is that it polls the CPU state and waits for 100ms if CPU state hasn't been marked to DEAD. The 100ms sleep doesn't make sense and is purely historic. To avoid such long sleeping, this patch adds a 'struct completion' to each CPU, waits for the completion in native_cpu_die() and wakes up the completion when the CPU state is marked to DEAD. Tested on an Intel Xeon server with 48 cores, Ivybridge and on Haswell laptops. The CPU offlining cost on these machines is reduced from more than 100ms to less than 5ms. The system suspend time is reduced by 2.3s on the servers. Borislav and Prarit also helped to test the patch on an AMD machine and a few systems of various sizes and configurations (multi-socket, single-socket, no hyper threading, etc.). No issues were seen. Tested-by: Prarit Bhargava <prarit@redhat.com> Signed-off-by: Lan Tianyu <tianyu.lan@intel.com> Acked-by: Borislav Petkov <bp@suse.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: srostedt@redhat.com Cc: toshi.kani@hp.com Cc: imammedo@redhat.com Cc: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/1409039025-32310-1-git-send-email-tianyu.lan@intel.com [ Improved a few minor details in the code, cleaned up the changelog. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/smpboot.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 2d872e08fab9..fdbc5fce8b97 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -102,6 +102,8 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
102DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info); 102DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
103EXPORT_PER_CPU_SYMBOL(cpu_info); 103EXPORT_PER_CPU_SYMBOL(cpu_info);
104 104
105static DEFINE_PER_CPU(struct completion, die_complete);
106
105atomic_t init_deasserted; 107atomic_t init_deasserted;
106 108
107/* 109/*
@@ -1323,26 +1325,24 @@ int native_cpu_disable(void)
1323 return ret; 1325 return ret;
1324 1326
1325 clear_local_APIC(); 1327 clear_local_APIC();
1326 1328 init_completion(&per_cpu(die_complete, smp_processor_id()));
1327 cpu_disable_common(); 1329 cpu_disable_common();
1330
1328 return 0; 1331 return 0;
1329} 1332}
1330 1333
1331void native_cpu_die(unsigned int cpu) 1334void native_cpu_die(unsigned int cpu)
1332{ 1335{
1333 /* We don't do anything here: idle task is faking death itself. */ 1336 /* We don't do anything here: idle task is faking death itself. */
1334 unsigned int i; 1337 wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ);
1335 1338
1336 for (i = 0; i < 10; i++) { 1339 /* They ack this in play_dead() by setting CPU_DEAD */
1337 /* They ack this in play_dead by setting CPU_DEAD */ 1340 if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
1338 if (per_cpu(cpu_state, cpu) == CPU_DEAD) { 1341 if (system_state == SYSTEM_RUNNING)
1339 if (system_state == SYSTEM_RUNNING) 1342 pr_info("CPU %u is now offline\n", cpu);
1340 pr_info("CPU %u is now offline\n", cpu); 1343 } else {
1341 return; 1344 pr_err("CPU %u didn't die...\n", cpu);
1342 }
1343 msleep(100);
1344 } 1345 }
1345 pr_err("CPU %u didn't die...\n", cpu);
1346} 1346}
1347 1347
1348void play_dead_common(void) 1348void play_dead_common(void)
@@ -1354,6 +1354,7 @@ void play_dead_common(void)
1354 mb(); 1354 mb();
1355 /* Ack it */ 1355 /* Ack it */
1356 __this_cpu_write(cpu_state, CPU_DEAD); 1356 __this_cpu_write(cpu_state, CPU_DEAD);
1357 complete(&per_cpu(die_complete, smp_processor_id()));
1357 1358
1358 /* 1359 /*
1359 * With physical CPU hotplug, we should halt the cpu 1360 * With physical CPU hotplug, we should halt the cpu