Skip to content

Commit

Permalink
Merge branches 'doc.2015.02.26a', 'earlycb.2015.03.03a', 'fixes.2015.…
Browse files Browse the repository at this point in the history
…03.03a', 'gpexp.2015.02.26a', 'hotplug.2015.03.20a', 'sysidle.2015.02.26b' and 'tiny.2015.02.26a' into HEAD

doc.2015.02.26a:  Documentation changes
earlycb.2015.03.03a:  Permit early-boot RCU callbacks
fixes.2015.03.03a:  Miscellaneous fixes
gpexp.2015.02.26a:  In-kernel expediting of normal grace periods
hotplug.2015.03.20a:  CPU hotplug fixes
sysidle.2015.02.26b:  NO_HZ_FULL_SYSIDLE fixes
tiny.2015.02.26a:  TINY_RCU fixes
  • Loading branch information
paulmck committed Mar 20, 2015
7 parents ff38281 + 4762767 + 9910aff + c136f99 + 654e953 + 5871968 + 915e8a4 commit 4252879
Show file tree
Hide file tree
Showing 26 changed files with 863 additions and 377 deletions.
6 changes: 6 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2968,6 +2968,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Set maximum number of finished RCU callbacks to
process in one batch.

rcutree.gp_init_delay= [KNL]
Set the number of jiffies to delay each step of
RCU grace-period initialization. This only has
effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT is
set.

rcutree.rcu_fanout_leaf= [KNL]
Increase the number of CPUs assigned to each
leaf rcu_node structure. Useful for very large
Expand Down
6 changes: 2 additions & 4 deletions arch/blackfin/mach-common/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,16 +413,14 @@ int __cpu_disable(void)
return 0;
}

static DECLARE_COMPLETION(cpu_killed);

int __cpu_die(unsigned int cpu)
{
return wait_for_completion_timeout(&cpu_killed, 5000);
return cpu_wait_death(cpu, 5);
}

void cpu_die(void)
{
complete(&cpu_killed);
(void)cpu_report_death();

atomic_dec(&init_mm.mm_users);
atomic_dec(&init_mm.mm_count);
Expand Down
5 changes: 2 additions & 3 deletions arch/metag/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
}

#ifdef CONFIG_HOTPLUG_CPU
static DECLARE_COMPLETION(cpu_killed);

/*
* __cpu_disable runs on the processor to be shutdown.
Expand Down Expand Up @@ -299,7 +298,7 @@ int __cpu_disable(void)
*/
void __cpu_die(unsigned int cpu)
{
if (!wait_for_completion_timeout(&cpu_killed, msecs_to_jiffies(1)))
if (!cpu_wait_death(cpu, 1))
pr_err("CPU%u: unable to kill\n", cpu);
}

Expand All @@ -314,7 +313,7 @@ void cpu_die(void)
local_irq_disable();
idle_task_exit();

complete(&cpu_killed);
(void)cpu_report_death();

asm ("XOR TXENABLE, D0Re0,D0Re0\n");
}
Expand Down
2 changes: 0 additions & 2 deletions arch/x86/include/asm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ extern int _debug_hotplug_cpu(int cpu, int action);
#endif
#endif

DECLARE_PER_CPU(int, cpu_state);

int mwait_usable(const struct cpuinfo_x86 *);

#endif /* _ASM_X86_CPU_H */
2 changes: 1 addition & 1 deletion arch/x86/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
}

void cpu_disable_common(void);
void cpu_die_common(unsigned int cpu);
void native_smp_prepare_boot_cpu(void);
void native_smp_prepare_cpus(unsigned int max_cpus);
void native_smp_cpus_done(unsigned int max_cpus);
int native_cpu_up(unsigned int cpunum, struct task_struct *tidle);
int native_cpu_disable(void);
int common_cpu_die(unsigned int cpu);
void native_cpu_die(unsigned int cpu);
void native_play_dead(void);
void play_dead_common(void);
Expand Down
39 changes: 18 additions & 21 deletions arch/x86/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@
#include <asm/realmode.h>
#include <asm/misc.h>

/* State of each CPU */
DEFINE_PER_CPU(int, cpu_state) = { 0 };

/* Number of siblings per CPU package */
int smp_num_siblings = 1;
EXPORT_SYMBOL(smp_num_siblings);
Expand Down Expand Up @@ -257,7 +254,7 @@ static void notrace start_secondary(void *unused)
lock_vector_lock();
set_cpu_online(smp_processor_id(), true);
unlock_vector_lock();
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
cpu_set_state_online(smp_processor_id());
x86_platform.nmi_init();

/* enable local interrupts */
Expand Down Expand Up @@ -948,7 +945,10 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
*/
mtrr_save_state();

per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* x86 CPUs take themselves offline, so delayed offline is OK. */
err = cpu_check_up_prepare(cpu);
if (err && err != -EBUSY)
return err;

/* the FPU context is blank, nobody can own it */
__cpu_disable_lazy_restore(cpu);
Expand Down Expand Up @@ -1191,7 +1191,7 @@ void __init native_smp_prepare_boot_cpu(void)
switch_to_new_gdt(me);
/* already set me in cpu_online_mask in boot_cpu_init() */
cpumask_set_cpu(me, cpu_callout_mask);
per_cpu(cpu_state, me) = CPU_ONLINE;
cpu_set_state_online(me);
}

void __init native_smp_cpus_done(unsigned int max_cpus)
Expand Down Expand Up @@ -1318,14 +1318,10 @@ static void __ref remove_cpu_from_maps(int cpu)
numa_remove_cpu(cpu);
}

static DEFINE_PER_CPU(struct completion, die_complete);

