Skip to content

Commit

Permalink
Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  ...
  • Loading branch information
torvalds committed Apr 30, 2013
2 parents 16fa94b + d190e81 commit 8700c95
Show file tree
Hide file tree
Showing 101 changed files with 455 additions and 1,328 deletions.
2 changes: 0 additions & 2 deletions arch/alpha/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
#define TS_POLLING 0x0010 /* idle task polling need_resched,
skip sending interrupt */

#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)
Expand Down
19 changes: 0 additions & 19 deletions arch/alpha/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,6 @@
void (*pm_power_off)(void) = machine_power_off;
EXPORT_SYMBOL(pm_power_off);

void
cpu_idle(void)
{
current_thread_info()->status |= TS_POLLING;

while (1) {
/* FIXME -- EV6 and LCA45 know how to power down
the CPU. */

rcu_idle_enter();
while (!need_resched())
cpu_relax();

rcu_idle_exit();
schedule_preempt_disabled();
}
}


struct halt_info {
int mode;
char *restart_cmd;
Expand Down
3 changes: 1 addition & 2 deletions arch/alpha/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ smp_callin(void)
cpuid, current, current->active_mm));

preempt_disable();
/* Do nothing. */
cpu_idle();
cpu_startup_entry(CPUHP_ONLINE);
}

/* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */
Expand Down
27 changes: 1 addition & 26 deletions arch/arc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,12 @@ SYSCALL_DEFINE0(arc_gettls)
return task_thread_info(current)->thr_ptr;
}

static inline void arch_idle(void)
void arch_cpu_idle(void)
{
/* sleep, but enable all interrupts before committing */
__asm__("sleep 0x3");
}

void cpu_idle(void)
{
/* Since we SLEEP in idle loop, TIF_POLLING_NRFLAG can't be set */

/* endless idle loop with no priority at all */
while (1) {
tick_nohz_idle_enter();
rcu_idle_enter();

doze:
local_irq_disable();
if (!need_resched()) {
arch_idle();
goto doze;
} else {
local_irq_enable();
}

rcu_idle_exit();
tick_nohz_idle_exit();

schedule_preempt_disabled();
}
}

asmlinkage void ret_from_fork(void);

/* Layout of Child kernel mode stack as setup at the end of this function is
Expand Down
2 changes: 1 addition & 1 deletion arch/arc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void __cpuinit start_kernel_secondary(void)

local_irq_enable();
preempt_disable();
cpu_idle();
cpu_startup_entry(CPUHP_ONLINE);
}

/*
Expand Down
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ config ARM
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP
select GENERIC_SMP_IDLE_THREAD
select GENERIC_IDLE_POLL_SETUP
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select HARDIRQS_SW_RESEND
Expand Down
3 changes: 0 additions & 3 deletions arch/arm/include/asm/system_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ extern void (*arm_pm_idle)(void);

extern unsigned int user_debug;

extern void disable_hlt(void);
extern void enable_hlt(void);

#endif /* !__ASSEMBLY__ */

#endif /* __ASM_ARM_SYSTEM_MISC_H */
100 changes: 26 additions & 74 deletions arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,38 +57,6 @@ static const char *isa_modes[] = {
"ARM" , "Thumb" , "Jazelle", "ThumbEE"
};

static volatile int hlt_counter;

void disable_hlt(void)
{
hlt_counter++;
}

EXPORT_SYMBOL(disable_hlt);

void enable_hlt(void)
{
hlt_counter--;
BUG_ON(hlt_counter < 0);
}

EXPORT_SYMBOL(enable_hlt);

static int __init nohlt_setup(char *__unused)
{
hlt_counter = 1;
return 1;
}

static int __init hlt_setup(char *__unused)
{
hlt_counter = 0;
return 1;
}

__setup("nohlt", nohlt_setup);
__setup("hlt", hlt_setup);

extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
typedef void (*phys_reset_t)(unsigned long);

Expand Down Expand Up @@ -172,54 +140,38 @@ static void default_idle(void)
local_irq_enable();
}

/*
* The idle thread.
* We always respect 'hlt_counter' to prevent low power idle.
*/
void cpu_idle(void)
void arch_cpu_idle_prepare(void)
{
local_fiq_enable();
}

/* endless idle loop with no priority at all */
while (1) {
tick_nohz_idle_enter();
rcu_idle_enter();
ledtrig_cpu(CPU_LED_IDLE_START);
while (!need_resched()) {
#ifdef CONFIG_HOTPLUG_CPU
if (cpu_is_offline(smp_processor_id()))
cpu_die();
void arch_cpu_idle_enter(void)
{
ledtrig_cpu(CPU_LED_IDLE_START);
#ifdef CONFIG_PL310_ERRATA_769419
wmb();
#endif
}

/*
* We need to disable interrupts here
* to ensure we don't miss a wakeup call.
*/
local_irq_disable();
#ifdef CONFIG_PL310_ERRATA_769419
wmb();
void arch_cpu_idle_exit(void)
{
ledtrig_cpu(CPU_LED_IDLE_END);
}

#ifdef CONFIG_HOTPLUG_CPU
void arch_cpu_idle_dead(void)
{
cpu_die();
}
#endif
if (hlt_counter) {
local_irq_enable();
cpu_relax();
} else if (!need_resched()) {
stop_critical_timings();
if (cpuidle_idle_call())
default_idle();
start_critical_timings();
/*
* default_idle functions must always
* return with IRQs enabled.
*/
WARN_ON(irqs_disabled());
} else
local_irq_enable();
}
ledtrig_cpu(CPU_LED_IDLE_END);
rcu_idle_exit();
tick_nohz_idle_exit();
schedule_preempt_disabled();
}

