Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (43 commits)
  [POWERPC] Use little-endian bit from firmware ibm,pa-features property
  [POWERPC] Make sure smp_processor_id works very early in boot
  [POWERPC] U4 DART improvements
  [POWERPC] todc: add support for Time-Of-Day-Clock
  [POWERPC] Make lparcfg.c work when both iseries and pseries are selected
  [POWERPC] Fix idr locking in init_new_context
  [POWERPC] mpc7448hpc2 (taiga) board config file
  [POWERPC] Add tsi108 pci and platform device data register function
  [POWERPC] Add general support for mpc7448hpc2 (Taiga) platform
  [POWERPC] Correct the MAX_CONTEXT definition
  powerpc: minor cleanups for mpc86xx
  [POWERPC] Make sure we select CONFIG_NEW_LEDS if ADB_PMU_LED is set
  [POWERPC] Simplify the code defining the 64-bit CPU features
  [POWERPC] powerpc: kconfig warning fix
  [POWERPC] Consolidate some of kernel/misc*.S
  [POWERPC] Remove unused function call_with_mmu_off
  [POWERPC] update asm-powerpc/time.h
  [POWERPC] Clean up it_lp_queue.h
  [POWERPC] Skip the "copy down" of the kernel if it is already at zero.
  [POWERPC] Add the use of the firmware soft-reset-nmi to kdump.
  ...
This commit is contained in:
Linus Torvalds
2006-06-29 11:32:34 -07:00
77 changed files with 4088 additions and 1112 deletions

View File

@ -24,9 +24,11 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/machdep.h>
#include <asm/kexec.h>
#include <asm/kdump.h>
#include <asm/lmb.h>
#include <asm/firmware.h>
@ -41,6 +43,7 @@
/* This keeps a track of which one is crashing cpu. */
int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
size_t data_len)
@ -98,34 +101,66 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
}
#ifdef CONFIG_SMP
static atomic_t waiting_for_crash_ipi;
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
void crash_ipi_callback(struct pt_regs *regs)
{
int cpu = smp_processor_id();
if (cpu == crashing_cpu)
return;
if (!cpu_online(cpu))
return;
local_irq_disable();
if (!cpu_isset(cpu, cpus_in_crash))
crash_save_this_cpu(regs, cpu);
cpu_set(cpu, cpus_in_crash);
/*
* Entered via soft-reset - could be the kdump
* process is invoked using soft-reset or user activated
* it if some CPU did not respond to an IPI.
* For soft-reset, the secondary CPU can enter this func
* twice. 1 - using IPI, and 2. soft-reset.
* Tell the kexec CPU that entered via soft-reset and ready
* to go down.
*/
if (cpu_isset(cpu, cpus_in_sr)) {
cpu_clear(cpu, cpus_in_sr);
atomic_inc(&enter_on_soft_reset);
}
/*
* Starting the kdump boot.
* This barrier is needed to make sure that all CPUs are stopped.
* If not, soft-reset will be invoked to bring other CPUs.
*/
while (!cpu_isset(crashing_cpu, cpus_in_crash))
cpu_relax();
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 1);
local_irq_disable();
crash_save_this_cpu(regs, cpu);
atomic_dec(&waiting_for_crash_ipi);
kexec_smp_wait();
/* NOTREACHED */
}
static void crash_kexec_prepare_cpus(void)
/*
* Wait until all CPUs are entered via soft-reset.
*/
static void crash_soft_reset_check(int cpu)
{
unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
cpu_clear(cpu, cpus_in_sr);
while (atomic_read(&enter_on_soft_reset) != ncpus)
cpu_relax();
}
static void crash_kexec_prepare_cpus(int cpu)
{
unsigned int msecs;
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
crash_send_ipi(crash_ipi_callback);
smp_wmb();
@ -133,14 +168,13 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: Until we will have the way to stop other CPUSs reliabally,
* the crash CPU will send an IPI and wait for other CPUs to
* respond. If not, proceed the kexec boot even though we failed to
* capture other CPU states.
* respond.
* Delay of at least 10 seconds.
*/
printk(KERN_ALERT "Sending IPI to other cpus...\n");
printk(KERN_EMERG "Sending IPI to other cpus...\n");
msecs = 10000;
while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
barrier();
while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
cpu_relax();
mdelay(1);
}
@ -149,18 +183,71 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: In case if we do not get all CPUs, one possibility: ask the
* user to do soft reset such that we get all.
* IPI handler is already set by the panic cpu initially. Therefore,
* all cpus could invoke this handler from die() and the panic CPU
* will call machine_kexec() directly from this handler to do
* kexec boot.
* Soft-reset will be used until better mechanism is implemented.
*/
if (atomic_read(&waiting_for_crash_ipi))
printk(KERN_ALERT "done waiting: %d cpus not responding\n",
atomic_read(&waiting_for_crash_ipi));
if (cpus_weight(cpus_in_crash) < ncpus) {
printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
ncpus - cpus_weight(cpus_in_crash));
printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
cpus_in_sr = CPU_MASK_NONE;
atomic_set(&enter_on_soft_reset, 0);
while (cpus_weight(cpus_in_crash) < ncpus)
cpu_relax();
}
/*
* Make sure all CPUs are entered via soft-reset if the kdump is
* invoked using soft-reset.
*/
if (cpu_isset(cpu, cpus_in_sr))
crash_soft_reset_check(cpu);
/* Leave the IPI callback set */
}
/*
* This function will be called by secondary cpus or by kexec cpu
* if soft-reset is activated to stop some CPUs.
*/
void crash_kexec_secondary(struct pt_regs *regs)
{
int cpu = smp_processor_id();
unsigned long flags;
int msecs = 5;
local_irq_save(flags);
/* Wait 5ms if the kexec CPU is not entered yet. */
while (crashing_cpu < 0) {
if (--msecs < 0) {
/*
* Either kdump image is not loaded or
* kdump process is not started - Probably xmon
* exited using 'x'(exit and recover) or
* kexec_should_crash() failed for all running tasks.
*/
cpu_clear(cpu, cpus_in_sr);
local_irq_restore(flags);
return;
}
mdelay(1);
cpu_relax();
}
if (cpu == crashing_cpu) {
/*
* Panic CPU will enter this func only via soft-reset.
* Wait until all secondary CPUs entered and
* then start kexec boot.
*/
crash_soft_reset_check(cpu);
cpu_set(crashing_cpu, cpus_in_crash);
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
machine_kexec(kexec_crash_image);
/* NOTREACHED */
}
crash_ipi_callback(regs);
}
#else
static void crash_kexec_prepare_cpus(void)
static void crash_kexec_prepare_cpus(int cpu)
{
/*
* move the secondarys to us so that we can copy
@ -171,6 +258,10 @@ static void crash_kexec_prepare_cpus(void)
smp_release_cpus();
}
void crash_kexec_secondary(struct pt_regs *regs)
{
cpus_in_sr = CPU_MASK_NONE;
}
#endif
void default_machine_crash_shutdown(struct pt_regs *regs)
@ -199,14 +290,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
desc->chip->disable(irq);
}
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
/*
* Make a note of crashing cpu. Will be used in machine_kexec
* such that another IPI will not be sent.
*/
crashing_cpu = smp_processor_id();
crash_kexec_prepare_cpus();
crash_save_this_cpu(regs, crashing_cpu);
crash_kexec_prepare_cpus(crashing_cpu);
cpu_set(crashing_cpu, cpus_in_crash);
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
}