void cpu_disable_common(void)
{
int cpu = smp_processor_id();

init_completion(&per_cpu(die_complete, smp_processor_id()));

remove_siblinginfo(cpu);

/* It's now safe to remove this processor from the online map */
Expand All @@ -1349,24 +1345,27 @@ int native_cpu_disable(void)
return 0;
}

void cpu_die_common(unsigned int cpu)
int common_cpu_die(unsigned int cpu)
{
wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ);
}
int ret = 0;

void native_cpu_die(unsigned int cpu)
{
/* We don't do anything here: idle task is faking death itself. */

cpu_die_common(cpu);

/* They ack this in play_dead() by setting CPU_DEAD */
if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
if (cpu_wait_death(cpu, 5)) {
if (system_state == SYSTEM_RUNNING)
pr_info("CPU %u is now offline\n", cpu);
} else {
pr_err("CPU %u didn't die...\n", cpu);
ret = -1;
}

return ret;
}

void native_cpu_die(unsigned int cpu)
{
common_cpu_die(cpu);
}

void play_dead_common(void)
Expand All @@ -1375,10 +1374,8 @@ void play_dead_common(void)
reset_lazy_tlbstate();
amd_e400_remove_cpu(raw_smp_processor_id());

mb();
/* Ack it */
__this_cpu_write(cpu_state, CPU_DEAD);
complete(&per_cpu(die_complete, smp_processor_id()));
(void)cpu_report_death();

/*
* With physical CPU hotplug, we should halt the cpu
Expand Down
46 changes: 25 additions & 21 deletions arch/x86/xen/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,10 @@ static void cpu_bringup(void)

set_cpu_online(cpu, true);

this_cpu_write(cpu_state, CPU_ONLINE);

wmb();
cpu_set_state_online(cpu); /* Implies full memory barrier. */

/* We can take interrupts now: we're officially "up". */
local_irq_enable();

wmb(); /* make sure everything is out */
}

/*
Expand Down Expand Up @@ -459,7 +455,13 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
xen_setup_timer(cpu);
xen_init_lock_cpu(cpu);

per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/*
* PV VCPUs are always successfully taken down (see 'while' loop
* in xen_cpu_die()), so -EBUSY is an error.
*/
rc = cpu_check_up_prepare(cpu);
if (rc)
return rc;

/* make sure interrupts start blocked */
per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
Expand All @@ -479,10 +481,8 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
BUG_ON(rc);

while(per_cpu(cpu_state, cpu) != CPU_ONLINE) {
while (cpu_report_state(cpu) != CPU_ONLINE)
HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
barrier();
}

return 0;
}
Expand Down Expand Up @@ -511,11 +511,11 @@ static void xen_cpu_die(unsigned int cpu)
schedule_timeout(HZ/10);
}

cpu_die_common(cpu);

xen_smp_intr_free(cpu);
xen_uninit_lock_cpu(cpu);
xen_teardown_timer(cpu);
if (common_cpu_die(cpu) == 0) {
xen_smp_intr_free(cpu);
xen_uninit_lock_cpu(cpu);
xen_teardown_timer(cpu);
}
}

static void xen_play_dead(void) /* used only with HOTPLUG_CPU */
Expand Down Expand Up @@ -747,6 +747,16 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int rc;

/*
* This can happen if CPU was offlined earlier and
* offlining timed out in common_cpu_die().
*/
if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) {
xen_smp_intr_free(cpu);
xen_uninit_lock_cpu(cpu);
}

/*
* xen_smp_intr_init() needs to run before native_cpu_up()
* so that IPI vectors are set up on the booting CPU before
Expand All @@ -768,20 +778,14 @@ static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
return rc;
}

static void xen_hvm_cpu_die(unsigned int cpu)
{
xen_cpu_die(cpu);
native_cpu_die(cpu);
}

void __init xen_hvm_smp_init(void)
{
if (!xen_have_vector_callback)
return;
smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
smp_ops.cpu_up = xen_hvm_cpu_up;
smp_ops.cpu_die = xen_hvm_cpu_die;
smp_ops.cpu_die = xen_cpu_die;
smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
smp_ops.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu;
Expand Down
14 changes: 14 additions & 0 deletions include/linux/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ enum {
* Called on the new cpu, just before
* enabling interrupts. Must not sleep,
* must not fail */
#define CPU_DYING_IDLE 0x000B /* CPU (unsigned)v dying, reached
* idle loop. */
#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly,
* perhaps due to preemption. */

/* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
* operation in progress
Expand Down Expand Up @@ -271,4 +275,14 @@ void arch_cpu_idle_enter(void);
void arch_cpu_idle_exit(void);
void arch_cpu_idle_dead(void);

DECLARE_PER_CPU(bool, cpu_dead_idle);

int cpu_report_state(int cpu);
int cpu_check_up_prepare(int cpu);
void cpu_set_state_online(int cpu);
#ifdef CONFIG_HOTPLUG_CPU
bool cpu_wait_death(unsigned int cpu, int seconds);
bool cpu_report_death(void);
#endif /* #ifdef CONFIG_HOTPLUG_CPU */

#endif /* _LINUX_CPU_H_ */
7 changes: 6 additions & 1 deletion include/linux/lockdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,13 @@ do { \
# define might_lock_read(lock) do { } while (0)
#endif

#ifdef CONFIG_PROVE_RCU
#ifdef CONFIG_LOCKDEP
void lockdep_rcu_suspicious(const char *file, const int line, const char *s);
#else
static inline void
lockdep_rcu_suspicious(const char *file, const int line, const char *s)
{
}
#endif

#endif /* __LINUX_LOCKDEP_H */
Loading

0 comments on commit 4252879

Please sign in to comment.