Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull SMP/hotplug changes from Ingo Molnar:
 "This is a pretty large, multi-arch series unifying and generalizing
  the various disjunct pieces of idle routines that architectures have
  historically copied from each other and have grown in random, wildly
  inconsistent and sometimes buggy directions:

   101 files changed, 455 insertions(+), 1328 deletions(-)

  this went through a number of review and test iterations before it was
  committed, it was tested on various architectures, was exposed to
  linux-next for quite some time - nevertheless it might cause problems
  on architectures that don't read the mailing lists and don't regularly
  test linux-next.

  This cat herding excercise was motivated by the -rt kernel, and was
  brought to you by Thomas "the Whip" Gleixner."

* 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (40 commits)
  idle: Remove GENERIC_IDLE_LOOP config switch
  um: Use generic idle loop
  ia64: Make sure interrupts enabled when we "safe_halt()"
  sparc: Use generic idle loop
  idle: Remove unused ARCH_HAS_DEFAULT_IDLE
  bfin: Fix typo in arch_cpu_idle()
  xtensa: Use generic idle loop
  x86: Use generic idle loop
  unicore: Use generic idle loop
  tile: Use generic idle loop
  tile: Enter idle with preemption disabled
  sh: Use generic idle loop
  score: Use generic idle loop
  s390: Use generic idle loop
  powerpc: Use generic idle loop
  parisc: Use generic idle loop
  openrisc: Use generic idle loop
  mn10300: Use generic idle loop
  mips: Use generic idle loop
  microblaze: Use generic idle loop
  ...
This commit is contained in:
Linus Torvalds
2013-04-30 07:50:17 -07:00
101 changed files with 461 additions and 1334 deletions

View File

@@ -89,6 +89,7 @@ static inline bool arch_irqs_disabled(void)
static inline void arch_safe_halt(void)
{
arch_local_irq_enable();
ia64_pal_halt_light(); /* PAL_HALT_LIGHT */
}

View File

@@ -131,8 +131,6 @@ struct thread_info {
#define TS_POLLING 1 /* true if in idle loop and not sleeping */
#define TS_RESTORE_SIGMASK 2 /* restore signal mask in do_signal() */
#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
#ifndef __ASSEMBLY__
#define HAVE_SET_RESTORE_SIGMASK 1
static inline void set_restore_sigmask(void)

View File

@@ -42,6 +42,7 @@
#include <linux/completion.h>
#include <linux/tracehook.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <asm/errno.h>
#include <asm/intrinsics.h>
@@ -1322,8 +1323,6 @@ out:
}
EXPORT_SYMBOL(pfm_unregister_buffer_fmt);
extern void update_pal_halt_status(int);
static int
pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
{
@@ -1371,9 +1370,9 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
cpu));
/*
* disable default_idle() to go to PAL_HALT
* Force idle() into poll mode
*/
update_pal_halt_status(0);
cpu_idle_poll_ctrl(true);
UNLOCK_PFS(flags);
@@ -1430,11 +1429,8 @@ pfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu)
is_syswide,
cpu));
/*
* if possible, enable default_idle() to go into PAL_HALT
*/
if (pfm_sessions.pfs_task_sessions == 0 && pfm_sessions.pfs_sys_sessions == 0)
update_pal_halt_status(1);
/* Undo forced polling. Last session reenables pal_halt */
cpu_idle_poll_ctrl(false);
UNLOCK_PFS(flags);

View File

@@ -209,41 +209,13 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
local_irq_disable(); /* force interrupt disable */
}
static int pal_halt = 1;
static int can_do_pal_halt = 1;
static int __init nohalt_setup(char * str)
{
pal_halt = can_do_pal_halt = 0;
cpu_idle_poll_ctrl(true);
return 1;
}
__setup("nohalt", nohalt_setup);
void
update_pal_halt_status(int status)
{
can_do_pal_halt = pal_halt && status;
}
/*
* We use this if we don't have any better idle routine..
*/
void
default_idle (void)
{
local_irq_enable();
while (!need_resched()) {
if (can_do_pal_halt) {
local_irq_disable();
if (!need_resched()) {
safe_halt();
}
local_irq_enable();
} else
cpu_relax();
}
}
#ifdef CONFIG_HOTPLUG_CPU
/* We don't actually take CPU down, just spin without interrupts. */
static inline void play_dead(void)
@@ -270,47 +242,29 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
void __attribute__((noreturn))
cpu_idle (void)
void arch_cpu_idle_dead(void)
{
play_dead();
}
void arch_cpu_idle(void)
{
void (*mark_idle)(int) = ia64_mark_idle;
int cpu = smp_processor_id();
/* endless idle loop with no priority at all */
while (1) {
rcu_idle_enter();
if (can_do_pal_halt) {
current_thread_info()->status &= ~TS_POLLING;
/*
* TS_POLLING-cleared state must be visible before we
* test NEED_RESCHED:
*/
smp_mb();
} else {
current_thread_info()->status |= TS_POLLING;
}
if (!need_resched()) {
#ifdef CONFIG_SMP
min_xtp();
min_xtp();
#endif
rmb();
if (mark_idle)
(*mark_idle)(1);
rmb();
if (mark_idle)
(*mark_idle)(1);
default_idle();
if (mark_idle)
(*mark_idle)(0);
safe_halt();
if (mark_idle)
(*mark_idle)(0);
#ifdef CONFIG_SMP
normal_xtp();
normal_xtp();
#endif
}
rcu_idle_exit();
schedule_preempt_disabled();
check_pgt_cache();
if (cpu_is_offline(cpu))
play_dead();
}
}
void

View File

@@ -455,7 +455,7 @@ start_secondary (void *unused)
preempt_disable();
smp_callin();
cpu_idle();
cpu_startup_entry(CPUHP_ONLINE);
return 0;
}