/*
* Called from the core idle loop.
*/
void arch_cpu_idle(void)
{
if (cpuidle_idle_call())
default_idle();
}

static char reboot_mode = 'h';
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
/*
* OK, it's off to the idle thread for us
*/
cpu_idle();
cpu_startup_entry(CPUHP_ONLINE);
}

void __init smp_cpus_done(unsigned int max_cpus)
Expand Down
4 changes: 3 additions & 1 deletion arch/arm/mach-gemini/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ static void gemini_idle(void)
* will never wakeup... Acctualy it is not very good to enable
* interrupts first since scheduler can miss a tick, but there is
* no other way around this. Platforms that needs it for power saving
* should call enable_hlt() in init code, since by default it is
* should enable it in init code, since by default it is
* disabled.
*/

/* FIXME: Enabling interrupts here is racy! */
local_irq_enable();
cpu_do_idle();
}
Expand Down
4 changes: 3 additions & 1 deletion arch/arm/mach-gemini/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <linux/stddef.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/cpu.h>

#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/system_misc.h>
Expand Down Expand Up @@ -77,7 +79,7 @@ void __init gemini_init_irq(void)
* Disable the idle handler by default since it is buggy
* For more info see arch/arm/mach-gemini/idle.c
*/
disable_hlt();
cpu_idle_poll_ctrl(true);

request_resource(&iomem_resource, &irq_resource);

Expand Down
3 changes: 2 additions & 1 deletion arch/arm/mach-ixp4xx/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/io.h>
#include <linux/export.h>
#include <linux/gpio.h>
#include <linux/cpu.h>

#include <mach/udc.h>
#include <mach/hardware.h>
Expand Down Expand Up @@ -239,7 +240,7 @@ void __init ixp4xx_init_irq(void)
* ixp4xx does not implement the XScale PWRMODE register
* so it must not call cpu_do_idle().
*/
disable_hlt();
cpu_idle_poll_ctrl(true);

/* Route all sources to IRQ instead of FIQ */
*IXP4XX_ICLR = 0x0;
Expand Down
6 changes: 3 additions & 3 deletions arch/arm/mach-omap1/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/atomic.h>
#include <linux/cpu.h>

#include <asm/fncpy.h>
#include <asm/system_misc.h>
Expand Down Expand Up @@ -584,8 +585,7 @@ static void omap_pm_init_proc(void)
static int omap_pm_prepare(void)
{
/* We cannot sleep in idle until we have resumed */
disable_hlt();

cpu_idle_poll_ctrl(true);
return 0;
}

Expand Down Expand Up @@ -621,7 +621,7 @@ static int omap_pm_enter(suspend_state_t state)

static void omap_pm_finish(void)
{
enable_hlt();
cpu_idle_poll_ctrl(false);
}


Expand Down
7 changes: 4 additions & 3 deletions arch/arm/mach-omap2/omap_hwmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <linux/cpu.h>

#include <asm/system_misc.h>

Expand Down Expand Up @@ -2157,7 +2158,7 @@ static int _enable(struct omap_hwmod *oh)
if (soc_ops.enable_module)
soc_ops.enable_module(oh);
if (oh->flags & HWMOD_BLOCK_WFI)
disable_hlt();
cpu_idle_poll_ctrl(true);

if (soc_ops.update_context_lost)
soc_ops.update_context_lost(oh);
Expand Down Expand Up @@ -2221,7 +2222,7 @@ static int _idle(struct omap_hwmod *oh)
_del_initiator_dep(oh, mpu_oh);

if (oh->flags & HWMOD_BLOCK_WFI)
enable_hlt();
cpu_idle_poll_ctrl(false);
if (soc_ops.disable_module)
soc_ops.disable_module(oh);

Expand Down Expand Up @@ -2331,7 +2332,7 @@ static int _shutdown(struct omap_hwmod *oh)
_del_initiator_dep(oh, mpu_oh);
/* XXX what about the other system initiators here? dma, dsp */
if (oh->flags & HWMOD_BLOCK_WFI)
enable_hlt();
cpu_idle_poll_ctrl(false);
if (soc_ops.disable_module)
soc_ops.disable_module(oh);
_disable_clocks(oh);
Expand Down
5 changes: 2 additions & 3 deletions arch/arm/mach-omap2/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,15 @@ static int omap_pm_enter(suspend_state_t suspend_state)

static int omap_pm_begin(suspend_state_t state)
{
disable_hlt();
cpu_idle_poll_ctrl(true);
if (cpu_is_omap34xx())
omap_prcm_irq_prepare();
return 0;
}

static void omap_pm_end(void)
{
enable_hlt();
return;
cpu_idle_poll_ctrl(false);
}

static void omap_pm_finish(void)
Expand Down
3 changes: 2 additions & 1 deletion arch/arm/mach-orion5x/board-dt.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/cpu.h>
#include <asm/system_misc.h>
#include <asm/mach/arch.h>
#include <mach/orion5x.h>
Expand Down Expand Up @@ -52,7 +53,7 @@ static void __init orion5x_dt_init(void)
*/
if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
disable_hlt();
cpu_idle_poll_ctrl(true);
}

if (of_machine_is_compatible("lacie,ethernet-disk-mini-v2"))
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-orion5x/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void __init orion5x_init(void)
*/
if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) {
printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
disable_hlt();
cpu_idle_poll_ctrl(true);
}

/*
Expand Down
Loading

0 comments on commit 8700c95

Please sign in to comment.