GIT 649e85797259162f7fdc696420e7492f20226f2d git+ssh://master.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git commit 649e85797259162f7fdc696420e7492f20226f2d Author: Paul Mackerras Date: Wed Jun 28 13:57:16 2006 +1000 [POWERPC] Make sure we select CONFIG_NEW_LEDS if ADB_PMU_LED is set Signed-off-by: Paul Mackerras commit 3965f8c59778b0d37460ec268f92c0c382546b5c Author: Paul Mackerras Date: Wed Jun 28 13:50:39 2006 +1000 [POWERPC] Simplify the code defining the 64-bit CPU features Signed-off-by: Paul Mackerras commit f127a2b5cf542968ea1c428f86ffc780ea929452 Author: Andrew Morton Date: Sun Jun 25 01:49:07 2006 -0700 [POWERPC] powerpc: kconfig warning fix arch/powerpc/Kconfig:420:warning: leading whitespace ignored Stop doing that. Cc: Benjamin Herrenschmidt Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras commit 127efeb286bb772019236182a1b4fc14ff2ae00c Author: Stephen Rothwell Date: Wed Jun 28 11:55:49 2006 +1000 [POWERPC] Consolidate some of kernel/misc*.S There were some common functions (mainly i/o). Also some small white space cleanups and remove a couple of small unused functions. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit a240da35a1087804cbdc3faba949445e64d1eecb Author: Stephen Rothwell Date: Wed Jun 28 11:53:56 2006 +1000 [POWERPC] Remove unused function call_with_mmu_off Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 9b47569a9d410199aea6386917fd0662809c60be Author: Stephen Rothwell Date: Wed Jun 28 11:51:41 2006 +1000 [POWERPC] update asm-powerpc/time.h If we ever build a combined kernel including iSeries, then this will be needed. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit 612f02d6d6eadd9c5dde5a5b97b55a3a620d28e5 Author: Stephen Rothwell Date: Wed Jun 28 11:49:10 2006 +1000 [POWERPC] Clean up it_lp_queue.h No more StudlyCaps. Remove from a couple of places it is no longer needed. Use C style comments. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras commit d0b79c54fc14f1f2db64180a21b84146028c598b Author: Jimi Xenidis Date: Mon Jun 26 04:56:58 2006 -0400 [POWERPC] Skip the "copy down" of the kernel if it is already at zero. This patch allows the kernel to recognized that it was loaded at zero and the copy down of the image is unnecessary. This is useful for Simulators and kexec models. On a typical 3.8 MiB vmlinux.strip this saves about 2.3 million instructions. Signed-off-by: Paul Mackerras commit c0ce7d0886cf0c2579c604eac41a7e125bc0e96d Author: David Wilder Date: Fri Jun 23 15:29:34 2006 -0700 [POWERPC] Add the use of the firmware soft-reset-nmi to kdump. With this patch, kdump uses the firmware soft-reset NMI for two purposes: 1) Initiate the kdump (take a crash dump) by issuing a soft-reset. 2) Break a CPU out of a deadlock condition that is detected during kdump processing. When a soft-reset is initiated each CPU will enter system_reset_exception() and set its corresponding bit in the global bit-array cpus_in_sr then call die(). When die() finds the CPU's bit set in cpu_in_sr crash_kexec() is called to initiate a crash dump. The first CPU to enter crash_kexec() is called the "crashing CPU". All other CPUs are "secondary CPUs". The secondary CPU's pass through to crash_kexec_secondary() and sleep. The crashing CPU waits for all CPUs to enter via soft-reset then boots the kdump kernel (see crash_soft_reset_check()) When the system crashes due to a panic or exception, crash_kexec() is called by panic() or die(). The crashing CPU sends an IPI to all other CPUs to notify them of the pending shutdown. If a CPU is in a deadlock or hung state with interrupts disabled, the IPI will not be delivered. The result being, that the kdump kernel is not booted. This problem is solved with the use of a firmware generated soft-reset. After the crashing_cpu has issued the IPI, it waits for 10 sec for all CPUs to enter crash_ipi_callback(). A CPU signifies its entry to crash_ipi_callback() by setting its corresponding bit in the cpus_in_crash bit array. After 10 sec, if one or more CPUs have not set their bit in cpus_in_crash we assume that the CPU(s) is deadlocked. The operator is then prompted to generate a soft-reset to break the deadlock. Each CPU enters the soft reset handler as described above. Two conditions must be handled at this point: 1) The system crashed because the operator generated a soft-reset. See 2) The system had crashed before the soft-reset was generated ( in the case of a Panic or oops). The first CPU to enter crash_kexec() uses the state of the kexec_lock to determine this state. If kexec_lock is already held then condition 2 is true and crash_kexec_secondary() is called, else; this CPU is flagged as the crashing CPU, the kexec_lock is acquired and crash_kexec() proceeds as described above. Each additional CPUs responding to the soft-reset will pass through crash_kexec() to kexec_secondary(). All secondary CPUs call crash_ipi_callback() readying them self's for the shutdown. When ready they clear their bit in cpus_in_sr. The crashing CPU waits in kexec_secondary() until all other CPUs have cleared their bits in cpus_in_sr. The kexec kernel boot is then started. Signed-off-by: Haren Myneni Signed-off-by: David Wilder Signed-off-by: Paul Mackerras commit 2cd90bc8fba8720ef7f3fdfd1e0c1a5397a18271 Author: Arnd Bergmann Date: Fri Jun 23 20:57:50 2006 +0200 [POWERPC] spufs: fix class0 interrupt assignment The class zero interrupt handling for spus was confusing alignment and error interrupts, so swap them. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 4da30d15b6d5036b0d96422d6946ca758111fae3 Author: Geoff Levand Date: Fri Jun 23 20:57:49 2006 +0200 [POWERPC] spufs: fix memory hotplug dependency spufs_base.c calls __add_pages, which depends on CONFIG_MEMORY_HOTPLUG. Moved the selection of CONFIG_MEMORY_HOTPLUG from CONFIG_SPUFS_MMAP to CONFIG_SPU_FS. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 910ab66b1c94a2758725874d389136cf9acdc04c Author: Benjamin Herrenschmidt Date: Fri Jun 23 20:57:48 2006 +0200 [POWERPC] spufs: fix MFC command queue purge In the context save/restore code, the SPU MFC command queue purge code has a bug: static inline void wait_purge_complete(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; /* Save, Step 28: * Poll MFC_CNTL[Ps] until value '11' is * read * (purge complete). */ POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) & MFC_CNTL_PURGE_DMA_COMPLETE); } This will exit as soon as _one_ of the 2 bits that compose MFC_CNTL_PURGE_DMA_COMPLETE is set, and one of them happens to be "purge in progress"... which means that we'll happily continue restoring the MFC while it's being purged at the same time. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit 23cc770107c2d27dd1f5dee53177ea1163ee9295 Author: Benjamin Herrenschmidt Date: Fri Jun 23 20:57:47 2006 +0200 [POWERPC] spufs: map mmio space as guarded into user space This fixes a bug where we don't properly map SPE MMIO space as guarded, causing various test cases to fail, probably due to write combining and other niceties caused by the lack of the G bit. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit 6b7290be0c045f3978c6b12f0a8aedd21ca6fa9c Author: Michael Ellerman Date: Fri Jun 23 18:20:24 2006 +1000 [POWERPC] Enable XMON in cell_defconfig Now that we have the udbg callbacks we can enable XMON by default. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 94b60ec166bc410d544d7635c9575ea5e53ec052 Author: Michael Ellerman Date: Fri Jun 23 18:20:22 2006 +1000 [POWERPC] Enable the RTAS udbg console on IBM Cell Blade Enable the RTAS udbg console on IBM Cell Blade, this allows xmon to work. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit cc46bb98c0d52695f26c239de701050660f5c79f Author: Michael Ellerman Date: Fri Jun 23 18:20:16 2006 +1000 [POWERPC] Add udbg support for RTAS console Add udbg hooks for the RTAS console, based on the RTAS put-term-char and get-term-char calls. Along with my previous patches, this should enable debugging as soon as early_init_dt_scan_rtas() is called. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 458148c00b97864a27ecf528a1d45a8e5ebd9bbc Author: Michael Ellerman Date: Fri Jun 23 18:20:13 2006 +1000 [POWERPC] Setup RTAS values earlier, to enable rtas_call() earlier Althought RTAS is instantiated when we enter the kernel, we can't actually call into it until we know its entry point address. Currently we grab that in rtas_initialize(), however that's quite late in the boot sequence. To enable rtas_call() earlier, we can grab the RTAS entry etc. values while we're scanning the flattened device tree. There's existing code to retrieve the values from /chosen, however we don't store them there anymore, so remove that code. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit ab3ab74d9b6b3920be70f502b40cb3f7f08d23fa Author: Michael Ellerman Date: Fri Jun 23 18:20:11 2006 +1000 [POWERPC] Move RTAS exports next to their declarations Move RTAS exports next to their declarations. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 24da3dd53430ec07ce9110b1eaaad080c3c7ecf6 Author: Michael Ellerman Date: Fri Jun 23 18:20:10 2006 +1000 [POWERPC] Make rtas_call() safe if RTAS hasn't been initialised Currently it's unsafe to call rtas_call() prior to rtas_initialize(). This is because the rtas.entry value hasn't been setup and so we don't know where to enter, but we just try anyway. We can't do anything intelligent without rtas.entry, so if it's not set, just return. Code that calls rtas_call() early needs to be aware that the call might fail. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 4ba99b97dadd35b9ce1438b2bc7c992a4a14a8b1 Author: Michael Ellerman Date: Fri Jun 23 18:20:09 2006 +1000 [POWERPC] Setup the boot cpu's paca pointer in C rather than asm There's no need to set the boot cpu paca in asm, so do it in C so us mere mortals can understand it. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit aa98c50dcb5d5b85d2a4c26d54fa1e3c31c11e4b Author: Michael Ellerman Date: Fri Jun 23 18:17:32 2006 +1000 [POWERPC] Make kexec_setup() a regular initcall There's no reason kexec_setup() needs to be called explicitly from setup_system(), it can just be a regular initcall. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit c30a4df3f134f511e8cdf828da429e333753daab Author: Michael Ellerman Date: Fri Jun 23 18:16:39 2006 +1000 [POWERPC] Use ppc_md.hpte_insert() in htab_bolt_mapping() With the ppc_md htab pointers setup earlier, we can use ppc_md.hpte_insert in htab_bolt_mapping(), rather than deciding which version to call by hand. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 7d0daae4ae1a3e80d78b83cddf414a3b98a962f4 Author: Michael Ellerman Date: Fri Jun 23 18:16:38 2006 +1000 [POWERPC] powerpc: Initialise ppc_md htab pointers earlier Initialise the ppc_md htab callbacks earlier, in the probe routines. This allows us to call htab_finish_init() from htab_initialize(), and makes it private to hash_utils_64.c. Move htab_finish_init() and make_bl() above htab_initialize() to avoid forward declarations. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 7a4571ae553e2972b7958306fd796a2fd24fd7d1 Author: Michael Ellerman Date: Fri Jun 23 18:16:03 2006 +1000 [POWERPC] Export flat device tree via debugfs for debugging If DEBUG is turned on in prom.c, export the flat device tree via debugfs. This has been handy on several occasions. To look at it: # mount -t debugfs none /sys/kernel/debug # od -a /sys/kernel/debug/powerpc/flat-device-tree and/or # dtc -fI dtb /sys/kernel/debug/powerpc/flat-device-tree -O dts Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 1dce0e30471ac863fd141d137c98e3644817975e Author: Michael Ellerman Date: Fri Jun 23 18:15:37 2006 +1000 [POWERPC] Remove remaining iSeries debugger cruft None of this seems to be necessary, so let's see if can remove it and not break anything. Booted on iSeries & pSeries here. NB. we don't remove the hvReleaseData, we just move it down so that the file reads more clearly. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras commit 5f50867b4f1938ab80d249206efbec37bba48c39 Author: Haren Myneni Date: Thu Jun 22 23:35:10 2006 -0700 [POWERPC] kdump: Reserve the existing TCE mappings left by the first kernel During kdump boot, noticed some machines checkstop on dma protection fault for ongoing DMA left in the first kernel. Instead of initializing TCE entries in iommu_init() for the kdump boot, this patch fixes this issue by walking through the each TCE table and checks whether the entries are in use by the first kernel. If so, reserve those entries by setting the corresponding bit in tbl->it_map such that these entries will not be available for the kdump boot. However it could be possible that all TCE entries might be used up due to the driver bug that does continuous mapping. My observation is around 1700 TCE entries are used on some systems (Ex: P4) at some point of time during kdump boot and saving dump (either write into the disk or sending to remote machine). Hence, this patch will make sure that minimum of 2048 entries will be available such that kdump boot could be successful in some cases. Signed-off-by: Haren Myneni Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit f93d6d071fdbf27141c5331d6cd988664650bc1f Author: Jon Loeliger Date: Thu Jun 22 13:02:58 2006 -0500 [POWERPC] Remove obsolete #include . Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 790d427616ae68559b711bf4348003c17249abf4 Author: Jon Loeliger Date: Thu Jun 22 13:01:48 2006 -0500 [POWERPC] Remove redundant STD_MMU selection. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit f17607fb17aabd3a963da39799bde17d81211ab0 Author: Jon Loeliger Date: Thu Jun 22 13:00:46 2006 -0500 [POWERPC] Move I8259 selection under MPC8641HPCN board Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit c53b33420a2e0ed1eb86be1c00b2dc21bb92bd6e Author: Jon Loeliger Date: Thu Jun 22 12:59:25 2006 -0500 [POWERPC] Remove redundant PPC_86XX check. Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras commit 6d7c466292fc7c90bb160c1c7df74035c7c12595 Author: Jimi Xenidis Date: Wed Jun 21 19:15:55 2006 -0400 [POWERPC] Don't access HID registers if running on a Hypervisor. The following patch avoids accessing Hypervisor privilege HID registers when running on a Hypervisor (MSR[HV]=0). Signed-off-by: Jimi Xenidis Signed-off-by: Paul Mackerras commit 70c3967d4f8029f3d53323a9f0490df61d8cb77d Author: Johannes Berg Date: Wed Jun 21 12:11:16 2006 +0200 [POWERPC] Convert powermac ide blink to new led infrastructure This patch removes the old pmac ide led blink code and adds generic LED subsystem support for the LED. It maintains backward compatibility with the old BLK_DEV_IDE_PMAC_BLINK Kconfig option which now simply selects the new code and influences the default trigger. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e922a88..baec4e3 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -413,12 +413,17 @@ config PPC_CELL_NATIVE default n config PPC_IBM_CELL_BLADE - bool " IBM Cell Blade" + bool "IBM Cell Blade" depends on PPC_MULTIPLATFORM && PPC64 select PPC_CELL_NATIVE select PPC_RTAS select MMIO_NVRAM select PPC_UDBG_16550 + select UDBG_RTAS_CONSOLE + +config UDBG_RTAS_CONSOLE + bool + default n config XICS depends on PPC_PSERIES @@ -794,7 +799,6 @@ config GENERIC_ISA_DMA config PPC_I8259 bool - default y if MPC8641_HPCN default n config PPC_INDIRECT_PCI diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index c69006a..e29ef77 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -134,12 +134,19 @@ config PPC_EARLY_DEBUG_G5 help Select this to enable early debugging for Apple G5 machines. -config PPC_EARLY_DEBUG_RTAS +config PPC_EARLY_DEBUG_RTAS_PANEL bool "RTAS Panel" depends on PPC_RTAS help Select this to enable early debugging via the RTAS panel. +config PPC_EARLY_DEBUG_RTAS_CONSOLE + bool "RTAS Console" + depends on PPC_RTAS + select UDBG_RTAS_CONSOLE + help + Select this to enable early debugging via the RTAS console. + config PPC_EARLY_DEBUG_MAPLE bool "Maple real mode" depends on PPC_MAPLE diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index b8b8d46..e028a2e 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17 -# Mon Jun 19 17:23:03 2006 +# Linux kernel version: 2.6.17-rc6 +# Thu Jun 22 15:28:36 2006 # CONFIG_PPC64=y CONFIG_64BIT=y @@ -1063,7 +1063,8 @@ # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set CONFIG_DEBUGGER=y -# CONFIG_XMON is not set +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set # CONFIG_PPC_EARLY_DEBUG is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 803858e..814f242 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -50,7 +50,8 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_bo extra-$(CONFIG_8xx) := head_8xx.o extra-y += vmlinux.lds -obj-y += time.o prom.o traps.o setup-common.o udbg.o +obj-y += time.o prom.o traps.o setup-common.o \ + udbg.o misc.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index 2714183..1fc8632 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -125,7 +125,12 @@ _GLOBAL(__save_cpu_setup) cmpwi r0,0x44 bne 2f -1: /* Save HID0,1,4 and 5 */ +1: /* skip if not running in HV mode */ + mfmsr r0 + rldicl. r0,r0,4,63 + beq 2f + + /* Save HID0,1,4 and 5 */ mfspr r3,SPRN_HID0 std r3,CS_HID0(r5) mfspr r3,SPRN_HID1 @@ -159,7 +164,12 @@ _GLOBAL(__restore_cpu_setup) cmpwi r0,0x44 bnelr -1: /* Before accessing memory, we make sure rm_ci is clear */ +1: /* skip if not running in HV mode */ + mfmsr r0 + rldicl. r0,r0,4,63 + beqlr + + /* Before accessing memory, we make sure rm_ci is clear */ li r0,0 mfspr r3,SPRN_HID4 rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */ diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index e253a45..b537cfa 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -24,9 +24,11 @@ #include #include #include #include +#include #include #include +#include #include #include #include @@ -41,6 +43,7 @@ #endif /* 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 p } #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; - if (ppc_md.kexec_cpu_down) - ppc_md.kexec_cpu_down(1, 1); - local_irq_disable(); + if (!cpu_isset(cpu, cpus_in_crash)) + crash_save_this_cpu(regs, cpu); + cpu_set(cpu, cpus_in_crash); - crash_save_this_cpu(regs, cpu); - atomic_dec(&waiting_for_crash_ipi); + /* + * 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); 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(voi /* * 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(voi /* * 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 (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 (atomic_read(&waiting_for_crash_ipi)) - printk(KERN_ALERT "done waiting: %d cpus not responding\n", - atomic_read(&waiting_for_crash_ipi)); + 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(voi 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(stru desc->handler->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); } diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 831acbd..f2fab68 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -85,34 +85,6 @@ #endif /* CONFIG_PPC_MULTIPLATFORM */ /* Catch branch to 0 in real mode */ trap -#ifdef CONFIG_PPC_ISERIES - /* - * At offset 0x20, there is a pointer to iSeries LPAR data. - * This is required by the hypervisor - */ - . = 0x20 - .llong hvReleaseData-KERNELBASE - - /* - * At offset 0x28 and 0x30 are offsets to the mschunks_map - * array (used by the iSeries LPAR debugger to do translation - * between physical addresses and absolute addresses) and - * to the pidhash table (also used by the debugger) - */ - .llong mschunks_map-KERNELBASE - .llong 0 /* pidhash-KERNELBASE SFRXXX */ - - /* Offset 0x38 - Pointer to start of embedded System.map */ - .globl embedded_sysmap_start -embedded_sysmap_start: - .llong 0 - /* Offset 0x40 - Pointer to end of embedded System.map */ - .globl embedded_sysmap_end -embedded_sysmap_end: - .llong 0 - -#endif /* CONFIG_PPC_ISERIES */ - /* Secondary processors spin on this value until it goes to 1. */ .globl __secondary_hold_spinloop __secondary_hold_spinloop: @@ -124,6 +96,15 @@ __secondary_hold_spinloop: __secondary_hold_acknowledge: .llong 0x0 +#ifdef CONFIG_PPC_ISERIES + /* + * At offset 0x20, there is a pointer to iSeries LPAR data. + * This is required by the hypervisor + */ + . = 0x20 + .llong hvReleaseData-KERNELBASE +#endif /* CONFIG_PPC_ISERIES */ + . = 0x60 /* * The following code is used on pSeries to hold secondary processors @@ -1683,6 +1664,9 @@ _STATIC(__after_prom_start) /* i.e. where we are running */ /* the source addr */ + cmpdi r4,0 /* In some cases the loader may */ + beq .start_here_multiplatform /* have already put us at zero */ + /* so we can skip the copy. */ LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */ sub r5,r5,r27 @@ -1995,17 +1979,6 @@ #endif /* Not reached */ BUG_OPCODE -/* Put the paca pointer into r13 and SPRG3 */ -_GLOBAL(setup_boot_paca) - LOAD_REG_IMMEDIATE(r3, boot_cpuid) - lwz r3,0(r3) - LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ - mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */ - add r13,r3,r4 /* for this processor. */ - mtspr SPRN_SPRG3,r13 - - blr - /* * We put a few things here that have to be page-aligned. * This stuff goes at the beginning of the bss, which is page-aligned. diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 7cb77c2..3d677ac 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -38,6 +38,7 @@ #include #include #include #include +#include #define DBG(...) @@ -440,8 +441,37 @@ struct iommu_table *iommu_init_table(str tbl->it_largehint = tbl->it_halfpoint; spin_lock_init(&tbl->it_lock); +#ifdef CONFIG_CRASH_DUMP + if (ppc_md.tce_get) { + unsigned long index, tceval; + unsigned long tcecount = 0; + + /* + * Reserve the existing mappings left by the first kernel. + */ + for (index = 0; index < tbl->it_size; index++) { + tceval = ppc_md.tce_get(tbl, index + tbl->it_offset); + /* + * Freed TCE entry contains 0x7fffffffffffffff on JS20 + */ + if (tceval && (tceval != 0x7fffffffffffffffUL)) { + __set_bit(index, tbl->it_map); + tcecount++; + } + } + if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) { + printk(KERN_WARNING "TCE table is full; "); + printk(KERN_WARNING "freeing %d entries for the kdump boot\n", + KDUMP_MIN_TCE_ENTRIES); + for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES; + index < tbl->it_size; index++) + __clear_bit(index, tbl->it_map); + } + } +#else /* Clear the hardware table in case firmware left allocations in it */ ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size); +#endif if (!welcomed) { printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index a8fa04e..b438d45 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -378,11 +378,13 @@ static void __init export_crashk_values( of_node_put(node); } -void __init kexec_setup(void) +static int __init kexec_setup(void) { export_htab_values(); export_crashk_values(); + return 0; } +__initcall(kexec_setup); static int __init early_parse_crashk(char *p) { diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S new file mode 100644 index 0000000..fc23040 --- /dev/null +++ b/arch/powerpc/kernel/misc.S @@ -0,0 +1,203 @@ +/* + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras. + * + * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) + * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include + + .text + +#ifdef CONFIG_PPC64 +#define IN_SYNC twi 0,r5,0; isync +#define EIEIO_32 +#define SYNC_64 sync +#else /* CONFIG_PPC32 */ +#define IN_SYNC +#define EIEIO_32 eieio +#define SYNC_64 +#endif +/* + * Returns (address we are running at) - (address we were linked at) + * for use before the text and data are mapped to KERNELBASE. + */ + +_GLOBAL(reloc_offset) + mflr r0 + bl 1f +1: mflr r3 + LOAD_REG_IMMEDIATE(r4,1b) + subf r3,r4,r3 + mtlr r0 + blr + +/* + * add_reloc_offset(x) returns x + reloc_offset(). + */ +_GLOBAL(add_reloc_offset) + mflr r0 + bl 1f +1: mflr r5 + LOAD_REG_IMMEDIATE(r4,1b) + subf r5,r4,r5 + add r3,r3,r5 + mtlr r0 + blr + +/* + * I/O string operations + * + * insb(port, buf, len) + * outsb(port, buf, len) + * insw(port, buf, len) + * outsw(port, buf, len) + * insl(port, buf, len) + * outsl(port, buf, len) + * insw_ns(port, buf, len) + * outsw_ns(port, buf, len) + * insl_ns(port, buf, len) + * outsl_ns(port, buf, len) + * + * The *_ns versions don't do byte-swapping. + */ +_GLOBAL(_insb) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,1 + blelr- +00: lbz r5,0(r3) + eieio + stbu r5,1(r4) + bdnz 00b + IN_SYNC + blr + +_GLOBAL(_outsb) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,1 + blelr- +00: lbzu r5,1(r4) + stb r5,0(r3) + EIEIO_32 + bdnz 00b + SYNC_64 + blr + +_GLOBAL(_insw) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhbrx r5,0,r3 + eieio + sthu r5,2(r4) + bdnz 00b + IN_SYNC + blr + +_GLOBAL(_outsw) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhzu r5,2(r4) + EIEIO_32 + sthbrx r5,0,r3 + bdnz 00b + SYNC_64 + blr + +_GLOBAL(_insl) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwbrx r5,0,r3 + eieio + stwu r5,4(r4) + bdnz 00b + IN_SYNC + blr + +_GLOBAL(_outsl) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwzu r5,4(r4) + stwbrx r5,0,r3 + EIEIO_32 + bdnz 00b + SYNC_64 + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_insw) +#endif +_GLOBAL(_insw_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhz r5,0(r3) + eieio + sthu r5,2(r4) + bdnz 00b + IN_SYNC + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_outsw) +#endif +_GLOBAL(_outsw_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhzu r5,2(r4) + sth r5,0(r3) + EIEIO_32 + bdnz 00b + SYNC_64 + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_insl) +#endif +_GLOBAL(_insl_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwz r5,0(r3) + eieio + stwu r5,4(r4) + bdnz 00b + IN_SYNC + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_outsl) +#endif +_GLOBAL(_outsl_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwzu r5,4(r4) + stw r5,0(r3) + EIEIO_32 + bdnz 00b + SYNC_64 + blr + diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 01d3916..c74774e 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -61,32 +61,6 @@ _GLOBAL(mulhdu) blr /* - * Returns (address we're running at) - (address we were linked at) - * for use before the text and data are mapped to KERNELBASE. - */ -_GLOBAL(reloc_offset) - mflr r0 - bl 1f -1: mflr r3 - LOAD_REG_IMMEDIATE(r4,1b) - subf r3,r4,r3 - mtlr r0 - blr - -/* - * add_reloc_offset(x) returns x + reloc_offset(). - */ -_GLOBAL(add_reloc_offset) - mflr r0 - bl 1f -1: mflr r5 - LOAD_REG_IMMEDIATE(r4,1b) - subf r5,r4,r5 - add r3,r3,r5 - mtlr r0 - blr - -/* * sub_reloc_offset(x) returns x - reloc_offset(). */ _GLOBAL(sub_reloc_offset) @@ -781,136 +755,6 @@ _GLOBAL(atomic_set_mask) blr /* - * I/O string operations - * - * insb(port, buf, len) - * outsb(port, buf, len) - * insw(port, buf, len) - * outsw(port, buf, len) - * insl(port, buf, len) - * outsl(port, buf, len) - * insw_ns(port, buf, len) - * outsw_ns(port, buf, len) - * insl_ns(port, buf, len) - * outsl_ns(port, buf, len) - * - * The *_ns versions don't do byte-swapping. - */ -_GLOBAL(_insb) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,1 - blelr- -00: lbz r5,0(r3) - eieio - stbu r5,1(r4) - bdnz 00b - blr - -_GLOBAL(_outsb) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,1 - blelr- -00: lbzu r5,1(r4) - stb r5,0(r3) - eieio - bdnz 00b - blr - -_GLOBAL(_insw) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhbrx r5,0,r3 - eieio - sthu r5,2(r4) - bdnz 00b - blr - -_GLOBAL(_outsw) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhzu r5,2(r4) - eieio - sthbrx r5,0,r3 - bdnz 00b - blr - -_GLOBAL(_insl) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwbrx r5,0,r3 - eieio - stwu r5,4(r4) - bdnz 00b - blr - -_GLOBAL(_outsl) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwzu r5,4(r4) - stwbrx r5,0,r3 - eieio - bdnz 00b - blr - -_GLOBAL(__ide_mm_insw) -_GLOBAL(_insw_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhz r5,0(r3) - eieio - sthu r5,2(r4) - bdnz 00b - blr - -_GLOBAL(__ide_mm_outsw) -_GLOBAL(_outsw_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhzu r5,2(r4) - sth r5,0(r3) - eieio - bdnz 00b - blr - -_GLOBAL(__ide_mm_insl) -_GLOBAL(_insl_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwz r5,0(r3) - eieio - stwu r5,4(r4) - bdnz 00b - blr - -_GLOBAL(__ide_mm_outsl) -_GLOBAL(_outsl_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwzu r5,4(r4) - stw r5,0(r3) - eieio - bdnz 00b - blr - -/* * Extended precision shifts. * * Updated to be valid for shift counts from 0 to 63 inclusive. diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index e8883d4..580891c 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -1,14 +1,12 @@ /* - * arch/powerpc/kernel/misc64.S - * * This file contains miscellaneous low-level functions. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) * and Paul Mackerras. * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) - * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) - * + * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version @@ -30,41 +28,10 @@ #include .text -/* - * Returns (address we are running at) - (address we were linked at) - * for use before the text and data are mapped to KERNELBASE. - */ - -_GLOBAL(reloc_offset) - mflr r0 - bl 1f -1: mflr r3 - LOAD_REG_IMMEDIATE(r4,1b) - subf r3,r4,r3 - mtlr r0 - blr - -/* - * add_reloc_offset(x) returns x + reloc_offset(). - */ -_GLOBAL(add_reloc_offset) - mflr r0 - bl 1f -1: mflr r5 - LOAD_REG_IMMEDIATE(r4,1b) - subf r5,r4,r5 - add r3,r3,r5 - mtlr r0 - blr - _GLOBAL(get_msr) mfmsr r3 blr -_GLOBAL(get_dar) - mfdar r3 - blr - _GLOBAL(get_srr0) mfsrr0 r3 blr @@ -72,10 +39,6 @@ _GLOBAL(get_srr0) _GLOBAL(get_srr1) mfsrr1 r3 blr - -_GLOBAL(get_sp) - mr r3,r1 - blr #ifdef CONFIG_IRQSTACKS _GLOBAL(call_do_softirq) @@ -101,48 +64,6 @@ _GLOBAL(call___do_IRQ) blr #endif /* CONFIG_IRQSTACKS */ - /* - * To be called by C code which needs to do some operations with MMU - * disabled. Note that interrupts have to be disabled by the caller - * prior to calling us. The code called _MUST_ be in the RMO of course - * and part of the linear mapping as we don't attempt to translate the - * stack pointer at all. The function is called with the stack switched - * to this CPU emergency stack - * - * prototype is void *call_with_mmu_off(void *func, void *data); - * - * the called function is expected to be of the form - * - * void *called(void *data); - */ -_GLOBAL(call_with_mmu_off) - mflr r0 /* get link, save it on stackframe */ - std r0,16(r1) - mr r1,r5 /* save old stack ptr */ - ld r1,PACAEMERGSP(r13) /* get emerg. stack */ - subi r1,r1,STACK_FRAME_OVERHEAD - std r0,16(r1) /* save link on emerg. stack */ - std r5,0(r1) /* save old stack ptr in backchain */ - ld r3,0(r3) /* get to real function ptr (assume same TOC) */ - bl 2f /* we need LR to return, continue at label 2 */ - - ld r0,16(r1) /* we return here from the call, get LR and */ - ld r1,0(r1) /* .. old stack ptr */ - mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ - mfmsr r4 - ori r4,r4,MSR_IR|MSR_DR - mtspr SPRN_SRR1,r4 - rfid - -2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ - mr r3,r4 /* get parameter */ - mfmsr r0 - ori r0,r0,MSR_IR|MSR_DR - xori r0,r0,MSR_IR|MSR_DR - mtspr SPRN_SRR1,r0 - rfid - - .section ".toc","aw" PPC64_CACHES: .tc ppc64_caches[TC],ppc64_caches @@ -323,144 +244,6 @@ _GLOBAL(__flush_dcache_icache) bdnz 1b isync blr - -/* - * I/O string operations - * - * insb(port, buf, len) - * outsb(port, buf, len) - * insw(port, buf, len) - * outsw(port, buf, len) - * insl(port, buf, len) - * outsl(port, buf, len) - * insw_ns(port, buf, len) - * outsw_ns(port, buf, len) - * insl_ns(port, buf, len) - * outsl_ns(port, buf, len) - * - * The *_ns versions don't do byte-swapping. - */ -_GLOBAL(_insb) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,1 - blelr- -00: lbz r5,0(r3) - eieio - stbu r5,1(r4) - bdnz 00b - twi 0,r5,0 - isync - blr - -_GLOBAL(_outsb) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,1 - blelr- -00: lbzu r5,1(r4) - stb r5,0(r3) - bdnz 00b - sync - blr - -_GLOBAL(_insw) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhbrx r5,0,r3 - eieio - sthu r5,2(r4) - bdnz 00b - twi 0,r5,0 - isync - blr - -_GLOBAL(_outsw) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhzu r5,2(r4) - sthbrx r5,0,r3 - bdnz 00b - sync - blr - -_GLOBAL(_insl) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwbrx r5,0,r3 - eieio - stwu r5,4(r4) - bdnz 00b - twi 0,r5,0 - isync - blr - -_GLOBAL(_outsl) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwzu r5,4(r4) - stwbrx r5,0,r3 - bdnz 00b - sync - blr - -/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ -_GLOBAL(_insw_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhz r5,0(r3) - eieio - sthu r5,2(r4) - bdnz 00b - twi 0,r5,0 - isync - blr - -/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ -_GLOBAL(_outsw_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,2 - blelr- -00: lhzu r5,2(r4) - sth r5,0(r3) - bdnz 00b - sync - blr - -_GLOBAL(_insl_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwz r5,0(r3) - eieio - stwu r5,4(r4) - bdnz 00b - twi 0,r5,0 - isync - blr - -_GLOBAL(_outsl_ns) - cmpwi 0,r5,0 - mtctr r5 - subi r4,r4,4 - blelr- -00: lwzu r5,4(r4) - stw r5,0(r3) - bdnz 00b - sync - blr /* * identify_cpu and calls setup_cpu @@ -605,6 +388,7 @@ _GLOBAL(real_writeb) blr #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ +#ifdef CONFIG_CPU_FREQ_PMAC64 /* * SCOM access functions for 970 (FX only for now) * @@ -673,6 +457,7 @@ _GLOBAL(scom970_write) /* restore interrupts */ mtmsrd r5,1 blr +#endif /* CONFIG_CPU_FREQ_PMAC64 */ /* diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index f505a88..a0bb354 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -16,7 +16,6 @@ #include #include #include #include -#include #include #include diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 483455c..ce02c05 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -30,6 +30,7 @@ #include #include #include #include +#include #include #include @@ -1124,24 +1125,6 @@ #ifdef CONFIG_PPC64 tce_alloc_end = *lprop; #endif -#ifdef CONFIG_PPC_RTAS - /* To help early debugging via the front panel, we retrieve a minimal - * set of RTAS infos now if available - */ - { - u64 *basep, *entryp, *sizep; - - basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); - entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); - sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); - if (basep && entryp && sizep) { - rtas.base = *basep; - rtas.entry = *entryp; - rtas.size = *sizep; - } - } -#endif /* CONFIG_PPC_RTAS */ - #ifdef CONFIG_KEXEC lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL); if (lprop) @@ -1326,6 +1309,11 @@ void __init early_init_devtree(void *par /* Setup flat device-tree pointer */ initial_boot_params = params; +#ifdef CONFIG_PPC_RTAS + /* Some machines might need RTAS info for debugging, grab it now. */ + of_scan_flat_dt(early_init_dt_scan_rtas, NULL); +#endif + /* Retrieve various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... @@ -2148,3 +2136,27 @@ struct device_node *of_get_cpu_node(int } return NULL; } + +#ifdef DEBUG +static struct debugfs_blob_wrapper flat_dt_blob; + +static int __init export_flat_device_tree(void) +{ + struct dentry *d; + + d = debugfs_create_dir("powerpc", NULL); + if (!d) + return 1; + + flat_dt_blob.data = initial_boot_params; + flat_dt_blob.size = initial_boot_params->totalsize; + + d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, + d, &flat_dt_blob); + if (!d) + return 1; + + return 0; +} +__initcall(export_flat_device_tree); +#endif diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 17dc791..4a4cb55 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -38,16 +38,19 @@ #include struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED }; +EXPORT_SYMBOL(rtas); struct rtas_suspend_me_data { long waiting; struct rtas_args *args; }; -EXPORT_SYMBOL(rtas); - DEFINE_SPINLOCK(rtas_data_buf_lock); +EXPORT_SYMBOL(rtas_data_buf_lock); + char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; +EXPORT_SYMBOL(rtas_data_buf); + unsigned long rtas_rmo_buf; /* @@ -106,11 +109,71 @@ static void call_rtas_display_status_del } } -void __init udbg_init_rtas(void) +void __init udbg_init_rtas_panel(void) { udbg_putc = call_rtas_display_status_delay; } +#ifdef CONFIG_UDBG_RTAS_CONSOLE + +/* If you think you're dying before early_init_dt_scan_rtas() does its + * work, you can hard code the token values for your firmware here and + * hardcode rtas.base/entry etc. + */ +static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE; +static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE; + +static void udbg_rtascon_putc(char c) +{ + int tries; + + if (!rtas.base) + return; + + /* Add CRs before LFs */ + if (c == '\n') + udbg_rtascon_putc('\r'); + + /* if there is more than one character to be displayed, wait a bit */ + for (tries = 0; tries < 16; tries++) { + if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0) + break; + udelay(1000); + } +} + +static int udbg_rtascon_getc_poll(void) +{ + int c; + + if (!rtas.base) + return -1; + + if (rtas_call(rtas_getchar_token, 0, 2, &c)) + return -1; + + return c; +} + +static int udbg_rtascon_getc(void) +{ + int c; + + while ((c = udbg_rtascon_getc_poll()) == -1) + ; + + return c; +} + + +void __init udbg_init_rtas_console(void) +{ + udbg_putc = udbg_rtascon_putc; + udbg_getc = udbg_rtascon_getc; + udbg_getc_poll = udbg_rtascon_getc_poll; +} +#endif /* CONFIG_UDBG_RTAS_CONSOLE */ + void rtas_progress(char *s, unsigned short hex) { struct device_node *root; @@ -236,6 +299,7 @@ int rtas_token(const char *service) tokp = (int *) get_property(rtas.dev, service, NULL); return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } +EXPORT_SYMBOL(rtas_token); #ifdef CONFIG_RTAS_ERROR_LOGGING /* @@ -328,7 +392,7 @@ int rtas_call(int token, int nargs, int char *buff_copy = NULL; int ret; - if (token == RTAS_UNKNOWN_SERVICE) + if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) return -1; /* Gotta do something different here, use global lock for now... */ @@ -369,6 +433,7 @@ int rtas_call(int token, int nargs, int } return ret; } +EXPORT_SYMBOL(rtas_call); /* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. @@ -388,6 +453,7 @@ unsigned int rtas_busy_delay_time(int st return ms; } +EXPORT_SYMBOL(rtas_busy_delay_time); /* For an RTAS busy status code, perform the hinted delay. */ unsigned int rtas_busy_delay(int status) @@ -401,6 +467,7 @@ unsigned int rtas_busy_delay(int status) return ms; } +EXPORT_SYMBOL(rtas_busy_delay); int rtas_error_rc(int rtas_rc) { @@ -446,6 +513,7 @@ int rtas_get_power_level(int powerdomain return rtas_error_rc(rc); return rc; } +EXPORT_SYMBOL(rtas_get_power_level); int rtas_set_power_level(int powerdomain, int level, int *setlevel) { @@ -463,6 +531,7 @@ int rtas_set_power_level(int powerdomain return rtas_error_rc(rc); return rc; } +EXPORT_SYMBOL(rtas_set_power_level); int rtas_get_sensor(int sensor, int index, int *state) { @@ -480,6 +549,7 @@ int rtas_get_sensor(int sensor, int inde return rtas_error_rc(rc); return rc; } +EXPORT_SYMBOL(rtas_get_sensor); int rtas_set_indicator(int indicator, int index, int new_value) { @@ -497,6 +567,7 @@ int rtas_set_indicator(int indicator, in return rtas_error_rc(rc); return rc; } +EXPORT_SYMBOL(rtas_set_indicator); void rtas_restart(char *cmd) { @@ -791,14 +862,34 @@ #ifdef CONFIG_RTAS_ERROR_LOGGING #endif } +int __init early_init_dt_scan_rtas(unsigned long node, + const char *uname, int depth, void *data) +{ + u32 *basep, *entryp, *sizep; -EXPORT_SYMBOL(rtas_token); -EXPORT_SYMBOL(rtas_call); -EXPORT_SYMBOL(rtas_data_buf); -EXPORT_SYMBOL(rtas_data_buf_lock); -EXPORT_SYMBOL(rtas_busy_delay_time); -EXPORT_SYMBOL(rtas_busy_delay); -EXPORT_SYMBOL(rtas_get_sensor); -EXPORT_SYMBOL(rtas_get_power_level); -EXPORT_SYMBOL(rtas_set_power_level); -EXPORT_SYMBOL(rtas_set_indicator); + if (depth != 1 || strcmp(uname, "rtas") != 0) + return 0; + + basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); + entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); + sizep = of_get_flat_dt_prop(node, "rtas-size", NULL); + + if (basep && entryp && sizep) { + rtas.base = *basep; + rtas.entry = *entryp; + rtas.size = *sizep; + } + +#ifdef CONFIG_UDBG_RTAS_CONSOLE + basep = of_get_flat_dt_prop(node, "put-term-char", NULL); + if (basep) + rtas_putchar_token = *basep; + + basep = of_get_flat_dt_prop(node, "get-term-char", NULL); + if (basep) + rtas_getchar_token = *basep; +#endif + + /* break now */ + return 1; +} diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 78f3a5f..a2fb2e6 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -149,6 +149,13 @@ #else #define check_smt_enabled() #endif /* CONFIG_SMP */ +/* Put the paca pointer into r13 and SPRG3 */ +void __init setup_paca(int cpu) +{ + local_paca = &paca[cpu]; + mtspr(SPRN_SPRG3, local_paca); +} + /* * Early initialization entry point. This is called by head.S * with MMU translation disabled. We rely on the "feature" of @@ -183,7 +190,7 @@ void __init early_setup(unsigned long dt early_init_devtree(__va(dt_ptr)); /* Now we know the logical id of our boot cpu, setup the paca. */ - setup_boot_paca(); + setup_paca(boot_cpuid); /* Fix up paca fields required for the boot cpu */ get_paca()->cpu_start = 1; @@ -350,19 +357,11 @@ void __init setup_system(void) */ unflatten_device_tree(); -#ifdef CONFIG_KEXEC - kexec_setup(); /* requires unflattened device tree. */ -#endif - /* * Fill the ppc64_caches & systemcfg structures with informations * retrieved from the device-tree. Need to be called before * finish_device_tree() since the later requires some of the - * informations filled up here to properly parse the interrupt - * tree. - * It also sets up the cache line sizes which allows to call - * routines like flush_icache_range (used by the hash init - * later on). + * informations filled up here to properly parse the interrupt tree. */ initialize_cache_info(); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 52f5659..fa6bd97 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -52,9 +52,13 @@ #ifdef CONFIG_PPC64 #include #include #endif +#include #ifdef CONFIG_PPC64 /* XXX */ #define _IO_BASE pci_io_base +#ifdef CONFIG_KEXEC +cpumask_t cpus_in_sr = CPU_MASK_NONE; +#endif #endif #ifdef CONFIG_DEBUGGER @@ -97,7 +101,7 @@ static DEFINE_SPINLOCK(die_lock); int die(const char *str, struct pt_regs *regs, long err) { - static int die_counter, crash_dump_start = 0; + static int die_counter; if (debugger(regs)) return 1; @@ -137,21 +141,12 @@ #endif print_modules(); show_regs(regs); bust_spinlocks(0); + spin_unlock_irq(&die_lock); - if (!crash_dump_start && kexec_should_crash(current)) { - crash_dump_start = 1; - spin_unlock_irq(&die_lock); + if (kexec_should_crash(current) || + kexec_sr_activated(smp_processor_id())) crash_kexec(regs); - /* NOTREACHED */ - } - spin_unlock_irq(&die_lock); - if (crash_dump_start) - /* - * Only for soft-reset: Other CPUs will be responded to an IPI - * sent by first kexec CPU. - */ - for(;;) - ; + crash_kexec_secondary(regs); if (in_interrupt()) panic("Fatal exception in interrupt"); @@ -215,6 +210,10 @@ void system_reset_exception(struct pt_re return; } +#ifdef CONFIG_KEXEC + cpu_set(smp_processor_id(), cpus_in_sr); +#endif + die("System Reset", regs, SIGABRT); /* Must die if the interrupt is not recoverable */ diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 67d9fd9..759afd5 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -34,9 +34,12 @@ #if defined(CONFIG_PPC_EARLY_DEBUG_LPAR) #elif defined(CONFIG_PPC_EARLY_DEBUG_G5) /* For use on Apple G5 machines */ udbg_init_pmac_realmode(); -#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS) +#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL) /* RTAS panel debug */ - udbg_init_rtas(); + udbg_init_rtas_panel(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE) + /* RTAS console debug */ + udbg_init_rtas_console(); #elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE) /* Maple real mode debug */ udbg_init_maple_realmode(); diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index a0f3cbd..c90f124 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c @@ -520,7 +520,7 @@ static inline int tlb_batching_enabled(v } #endif -void hpte_init_native(void) +void __init hpte_init_native(void) { ppc_md.hpte_invalidate = native_hpte_invalidate; ppc_md.hpte_updatepp = native_hpte_updatepp; @@ -530,5 +530,4 @@ void hpte_init_native(void) ppc_md.hpte_clear_all = native_hpte_clear; if (tlb_batching_enabled()) ppc_md.flush_hash_range = native_flush_hash_range; - htab_finish_init(); } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index d03fd2b..3cc6d68 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -167,34 +167,12 @@ int htab_bolt_mapping(unsigned long vsta hash = hpt_hash(va, shift); hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); - /* The crap below can be cleaned once ppd_md.probe() can - * set up the hash callbacks, thus we can just used the - * normal insert callback here. - */ -#ifdef CONFIG_PPC_ISERIES - if (machine_is(iseries)) - ret = iSeries_hpte_insert(hpteg, va, - paddr, - tmp_mode, - HPTE_V_BOLTED, - psize); - else -#endif -#ifdef CONFIG_PPC_PSERIES - if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) - ret = pSeries_lpar_hpte_insert(hpteg, va, - paddr, - tmp_mode, - HPTE_V_BOLTED, - psize); - else -#endif -#ifdef CONFIG_PPC_MULTIPLATFORM - ret = native_hpte_insert(hpteg, va, - paddr, - tmp_mode, HPTE_V_BOLTED, - psize); -#endif + DBG("htab_bolt_mapping: calling %p\n", ppc_md.hpte_insert); + + BUG_ON(!ppc_md.hpte_insert); + ret = ppc_md.hpte_insert(hpteg, va, paddr, + tmp_mode, HPTE_V_BOLTED, psize); + if (ret < 0) break; } @@ -413,6 +391,41 @@ void create_section_mapping(unsigned lon } #endif /* CONFIG_MEMORY_HOTPLUG */ +static inline void make_bl(unsigned int *insn_addr, void *func) +{ + unsigned long funcp = *((unsigned long *)func); + int offset = funcp - (unsigned long)insn_addr; + + *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc)); + flush_icache_range((unsigned long)insn_addr, 4+ + (unsigned long)insn_addr); +} + +static void __init htab_finish_init(void) +{ + extern unsigned int *htab_call_hpte_insert1; + extern unsigned int *htab_call_hpte_insert2; + extern unsigned int *htab_call_hpte_remove; + extern unsigned int *htab_call_hpte_updatepp; + +#ifdef CONFIG_PPC_64K_PAGES + extern unsigned int *ht64_call_hpte_insert1; + extern unsigned int *ht64_call_hpte_insert2; + extern unsigned int *ht64_call_hpte_remove; + extern unsigned int *ht64_call_hpte_updatepp; + + make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert); + make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove); + make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp); +#endif /* CONFIG_PPC_64K_PAGES */ + + make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); + make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); + make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); + make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp); +} + void __init htab_initialize(void) { unsigned long table; @@ -525,6 +538,8 @@ #endif /* CONFIG_U3_DART */ mmu_linear_psize)); } + htab_finish_init(); + DBG(" <- htab_initialize()\n"); } #undef KB @@ -787,16 +802,6 @@ void flush_hash_range(unsigned long numb } } -static inline void make_bl(unsigned int *insn_addr, void *func) -{ - unsigned long funcp = *((unsigned long *)func); - int offset = funcp - (unsigned long)insn_addr; - - *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc)); - flush_icache_range((unsigned long)insn_addr, 4+ - (unsigned long)insn_addr); -} - /* * low_hash_fault is called when we the low level hash code failed * to instert a PTE due to an hypervisor error @@ -815,28 +820,3 @@ void low_hash_fault(struct pt_regs *regs } bad_page_fault(regs, address, SIGBUS); } - -void __init htab_finish_init(void) -{ - extern unsigned int *htab_call_hpte_insert1; - extern unsigned int *htab_call_hpte_insert2; - extern unsigned int *htab_call_hpte_remove; - extern unsigned int *htab_call_hpte_updatepp; - -#ifdef CONFIG_PPC_64K_PAGES - extern unsigned int *ht64_call_hpte_insert1; - extern unsigned int *ht64_call_hpte_insert2; - extern unsigned int *ht64_call_hpte_remove; - extern unsigned int *ht64_call_hpte_updatepp; - - make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert); - make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert); - make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove); - make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp); -#endif /* CONFIG_PPC_64K_PAGES */ - - make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); - make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); - make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); - make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp); -} diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 3a87863..d1ecc0f 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -7,6 +7,7 @@ choice config MPC8641_HPCN bool "Freescale MPC8641 HPCN" + select PPC_I8259 help This option enables support for the MPC8641 HPCN board. @@ -28,9 +29,4 @@ config PPC_INDIRECT_PCI_BE depends on PPC_86xx default y -config PPC_STD_MMU - bool - depends on PPC_86xx - default y - endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 7be796c..476a6ee 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -2,9 +2,6 @@ # # Makefile for the PowerPC 86xx linux kernel. # - -ifeq ($(CONFIG_PPC_86xx),y) obj-$(CONFIG_SMP) += mpc86xx_smp.o -endif obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h index 5042253..5d2bcf7 100644 --- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h @@ -14,7 +14,6 @@ #ifndef __MPC8641_HPCN_H__ #define __MPC8641_HPCN_H__ -#include #include /* PCI interrupt controller */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 483c21d..a9a8539 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -12,7 +12,6 @@ * option) any later version. */ -#include #include #include #include diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c index 944ec4b..167f040 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -10,7 +10,6 @@ * option) any later version. */ -#include #include #include #include diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 5180df7..6dfdcb8 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c @@ -12,7 +12,6 @@ * option) any later version. */ -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 352bbba..0c8c7b6 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -6,6 +6,7 @@ config SPU_FS default m depends on PPC_CELL select SPU_BASE + select MEMORY_HOTPLUG help The SPU file system is used to access Synergistic Processing Units on machines implementing the Broadband Processor @@ -18,7 +19,6 @@ config SPU_BASE config SPUFS_MMAP bool depends on SPU_FS && SPARSEMEM - select MEMORY_HOTPLUG default y config CBE_RAS diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 3d1831d..00d112f 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -125,8 +125,6 @@ static void __init cell_init_early(void) { DBG(" -> cell_init_early()\n"); - hpte_init_native(); - cell_init_iommu(); ppc64_interrupt_controller = IC_CELL_PIC; @@ -139,11 +137,17 @@ static int __init cell_probe(void) { unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "IBM,CBEA") || - of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) - return 1; + if (!of_flat_dt_is_compatible(root, "IBM,CBEA") && + !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) + return 0; + +#ifdef CONFIG_UDBG_RTAS_CONSOLE + udbg_init_rtas_console(); +#endif + + hpte_init_native(); - return 0; + return 1; } /* diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index db82f50..b306723 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -168,12 +168,12 @@ spu_irq_class_0_bottom(struct spu *spu) stat &= mask; - if (stat & 1) /* invalid MFC DMA */ - __spu_trap_invalid_dma(spu); - - if (stat & 2) /* invalid DMA alignment */ + if (stat & 1) /* invalid DMA alignment */ __spu_trap_dma_align(spu); + if (stat & 2) /* invalid MFC DMA */ + __spu_trap_invalid_dma(spu); + if (stat & 4) /* error on SPU */ __spu_trap_error(spu); diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 7854a38..58e794f 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -204,7 +204,7 @@ static int spufs_cntl_mmap(struct file * vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE); + | _PAGE_NO_CACHE | _PAGE_GUARDED); vma->vm_ops = &spufs_cntl_mmap_vmops; return 0; @@ -675,7 +675,7 @@ static int spufs_signal1_mmap(struct fil vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE); + | _PAGE_NO_CACHE | _PAGE_GUARDED); vma->vm_ops = &spufs_signal1_mmap_vmops; return 0; @@ -762,7 +762,7 @@ static int spufs_signal2_mmap(struct fil /* FIXME: */ vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE); + | _PAGE_NO_CACHE | _PAGE_GUARDED); vma->vm_ops = &spufs_signal2_mmap_vmops; return 0; @@ -850,7 +850,7 @@ static int spufs_mss_mmap(struct file *f vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE); + | _PAGE_NO_CACHE | _PAGE_GUARDED); vma->vm_ops = &spufs_mss_mmap_vmops; return 0; @@ -899,7 +899,7 @@ static int spufs_mfc_mmap(struct file *f vma->vm_flags |= VM_RESERVED; vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) - | _PAGE_NO_CACHE); + | _PAGE_NO_CACHE | _PAGE_GUARDED); vma->vm_ops = &spufs_mfc_mmap_vmops; return 0; diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 3068b42..015a517 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -464,7 +464,8 @@ static inline void wait_purge_complete(s * Poll MFC_CNTL[Ps] until value '11' is read * (purge complete). */ - POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) & + POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & + MFC_CNTL_PURGE_DMA_STATUS_MASK) == MFC_CNTL_PURGE_DMA_COMPLETE); } @@ -1028,7 +1029,8 @@ static inline void wait_suspend_mfc_comp * Restore, Step 47. * Poll MFC_CNTL[Ss] until 11 is returned. */ - POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) & + POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) & + MFC_CNTL_SUSPEND_DMA_STATUS_MASK) == MFC_CNTL_SUSPEND_COMPLETE); } diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index 30bdcf3..ed44dfc 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c @@ -242,13 +242,11 @@ static void iSeries_hpte_invalidate(unsi local_irq_restore(flags); } -void hpte_init_iSeries(void) +void __init hpte_init_iSeries(void) { ppc_md.hpte_invalidate = iSeries_hpte_invalidate; ppc_md.hpte_updatepp = iSeries_hpte_updatepp; ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; ppc_md.hpte_insert = iSeries_hpte_insert; ppc_md.hpte_remove = iSeries_hpte_remove; - - htab_finish_init(); } diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index 8ca7b93..2a9f81e 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -51,20 +51,21 @@ static unsigned lpEventHandlerPaths[HvLp static struct HvLpEvent * get_next_hvlpevent(void) { struct HvLpEvent * event; - event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; + event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event; if (hvlpevent_is_valid(event)) { /* rmb() needed only for weakly consistent machines (regatta) */ rmb(); /* Set pointer to next potential event */ - hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 + - LpEventAlign) / LpEventAlign) * LpEventAlign; + hvlpevent_queue.hq_current_event += ((event->xSizeMinus1 + + IT_LP_EVENT_ALIGN) / IT_LP_EVENT_ALIGN) * + IT_LP_EVENT_ALIGN; /* Wrap to beginning if no room at end */ - if (hvlpevent_queue.xSlicCurEventPtr > - hvlpevent_queue.xSlicLastValidEventPtr) { - hvlpevent_queue.xSlicCurEventPtr = - hvlpevent_queue.xSlicEventStackPtr; + if (hvlpevent_queue.hq_current_event > + hvlpevent_queue.hq_last_event) { + hvlpevent_queue.hq_current_event = + hvlpevent_queue.hq_event_stack; } } else { event = NULL; @@ -82,10 +83,10 @@ int hvlpevent_is_pending(void) if (smp_processor_id() >= spread_lpevents) return 0; - next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; + next_event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event; return hvlpevent_is_valid(next_event) || - hvlpevent_queue.xPlicOverflowIntPending; + hvlpevent_queue.hq_overflow_pending; } static void hvlpevent_clear_valid(struct HvLpEvent * event) @@ -95,18 +96,18 @@ static void hvlpevent_clear_valid(struct * ie. on 64-byte boundaries. */ struct HvLpEvent *tmp; - unsigned extra = ((event->xSizeMinus1 + LpEventAlign) / - LpEventAlign) - 1; + unsigned extra = ((event->xSizeMinus1 + IT_LP_EVENT_ALIGN) / + IT_LP_EVENT_ALIGN) - 1; switch (extra) { case 3: - tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign); + tmp = (struct HvLpEvent*)((char*)event + 3 * IT_LP_EVENT_ALIGN); hvlpevent_invalidate(tmp); case 2: - tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign); + tmp = (struct HvLpEvent*)((char*)event + 2 * IT_LP_EVENT_ALIGN); hvlpevent_invalidate(tmp); case 1: - tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign); + tmp = (struct HvLpEvent*)((char*)event + 1 * IT_LP_EVENT_ALIGN); hvlpevent_invalidate(tmp); } @@ -120,7 +121,7 @@ void process_hvlpevents(struct pt_regs * struct HvLpEvent * event; /* If we have recursed, just return */ - if (!spin_trylock(&hvlpevent_queue.lock)) + if (!spin_trylock(&hvlpevent_queue.hq_lock)) return; for (;;) { @@ -148,17 +149,17 @@ void process_hvlpevents(struct pt_regs * printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType ); hvlpevent_clear_valid(event); - } else if (hvlpevent_queue.xPlicOverflowIntPending) + } else if (hvlpevent_queue.hq_overflow_pending) /* * No more valid events. If overflow events are * pending process them */ - HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex); + HvCallEvent_getOverflowLpEvents(hvlpevent_queue.hq_index); else break; } - spin_unlock(&hvlpevent_queue.lock); + spin_unlock(&hvlpevent_queue.hq_lock); } static int set_spread_lpevents(char *str) @@ -184,20 +185,20 @@ void setup_hvlpevent_queue(void) { void *eventStack; - spin_lock_init(&hvlpevent_queue.lock); + spin_lock_init(&hvlpevent_queue.hq_lock); /* Allocate a page for the Event Stack. */ - eventStack = alloc_bootmem_pages(LpEventStackSize); - memset(eventStack, 0, LpEventStackSize); + eventStack = alloc_bootmem_pages(IT_LP_EVENT_STACK_SIZE); + memset(eventStack, 0, IT_LP_EVENT_STACK_SIZE); /* Invoke the hypervisor to initialize the event stack */ - HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize); + HvCallEvent_setLpEventStack(0, eventStack, IT_LP_EVENT_STACK_SIZE); - hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack; - hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack; - hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack + - (LpEventStackSize - LpEventMaxSize); - hvlpevent_queue.xIndex = 0; + hvlpevent_queue.hq_event_stack = eventStack; + hvlpevent_queue.hq_current_event = eventStack; + hvlpevent_queue.hq_last_event = (char *)eventStack + + (IT_LP_EVENT_STACK_SIZE - IT_LP_EVENT_MAX_SIZE); + hvlpevent_queue.hq_index = 0; } /* Register a handler for an LpEvent type */ diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c index e68b6b5..c241413 100644 --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -24,7 +24,6 @@ #include #include #include #include -#include #include #include "processor_vpd.h" diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 617c724..66c77e4 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -81,8 +81,6 @@ static void iSeries_pci_final_fixup(void #endif extern int rd_size; /* Defined in drivers/block/rd.c */ -extern unsigned long embedded_sysmap_start; -extern unsigned long embedded_sysmap_end; extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; @@ -321,11 +319,6 @@ #endif /* CONFIG_BLK_DEV_INITRD */ iSeries_recal_titan = HvCallXm_loadTod(); /* - * Initialize the hash table management pointers - */ - hpte_init_iSeries(); - - /* * Initialize the DMA/TCE management */ iommu_init_early_iSeries(); @@ -563,16 +556,6 @@ static void __init iSeries_fixup_klimit( if (naca.xRamDisk) klimit = KERNELBASE + (u64)naca.xRamDisk + (naca.xRamDiskSize * HW_PAGE_SIZE); - else { - /* - * No ram disk was included - check and see if there - * was an embedded system map. Change klimit to take - * into account any embedded system map - */ - if (embedded_sysmap_end) - klimit = KERNELBASE + ((embedded_sysmap_end + 4095) & - 0xfffffffffffff000); - } } static int __init iSeries_src_init(void) @@ -683,6 +666,8 @@ static int __init iseries_probe(void) */ virt_irq_max = 255; + hpte_init_iSeries(); + return 1; } diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index a0505ea..4e32a54 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -199,11 +199,6 @@ static void __init maple_init_early(void { DBG(" -> maple_init_early\n"); - /* Initialize hash table, from now on, we can take hash faults - * and call ioremap - */ - hpte_init_native(); - /* Setup interrupt mapping options */ ppc64_interrupt_controller = IC_OPEN_PIC; @@ -272,6 +267,8 @@ static int __init maple_probe(void) */ alloc_dart_table(); + hpte_init_native(); + return 1; } diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 9cc7db7..89c5775 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -600,13 +600,6 @@ pmac_halt(void) */ static void __init pmac_init_early(void) { -#ifdef CONFIG_PPC64 - /* Initialize hash table, from now on, we can take hash faults - * and call ioremap - */ - hpte_init_native(); -#endif - /* Enable early btext debug if requested */ if (strstr(cmd_line, "btextdbg")) { udbg_adb_init_early(); @@ -683,6 +676,8 @@ #ifdef CONFIG_PPC64 * part of the cacheable linar mapping */ alloc_dart_table(); + + hpte_init_native(); #endif #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index d03a8b0..8cfb570 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -92,6 +92,15 @@ static void tce_free_pSeries(struct iomm *(tcep++) = 0; } +static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) +{ + u64 *tcep; + + index <<= TCE_PAGE_FACTOR; + tcep = ((u64 *)tbl->it_base) + index; + + return *tcep; +} static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages, unsigned long uaddr, @@ -235,6 +244,25 @@ static void tce_freemulti_pSeriesLP(stru } } +static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) +{ + u64 rc; + unsigned long tce_ret; + + tcenum <<= TCE_PAGE_FACTOR; + rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret); + + if (rc && printk_ratelimit()) { + printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%ld\n", + rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\ttcenum = 0x%lx\n", (u64)tcenum); + show_stack(current, (unsigned long *)__get_SP()); + } + + return tce_ret; +} + static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) @@ -254,7 +282,10 @@ static void iommu_table_setparms(struct } tbl->it_base = (unsigned long)__va(*basep); + +#ifndef CONFIG_CRASH_DUMP memset((void *)tbl->it_base, 0, *sizep); +#endif tbl->it_busno = phb->bus->number; @@ -560,11 +591,13 @@ void iommu_init_early_pSeries(void) ppc_md.tce_build = tce_build_pSeriesLP; ppc_md.tce_free = tce_free_pSeriesLP; } + ppc_md.tce_get = tce_get_pSeriesLP; ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; } else { ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_free = tce_free_pSeries; + ppc_md.tce_get = tce_get_pseries; ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; } diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 634b7d0..2748070 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -513,7 +513,7 @@ void pSeries_lpar_flush_hash_range(unsig spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); } -void hpte_init_lpar(void) +void __init hpte_init_lpar(void) { ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp; @@ -522,6 +522,4 @@ void hpte_init_lpar(void) ppc_md.hpte_remove = pSeries_lpar_hpte_remove; ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear; - - htab_finish_init(); } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 1e28518..b3197ff 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -322,11 +322,6 @@ static void __init pSeries_init_early(vo DBG(" -> pSeries_init_early()\n"); fw_feature_init(); - - if (firmware_has_feature(FW_FEATURE_LPAR)) - hpte_init_lpar(); - else - hpte_init_native(); if (firmware_has_feature(FW_FEATURE_LPAR)) find_udbg_vterm(); @@ -384,6 +379,11 @@ static int __init pSeries_probe_hypertas if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) powerpc_firmware_features |= FW_FEATURE_LPAR; + if (firmware_has_feature(FW_FEATURE_LPAR)) + hpte_init_lpar(); + else + hpte_init_native(); + return 1; } diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d633081..d1266fe 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -774,11 +774,18 @@ config BLK_DEV_IDEDMA_PMAC performance. config BLK_DEV_IDE_PMAC_BLINK - bool "Blink laptop LED on drive activity" + bool "Blink laptop LED on drive activity (DEPRECATED)" depends on BLK_DEV_IDE_PMAC && ADB_PMU + select ADB_PMU_LED + select LEDS_TRIGGERS + select LEDS_TRIGGER_IDE_DISK help This option enables the use of the sleep LED as a hard drive activity LED. + This option is deprecated, it only selects ADB_PMU_LED and + LEDS_TRIGGER_IDE_DISK and changes the code in the new led class + device to default to the ide-disk trigger (which should be set + from userspace via sysfs). config BLK_DEV_IDE_SWARM tristate "IDE for Sibyte evaluation boards" diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index ffca8b6..e8ef345 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -421,107 +421,6 @@ static void pmac_ide_kauai_selectproc(id #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ /* - * Below is the code for blinking the laptop LED along with hard - * disk activity. - */ - -#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK - -/* Set to 50ms minimum led-on time (also used to limit frequency - * of requests sent to the PMU - */ -#define PMU_HD_BLINK_TIME (HZ/50) - -static struct adb_request pmu_blink_on, pmu_blink_off; -static spinlock_t pmu_blink_lock; -static unsigned long pmu_blink_stoptime; -static int pmu_blink_ledstate; -static struct timer_list pmu_blink_timer; -static int pmu_ide_blink_enabled; - - -static void -pmu_hd_blink_timeout(unsigned long data) -{ - unsigned long flags; - - spin_lock_irqsave(&pmu_blink_lock, flags); - - /* We may have been triggered again in a racy way, check - * that we really want to switch it off - */ - if (time_after(pmu_blink_stoptime, jiffies)) - goto done; - - /* Previous req. not complete, try 100ms more */ - if (pmu_blink_off.complete == 0) - mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME); - else if (pmu_blink_ledstate) { - pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0); - pmu_blink_ledstate = 0; - } -done: - spin_unlock_irqrestore(&pmu_blink_lock, flags); -} - -static void -pmu_hd_kick_blink(void *data, int rw) -{ - unsigned long flags; - - pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME; - wmb(); - mod_timer(&pmu_blink_timer, pmu_blink_stoptime); - /* Fast path when LED is already ON */ - if (pmu_blink_ledstate == 1) - return; - spin_lock_irqsave(&pmu_blink_lock, flags); - if (pmu_blink_on.complete && !pmu_blink_ledstate) { - pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1); - pmu_blink_ledstate = 1; - } - spin_unlock_irqrestore(&pmu_blink_lock, flags); -} - -static int -pmu_hd_blink_init(void) -{ - struct device_node *dt; - const char *model; - - /* Currently, I only enable this feature on KeyLargo based laptops, - * older laptops may support it (at least heathrow/paddington) but - * I don't feel like loading those venerable old machines with so - * much additional interrupt & PMU activity... - */ - if (pmu_get_model() != PMU_KEYLARGO_BASED) - return 0; - - dt = of_find_node_by_path("/"); - if (dt == NULL) - return 0; - model = (const char *)get_property(dt, "model", NULL); - if (model == NULL) - return 0; - if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && - strncmp(model, "iBook", strlen("iBook")) != 0) { - of_node_put(dt); - return 0; - } - of_node_put(dt); - - pmu_blink_on.complete = 1; - pmu_blink_off.complete = 1; - spin_lock_init(&pmu_blink_lock); - init_timer(&pmu_blink_timer); - pmu_blink_timer.function = pmu_hd_blink_timeout; - - return 1; -} - -#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ - -/* * N.B. this can't be an initfunc, because the media-bay task can * call ide_[un]register at any time. */ @@ -1192,23 +1091,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif) pmif->timings[0] = 0; pmif->timings[1] = 0; -#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK - /* Note: This code will be called for every hwif, thus we'll - * try several time to stop the LED blinker timer, but that - * should be harmless - */ - if (pmu_ide_blink_enabled) { - unsigned long flags; - - /* Make sure we don't hit the PMU blink */ - spin_lock_irqsave(&pmu_blink_lock, flags); - if (pmu_blink_ledstate) - del_timer(&pmu_blink_timer); - pmu_blink_ledstate = 0; - spin_unlock_irqrestore(&pmu_blink_lock, flags); - } -#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */ - disable_irq(pmif->irq); /* The media bay will handle itself just fine */ @@ -1376,13 +1258,6 @@ #endif hwif->selectproc = pmac_ide_selectproc; hwif->speedproc = pmac_ide_tune_chipset; -#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK - pmu_ide_blink_enabled = pmu_hd_blink_init(); - - if (pmu_ide_blink_enabled) - hwif->led_act = pmu_hd_kick_blink; -#endif - printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, pmif->mediabay ? " (mediabay)" : "", hwif->irq); diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 37cd6ee..54f3f6b 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -78,6 +78,18 @@ config ADB_PMU this device; you should do so if your machine is one of those mentioned above. +config ADB_PMU_LED + bool "Support for the Power/iBook front LED" + depends on ADB_PMU + select NEW_LEDS + select LEDS_CLASS + help + Support the front LED on Power/iBooks as a generic LED that can + be triggered by any of the supported triggers. To get the + behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this + and the ide-disk LED trigger and configure appropriately through + sysfs. + config PMAC_SMU bool "Support for SMU based PowerMacs" depends on PPC_PMAC64 diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 45a268f..b53d45f 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_ANSLCD) += ans-lcd.o obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o +obj-$(CONFIG_ADB_PMU_LED) += via-pmu-led.o obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o obj-$(CONFIG_ADB_CUDA) += via-cuda.o obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c new file mode 100644 index 0000000..af8375e --- /dev/null +++ b/drivers/macintosh/via-pmu-led.c @@ -0,0 +1,144 @@ +/* + * via-pmu LED class device + * + * Copyright 2006 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include +#include +#include +#include +#include +#include + +static spinlock_t pmu_blink_lock; +static struct adb_request pmu_blink_req; +/* -1: no change, 0: request off, 1: request on */ +static int requested_change; +static int sleeping; + +static void pmu_req_done(struct adb_request * req) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + /* if someone requested a change in the meantime + * (we only see the last one which is fine) + * then apply it now */ + if (requested_change != -1 && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + /* reset requested change */ + requested_change = -1; + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static void pmu_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + switch (brightness) { + case LED_OFF: + requested_change = 0; + break; + case LED_FULL: + requested_change = 1; + break; + default: + goto out; + break; + } + /* if request isn't done, then don't do anything */ + if (pmu_blink_req.complete && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + out: + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static struct led_classdev pmu_led = { + .name = "pmu-front-led", +#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK + .default_trigger = "ide-disk", +#endif + .brightness_set = pmu_led_set, +}; + +#ifdef CONFIG_PM +static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + + switch (when) { + case PBOOK_SLEEP_REQUEST: + sleeping = 1; + break; + case PBOOK_WAKE: + sleeping = 0; + break; + default: + /* do nothing */ + break; + } + spin_unlock_irqrestore(&pmu_blink_lock, flags); + + return PBOOK_SLEEP_OK; +} + +static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { + .notifier_call = pmu_led_sleep_call, +}; +#endif + +static int __init via_pmu_led_init(void) +{ + struct device_node *dt; + const char *model; + + /* only do this on keylargo based models */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + dt = of_find_node_by_path("/"); + if (dt == NULL) + return -ENODEV; + model = (const char *)get_property(dt, "model", NULL); + if (model == NULL) + return -ENODEV; + if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && + strncmp(model, "iBook", strlen("iBook")) != 0) { + of_node_put(dt); + /* ignore */ + return -ENODEV; + } + of_node_put(dt); + + spin_lock_init(&pmu_blink_lock); + /* no outstanding req */ + pmu_blink_req.complete = 1; + pmu_blink_req.done = pmu_req_done; +#ifdef CONFIG_PM + pmu_register_sleep_notifier(&via_pmu_led_sleep_notif); +#endif + return led_classdev_register(NULL, &pmu_led); +} + +late_initcall(via_pmu_led_init); diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index fab41c2..1ba3c99 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -117,38 +117,30 @@ #define CPU_FTR_NODSISRALIGN ASM_CONST( #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) +/* + * Add the 64-bit processor unique features in the top half of the word; + * on 32-bit, make the names available but defined to be 0. + */ #ifdef __powerpc64__ -/* Add the 64b processor unique features in the top half of the word */ -#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) -#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) -#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) -#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) -#define CPU_FTR_CTRL ASM_CONST(0x0000008000000000) -#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) -#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) -#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) -#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) -#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000) -#define CPU_FTR_PURR ASM_CONST(0x0000400000000000) +#define LONG_ASM_CONST(x) ASM_CONST(x) #else -/* ensure on 32b processors the flags are available for compiling but - * don't do anything */ -#define CPU_FTR_SLB ASM_CONST(0x0) -#define CPU_FTR_16M_PAGE ASM_CONST(0x0) -#define CPU_FTR_TLBIEL ASM_CONST(0x0) -#define CPU_FTR_NOEXECUTE ASM_CONST(0x0) -#define CPU_FTR_IABR ASM_CONST(0x0) -#define CPU_FTR_MMCRA ASM_CONST(0x0) -#define CPU_FTR_CTRL ASM_CONST(0x0) -#define CPU_FTR_SMT ASM_CONST(0x0) -#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) -#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) -#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) -#define CPU_FTR_PURR ASM_CONST(0x0) +#define LONG_ASM_CONST(x) 0 #endif +#define CPU_FTR_SLB LONG_ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE LONG_ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL LONG_ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE LONG_ASM_CONST(0x0000000800000000) +#define CPU_FTR_IABR LONG_ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) +#define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) +#define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000) +#define CPU_FTR_COHERENT_ICACHE LONG_ASM_CONST(0x0000020000000000) +#define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000) +#define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) +#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) +#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) + #ifndef __ASSEMBLY__ #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h index b7c6fc1..284c5a7 100644 --- a/include/asm-powerpc/iseries/it_lp_queue.h +++ b/include/asm-powerpc/iseries/it_lp_queue.h @@ -29,20 +29,20 @@ #include struct HvLpEvent; -#define ITMaxLpQueues 8 +#define IT_LP_MAX_QUEUES 8 -#define NotUsed 0 // Queue will not be used by PLIC -#define DedicatedIo 1 // Queue dedicated to IO processor specified -#define DedicatedLp 2 // Queue dedicated to LP specified -#define Shared 3 // Queue shared for both IO and LP +#define IT_LP_NOT_USED 0 /* Queue will not be used by PLIC */ +#define IT_LP_DEDICATED_IO 1 /* Queue dedicated to IO processor specified */ +#define IT_LP_DEDICATED_LP 2 /* Queue dedicated to LP specified */ +#define IT_LP_SHARED 3 /* Queue shared for both IO and LP */ -#define LpEventStackSize 4096 -#define LpEventMaxSize 256 -#define LpEventAlign 64 +#define IT_LP_EVENT_STACK_SIZE 4096 +#define IT_LP_EVENT_MAX_SIZE 256 +#define IT_LP_EVENT_ALIGN 64 struct hvlpevent_queue { /* - * The xSlicCurEventPtr is the pointer to the next event stack entry + * The hq_current_event is the pointer to the next event stack entry * that will become valid. The OS must peek at this entry to determine * if it is valid. PLIC will set the valid indicator as the very last * store into that entry. @@ -52,23 +52,23 @@ struct hvlpevent_queue { * location again. * * If the event stack fills and there are overflow events, then PLIC - * will set the xPlicOverflowIntPending flag in which case the OS will + * will set the hq_overflow_pending flag in which case the OS will * have to fetch the additional LP events once they have drained the * event stack. * * The first 16-bytes are known by both the OS and PLIC. The remainder * of the cache line is for use by the OS. */ - u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending - u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed - u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation - u8 xPlicRsvd[12]; // 0x04 - char *xSlicCurEventPtr; // 0x10 - char *xSlicLastValidEventPtr; // 0x18 - char *xSlicEventStackPtr; // 0x20 - u8 xIndex; // 0x28 unique sequential index. - u8 xSlicRsvd[3]; // 0x29-2b - spinlock_t lock; + u8 hq_overflow_pending; /* 0x00 Overflow events are pending */ + u8 hq_status; /* 0x01 DedicatedIo or DedicatedLp or NotUsed */ + u16 hq_proc_index; /* 0x02 Logical Proc Index for correlation */ + u8 hq_reserved1[12]; /* 0x04 */ + char *hq_current_event; /* 0x10 */ + char *hq_last_event; /* 0x18 */ + char *hq_event_stack; /* 0x20 */ + u8 hq_index; /* 0x28 unique sequential index. */ + u8 hq_reserved2[3]; /* 0x29-2b */ + spinlock_t hq_lock; }; extern struct hvlpevent_queue hvlpevent_queue; diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h index 5a5c3b5..dc1574c 100644 --- a/include/asm-powerpc/kdump.h +++ b/include/asm-powerpc/kdump.h @@ -15,6 +15,8 @@ #define PHYSICAL_START KDUMP_KERNELBASE #define KDUMP_TRAMPOLINE_START 0x0100 #define KDUMP_TRAMPOLINE_END 0x3000 +#define KDUMP_MIN_TCE_ENTRIES 2048 + #else /* !CONFIG_CRASH_DUMP */ #define PHYSICAL_START 0x0 diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index efe8872..8f7fd5c 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -112,9 +112,13 @@ #define MAX_NOTE_BYTES 1024 #ifdef __powerpc64__ extern void kexec_smp_wait(void); /* get and clear naca physid, wait for master to copy new code to 0 */ -extern void __init kexec_setup(void); extern int crashing_cpu; extern void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)); +extern cpumask_t cpus_in_sr; +static inline int kexec_sr_activated(int cpu) +{ + return cpu_isset(cpu,cpus_in_sr); +} #endif /* __powerpc64 __ */ struct kimage; @@ -124,10 +128,13 @@ extern int default_machine_kexec_prepare extern void default_machine_crash_shutdown(struct pt_regs *regs); extern void machine_kexec_simple(struct kimage *image); +extern void crash_kexec_secondary(struct pt_regs *regs); extern int overlaps_crashkernel(unsigned long start, unsigned long size); extern void reserve_crashkernel(void); #else /* !CONFIG_KEXEC */ +static inline int kexec_sr_activated(int cpu) { return 0; } +static inline void crash_kexec_secondary(struct pt_regs *regs) { } static inline int overlaps_crashkernel(unsigned long start, unsigned long size) { diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 73db1f7..eba133d 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -81,6 +81,8 @@ #ifdef CONFIG_PPC64 void (*tce_free)(struct iommu_table *tbl, long index, long npages); + unsigned long (*tce_get)(struct iommu_table *tbl, + long index); void (*tce_flush)(struct iommu_table *tbl); void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 3a5ebe2..c3fc7a2 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -238,7 +238,6 @@ extern int hash_huge_page(struct mm_stru unsigned long ea, unsigned long vsid, int local, unsigned long trap); -extern void htab_finish_init(void); extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, unsigned long pstart, unsigned long mode, int psize); diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h index d0a6718..1ed72f6 100644 --- a/include/asm-powerpc/mpc86xx.h +++ b/include/asm-powerpc/mpc86xx.h @@ -15,7 +15,6 @@ #ifdef __KERNEL__ #ifndef __ASM_POWERPC_MPC86xx_H__ #define __ASM_POWERPC_MPC86xx_H__ -#include #include #ifdef CONFIG_PPC_86xx diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index 02e213e..a33c6ac 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -181,6 +181,9 @@ extern int rtas_set_rtc_time(struct rtc_ extern unsigned int rtas_busy_delay_time(int status); extern unsigned int rtas_busy_delay(int status); +extern int early_init_dt_scan_rtas(unsigned long node, + const char *uname, int depth, void *data); + extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); /* Error types logged. */ diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index 4463148..dcde441 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -18,8 +18,9 @@ #include #include #include -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_ISERIES #include +#include #include #endif @@ -177,7 +178,8 @@ #else #ifdef CONFIG_PPC_ISERIES int cur_dec; - if (get_lppaca()->shared_proc) { + if (firmware_has_feature(FW_FEATURE_ISERIES) && + get_lppaca()->shared_proc) { get_lppaca()->virtual_decr = val; cur_dec = get_dec(); if (cur_dec > val) diff --git a/include/asm-powerpc/udbg.h b/include/asm-powerpc/udbg.h index 19a1517..55e5784 100644 --- a/include/asm-powerpc/udbg.h +++ b/include/asm-powerpc/udbg.h @@ -42,7 +42,8 @@ extern void __init udbg_init_debug_lpar( extern void __init udbg_init_pmac_realmode(void); extern void __init udbg_init_maple_realmode(void); extern void __init udbg_init_iseries(void); -extern void __init udbg_init_rtas(void); +extern void __init udbg_init_rtas_panel(void); +extern void __init udbg_init_rtas_console(void); #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_UDBG_H */ diff --git a/kernel/kexec.c b/kernel/kexec.c index 58f0f38..50087ec 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1042,7 +1042,6 @@ #endif void crash_kexec(struct pt_regs *regs) { - struct kimage *image; int locked; @@ -1056,12 +1055,11 @@ void crash_kexec(struct pt_regs *regs) */ locked = xchg(&kexec_lock, 1); if (!locked) { - image = xchg(&kexec_crash_image, NULL); - if (image) { + if (kexec_crash_image) { struct pt_regs fixed_regs; crash_setup_regs(&fixed_regs, regs); machine_crash_shutdown(&fixed_regs); - machine_kexec(image); + machine_kexec(kexec_crash_image); } xchg(&kexec_lock, 0); }