diff options
| author | Marcelo Tosatti <mtosatti@redhat.com> | 2013-03-04 18:10:32 -0500 |
|---|---|---|
| committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-03-04 18:10:32 -0500 |
| commit | ee2c25efdd46d7ed5605d6fe877bdf4b47a4ab2e (patch) | |
| tree | 35890281e93e667a8e262d76ef250025eb30a8c1 /arch/x86/kernel/process.c | |
| parent | 3ab66e8a455a4877889c65a848f2fb32be502f2c (diff) | |
| parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (diff) | |
Merge branch 'master' into queue
* master: (15791 commits)
Linux 3.9-rc1
btrfs/raid56: Add missing #include <linux/vmalloc.h>
fix compat_sys_rt_sigprocmask()
SUNRPC: One line comment fix
ext4: enable quotas before orphan cleanup
ext4: don't allow quota mount options when quota feature enabled
ext4: fix a warning from sparse check for ext4_dir_llseek
ext4: convert number of blocks to clusters properly
ext4: fix possible memory leak in ext4_remount()
jbd2: fix ERR_PTR dereference in jbd2__journal_start
metag: Provide dma_get_sgtable()
metag: prom.h: remove declaration of metag_dt_memblock_reserve()
metag: copy devicetree to non-init memory
metag: cleanup metag_ksyms.c includes
metag: move mm/init.c exports out of metag_ksyms.c
metag: move usercopy.c exports out of metag_ksyms.c
metag: move setup.c exports out of metag_ksyms.c
metag: move kick.c exports out of metag_ksyms.c
metag: move traps.c exports out of metag_ksyms.c
metag: move irq enable out of irqflags.h on SMP
...
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Conflicts:
arch/x86/kernel/kvmclock.c
Diffstat (limited to 'arch/x86/kernel/process.c')
| -rw-r--r-- | arch/x86/kernel/process.c | 122 |
1 files changed, 17 insertions, 105 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2ed787f15bf0..14ae10031ff0 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -268,13 +268,7 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
| 268 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; | 268 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; |
| 269 | EXPORT_SYMBOL(boot_option_idle_override); | 269 | EXPORT_SYMBOL(boot_option_idle_override); |
| 270 | 270 | ||
| 271 | /* | 271 | static void (*x86_idle)(void); |
| 272 | * Powermanagement idle function, if any.. | ||
| 273 | */ | ||
| 274 | void (*pm_idle)(void); | ||
| 275 | #ifdef CONFIG_APM_MODULE | ||
| 276 | EXPORT_SYMBOL(pm_idle); | ||
| 277 | #endif | ||
| 278 | 272 | ||
| 279 | #ifndef CONFIG_SMP | 273 | #ifndef CONFIG_SMP |
| 280 | static inline void play_dead(void) | 274 | static inline void play_dead(void) |
| @@ -351,7 +345,7 @@ void cpu_idle(void) | |||
| 351 | rcu_idle_enter(); | 345 | rcu_idle_enter(); |
| 352 | 346 | ||
| 353 | if (cpuidle_idle_call()) | 347 | if (cpuidle_idle_call()) |
| 354 | pm_idle(); | 348 | x86_idle(); |
| 355 | 349 | ||
| 356 | rcu_idle_exit(); | 350 | rcu_idle_exit(); |
| 357 | start_critical_timings(); | 351 | start_critical_timings(); |
| @@ -375,7 +369,6 @@ void cpu_idle(void) | |||
| 375 | */ | 369 | */ |
| 376 | void default_idle(void) | 370 | void default_idle(void) |
| 377 | { | 371 | { |
| 378 | trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id()); | ||
| 379 | trace_cpu_idle_rcuidle(1, smp_processor_id()); | 372 | trace_cpu_idle_rcuidle(1, smp_processor_id()); |
| 380 | current_thread_info()->status &= ~TS_POLLING; | 373 | current_thread_info()->status &= ~TS_POLLING; |
| 381 | /* | 374 | /* |
| @@ -389,21 +382,22 @@ void default_idle(void) | |||
| 389 | else | 382 | else |
| 390 | local_irq_enable(); | 383 | local_irq_enable(); |
| 391 | current_thread_info()->status |= TS_POLLING; | 384 | current_thread_info()->status |= TS_POLLING; |
| 392 | trace_power_end_rcuidle(smp_processor_id()); | ||
| 393 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | 385 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); |
| 394 | } | 386 | } |
| 395 | #ifdef CONFIG_APM_MODULE | 387 | #ifdef CONFIG_APM_MODULE |
| 396 | EXPORT_SYMBOL(default_idle); | 388 | EXPORT_SYMBOL(default_idle); |
| 397 | #endif | 389 | #endif |
| 398 | 390 | ||
| 399 | bool set_pm_idle_to_default(void) | 391 | #ifdef CONFIG_XEN |
| 392 | bool xen_set_default_idle(void) | ||
| 400 | { | 393 | { |
| 401 | bool ret = !!pm_idle; | 394 | bool ret = !!x86_idle; |
| 402 | 395 | ||
| 403 | pm_idle = default_idle; | 396 | x86_idle = default_idle; |
| 404 | 397 | ||
| 405 | return ret; | 398 | return ret; |
| 406 | } | 399 | } |
| 400 | #endif | ||
| 407 | void stop_this_cpu(void *dummy) | 401 | void stop_this_cpu(void *dummy) |
| 408 | { | 402 | { |
| 409 | local_irq_disable(); | 403 | local_irq_disable(); |
| @@ -413,31 +407,8 @@ void stop_this_cpu(void *dummy) | |||
| 413 | set_cpu_online(smp_processor_id(), false); | 407 | set_cpu_online(smp_processor_id(), false); |
| 414 | disable_local_APIC(); | 408 | disable_local_APIC(); |
| 415 | 409 | ||
| 416 | for (;;) { | 410 | for (;;) |
| 417 | if (hlt_works(smp_processor_id())) | 411 | halt(); |
| 418 | halt(); | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | /* Default MONITOR/MWAIT with no hints, used for default C1 state */ | ||
| 423 | static void mwait_idle(void) | ||
| 424 | { | ||
| 425 | if (!need_resched()) { | ||
| 426 | trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id()); | ||
| 427 | trace_cpu_idle_rcuidle(1, smp_processor_id()); | ||
| 428 | if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) | ||
| 429 | clflush((void *)¤t_thread_info()->flags); | ||
| 430 | |||
| 431 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
| 432 | smp_mb(); | ||
| 433 | if (!need_resched()) | ||
| 434 | __sti_mwait(0, 0); | ||
| 435 | else | ||
| 436 | local_irq_enable(); | ||
| 437 | trace_power_end_rcuidle(smp_processor_id()); | ||
| 438 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | ||
| 439 | } else | ||
| 440 | local_irq_enable(); | ||
| 441 | } | 412 | } |
| 442 | 413 | ||
| 443 | /* | 414 | /* |
| @@ -447,62 +418,13 @@ static void mwait_idle(void) | |||
| 447 | */ | 418 | */ |
| 448 | static void poll_idle(void) | 419 | static void poll_idle(void) |
| 449 | { | 420 | { |
| 450 | trace_power_start_rcuidle(POWER_CSTATE, 0, smp_processor_id()); | ||
| 451 | trace_cpu_idle_rcuidle(0, smp_processor_id()); | 421 | trace_cpu_idle_rcuidle(0, smp_processor_id()); |
| 452 | local_irq_enable(); | 422 | local_irq_enable(); |
| 453 | while (!need_resched()) | 423 | while (!need_resched()) |
| 454 | cpu_relax(); | 424 | cpu_relax(); |
| 455 | trace_power_end_rcuidle(smp_processor_id()); | ||
| 456 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); | 425 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); |
| 457 | } | 426 | } |
| 458 | 427 | ||
| 459 | /* | ||
| 460 | * mwait selection logic: | ||
| 461 | * | ||
| 462 | * It depends on the CPU. For AMD CPUs that support MWAIT this is | ||
| 463 | * wrong. Family 0x10 and 0x11 CPUs will enter C1 on HLT. Powersavings | ||
| 464 | * then depend on a clock divisor and current Pstate of the core. If | ||
| 465 | * all cores of a processor are in halt state (C1) the processor can | ||
| 466 | * enter the C1E (C1 enhanced) state. If mwait is used this will never | ||
| 467 | * happen. | ||
| 468 | * | ||
| 469 | * idle=mwait overrides this decision and forces the usage of mwait. | ||
| 470 | */ | ||
| 471 | |||
| 472 | #define MWAIT_INFO 0x05 | ||
| 473 | #define MWAIT_ECX_EXTENDED_INFO 0x01 | ||
| 474 | #define MWAIT_EDX_C1 0xf0 | ||
| 475 | |||
| 476 | int mwait_usable(const struct cpuinfo_x86 *c) | ||
| 477 | { | ||
| 478 | u32 eax, ebx, ecx, edx; | ||
| 479 | |||
| 480 | /* Use mwait if idle=mwait boot option is given */ | ||
| 481 | if (boot_option_idle_override == IDLE_FORCE_MWAIT) | ||
| 482 | return 1; | ||
| 483 | |||
| 484 | /* | ||
| 485 | * Any idle= boot option other than idle=mwait means that we must not | ||
| 486 | * use mwait. Eg: idle=halt or idle=poll or idle=nomwait | ||
| 487 | */ | ||
| 488 | if (boot_option_idle_override != IDLE_NO_OVERRIDE) | ||
| 489 | return 0; | ||
| 490 | |||
| 491 | if (c->cpuid_level < MWAIT_INFO) | ||
| 492 | return 0; | ||
| 493 | |||
| 494 | cpuid(MWAIT_INFO, &eax, &ebx, &ecx, &edx); | ||
| 495 | /* Check, whether EDX has extended info about MWAIT */ | ||
| 496 | if (!(ecx & MWAIT_ECX_EXTENDED_INFO)) | ||
| 497 | return 1; | ||
| 498 | |||
| 499 | /* | ||
| 500 | * edx enumeratios MONITOR/MWAIT extensions. Check, whether | ||
| 501 | * C1 supports MWAIT | ||
| 502 | */ | ||
| 503 | return (edx & MWAIT_EDX_C1); | ||
| 504 | } | ||
| 505 | |||
| 506 | bool amd_e400_c1e_detected; | 428 | bool amd_e400_c1e_detected; |
| 507 | EXPORT_SYMBOL(amd_e400_c1e_detected); | 429 | EXPORT_SYMBOL(amd_e400_c1e_detected); |
| 508 | 430 | ||
| @@ -567,31 +489,24 @@ static void amd_e400_idle(void) | |||
| 567 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | 489 | void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) |
| 568 | { | 490 | { |
| 569 | #ifdef CONFIG_SMP | 491 | #ifdef CONFIG_SMP |
| 570 | if (pm_idle == poll_idle && smp_num_siblings > 1) { | 492 | if (x86_idle == poll_idle && smp_num_siblings > 1) |
| 571 | pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n"); | 493 | pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n"); |
| 572 | } | ||
| 573 | #endif | 494 | #endif |
| 574 | if (pm_idle) | 495 | if (x86_idle) |
| 575 | return; | 496 | return; |
| 576 | 497 | ||
| 577 | if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) { | 498 | if (cpu_has_amd_erratum(amd_erratum_400)) { |
| 578 | /* | ||
| 579 | * One CPU supports mwait => All CPUs supports mwait | ||
| 580 | */ | ||
| 581 | pr_info("using mwait in idle threads\n"); | ||
| 582 | pm_idle = mwait_idle; | ||
| 583 | } else if (cpu_has_amd_erratum(amd_erratum_400)) { | ||
| 584 | /* E400: APIC timer interrupt does not wake up CPU from C1e */ | 499 | /* E400: APIC timer interrupt does not wake up CPU from C1e */ |
| 585 | pr_info("using AMD E400 aware idle routine\n"); | 500 | pr_info("using AMD E400 aware idle routine\n"); |
| 586 | pm_idle = amd_e400_idle; | 501 | x86_idle = amd_e400_idle; |
| 587 | } else | 502 | } else |
| 588 | pm_idle = default_idle; | 503 | x86_idle = default_idle; |
| 589 | } | 504 | } |
| 590 | 505 | ||
| 591 | void __init init_amd_e400_c1e_mask(void) | 506 | void __init init_amd_e400_c1e_mask(void) |
| 592 | { | 507 | { |
| 593 | /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */ | 508 | /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */ |
| 594 | if (pm_idle == amd_e400_idle) | 509 | if (x86_idle == amd_e400_idle) |
| 595 | zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); | 510 | zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL); |
| 596 | } | 511 | } |
| 597 | 512 | ||
| @@ -602,11 +517,8 @@ static int __init idle_setup(char *str) | |||
| 602 | 517 | ||
| 603 | if (!strcmp(str, "poll")) { | 518 | if (!strcmp(str, "poll")) { |
| 604 | pr_info("using polling idle threads\n"); | 519 | pr_info("using polling idle threads\n"); |
| 605 | pm_idle = poll_idle; | 520 | x86_idle = poll_idle; |
| 606 | boot_option_idle_override = IDLE_POLL; | 521 | boot_option_idle_override = IDLE_POLL; |
| 607 | } else if (!strcmp(str, "mwait")) { | ||
| 608 | boot_option_idle_override = IDLE_FORCE_MWAIT; | ||
| 609 | WARN_ONCE(1, "\"idle=mwait\" will be removed in 2012\n"); | ||
| 610 | } else if (!strcmp(str, "halt")) { | 522 | } else if (!strcmp(str, "halt")) { |
| 611 | /* | 523 | /* |
| 612 | * When the boot option of idle=halt is added, halt is | 524 | * When the boot option of idle=halt is added, halt is |
| @@ -615,7 +527,7 @@ static int __init idle_setup(char *str) | |||
| 615 | * To continue to load the CPU idle driver, don't touch | 527 | * To continue to load the CPU idle driver, don't touch |
| 616 | * the boot_option_idle_override. | 528 | * the boot_option_idle_override. |
| 617 | */ | 529 | */ |
| 618 | pm_idle = default_idle; | 530 | x86_idle = default_idle; |
| 619 | boot_option_idle_override = IDLE_HALT; | 531 | boot_option_idle_override = IDLE_HALT; |
| 620 | } else if (!strcmp(str, "nomwait")) { | 532 | } else if (!strcmp(str, "nomwait")) { |
| 621 | /* | 533 | /* |
