summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/Makefile3
-rw-r--r--arch/powerpc/kernel/align.c189
-rw-r--r--arch/powerpc/kernel/asm-offsets.c6
-rw-r--r--arch/powerpc/kernel/binfmt_elf32.c1
-rw-r--r--arch/powerpc/kernel/btext.c1
-rw-r--r--arch/powerpc/kernel/cpu_setup_6xx.S3
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S32
-rw-r--r--arch/powerpc/kernel/cputable.c126
-rw-r--r--arch/powerpc/kernel/crash.c160
-rw-r--r--arch/powerpc/kernel/crash_dump.c11
-rw-r--r--arch/powerpc/kernel/entry_32.S1
-rw-r--r--arch/powerpc/kernel/entry_64.S3
-rw-r--r--arch/powerpc/kernel/firmware.c1
-rw-r--r--arch/powerpc/kernel/fpu.S7
-rw-r--r--arch/powerpc/kernel/head_32.S15
-rw-r--r--arch/powerpc/kernel/head_44x.S1
-rw-r--r--arch/powerpc/kernel/head_4xx.S1
-rw-r--r--arch/powerpc/kernel/head_64.S92
-rw-r--r--arch/powerpc/kernel/head_8xx.S1
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S1
-rw-r--r--arch/powerpc/kernel/idle.c1
-rw-r--r--arch/powerpc/kernel/idle_6xx.S1
-rw-r--r--arch/powerpc/kernel/idle_power4.S1
-rw-r--r--arch/powerpc/kernel/iomap.c2
-rw-r--r--arch/powerpc/kernel/iommu.c54
-rw-r--r--arch/powerpc/kernel/irq.c40
-rw-r--r--arch/powerpc/kernel/kprobes.c1
-rw-r--r--arch/powerpc/kernel/l2cr_6xx.S1
-rw-r--r--arch/powerpc/kernel/legacy_serial.c12
-rw-r--r--arch/powerpc/kernel/lparcfg.c152
-rw-r--r--arch/powerpc/kernel/machine_kexec_32.c4
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c103
-rw-r--r--arch/powerpc/kernel/misc.S203
-rw-r--r--arch/powerpc/kernel/misc_32.S159
-rw-r--r--arch/powerpc/kernel/misc_64.S229
-rw-r--r--arch/powerpc/kernel/nvram_64.c2
-rw-r--r--arch/powerpc/kernel/of_device.c1
-rw-r--r--arch/powerpc/kernel/paca.c2
-rw-r--r--arch/powerpc/kernel/pci_32.c56
-rw-r--r--arch/powerpc/kernel/pci_64.c68
-rw-r--r--arch/powerpc/kernel/pci_direct_iommu.c18
-rw-r--r--arch/powerpc/kernel/pci_dn.c6
-rw-r--r--arch/powerpc/kernel/pci_iommu.c41
-rw-r--r--arch/powerpc/kernel/perfmon_fsl_booke.c1
-rw-r--r--arch/powerpc/kernel/pmc.c1
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c5
-rw-r--r--arch/powerpc/kernel/process.c56
-rw-r--r--arch/powerpc/kernel/prom.c187
-rw-r--r--arch/powerpc/kernel/prom_init.c123
-rw-r--r--arch/powerpc/kernel/prom_parse.c25
-rw-r--r--arch/powerpc/kernel/ptrace-common.h1
-rw-r--r--arch/powerpc/kernel/ptrace.c3
-rw-r--r--arch/powerpc/kernel/ptrace32.c1
-rw-r--r--arch/powerpc/kernel/rtas-rtc.c30
-rw-r--r--arch/powerpc/kernel/rtas.c223
-rw-r--r--arch/powerpc/kernel/rtas_flash.c25
-rw-r--r--arch/powerpc/kernel/rtas_pci.c4
-rw-r--r--arch/powerpc/kernel/setup-common.c21
-rw-r--r--arch/powerpc/kernel/setup.h3
-rw-r--r--arch/powerpc/kernel/setup_32.c21
-rw-r--r--arch/powerpc/kernel/setup_64.c54
-rw-r--r--arch/powerpc/kernel/signal_32.c24
-rw-r--r--arch/powerpc/kernel/signal_64.c17
-rw-r--r--arch/powerpc/kernel/smp-tbsync.c1
-rw-r--r--arch/powerpc/kernel/smp.c3
-rw-r--r--arch/powerpc/kernel/swsusp_32.S1
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c1
-rw-r--r--arch/powerpc/kernel/sysfs.c32
-rw-r--r--arch/powerpc/kernel/systbl.S312
-rw-r--r--arch/powerpc/kernel/tau_6xx.c1
-rw-r--r--arch/powerpc/kernel/time.c70
-rw-r--r--arch/powerpc/kernel/traps.c51
-rw-r--r--arch/powerpc/kernel/udbg.c15
-rw-r--r--arch/powerpc/kernel/udbg_16550.c1
-rw-r--r--arch/powerpc/kernel/vdso.c58
-rw-r--r--arch/powerpc/kernel/vdso32/cacheflush.S1
-rw-r--r--arch/powerpc/kernel/vdso32/datapage.S1
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S1
-rw-r--r--arch/powerpc/kernel/vdso32/sigtramp.S1
-rw-r--r--arch/powerpc/kernel/vdso64/cacheflush.S1
-rw-r--r--arch/powerpc/kernel/vdso64/datapage.S1
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S1
-rw-r--r--arch/powerpc/kernel/vdso64/sigtramp.S1
-rw-r--r--arch/powerpc/kernel/vector.S5
-rw-r--r--arch/powerpc/kernel/vio.c344
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S6
87 files changed, 1868 insertions, 1679 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 803858e8616..814f242aeb8 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -50,7 +50,8 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
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/align.c b/arch/powerpc/kernel/align.c
index faaec9c6f78..4734b5de599 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -35,17 +35,19 @@ struct aligninfo {
#define INVALID { 0, 0 }
-#define LD 1 /* load */
-#define ST 2 /* store */
-#define SE 4 /* sign-extend value */
-#define F 8 /* to/from fp regs */
-#define U 0x10 /* update index register */
-#define M 0x20 /* multiple load/store */
-#define SW 0x40 /* byte swap int or ... */
-#define S 0x40 /* ... single-precision fp */
-#define SX 0x40 /* byte count in XER */
+/* Bits in the flags field */
+#define LD 0 /* load */
+#define ST 1 /* store */
+#define SE 2 /* sign-extend value */
+#define F 4 /* to/from fp regs */
+#define U 8 /* update index register */
+#define M 0x10 /* multiple load/store */
+#define SW 0x20 /* byte swap */
+#define S 0x40 /* single-precision fp or... */
+#define SX 0x40 /* ... byte count in XER */
#define HARD 0x80 /* string, stwcx. */
+/* DSISR bits reported for a DCBZ instruction: */
#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
#define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
@@ -256,12 +258,16 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
#define REG_BYTE(rp, i) *((u8 *)(rp) + (i))
#endif
+#define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz))
+
static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
unsigned int reg, unsigned int nb,
- unsigned int flags, unsigned int instr)
+ unsigned int flags, unsigned int instr,
+ unsigned long swiz)
{
unsigned long *rptr;
- unsigned int nb0, i;
+ unsigned int nb0, i, bswiz;
+ unsigned long p;
/*
* We do not try to emulate 8 bytes multiple as they aren't really
@@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
if (nb == 0)
return 1;
} else {
- if (__get_user(instr,
- (unsigned int __user *)regs->nip))
+ unsigned long pc = regs->nip ^ (swiz & 4);
+
+ if (__get_user(instr, (unsigned int __user *)pc))
return -EFAULT;
+ if (swiz == 0 && (flags & SW))
+ instr = cpu_to_le32(instr);
nb = (instr >> 11) & 0x1f;
if (nb == 0)
nb = 32;
@@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
return -EFAULT; /* bad address */
rptr = &regs->gpr[reg];
- if (flags & LD) {
+ p = (unsigned long) addr;
+ bswiz = (flags & SW)? 3: 0;
+
+ if (!(flags & ST)) {
/*
* This zeroes the top 4 bytes of the affected registers
* in 64-bit mode, and also zeroes out any remaining
@@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
memset(&regs->gpr[0], 0,
((nb0 + 3) / 4) * sizeof(unsigned long));
- for (i = 0; i < nb; ++i)
- if (__get_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb; ++i, ++p)
+ if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
- for (i = 0; i < nb0; ++i)
- if (__get_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb0; ++i, ++p)
+ if (__get_user(REG_BYTE(rptr, i ^ bswiz),
+ SWIZ_PTR(p)))
return -EFAULT;
}
} else {
- for (i = 0; i < nb; ++i)
- if (__put_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb; ++i, ++p)
+ if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
- for (i = 0; i < nb0; ++i)
- if (__put_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb0; ++i, ++p)
+ if (__put_user(REG_BYTE(rptr, i ^ bswiz),
+ SWIZ_PTR(p)))
return -EFAULT;
}
}
@@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs)
unsigned int reg, areg;
unsigned int dsisr;
unsigned char __user *addr;
- unsigned char __user *p;
+ unsigned long p, swiz;
int ret, t;
union {
u64 ll;
@@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs)
* let's make one up from the instruction
*/
if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
- unsigned int real_instr;
- if (unlikely(__get_user(real_instr,
- (unsigned int __user *)regs->nip)))
+ unsigned long pc = regs->nip;
+
+ if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
+ pc ^= 4;
+ if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
return -EFAULT;
- dsisr = make_dsisr(real_instr);
+ if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
+ instr = cpu_to_le32(instr);
+ dsisr = make_dsisr(instr);
}
/* extract the operation and registers from the dsisr */
@@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs)
nb = aligninfo[instr].len;
flags = aligninfo[instr].flags;
+ /* Byteswap little endian loads and stores */
+ swiz = 0;
+ if (regs->msr & MSR_LE) {
+ flags ^= SW;
+ /*
+ * So-called "PowerPC little endian" mode works by
+ * swizzling addresses rather than by actually doing
+ * any byte-swapping. To emulate this, we XOR each
+ * byte address with 7. We also byte-swap, because
+ * the processor's address swizzling depends on the
+ * operand size (it xors the address with 7 for bytes,
+ * 6 for halfwords, 4 for words, 0 for doublewords) but
+ * we will xor with 7 and load/store each byte separately.
+ */
+ if (cpu_has_feature(CPU_FTR_PPC_LE))
+ swiz = 7;
+ }
+
/* DAR has the operand effective address */
addr = (unsigned char __user *)regs->dar;
@@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs)
* function
*/
if (flags & M)
- return emulate_multiple(regs, addr, reg, nb, flags, instr);
+ return emulate_multiple(regs, addr, reg, nb,
+ flags, instr, swiz);
/* Verify the address of the operand */
if (unlikely(user_mode(regs) &&
@@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs)
/* If we are loading, get the data from user space, else
* get it from register values
*/
- if (flags & LD) {
+ if (!(flags & ST)) {
data.ll = 0;
ret = 0;
- p = addr;
+ p = (unsigned long) addr;
switch (nb) {
case 8:
- ret |= __get_user(data.v[0], p++);
- ret |= __get_user(data.v[1], p++);
- ret |= __get_user(data.v[2], p++);
- ret |= __get_user(data.v[3], p++);
+ ret |= __get_user(data.v[0], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[1], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[2], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[3], SWIZ_PTR(p++));
case 4:
- ret |= __get_user(data.v[4], p++);
- ret |= __get_user(data.v[5], p++);
+ ret |= __get_user(data.v[4], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[5], SWIZ_PTR(p++));
case 2:
- ret |= __get_user(data.v[6], p++);
- ret |= __get_user(data.v[7], p++);
+ ret |= __get_user(data.v[6], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[7], SWIZ_PTR(p++));
if (unlikely(ret))
return -EFAULT;
}
- } else if (flags & F)
+ } else if (flags & F) {
data.dd = current->thread.fpr[reg];
- else
+ if (flags & S) {
+ /* Single-precision FP store requires conversion... */
+#ifdef CONFIG_PPC_FPU
+ preempt_disable();
+ enable_kernel_fp();
+ cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+ preempt_enable();
+#else
+ return 0;
+#endif
+ }
+ } else
data.ll = regs->gpr[reg];
- /* Perform other misc operations like sign extension, byteswap,
+ if (flags & SW) {
+ switch (nb) {
+ case 8:
+ SWAP(data.v[0], data.v[7]);
+ SWAP(data.v[1], data.v[6]);
+ SWAP(data.v[2], data.v[5]);
+ SWAP(data.v[3], data.v[4]);
+ break;
+ case 4:
+ SWAP(data.v[4], data.v[7]);
+ SWAP(data.v[5], data.v[6]);
+ break;
+ case 2:
+ SWAP(data.v[6], data.v[7]);
+ break;
+ }
+ }
+
+ /* Perform other misc operations like sign extension
* or floating point single precision conversion
*/
- switch (flags & ~U) {
+ switch (flags & ~(U|SW)) {
case LD+SE: /* sign extend */
if ( nb == 2 )
data.ll = data.x16.low16;
else /* nb must be 4 */
data.ll = data.x32.low32;
break;
- case LD+S: /* byte-swap */
- case ST+S:
- if (nb == 2) {
- SWAP(data.v[6], data.v[7]);
- } else {
- SWAP(data.v[4], data.v[7]);
- SWAP(data.v[5], data.v[6]);
- }
- break;
- /* Single-precision FP load and store require conversions... */
+ /* Single-precision FP load requires conversion... */
case LD+F+S:
#ifdef CONFIG_PPC_FPU
preempt_disable();
@@ -486,34 +543,24 @@ int fix_alignment(struct pt_regs *regs)
return 0;
#endif
break;
- case ST+F+S:
-#ifdef CONFIG_PPC_FPU
- preempt_disable();
- enable_kernel_fp();
- cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
- preempt_enable();
-#else
- return 0;
-#endif
- break;
}
/* Store result to memory or update registers */
if (flags & ST) {
ret = 0;
- p = addr;
+ p = (unsigned long) addr;
switch (nb) {
case 8:
- ret |= __put_user(data.v[0], p++);
- ret |= __put_user(data.v[1], p++);
- ret |= __put_user(data.v[2], p++);
- ret |= __put_user(data.v[3], p++);
+ ret |= __put_user(data.v[0], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[1], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[2], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[3], SWIZ_PTR(p++));
case 4:
- ret |= __put_user(data.v[4], p++);
- ret |= __put_user(data.v[5], p++);
+ ret |= __put_user(data.v[4], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[5], SWIZ_PTR(p++));
case 2:
- ret |= __put_user(data.v[6], p++);
- ret |= __put_user(data.v[7], p++);
+ ret |= __put_user(data.v[6], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[7], SWIZ_PTR(p++));
}
if (unlikely(ret))
return -EFAULT;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8f85c5e8a55..7ee84968087 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -13,7 +13,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -122,9 +121,8 @@ int main(void)
DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-#ifdef CONFIG_PPC_64K_PAGES
- DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir));
-#endif
+ DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
+ DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
#ifdef CONFIG_HUGETLB_PAGE
DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c
index 8ad6b0f3365..5cb58757e1b 100644
--- a/arch/powerpc/kernel/binfmt_elf32.c
+++ b/arch/powerpc/kernel/binfmt_elf32.c
@@ -19,7 +19,6 @@
#include <asm/processor.h>
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/elfcore.h>
#include <linux/compat.h>
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 6223d39177c..a6920919d68 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -3,7 +3,6 @@
*
* Benjamin Herrenschmidt <benh@kernel.crashing.org>
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 55ed7716636..8b4a4ee85ec 100644
--- a/arch/powerpc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
@@ -210,9 +209,11 @@ setup_745x_specifics:
* the firmware. If any, we disable NAP capability as
* it's known to be bogus on rev 2.1 and earlier
*/
+BEGIN_FTR_SECTION
mfspr r11,SPRN_L3CR
andis. r11,r11,L3CR_L3E@h
beq 1f
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
lwz r6,CPU_SPEC_FEATURES(r5)
andi. r0,r6,CPU_FTR_L3_DISABLE_NAP
beq 1f
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index b61d86e7ceb..f69af2c5d7b 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
@@ -73,23 +72,6 @@ _GLOBAL(__970_cpu_preinit)
isync
blr
-_GLOBAL(__setup_cpu_power4)
- blr
-
-_GLOBAL(__setup_cpu_be)
- /* Set large page sizes LP=0: 16MB, LP=1: 64KB */
- addi r3, 0, 0
- ori r3, r3, HID6_LB
- sldi r3, r3, 32
- nor r3, r3, r3
- mfspr r4, SPRN_HID6
- and r4, r4, r3
- addi r3, 0, 0x02000
- sldi r3, r3, 32
- or r4, r4, r3
- mtspr SPRN_HID6, r4
- blr
-
_GLOBAL(__setup_cpu_ppc970)
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
@@ -142,7 +124,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
@@ -176,7 +163,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/cputable.c b/arch/powerpc/kernel/cputable.c
index 3f7182db9ed..272e43622fd 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -10,7 +10,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/threads.h>
@@ -30,11 +29,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
* part of the cputable though. That has to be fixed for both ppc32
* and ppc64
*/
-#ifdef CONFIG_PPC64
-extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
-#else
+#ifdef CONFIG_PPC32
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -58,7 +53,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
- PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
+ PPC_FEATURE_TRUE_LE)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -78,11 +74,10 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00400000,
.cpu_name = "POWER3 (630)",
.cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64,
+ .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/power3",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "power3",
@@ -92,11 +87,10 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00410000,
.cpu_name = "POWER3 (630+)",
.cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64,
+ .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/power3",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "power3",
@@ -110,7 +104,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "rs64",
@@ -124,7 +117,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "rs64",
@@ -138,7 +130,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "rs64",
@@ -152,7 +143,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power3,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
.platform = "rs64",
@@ -166,7 +156,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power4,
.oprofile_cpu_type = "ppc64/power4",
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power4",
@@ -180,7 +169,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
- .cpu_setup = __setup_cpu_power4,
.oprofile_cpu_type = "ppc64/power4",
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power4",
@@ -200,17 +188,11 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "ppc970",
},
-#endif /* CONFIG_PPC64 */
-#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
{ /* PPC970FX */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003c0000,
.cpu_name = "PPC970FX",
-#ifdef CONFIG_PPC32
- .cpu_features = CPU_FTRS_970_32,
-#else
.cpu_features = CPU_FTRS_PPC970,
-#endif
.cpu_user_features = COMMON_USER_POWER4 |
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
@@ -221,8 +203,6 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "ppc970",
},
-#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
-#ifdef CONFIG_PPC64
{ /* PPC970MP */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00440000,
@@ -232,6 +212,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_type = PPC_OPROFILE_POWER4,
@@ -246,9 +227,13 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_power4,
.oprofile_cpu_type = "ppc64/power5",
.oprofile_type = PPC_OPROFILE_POWER4,
+ /* SIHV / SIPR bits are implemented on POWER4+ (GQ)
+ * and above but only works on POWER5 and above
+ */
+ .oprofile_mmcra_sihv = MMCRA_SIHV,
+ .oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5",
},
{ /* Power5 GS */
@@ -260,9 +245,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_power4,
.oprofile_cpu_type = "ppc64/power5+",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = MMCRA_SIHV,
+ .oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5+",
},
{ /* Power6 */
@@ -273,10 +259,13 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
- .cpu_setup = __setup_cpu_power4,
+ .num_pmcs = 8,
.oprofile_cpu_type = "ppc64/power6",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
+ .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
+ .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
+ POWER6_MMCRA_OTHER,
.platform = "power6",
},
{ /* Cell Broadband Engine */
@@ -289,7 +278,6 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_SMT,
.icache_bsize = 128,
.dcache_bsize = 128,
- .cpu_setup = __setup_cpu_be,
.platform = "ppc-cell-be",
},
{ /* default match */
@@ -301,7 +289,6 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_power4,
.platform = "power4",
}
#endif /* CONFIG_PPC64 */
@@ -323,7 +310,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00030000,
.cpu_name = "603",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -334,7 +321,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00060000,
.cpu_name = "603e",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -345,7 +332,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00070000,
.cpu_name = "603ev",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -356,7 +343,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00040000,
.cpu_name = "604",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 2,
@@ -368,7 +355,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00090000,
.cpu_name = "604e",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -380,7 +367,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00090000,
.cpu_name = "604r",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -392,7 +379,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x000a0000,
.cpu_name = "604ev",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -404,7 +391,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00084202,
.cpu_name = "740/750",
.cpu_features = CPU_FTRS_740_NOTAU,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -416,7 +403,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00080100,
.cpu_name = "750CX",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -428,7 +415,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00082200,
.cpu_name = "750CX",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -440,7 +427,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00082210,
.cpu_name = "750CXe",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -452,7 +439,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00083214,
.cpu_name = "750CXe",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -464,7 +451,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00083000,
.cpu_name = "745/755",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -476,7 +463,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x70000100,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX1,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -488,7 +475,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x70000200,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX2,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -500,7 +487,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x70000000,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -512,7 +499,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x70020000,
.cpu_name = "750GX",
.cpu_features = CPU_FTRS_750GX,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -524,7 +511,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x00080000,
.cpu_name = "740/750",
.cpu_features = CPU_FTRS_740,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -536,7 +523,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x000c1101,
.cpu_name = "7400 (1.1)",
.cpu_features = CPU_FTRS_7400_NOTAU,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -548,7 +536,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x000c0000,
.cpu_name = "7400",
.cpu_features = CPU_FTRS_7400,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -560,7 +549,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x800c0000,
.cpu_name = "7410",
.cpu_features = CPU_FTRS_7400,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -572,7 +562,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80000200,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_20,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -586,7 +577,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80000201,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_21,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -600,7 +592,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80000000,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_23,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -614,7 +607,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80010100,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455_1,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -628,7 +622,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80010200,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455_20,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -642,7 +637,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80010000,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -656,7 +652,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80020100,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447_10,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -670,7 +667,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80020101,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447_10,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -684,7 +682,7 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80020000,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -698,7 +696,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80030000,
.cpu_name = "7447A",
.cpu_features = CPU_FTRS_7447A,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -712,7 +711,8 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x80040000,
.cpu_name = "7448",
.cpu_features = CPU_FTRS_7447A,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 778f22fd85d..358cecdc6ae 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -22,10 +22,13 @@
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/types.h>
+#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/machdep.h>
+#include <asm/kexec.h>
#include <asm/kdump.h>
#include <asm/lmb.h>
#include <asm/firmware.h>
@@ -40,6 +43,7 @@
/* This keeps a track of which one is crashing cpu. */
int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
size_t data_len)
@@ -97,34 +101,66 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
}
#ifdef CONFIG_SMP
-static atomic_t waiting_for_crash_ipi;
+static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
void crash_ipi_callback(struct pt_regs *regs)
{
int cpu = smp_processor_id();
- if (cpu == crashing_cpu)
- return;
-
if (!cpu_online(cpu))
return;
- 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);
+
+ /*
+ * 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();
- crash_save_this_cpu(regs, cpu);
- atomic_dec(&waiting_for_crash_ipi);
+ 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();
@@ -132,14 +168,13 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: Until we will have the way to stop other CPUSs reliabally,
* the crash CPU will send an IPI and wait for other CPUs to
- * respond. If not, proceed the kexec boot even though we failed to
- * capture other CPU states.
+ * respond.
* Delay of at least 10 seconds.
*/
- printk(KERN_ALERT "Sending IPI to other cpus...\n");
+ printk(KERN_EMERG "Sending IPI to other cpus...\n");
msecs = 10000;
- while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
- barrier();
+ while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+ cpu_relax();
mdelay(1);
}
@@ -148,18 +183,71 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: In case if we do not get all CPUs, one possibility: ask the
* user to do soft reset such that we get all.
- * IPI handler is already set by the panic cpu initially. Therefore,
- * all cpus could invoke this handler from die() and the panic CPU
- * will call machine_kexec() directly from this handler to do
- * kexec boot.
+ * Soft-reset will be used until better mechanism is implemented.
*/
- if (atomic_read(&waiting_for_crash_ipi))
- printk(KERN_ALERT "done waiting: %d cpus not responding\n",
- atomic_read(&waiting_for_crash_ipi));
+ if (cpus_weight(cpus_in_crash) < ncpus) {
+ printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
+ ncpus - cpus_weight(cpus_in_crash));
+ printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
+ cpus_in_sr = CPU_MASK_NONE;
+ atomic_set(&enter_on_soft_reset, 0);
+ while (cpus_weight(cpus_in_crash) < ncpus)
+ cpu_relax();
+ }
+ /*
+ * Make sure all CPUs are entered via soft-reset if the kdump is
+ * invoked using soft-reset.
+ */
+ if (cpu_isset(cpu, cpus_in_sr))
+ crash_soft_reset_check(cpu);
/* Leave the IPI callback set */
}
+
+/*
+ * This function will be called by secondary cpus or by kexec cpu
+ * if soft-reset is activated to stop some CPUs.
+ */
+void crash_kexec_secondary(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ int msecs = 5;
+
+ local_irq_save(flags);
+ /* Wait 5ms if the kexec CPU is not entered yet. */
+ while (crashing_cpu < 0) {
+ if (--msecs < 0) {
+ /*
+ * Either kdump image is not loaded or
+ * kdump process is not started - Probably xmon
+ * exited using 'x'(exit and recover) or
+ * kexec_should_crash() failed for all running tasks.
+ */
+ cpu_clear(cpu, cpus_in_sr);
+ local_irq_restore(flags);
+ return;
+ }
+ mdelay(1);
+ cpu_relax();
+ }
+ if (cpu == crashing_cpu) {
+ /*
+ * Panic CPU will enter this func only via soft-reset.
+ * Wait until all secondary CPUs entered and
+ * then start kexec boot.
+ */
+ crash_soft_reset_check(cpu);
+ cpu_set(crashing_cpu, cpus_in_crash);
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(1, 0);
+ machine_kexec(kexec_crash_image);
+ /* NOTREACHED */
+ }
+ crash_ipi_callback(regs);
+}
+
#else
-static void crash_kexec_prepare_cpus(void)
+static void crash_kexec_prepare_cpus(int cpu)
{
/*
* move the secondarys to us so that we can copy
@@ -170,13 +258,19 @@ static void crash_kexec_prepare_cpus(void)
smp_release_cpus();
}
+void crash_kexec_secondary(struct pt_regs *regs)
+{
+ cpus_in_sr = CPU_MASK_NONE;
+}
#endif
void default_machine_crash_shutdown(struct pt_regs *regs)
{
+ unsigned int irq;
+
/*
* This function is only called after the system
- * has paniced or is otherwise in a critical state.
+ * has panicked or is otherwise in a critical state.
* The minimum amount of code to allow a kexec'd kernel
* to run successfully needs to happen here.
*
@@ -186,14 +280,24 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
*/
local_irq_disable();
- if (ppc_md.kexec_cpu_down)
- ppc_md.kexec_cpu_down(1, 0);
+ for_each_irq(irq) {
+ struct irq_desc *desc = irq_desc + irq;
+
+ if (desc->status & IRQ_INPROGRESS)
+ desc->chip->end(irq);
+
+ if (!(desc->status & IRQ_DISABLED))
+ desc->chip->disable(irq);
+ }
/*
* 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/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 764d0732971..371973be8d7 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -25,6 +25,11 @@
#define DBG(fmt...)
#endif
+void reserve_kdump_trampoline(void)
+{
+ lmb_reserve(0, KDUMP_RESERVE_LIMIT);
+}
+
static void __init create_trampoline(unsigned long addr)
{
/* The maximum range of a single instruction branch, is the current
@@ -39,11 +44,11 @@ static void __init create_trampoline(unsigned long addr)
create_branch(addr + 4, addr + PHYSICAL_START, 0);
}
-void __init kdump_setup(void)
+void __init setup_kdump_trampoline(void)
{
unsigned long i;
- DBG(" -> kdump_setup()\n");
+ DBG(" -> setup_kdump_trampoline()\n");
for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
create_trampoline(i);
@@ -52,7 +57,7 @@ void __init kdump_setup(void)
create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
- DBG(" <- kdump_setup()\n");
+ DBG(" <- setup_kdump_trampoline()\n");
}
#ifdef CONFIG_PROC_VMCORE
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 8866fd26c6b..c03e829fee3 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -19,7 +19,6 @@
*
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sys.h>
#include <linux/threads.h>
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 19ad5c6b181..54d9f5cdaab 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -18,7 +18,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <asm/unistd.h>
#include <asm/processor.h>
@@ -57,6 +56,7 @@ system_call_common:
beq- 1f
ld r1,PACAKSAVE(r13)
1: std r10,0(r1)
+ crclr so
std r11,_NIP(r1)
std r12,_MSR(r1)
std r0,GPR0(r1)
@@ -75,7 +75,6 @@ system_call_common:
std r11,GPR11(r1)
std r11,GPR12(r1)
std r9,GPR13(r1)
- crclr so
mfcr r9
mflr r10
li r11,0xc01
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c
index 0bfe9061720..1679a70bbca 100644
--- a/arch/powerpc/kernel/firmware.c
+++ b/arch/powerpc/kernel/firmware.c
@@ -13,7 +13,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <asm/firmware.h>
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 340730fb8c9..7e2c9fe44ac 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -9,7 +9,6 @@
*
*/
-#include <linux/config.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -72,7 +71,7 @@ _GLOBAL(load_up_fpu)
std r12,_MSR(r1)
#endif
lfd fr0,THREAD_FPSCR(r5)
- mtfsf 0xff,fr0
+ MTFSF_L(fr0)
REST_32FPRS(0, r5)
#ifndef CONFIG_SMP
subi r4,r5,THREAD
@@ -127,7 +126,7 @@ _GLOBAL(giveup_fpu)
_GLOBAL(cvt_fd)
lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
- mtfsf 0xff,0
+ MTFSF_L(0)
lfs 0,0(r3)
stfd 0,0(r4)
mffs 0
@@ -136,7 +135,7 @@ _GLOBAL(cvt_fd)
_GLOBAL(cvt_df)
lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */
- mtfsf 0xff,0
+ MTFSF_L(0)
lfd 0,0(r3)
stfs 0,0(r4)
mffs 0
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index a0579e859b2..d88e182e40b 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -22,7 +22,6 @@
*
*/
-#include <linux/config.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -973,6 +972,13 @@ __secondary_start_gemini:
b __secondary_start
#endif /* CONFIG_GEMINI */
+ .globl __secondary_start_mpc86xx
+__secondary_start_mpc86xx:
+ mfspr r3, SPRN_PIR
+ stw r3, __secondary_hold_acknowledge@l(0)
+ mr r24, r3 /* cpu # */
+ b __secondary_start
+
.globl __secondary_start_pmac_0
__secondary_start_pmac_0:
/* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
@@ -1088,7 +1094,12 @@ load_up_mmu:
LOAD_BAT(1,r3,r4,r5)
LOAD_BAT(2,r3,r4,r5)
LOAD_BAT(3,r3,r4,r5)
-
+BEGIN_FTR_SECTION
+ LOAD_BAT(4,r3,r4,r5)
+ LOAD_BAT(5,r3,r4,r5)
+ LOAD_BAT(6,r3,r4,r5)
+ LOAD_BAT(7,r3,r4,r5)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
blr
/*
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 47c7fa148c9..accb39d4991 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -28,7 +28,6 @@
* option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
diff --git a/arch/powerpc/kernel/head_4xx.S b/arch/powerpc/kernel/head_4xx.S
index 2590e97f553..adc7f8097cd 100644
--- a/arch/powerpc/kernel/head_4xx.S
+++ b/arch/powerpc/kernel/head_4xx.S
@@ -31,7 +31,6 @@
*
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index b7d140430a4..e16eb2a3317 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -21,7 +21,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/reg.h>
#include <asm/page.h>
@@ -85,34 +84,6 @@ END_FTR_SECTION(0, 1)
/* 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 +95,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
@@ -316,6 +296,21 @@ label##_pSeries: \
mtspr SPRN_SPRG1,r13; /* save r13 */ \
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+#define HSTD_EXCEPTION_PSERIES(n, label) \
+ . = n; \
+ .globl label##_pSeries; \
+label##_pSeries: \
+ HMT_MEDIUM; \
+ mtspr SPRN_SPRG1,r20; /* save r20 */ \
+ mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \
+ mtspr SPRN_SRR0,r20; \
+ mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \
+ mtspr SPRN_SRR1,r20; \
+ mfspr r20,SPRN_SPRG1; /* restore r20 */ \
+ mtspr SPRN_SPRG1,r13; /* save r13 */ \
+ EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+
+
#define STD_EXCEPTION_ISERIES(n, label, area) \
.globl label##_iSeries; \
label##_iSeries: \
@@ -544,8 +539,17 @@ system_call_pSeries:
STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)
+#ifdef CONFIG_CBE_RAS
+ HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
+#endif /* CONFIG_CBE_RAS */
STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
+#ifdef CONFIG_CBE_RAS
+ HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
+#endif /* CONFIG_CBE_RAS */
STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
+#ifdef CONFIG_CBE_RAS
+ HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
+#endif /* CONFIG_CBE_RAS */
. = 0x3000
@@ -827,6 +831,11 @@ machine_check_common:
#else
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
#endif
+#ifdef CONFIG_CBE_RAS
+ STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
+ STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
+ STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
+#endif /* CONFIG_CBE_RAS */
/*
* Here we have detected that the kernel stack pointer is bad.
@@ -1573,9 +1582,6 @@ _GLOBAL(__start_initialization_multiplatform)
/* Setup some critical 970 SPRs before switching MMU off */
bl .__970_cpu_preinit
- /* cpu # */
- li r24,0
-
/* Switch off MMU if not already */
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r30
@@ -1654,6 +1660,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
@@ -1933,14 +1942,6 @@ _STATIC(start_here_common)
li r3,0
bl .do_cpu_ftr_fixups
- LOAD_REG_IMMEDIATE(r26, boot_cpuid)
- lwz r26,0(r26)
-
- LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
- mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
- add r13,r13,r24 /* for this processor. */
- mtspr SPRN_SPRG3,r13
-
/* ptr to current */
LOAD_REG_IMMEDIATE(r4, init_task)
std r4,PACACURRENT(r13)
@@ -1966,17 +1967,6 @@ _STATIC(start_here_common)
/* 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/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 28941f5ce67..901be47a02a 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -19,7 +19,6 @@
*
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index dd86bbed762..66877bdfe0b 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -30,7 +30,6 @@
* option) any later version.
*/
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index d491052c8e0..4180c3998b3 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -19,7 +19,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/smp.h>
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index b45fa0e3721..01bcd52bbf8 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -13,7 +13,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/reg.h>
#include <asm/page.h>
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index d85c7c938ee..30de81da7b4 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -7,7 +7,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c
index fd8214caede..a13a93dfc65 100644
--- a/arch/powerpc/kernel/iomap.c
+++ b/arch/powerpc/kernel/iomap.c
@@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep);
void __iomem *ioport_map(unsigned long port, unsigned int len)
{
- if (!_IO_IS_VALID(port))
- return NULL;
return (void __iomem *) (port+pci_io_base);
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 4eba60a3289..ba069407172 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -23,7 +23,6 @@
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
@@ -38,6 +37,7 @@
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
+#include <asm/kdump.h>
#define DBG(...)
@@ -418,10 +418,11 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
* Build a iommu_table structure. This contains a bit map which
* is used to manage allocation of the tce space.
*/
-struct iommu_table *iommu_init_table(struct iommu_table *tbl)
+struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
{
unsigned long sz;
static int welcomed = 0;
+ struct page *page;
/* Set aside 1/4 of the table for large allocations. */
tbl->it_halfpoint = tbl->it_size * 3 / 4;
@@ -429,18 +430,47 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
/* number of bytes needed for the bitmap */
sz = (tbl->it_size + 7) >> 3;
- tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz));
- if (!tbl->it_map)
+ page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz));
+ if (!page)
panic("iommu_init_table: Can't allocate %ld bytes\n", sz);
-
+ tbl->it_map = page_address(page);
memset(tbl->it_map, 0, sz);
tbl->it_hint = 0;
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",
@@ -536,11 +566,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* to the dma address (mapping) of the first page.
*/
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
+ dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
{
void *ret = NULL;
dma_addr_t mapping;
unsigned int npages, order;
+ struct page *page;
size = PAGE_ALIGN(size);
npages = size >> PAGE_SHIFT;
@@ -560,9 +591,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
return NULL;
/* Alloc enough pages (and possibly more) */
- ret = (void *)__get_free_pages(flag, order);
- if (!ret)
+ page = alloc_pages_node(node, flag, order);
+ if (!page)
return NULL;
+ ret = page_address(page);
memset(ret, 0, size);
/* Set up tces to cover the allocated range */
@@ -570,9 +602,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
mask >> PAGE_SHIFT, order);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
- ret = NULL;
- } else
- *dma_handle = mapping;
+ return NULL;
+ }
+ *dma_handle = mapping;
return ret;
}
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 57d560c6889..525baab45d2 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -38,7 +38,6 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -47,6 +46,7 @@
#include <linux/cpumask.h>
#include <linux/profile.h>
#include <linux/bitops.h>
+#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -119,8 +119,8 @@ int show_interrupts(struct seq_file *p, void *v)
#else
seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
- if (desc->handler)
- seq_printf(p, " %s ", desc->handler->typename);
+ if (desc->chip)
+ seq_printf(p, " %s ", desc->chip->typename);
else
seq_puts(p, " None ");
seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
@@ -163,13 +163,13 @@ void fixup_irqs(cpumask_t map)
if (irq_desc[irq].status & IRQ_PER_CPU)
continue;
- cpus_and(mask, irq_affinity[irq], map);
+ cpus_and(mask, irq_desc[irq].affinity, map);
if (any_online_cpu(mask) == NR_CPUS) {
printk("Breaking affinity for irq %i\n", irq);
mask = map;
}
- if (irq_desc[irq].handler->set_affinity)
- irq_desc[irq].handler->set_affinity(irq, mask);
+ if (irq_desc[irq].chip->set_affinity)
+ irq_desc[irq].chip->set_affinity(irq, mask);
else if (irq_desc[irq].action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}
@@ -379,8 +379,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
#endif /* CONFIG_PPC64 */
#ifdef CONFIG_IRQSTACKS
-struct thread_info *softirq_ctx[NR_CPUS];
-struct thread_info *hardirq_ctx[NR_CPUS];
+struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
+struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
void irq_ctx_init(void)
{
@@ -436,6 +436,30 @@ void do_softirq(void)
}
EXPORT_SYMBOL(do_softirq);
+#ifdef CONFIG_PCI_MSI
+int pci_enable_msi(struct pci_dev * pdev)
+{
+ if (ppc_md.enable_msi)
+ return ppc_md.enable_msi(pdev);
+ else
+ return -1;
+}
+
+void pci_disable_msi(struct pci_dev * pdev)
+{
+ if (ppc_md.disable_msi)
+ ppc_md.disable_msi(pdev);
+}
+
+void pci_scan_msi_device(struct pci_dev *dev) {}
+int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
+void pci_disable_msix(struct pci_dev *dev) {}
+void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
+void pci_no_msi(void) {}
+
+#endif
+
#ifdef CONFIG_PPC64
static int __init setup_noirqdistrib(char *str)
{
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index f78866367b7..9f0898c8975 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -26,7 +26,6 @@
* for PPC64
*/
-#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
#include <linux/preempt.h>
diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S
index d7f4e982b53..858f28ac8a0 100644
--- a/arch/powerpc/kernel/l2cr_6xx.S
+++ b/arch/powerpc/kernel/l2cr_6xx.S
@@ -40,7 +40,6 @@
Author: Terry Greeniaus (tgree@phys.ualberta.ca)
Please e-mail updates to this file to me, thanks!
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 6e67b5b49ba..4cf0b971976 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
@@ -302,6 +301,17 @@ void __init find_legacy_serial_ports(void)
of_node_put(isa);
}
+ /* First fill our array with tsi-bridge ports */
+ for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) {
+ struct device_node *tsi = of_get_parent(np);
+ if (tsi && !strcmp(tsi->type, "tsi-bridge")) {
+ index = add_legacy_soc_port(np, np);
+ if (index >= 0 && np == stdout)
+ legacy_serial_console = index;
+ }
+ of_node_put(tsi);
+ }
+
#ifdef CONFIG_PCI
/* Next, try to locate PCI ports */
for (np = NULL; (np = of_find_all_nodes(np));) {
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 2cbde865d4f..23f34daa044 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -18,7 +18,6 @@
* keyword - value pairs that specify the configuration of the partition.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -45,11 +44,9 @@
static struct proc_dir_entry *proc_ppc64_lparcfg;
#define LPARCFG_BUFF_SIZE 4096
-#ifdef CONFIG_PPC_ISERIES
-
/*
- * For iSeries legacy systems, the PPA purr function is available from the
- * emulated_time_base field in the paca.
+ * Track sum of all purrs across all processors. This is used to further
+ * calculate usage values by different applications
*/
static unsigned long get_purr(void)
{
@@ -57,48 +54,31 @@ static unsigned long get_purr(void)
int cpu;
for_each_possible_cpu(cpu) {
- sum_purr += lppaca[cpu].emulated_time_base;
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ sum_purr += lppaca[cpu].emulated_time_base;
+ else {
+ struct cpu_usage *cu;
-#ifdef PURR_DEBUG
- printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
- cpu, lppaca[cpu].emulated_time_base);
-#endif
+ cu = &per_cpu(cpu_usage_array, cpu);
+ sum_purr += cu->current_tb;
+ }
}
return sum_purr;
}
-#define lparcfg_write NULL
+#ifdef CONFIG_PPC_ISERIES
/*
* Methods used to fetch LPAR data when running on an iSeries platform.
*/
-static int lparcfg_data(struct seq_file *m, void *v)
+static int iseries_lparcfg_data(struct seq_file *m, void *v)
{
- unsigned long pool_id, lp_index;
+ unsigned long pool_id;
int shared, entitled_capacity, max_entitled_capacity;
int processors, max_processors;
unsigned long purr = get_purr();
- seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
-
shared = (int)(get_lppaca()->shared_proc);
- seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
- e2a(xItExtVpdPanel.mfgID[2]),
- e2a(xItExtVpdPanel.mfgID[3]),
- e2a(xItExtVpdPanel.systemSerial[1]),
- e2a(xItExtVpdPanel.systemSerial[2]),
- e2a(xItExtVpdPanel.systemSerial[3]),
- e2a(xItExtVpdPanel.systemSerial[4]),
- e2a(xItExtVpdPanel.systemSerial[5]));
-
- seq_printf(m, "system_type=%c%c%c%c\n",
- e2a(xItExtVpdPanel.machineType[0]),
- e2a(xItExtVpdPanel.machineType[1]),
- e2a(xItExtVpdPanel.machineType[2]),
- e2a(xItExtVpdPanel.machineType[3]));
-
- lp_index = HvLpConfig_getLpIndex();
- seq_printf(m, "partition_id=%d\n", (int)lp_index);
seq_printf(m, "system_active_processors=%d\n",
(int)HvLpConfig_getSystemPhysicalProcessors());
@@ -137,6 +117,14 @@ static int lparcfg_data(struct seq_file *m, void *v)
return 0;
}
+
+#else /* CONFIG_PPC_ISERIES */
+
+static int iseries_lparcfg_data(struct seq_file *m, void *v)
+{
+ return 0;
+}
+
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES
@@ -213,22 +201,6 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
log_plpar_hcall_return(rc, "H_PIC");
}
-/* Track sum of all purrs across all processors. This is used to further */
-/* calculate usage values by different applications */
-
-static unsigned long get_purr(void)
-{
- unsigned long sum_purr = 0;
- int cpu;
- struct cpu_usage *cu;
-
- for_each_possible_cpu(cpu) {
- cu = &per_cpu(cpu_usage_array, cpu);
- sum_purr += cu->current_tb;
- }
- return sum_purr;
-}
-
#define SPLPAR_CHARACTERISTICS_TOKEN 20
#define SPLPAR_MAXLENGTH 1026*(sizeof(char))
@@ -333,35 +305,13 @@ static int lparcfg_count_active_processors(void)
return count;
}
-static int lparcfg_data(struct seq_file *m, void *v)
+static int pseries_lparcfg_data(struct seq_file *m, void *v)
{
int partition_potential_processors;
int partition_active_processors;
- struct device_node *rootdn;
- const char *model = "";
- const char *system_id = "";
- unsigned int *lp_index_ptr, lp_index = 0;
struct device_node *rtas_node;
int *lrdrp = NULL;
- rootdn = find_path_device("/");
- if (rootdn) {
- model = get_property(rootdn, "model", NULL);
- system_id = get_property(rootdn, "system-id", NULL);
- lp_index_ptr = (unsigned int *)
- get_property(rootdn, "ibm,partition-no", NULL);
- if (lp_index_ptr)
- lp_index = *lp_index_ptr;
- }
-
- seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
-
- seq_printf(m, "serial_number=%s\n", system_id);
-
- seq_printf(m, "system_type=%s\n", model);
-
- seq_printf(m, "partition_id=%d\n", (int)lp_index);
-
rtas_node = find_path_device("/rtas");
if (rtas_node)
lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity",
@@ -521,10 +471,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
current_weight = (resource >> 5 * 8) & 0xFF;
- pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
+ pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
__FUNCTION__, current_entitled, current_weight);
- pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
+ pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
__FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
@@ -549,8 +499,61 @@ out:
return retval;
}
+#else /* CONFIG_PPC_PSERIES */
+
+static int pseries_lparcfg_data(struct seq_file *m, void *v)
+{
+ return 0;
+}
+
+static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * off)
+{
+ return count;
+}
+
#endif /* CONFIG_PPC_PSERIES */
+static int lparcfg_data(struct seq_file *m, void *v)
+{
+ struct device_node *rootdn;
+ const char *model = "";
+ const char *system_id = "";
+ const char *tmp;
+ unsigned int *lp_index_ptr, lp_index = 0;
+
+ seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
+
+ rootdn = find_path_device("/");
+ if (rootdn) {
+ tmp = get_property(rootdn, "model", NULL);
+ if (tmp) {
+ model = tmp;
+ /* Skip "IBM," - see platforms/iseries/dt.c */
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ model += 4;
+ }
+ tmp = get_property(rootdn, "system-id", NULL);
+ if (tmp) {
+ system_id = tmp;
+ /* Skip "IBM," - see platforms/iseries/dt.c */
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ system_id += 4;
+ }
+ lp_index_ptr = (unsigned int *)
+ get_property(rootdn, "ibm,partition-no", NULL);
+ if (lp_index_ptr)
+ lp_index = *lp_index_ptr;
+ }
+ seq_printf(m, "serial_number=%s\n", system_id);
+ seq_printf(m, "system_type=%s\n", model);
+ seq_printf(m, "partition_id=%d\n", (int)lp_index);
+
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return iseries_lparcfg_data(m, v);
+ return pseries_lparcfg_data(m, v);
+}
+
static int lparcfg_open(struct inode *inode, struct file *file)
{
return single_open(file, lparcfg_data, NULL);
@@ -569,7 +572,8 @@ int __init lparcfg_init(void)
mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
/* Allow writing if we have FW_FEATURE_SPLPAR */
- if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+ if (firmware_has_feature(FW_FEATURE_SPLPAR) &&
+ !firmware_has_feature(FW_FEATURE_ISERIES)) {
lparcfg_fops.write = lparcfg_write;
mode |= S_IWUSR;
}
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
index 443606134df..cbaa3419679 100644
--- a/arch/powerpc/kernel/machine_kexec_32.c
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -30,8 +30,8 @@ typedef NORET_TYPE void (*relocate_new_kernel_t)(
*/
void default_machine_kexec(struct kimage *image)
{
- const extern unsigned char relocate_new_kernel[];
- const extern unsigned int relocate_new_kernel_size;
+ extern const unsigned char relocate_new_kernel[];
+ extern const unsigned int relocate_new_kernel_size;
unsigned long page_list;
unsigned long reboot_code_buffer, reboot_code_buffer_phys;
relocate_new_kernel_t rnk;
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index ee166c58664..b438d45a068 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -21,6 +21,7 @@
#include <asm/machdep.h>
#include <asm/cacheflush.h>
#include <asm/paca.h>
+#include <asm/lmb.h>
#include <asm/mmu.h>
#include <asm/sections.h> /* _end */
#include <asm/prom.h>
@@ -335,7 +336,107 @@ static void __init export_htab_values(void)
of_node_put(node);
}
-void __init kexec_setup(void)
+static struct property crashk_base_prop = {
+ .name = "linux,crashkernel-base",
+ .length = sizeof(unsigned long),
+ .value = (unsigned char *)&crashk_res.start,
+};
+
+static unsigned long crashk_size;
+
+static struct property crashk_size_prop = {
+ .name = "linux,crashkernel-size",
+ .length = sizeof(unsigned long),
+ .value = (unsigned char *)&crashk_size,
+};
+
+static void __init export_crashk_values(void)
+{
+ struct device_node *node;
+ struct property *prop;
+
+ node = of_find_node_by_path("/chosen");
+ if (!node)
+ return;
+
+ /* There might be existing crash kernel properties, but we can't
+ * be sure what's in them, so remove them. */
+ prop = of_find_property(node, "linux,crashkernel-base", NULL);
+ if (prop)
+ prom_remove_property(node, prop);
+
+ prop = of_find_property(node, "linux,crashkernel-size", NULL);
+ if (prop)
+ prom_remove_property(node, prop);
+
+ if (crashk_res.start != 0) {
+ prom_add_property(node, &crashk_base_prop);
+ crashk_size = crashk_res.end - crashk_res.start + 1;
+ prom_add_property(node, &crashk_size_prop);
+ }
+
+ of_node_put(node);
+}
+
+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)
+{
+ unsigned long size;
+
+ if (!p)
+ return 1;
+
+ size = memparse(p, &p);
+
+ if (*p == '@')
+ crashk_res.start = memparse(p + 1, &p);
+ else
+ crashk_res.start = KDUMP_KERNELBASE;
+
+ crashk_res.end = crashk_res.start + size - 1;
+
+ return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+ unsigned long size;
+
+ if (crashk_res.start == 0)
+ return;
+
+ /* We might have got these values via the command line or the
+ * device tree, either way sanitise them now. */
+
+ size = crashk_res.end - crashk_res.start + 1;
+
+ if (crashk_res.start != KDUMP_KERNELBASE)
+ printk("Crash kernel location must be 0x%x\n",
+ KDUMP_KERNELBASE);
+
+ crashk_res.start = KDUMP_KERNELBASE;
+ size = PAGE_ALIGN(size);
+ crashk_res.end = crashk_res.start + size - 1;
+
+ /* Crash kernel trumps memory limit */
+ if (memory_limit && memory_limit <= crashk_res.end) {
+ memory_limit = crashk_res.end + 1;
+ printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+ memory_limit);
+ }
+
+ lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+ return (start + size) > crashk_res.start && start <= crashk_res.end;
}
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
new file mode 100644
index 00000000000..fc23040d5a2
--- /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 <asm/ppc_asm.h>
+
+ .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 be982023409..58758d88336 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -16,7 +16,6 @@
*
*/
-#include <linux/config.h>
#include <linux/sys.h>
#include <asm/unistd.h>
#include <asm/errno.h>
@@ -61,32 +60,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)
@@ -216,7 +189,7 @@ _GLOBAL(call_setup_cpu)
lwz r4,0(r4)
add r4,r4,r3
lwz r5,CPU_SPEC_SETUP(r4)
- cmpi 0,r5,0
+ cmpwi 0,r5,0
add r5,r5,r3
beqlr
mtctr r5
@@ -781,136 +754,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 2778cce058e..0c3c70d115c 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
@@ -16,7 +14,6 @@
*
*/
-#include <linux/config.h>
#include <linux/sys.h>
#include <asm/unistd.h>
#include <asm/errno.h>
@@ -30,41 +27,10 @@
.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 +38,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 +63,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 +243,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
@@ -482,7 +264,9 @@ _GLOBAL(identify_cpu)
sub r0,r3,r5
std r0,0(r4)
ld r4,CPU_SPEC_SETUP(r3)
+ cmpdi 0,r4,0
add r4,r4,r5
+ beqlr
ld r4,0(r4)
add r4,r4,r5
mtctr r4
@@ -603,6 +387,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)
*
@@ -671,6 +456,7 @@ _GLOBAL(scom970_write)
/* restore interrupts */
mtmsrd r5,1
blr
+#endif /* CONFIG_CPU_FREQ_PMAC64 */
/*
@@ -768,9 +554,6 @@ _GLOBAL(giveup_altivec)
#endif /* CONFIG_ALTIVEC */
-_GLOBAL(__setup_cpu_power3)
- blr
-
_GLOBAL(execve)
li r0,__NR_execve
sc
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index ada50aa5b60..6960f090991 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -204,7 +204,7 @@ static void nvram_print_partitions(char * label)
printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
list_for_each(p, &nvram_part->partition) {
tmp_part = list_entry(p, struct nvram_partition, partition);
- printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n",
+ printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n",
tmp_part->index, tmp_part->header.signature,
tmp_part->header.checksum, tmp_part->header.length,
tmp_part->header.name);
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 9feeeef5a87..3262b73a3a6 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index f505a8827e3..c68741fed14 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -7,7 +7,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/threads.h>
#include <linux/module.h>
@@ -16,7 +15,6 @@
#include <asm/ptrace.h>
#include <asm/page.h>
#include <asm/lppaca.h>
-#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/it_lp_reg_save.h>
#include <asm/paca.h>
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index b129d2e4b75..1333335c474 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -2,7 +2,6 @@
* Common pmac/prep/chrp pci routines. -- Cort
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -99,7 +98,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
if (!res->flags)
continue;
if (res->end == 0xffffffff) {
- DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+ DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
pci_name(dev), i, res->start, res->end);
res->end -= res->start;
res->start = 0;
@@ -117,7 +116,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
res->start += offset;
res->end += offset;
#ifdef DEBUG
- printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+ printk("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
i, res->flags, pci_name(dev),
res->start - offset, res->start);
#endif
@@ -173,18 +172,18 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
* but we want to try to avoid allocating at 0x2900-0x2bff
* which might have be mirrored at 0x0100-0x03ff..
*/
-void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
- unsigned long align)
+void pcibios_align_resource(void *data, struct resource *res,
+ resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
if (res->flags & IORESOURCE_IO) {
- unsigned long start = res->start;
+ resource_size_t start = res->start;
if (size > 0x100) {
printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- " (%ld bytes)\n", pci_name(dev),
- dev->resource - res, size);
+ " (%lld bytes)\n", pci_name(dev),
+ dev->resource - res, (unsigned long long)size);
}
if (start & 0x300) {
@@ -255,8 +254,8 @@ pcibios_allocate_bus_resources(struct list_head *bus_list)
}
}
- DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n",
- res->start, res->end, res->flags, pr);
+ DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
if (pr) {
if (request_resource(pr, res) == 0)
continue;
@@ -306,7 +305,7 @@ reparent_resources(struct resource *parent, struct resource *res)
*pp = NULL;
for (p = res->child; p != NULL; p = p->sibling) {
p->parent = res;
- DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n",
+ DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
p->name, p->start, p->end, res->name);
}
return 0;
@@ -362,13 +361,14 @@ pci_relocate_bridge_resource(struct pci_bus *bus, int i)
try = conflict->start - 1;
}
if (request_resource(pr, res)) {
- DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n",
+ DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
res->start, res->end);
return -1; /* "can't happen" */
}
update_bridge_base(bus, i);
- printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n",
- bus->number, i, res->start, res->end);
+ printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
+ bus->number, i, (unsigned long long)res->start,
+ (unsigned long long)res->end);
return 0;
}
@@ -479,14 +479,14 @@ static inline void alloc_resource(struct pci_dev *dev, int idx)
{
struct resource *pr, *r = &dev->resource[idx];
- DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+ DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
pci_name(dev), idx, r->start, r->end, r->flags);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate resource region %d"
" of device %s\n", idx, pci_name(dev));
if (pr)
- DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",
+ DBG("PCI: parent is %p: %016llx-%016llx (f=%lx)\n",
pr, pr->start, pr->end, pr->flags);
/* We'll assign a new address later */
r->flags |= IORESOURCE_UNSET;
@@ -956,7 +956,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
res = &hose->io_resource;
res->flags = IORESOURCE_IO;
res->start = ranges[2];
- DBG("PCI: IO 0x%lx -> 0x%lx\n",
+ DBG("PCI: IO 0x%llx -> 0x%llx\n",
res->start, res->start + size - 1);
break;
case 2: /* memory space */
@@ -978,7 +978,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
if(ranges[0] & 0x40000000)
res->flags |= IORESOURCE_PREFETCH;
res->start = ranges[na+2];
- DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
+ DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
res->start, res->start + size - 1);
}
break;
@@ -1074,7 +1074,7 @@ do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
- DBG(" IO window: %08lx-%08lx\n", res.start, res.end);
+ DBG(" IO window: %016llx-%016llx\n", res.start, res.end);
/* Set up the top and bottom of the PCI I/O segment for this bus. */
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
@@ -1113,9 +1113,10 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
int i;
int rc = 0;
-#define push_end(res, size) do { unsigned long __sz = (size) ; \
- res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
- } while (0)
+#define push_end(res, mask) do { \
+ BUG_ON((mask+1) & mask); \
+ res->end = (res->end + mask) | mask; \
+} while (0)
list_for_each_entry(dev, &bus->devices, bus_list) {
u16 class = dev->class >> 8;
@@ -1222,8 +1223,8 @@ do_fixup_p2p_level(struct pci_bus *bus)
continue;
if ((r->flags & IORESOURCE_IO) == 0)
continue;
- DBG("Trying to allocate from %08lx, size %08lx from parent"
- " res %d: %08lx -> %08lx\n",
+ DBG("Trying to allocate from %016llx, size %016llx from parent"
+ " res %d: %016llx -> %016llx\n",
res->start, res->end, i, r->start, r->end);
if (allocate_resource(r, res, res->end + 1, res->start, max,
@@ -1573,8 +1574,8 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
else
prot |= _PAGE_GUARDED;
- printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
- prot);
+ printk("PCI map for %s:%llx, prot: %lx\n", pci_name(dev),
+ (unsigned long long)rp->start, prot);
return __pgprot(prot);
}
@@ -1653,7 +1654,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
vma->vm_page_prot,
mmap_state, write_combine);
@@ -1755,7 +1755,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
- u64 *start, u64 *end)
+ resource_size_t *start, resource_size_t *end)
{
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
unsigned long offset = 0;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4c4449be81c..bea8451fb57 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -13,7 +13,6 @@
#undef DEBUG
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
@@ -42,14 +41,6 @@
unsigned long pci_probe_only = 1;
int pci_assign_all_buses = 0;
-/*
- * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch
- * devices we don't have access to.
- */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
#ifdef CONFIG_PPC_MULTIPLATFORM
static void fixup_resource(struct resource *res, struct pci_dev *dev);
static void do_bus_setup(struct pci_bus *bus);
@@ -146,11 +137,11 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
* which might have be mirrored at 0x0100-0x03ff..
*/
void pcibios_align_resource(void *data, struct resource *res,
- unsigned long size, unsigned long align)
+ resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long start = res->start;
+ resource_size_t start = res->start;
unsigned long alignto;
if (res->flags & IORESOURCE_IO) {
@@ -235,8 +226,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
pci_setup_pci_controller(phb);
phb->arch_data = dev;
phb->is_dynamic = mem_init_done;
- if (dev)
+ if (dev) {
+ PHB_SET_NODE(phb, of_node_to_nid(dev));
add_linux_pci_domain(dev, phb);
+ }
return phb;
}
@@ -396,7 +389,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
dev->current_state = 4; /* unknown power state */
- if (!strcmp(type, "pci")) {
+ if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
@@ -605,7 +598,7 @@ static int __init pcibios_init(void)
iSeries_pcibios_init();
#endif
- printk("PCI: Probing PCI hardware\n");
+ printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
/* Scan all of the recorded PCI controllers. */
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -630,14 +623,14 @@ static int __init pcibios_init(void)
/* Cache the location of the ISA bridge (if we have one) */
ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
if (ppc64_isabridge_dev != NULL)
- printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
+ printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
#ifdef CONFIG_PPC_MULTIPLATFORM
/* map in PCI I/O space */
phbs_remap_io();
#endif
- printk("PCI: Probing PCI hardware done\n");
+ printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
return 0;
}
@@ -804,7 +797,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
else
prot |= _PAGE_GUARDED;
- printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+ printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
prot);
return __pgprot(prot);
@@ -883,7 +876,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return -EINVAL;
vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
vma->vm_page_prot,
mmap_state, write_combine);
@@ -894,8 +886,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return ret;
}
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
@@ -907,13 +899,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att
return sprintf(buf, "%s", np->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
void pcibios_add_platform_entries(struct pci_dev *pdev)
{
-#ifdef CONFIG_PPC_MULTIPLATFORM
device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
}
#ifdef CONFIG_PPC_MULTIPLATFORM
@@ -1104,8 +1093,6 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
hose->io_base_virt);
of_node_put(isa_dn);
- /* Allow all IO */
- io_page_mask = -1;
}
}
@@ -1212,7 +1199,7 @@ int remap_bus_range(struct pci_bus *bus)
return 1;
if (start_phys == 0)
return 1;
- printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
+ printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
if (__ioremap_explicit(start_phys, start_virt, size,
_PAGE_NO_CACHE | _PAGE_GUARDED))
return 1;
@@ -1232,27 +1219,13 @@ static void phbs_remap_io(void)
static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned long start, end, mask, offset;
+ unsigned long offset;
if (res->flags & IORESOURCE_IO) {
offset = (unsigned long)hose->io_base_virt - pci_io_base;
- start = res->start += offset;
- end = res->end += offset;
-
- /* Need to allow IO access to pages that are in the
- ISA range */
- if (start < MAX_ISA_PORT) {
- if (end > MAX_ISA_PORT)
- end = MAX_ISA_PORT;
-
- start >>= PAGE_SHIFT;
- end >>= PAGE_SHIFT;
-
- /* get the range of pages for the map */
- mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
- io_page_mask |= mask;
- }
+ res->start += offset;
+ res->end += offset;
} else if (res->flags & IORESOURCE_MEM) {
res->start += hose->pci_mem_offset;
res->end += hose->pci_mem_offset;
@@ -1442,3 +1415,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
return -EOPNOTSUPP;
}
+
+#ifdef CONFIG_NUMA
+int pcibus_to_node(struct pci_bus *bus)
+{
+ struct pci_controller *phb = pci_bus_to_host(bus);
+ return phb->node;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+#endif
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c
index e1a32f802c0..72ce082ce73 100644
--- a/arch/powerpc/kernel/pci_direct_iommu.c
+++ b/arch/powerpc/kernel/pci_direct_iommu.c
@@ -82,13 +82,17 @@ static int pci_direct_dma_supported(struct device *dev, u64 mask)
return mask < 0x100000000ull;
}
+static struct dma_mapping_ops pci_direct_ops = {
+ .alloc_coherent = pci_direct_alloc_coherent,
+ .free_coherent = pci_direct_free_coherent,
+ .map_single = pci_direct_map_single,
+ .unmap_single = pci_direct_unmap_single,
+ .map_sg = pci_direct_map_sg,
+ .unmap_sg = pci_direct_unmap_sg,
+ .dma_supported = pci_direct_dma_supported,
+};
+
void __init pci_direct_iommu_init(void)
{
- pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
- pci_dma_ops.free_coherent = pci_direct_free_coherent;
- pci_dma_ops.map_single = pci_direct_map_single;
- pci_dma_ops.unmap_single = pci_direct_unmap_single;
- pci_dma_ops.map_sg = pci_direct_map_sg;
- pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
- pci_dma_ops.dma_supported = pci_direct_dma_supported;
+ pci_dma_ops = pci_direct_ops;
}
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 12c4c9e9bbc..1c18953514c 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -31,6 +31,7 @@
#include <asm/pci-bridge.h>
#include <asm/pSeries_reconfig.h>
#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
/*
* Traverse_func that inits the PCI fields of the device node.
@@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
pdn->busno = (regs[0] >> 16) & 0xff;
pdn->devfn = (regs[0] >> 8) & 0xff;
}
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+ if (busp)
+ pdn->bussubno = *busp;
+ }
pdn->pci_ext_config_space = (type && *type == 1);
return NULL;
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c1d95e14bbe..0688b2534ac 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -44,16 +44,16 @@
*/
#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
-static inline struct iommu_table *devnode_table(struct device *dev)
+static inline struct iommu_table *device_to_table(struct device *hwdev)
{
struct pci_dev *pdev;
- if (!dev) {
+ if (!hwdev) {
pdev = ppc64_isabridge_dev;
if (!pdev)
return NULL;
} else
- pdev = to_pci_dev(dev);
+ pdev = to_pci_dev(hwdev);
return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
}
@@ -85,14 +85,15 @@ static inline unsigned long device_to_mask(struct device *hwdev)
static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
- device_to_mask(hwdev), flag);
+ return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
+ device_to_mask(hwdev), flag,
+ pcibus_to_node(to_pci_dev(hwdev)->bus));
}
static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
+ iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
}
/* Creates TCEs for a user provided buffer. The user buffer must be
@@ -104,7 +105,7 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
- return iommu_map_single(devnode_table(hwdev), vaddr, size,
+ return iommu_map_single(device_to_table(hwdev), vaddr, size,
device_to_mask(hwdev), direction);
}
@@ -112,27 +113,27 @@ static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
+ iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
}
static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(pdev, devnode_table(pdev), sglist,
+ return iommu_map_sg(pdev, device_to_table(pdev), sglist,
nelems, device_to_mask(pdev), direction);
}
static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
+ iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
}
/* We support DMA to/from any memory page via the iommu */
static int pci_iommu_dma_supported(struct device *dev, u64 mask)
{
- struct iommu_table *tbl = devnode_table(dev);
+ struct iommu_table *tbl = device_to_table(dev);
if (!tbl || tbl->it_offset > mask) {
printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
@@ -147,13 +148,17 @@ static int pci_iommu_dma_supported(struct device *dev, u64 mask)
return 1;
}
+struct dma_mapping_ops pci_iommu_ops = {
+ .alloc_coherent = pci_iommu_alloc_coherent,
+ .free_coherent = pci_iommu_free_coherent,
+ .map_single = pci_iommu_map_single,
+ .unmap_single = pci_iommu_unmap_single,
+ .map_sg = pci_iommu_map_sg,
+ .unmap_sg = pci_iommu_unmap_sg,
+ .dma_supported = pci_iommu_dma_supported,
+};
+
void pci_iommu_init(void)
{
- pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
- pci_dma_ops.free_coherent = pci_iommu_free_coherent;
- pci_dma_ops.map_single = pci_iommu_map_single;
- pci_dma_ops.unmap_single = pci_iommu_unmap_single;
- pci_dma_ops.map_sg = pci_iommu_map_sg;
- pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
- pci_dma_ops.dma_supported = pci_iommu_dma_supported;
+ pci_dma_ops = pci_iommu_ops;
}
diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c
index 32455dfcc36..bdc3977a7b0 100644
--- a/arch/powerpc/kernel/perfmon_fsl_booke.c
+++ b/arch/powerpc/kernel/perfmon_fsl_booke.c
@@ -21,7 +21,6 @@
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/interrupt.h>
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/prctl.h>
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index e6fb194fe53..a0a2efadeab 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -12,7 +12,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/module.h>
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 4b052ae5dc3..e3b80f71748 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/threads.h>
#include <linux/smp.h>
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 3c2cf661f6d..f598cb51953 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
@@ -52,7 +51,7 @@ static int __init proc_ppc64_create(void)
if (!root)
return 1;
- if (!machine_is(pseries) && !machine_is(cell))
+ if (!of_find_node_by_path("/rtas"))
return 0;
if (!proc_mkdir("rtas", root))
@@ -115,8 +114,6 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
{
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
- vma->vm_flags |= VM_SHM | VM_LOCKED;
-
if ((vma->vm_end - vma->vm_start) > dp->size)
return -EINVAL;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2dd47d2dd99..a127a1e3c09 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -14,7 +14,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -708,6 +707,61 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
return put_user(val, (unsigned int __user *) adr);
}
+int set_endian(struct task_struct *tsk, unsigned int val)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+
+ if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) ||
+ (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE)))
+ return -EINVAL;
+
+ if (regs == NULL)
+ return -EINVAL;
+
+ if (val == PR_ENDIAN_BIG)
+ regs->msr &= ~MSR_LE;
+ else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE)
+ regs->msr |= MSR_LE;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int get_endian(struct task_struct *tsk, unsigned long adr)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+ unsigned int val;
+
+ if (!cpu_has_feature(CPU_FTR_PPC_LE) &&
+ !cpu_has_feature(CPU_FTR_REAL_LE))
+ return -EINVAL;
+
+ if (regs == NULL)
+ return -EINVAL;
+
+ if (regs->msr & MSR_LE) {
+ if (cpu_has_feature(CPU_FTR_REAL_LE))
+ val = PR_ENDIAN_LITTLE;
+ else
+ val = PR_ENDIAN_PPC_LITTLE;
+ } else
+ val = PR_ENDIAN_BIG;
+
+ return put_user(val, (unsigned int __user *)adr);
+}
+
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+ tsk->thread.align_ctl = val;
+ return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+ return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
+}
+
#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
int sys_clone(unsigned long clone_flags, unsigned long usp,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9a07f97f071..4c524cb5218 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -16,7 +16,6 @@
#undef DEBUG
#include <stdarg.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
@@ -30,6 +29,7 @@
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/kexec.h>
+#include <linux/debugfs.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -50,6 +50,7 @@
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
+#include <asm/kexec.h>
#ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
return mem;
}
+static int __init early_parse_mem(char *p)
+{
+ if (!p)
+ return 1;
+
+ memory_limit = PAGE_ALIGN(memparse(p, &p));
+ DBG("memory limit = 0x%lx\n", memory_limit);
+
+ return 0;
+}
+early_param("mem", early_parse_mem);
+
+/*
+ * The device tree may be allocated below our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out now.
+ */
+static void move_device_tree(void)
+{
+ unsigned long start, size;
+ void *p;
+
+ DBG("-> move_device_tree\n");
+
+ start = __pa(initial_boot_params);
+ size = initial_boot_params->totalsize;
+
+ if ((memory_limit && (start + size) > memory_limit) ||
+ overlaps_crashkernel(start, size)) {
+ p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
+ memcpy(p, initial_boot_params, size);
+ initial_boot_params = (struct boot_param_header *)p;
+ DBG("Moved device tree to 0x%p\n", p);
+ }
+
+ DBG("<- move_device_tree\n");
+}
/**
* unflattens the device-tree passed by the firmware, creating the
@@ -911,7 +948,11 @@ static struct ibm_pa_feature {
{CPU_FTR_CTRL, 0, 0, 3, 0},
{CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
{CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
+#if 0
+ /* put this back once we know how to test if firmware does 64k IO */
{CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
+#endif
+ {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
};
static void __init check_cpu_pa_features(unsigned long node)
@@ -1070,6 +1111,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
iommu_force_on = 1;
#endif
+ /* mem=x on the command line is the preferred mechanism */
lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
if (lprop)
memory_limit = *lprop;
@@ -1083,24 +1125,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
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)
@@ -1123,17 +1147,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
DBG("Command line is: %s\n", cmd_line);
- if (strstr(cmd_line, "mem=")) {
- char *p, *q;
-
- for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
- q = p + 4;
- if (p > cmd_line && p[-1] != ' ')
- continue;
- memory_limit = memparse(q, &q);
- }
- }
-
/* break now */
return 1;
}
@@ -1237,9 +1250,17 @@ static void __init early_reserve_mem(void)
{
u64 base, size;
u64 *reserve_map;
+ unsigned long self_base;
+ unsigned long self_size;
reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
initial_boot_params->off_mem_rsvmap);
+
+ /* before we do anything, lets reserve the dt blob */
+ self_base = __pa((unsigned long)initial_boot_params);
+ self_size = initial_boot_params->totalsize;
+ lmb_reserve(self_base, self_size);
+
#ifdef CONFIG_PPC32
/*
* Handle the case where we might be booting from an old kexec
@@ -1254,6 +1275,9 @@ static void __init early_reserve_mem(void)
size_32 = *(reserve_map_32++);
if (size_32 == 0)
break;
+ /* skip if the reservation is for the blob */
+ if (base_32 == self_base && size_32 == self_size)
+ continue;
DBG("reserving: %x -> %x\n", base_32, size_32);
lmb_reserve(base_32, size_32);
}
@@ -1265,6 +1289,9 @@ static void __init early_reserve_mem(void)
size = *(reserve_map++);
if (size == 0)
break;
+ /* skip if the reservation is for the blob */
+ if (base == self_base && size == self_size)
+ continue;
DBG("reserving: %llx -> %llx\n", base, size);
lmb_reserve(base, size);
}
@@ -1282,6 +1309,11 @@ void __init early_init_devtree(void *params)
/* 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 ...
@@ -1292,18 +1324,26 @@ void __init early_init_devtree(void *params)
lmb_init();
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
- lmb_enforce_memory_limit(memory_limit);
- lmb_analyze();
- DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
+ /* Save command line for /proc/cmdline and then parse parameters */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+ parse_early_param();
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
-#ifdef CONFIG_CRASH_DUMP
- lmb_reserve(0, KDUMP_RESERVE_LIMIT);
-#endif
+ reserve_kdump_trampoline();
+ reserve_crashkernel();
early_reserve_mem();
+ lmb_enforce_memory_limit(memory_limit);
+ lmb_analyze();
+
+ DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
+
+ /* We may need to relocate the flat tree, do it now.
+ * FIXME .. and the initrd too? */
+ move_device_tree();
+
DBG("Scanning CPUs ...\n");
/* Retreive CPU related informations from the flat tree
@@ -2053,29 +2093,70 @@ int prom_update_property(struct device_node *np,
return 0;
}
-#ifdef CONFIG_KEXEC
-/* We may have allocated the flat device tree inside the crash kernel region
- * in prom_init. If so we need to move it out into regular memory. */
-void kdump_move_device_tree(void)
+
+/* Find the device node for a given logical cpu number, also returns the cpu
+ * local thread number (index in ibm,interrupt-server#s) if relevant and
+ * asked for (non NULL)
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
{
- unsigned long start, end;
- struct boot_param_header *new;
+ int hardid;
+ struct device_node *np;
- start = __pa((unsigned long)initial_boot_params);
- end = start + initial_boot_params->totalsize;
+ hardid = get_hard_smp_processor_id(cpu);
- if (end < crashk_res.start || start > crashk_res.end)
- return;
+ for_each_node_by_type(np, "cpu") {
+ u32 *intserv;
+ unsigned int plen, t;
- new = (struct boot_param_header*)
- __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
+ /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
+ * fallback to "reg" property and assume no threads
+ */
+ intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
+ &plen);
+ if (intserv == NULL) {
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+ if (reg == NULL)
+ continue;
+ if (*reg == hardid) {
+ if (thread)
+ *thread = 0;
+ return np;
+ }
+ } else {
+ plen /= sizeof(u32);
+ for (t = 0; t < plen; t++) {
+ if (hardid == intserv[t]) {
+ if (thread)
+ *thread = t;
+ return np;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+#ifdef DEBUG
+static struct debugfs_blob_wrapper flat_dt_blob;
- memcpy(new, initial_boot_params, initial_boot_params->totalsize);
+static int __init export_flat_device_tree(void)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir("powerpc", NULL);
+ if (!d)
+ return 1;
- initial_boot_params = new;
+ flat_dt_blob.data = initial_boot_params;
+ flat_dt_blob.size = initial_boot_params->totalsize;
- DBG("Flat device tree blob moved to %p\n", initial_boot_params);
+ d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
+ d, &flat_dt_blob);
+ if (!d)
+ return 1;
- /* XXX should we unreserve the old DT? */
+ return 0;
}
-#endif /* CONFIG_KEXEC */
+__initcall(export_flat_device_tree);
+#endif
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f70bd090dac..1e95a9f8cda 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -16,7 +16,6 @@
#undef DEBUG_PROM
#include <stdarg.h>
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
@@ -194,19 +193,12 @@ static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
-static unsigned long __initdata prom_memory_limit;
-
static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
static unsigned long __initdata rmo_top;
static unsigned long __initdata ram_top;
-#ifdef CONFIG_KEXEC
-static unsigned long __initdata prom_crashk_base;
-static unsigned long __initdata prom_crashk_size;
-#endif
-
static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
static int __initdata mem_reserve_cnt;
@@ -574,7 +566,7 @@ static void __init early_cmdline_parse(void)
if ((long)_prom->chosen > 0)
l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
#ifdef CONFIG_CMDLINE
- if (l == 0) /* dbl check */
+ if (l <= 0 || p[0] == '\0') /* dbl check */
strlcpy(RELOC(prom_cmd_line),
RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
#endif /* CONFIG_CMDLINE */
@@ -593,45 +585,6 @@ static void __init early_cmdline_parse(void)
RELOC(iommu_force_on) = 1;
}
#endif
-
- opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
- if (opt) {
- opt += 4;
- RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
-#ifdef CONFIG_PPC64
- /* Align to 16 MB == size of ppc64 large page */
- RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
-#endif
- }
-
-#ifdef CONFIG_KEXEC
- /*
- * crashkernel=size@addr specifies the location to reserve for
- * crash kernel.
- */
- opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
- if (opt) {
- opt += 12;
- RELOC(prom_crashk_size) =
- prom_memparse(opt, (const char **)&opt);
-
- if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
- RELOC(prom_crashk_size)) {
- prom_printf("Warning: crashkernel size is not "
- "aligned to 16MB\n");
- }
-
- /*
- * At present, the crash kernel always run at 32MB.
- * Just ignore whatever user passed.
- */
- RELOC(prom_crashk_base) = 0x2000000;
- if (*opt == '@') {
- prom_printf("Warning: PPC64 kdump kernel always runs "
- "at 32 MB\n");
- }
- }
-#endif
}
#ifdef CONFIG_PPC_PSERIES
@@ -1034,7 +987,7 @@ static void reserve_mem(u64 base, u64 size)
}
/*
- * Initialize memory allocation mecanism, parse "memory" nodes and
+ * Initialize memory allocation mechanism, parse "memory" nodes and
* obtain that way the top of memory and RMO to setup out local allocator
*/
static void __init prom_init_mem(void)
@@ -1116,29 +1069,6 @@ static void __init prom_init_mem(void)
}
/*
- * If prom_memory_limit is set we reduce the upper limits *except* for
- * alloc_top_high. This must be the real top of RAM so we can put
- * TCE's up there.
- */
-
- RELOC(alloc_top_high) = RELOC(ram_top);
-
- if (RELOC(prom_memory_limit)) {
- if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
- prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
- RELOC(prom_memory_limit));
- RELOC(prom_memory_limit) = 0;
- } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
- prom_printf("Ignoring mem=%x >= ram_top.\n",
- RELOC(prom_memory_limit));
- RELOC(prom_memory_limit) = 0;
- } else {
- RELOC(ram_top) = RELOC(prom_memory_limit);
- RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
- }
- }
-
- /*
* Setup our top alloc point, that is top of RMO or top of
* segment 0 when running non-LPAR.
* Some RS64 machines have buggy firmware where claims up at
@@ -1150,20 +1080,14 @@ static void __init prom_init_mem(void)
RELOC(rmo_top) = RELOC(ram_top);
RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
RELOC(alloc_top) = RELOC(rmo_top);
+ RELOC(alloc_top_high) = RELOC(ram_top);
prom_printf("memory layout at init:\n");
- prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
prom_printf(" ram_top : %x\n", RELOC(ram_top));
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base)) {
- prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base));
- prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size));
- }
-#endif
}
@@ -1349,16 +1273,10 @@ static void __init prom_initialize_tce_table(void)
reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
- if (RELOC(prom_memory_limit)) {
- /*
- * We align the start to a 16MB boundary so we can map
- * the TCE area using large pages if possible.
- * The end should be the top of RAM so no need to align it.
- */
- RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
- 0x1000000);
- RELOC(prom_tce_alloc_end) = local_alloc_top;
- }
+ /* These are only really needed if there is a memory limit in
+ * effect, but we don't know so export them always. */
+ RELOC(prom_tce_alloc_start) = local_alloc_bottom;
+ RELOC(prom_tce_alloc_end) = local_alloc_top;
/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
@@ -2041,11 +1959,7 @@ static void __init flatten_device_tree(void)
/* Version 16 is not backward compatible */
hdr->last_comp_version = 0x10;
- /* Reserve the whole thing and copy the reserve map in, we
- * also bump mem_reserve_cnt to cause further reservations to
- * fail since it's too late.
- */
- reserve_mem(RELOC(dt_header_start), hdr->totalsize);
+ /* Copy the reserve map in */
memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
#ifdef DEBUG_PROM
@@ -2058,6 +1972,9 @@ static void __init flatten_device_tree(void)
RELOC(mem_reserve_map)[i].size);
}
#endif
+ /* Bump mem_reserve_cnt to cause further reservations to fail
+ * since it's too late.
+ */
RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
prom_printf("Device tree strings 0x%x -> 0x%x\n",
@@ -2280,10 +2197,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_init_mem();
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base))
- reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
-#endif
/*
* Determine which cpu is actually running right _now_
*/
@@ -2317,10 +2230,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
/*
* Fill in some infos for use by the kernel later on
*/
- if (RELOC(prom_memory_limit))
- prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
- &RELOC(prom_memory_limit),
- sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
@@ -2340,16 +2249,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
}
#endif
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base)) {
- prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
- PTRRELOC(&prom_crashk_base),
- sizeof(RELOC(prom_crashk_base)));
- prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
- PTRRELOC(&prom_crashk_size),
- sizeof(RELOC(prom_crashk_size)));
- }
-#endif
/*
* Fixup any known bugs in the device-tree
*/
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 3934c227549..45df420383c 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -548,3 +548,28 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
return __of_address_to_resource(dev, addrp, size, flags, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
+ unsigned long *busno, unsigned long *phys, unsigned long *size)
+{
+ u32 *dma_window, cells;
+ unsigned char *prop;
+
+ dma_window = (u32 *)dma_window_prop;
+
+ /* busno is always one cell */
+ *busno = *(dma_window++);
+
+ prop = get_property(dn, "ibm,#dma-address-cells", NULL);
+ if (!prop)
+ prop = get_property(dn, "#address-cells", NULL);
+
+ cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn);
+ *phys = of_read_addr(dma_window, cells);
+
+ dma_window += cells;
+
+ prop = get_property(dn, "ibm,#dma-size-cells", NULL);
+ cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
+ *size = of_read_addr(dma_window, cells);
+}
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
index c42a860c8d2..8797ae737a7 100644
--- a/arch/powerpc/kernel/ptrace-common.h
+++ b/arch/powerpc/kernel/ptrace-common.h
@@ -10,7 +10,6 @@
#ifndef _PPC64_PTRACE_COMMON_H
#define _PPC64_PTRACE_COMMON_H
-#include <linux/config.h>
#include <asm/system.h>
/*
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 4a677d1bd4e..dea75d73f98 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -15,7 +15,6 @@
* this archive for more details.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -404,7 +403,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = ptrace_detach(child, data);
break;
-#ifdef CONFIG_PPC64
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
int i;
unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
@@ -468,7 +466,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
break;
}
-#endif /* CONFIG_PPC64 */
#ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS:
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 826ee3d056d..9b9a230349b 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -17,7 +17,6 @@
* this archive for more details.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 34d073fb609..77578c093dd 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -14,19 +14,20 @@
unsigned long __init rtas_get_boot_time(void)
{
int ret[8];
- int error, wait_time;
+ int error;
+ unsigned int wait_time;
u64 max_wait_tb;
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
do {
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
- if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
- wait_time = rtas_extended_busy_delay_time(error);
+
+ wait_time = rtas_busy_delay_time(error);
+ if (wait_time) {
/* This is boot time so we spin. */
udelay(wait_time*1000);
- error = RTAS_CLOCK_BUSY;
}
- } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+ } while (wait_time && (get_tb() < max_wait_tb));
if (error != 0 && printk_ratelimit()) {
printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time(void)
void rtas_get_rtc_time(struct rtc_time *rtc_tm)
{
int ret[8];
- int error, wait_time;
+ int error;
+ unsigned int wait_time;
u64 max_wait_tb;
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
do {
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
- if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+ wait_time = rtas_busy_delay_time(error);
+ if (wait_time) {
if (in_interrupt() && printk_ratelimit()) {
memset(rtc_tm, 0, sizeof(struct rtc_time));
printk(KERN_WARNING "error: reading clock"
" would delay interrupt\n");
return; /* delay not allowed */
}
- wait_time = rtas_extended_busy_delay_time(error);
msleep(wait_time);
- error = RTAS_CLOCK_BUSY;
}
- } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+ } while (wait_time && (get_tb() < max_wait_tb));
if (error != 0 && printk_ratelimit()) {
printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *tm)
tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min,
tm->tm_sec, 0);
- if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+ wait_time = rtas_busy_delay_time(error);
+ if (wait_time) {
if (in_interrupt())
return 1; /* probably decrementer */
- wait_time = rtas_extended_busy_delay_time(error);
msleep(wait_time);
- error = RTAS_CLOCK_BUSY;
}
- } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+ } while (wait_time && (get_tb() < max_wait_tb));
if (error != 0 && printk_ratelimit())
printk(KERN_WARNING "error: setting the clock failed (%d)\n",
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 0112318213a..4a4cb559840 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -38,16 +38,19 @@
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_delay(char c)
}
}
-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 nret, int *outputs, ...)
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,26 +433,41 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
}
return ret;
}
+EXPORT_SYMBOL(rtas_call);
-/* Given an RTAS status code of 990n compute the hinted delay of 10^n
- * (last digit) milliseconds. For now we bound at n=5 (100 sec).
+/* 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.
*/
-unsigned int rtas_extended_busy_delay_time(int status)
+unsigned int rtas_busy_delay_time(int status)
{
- int order = status - 9900;
- unsigned long ms;
+ int order;
+ unsigned int ms = 0;
+
+ if (status == RTAS_BUSY) {
+ ms = 1;
+ } else if (status >= 9900 && status <= 9905) {
+ order = status - 9900;
+ for (ms = 1; order > 0; order--)
+ ms *= 10;
+ }
+
+ return ms;
+}
+EXPORT_SYMBOL(rtas_busy_delay_time);
- if (order < 0)
- order = 0; /* RTC depends on this for -2 clock busy */
- else if (order > 5)
- order = 5; /* bound */
+/* For an RTAS busy status code, perform the hinted delay. */
+unsigned int rtas_busy_delay(int status)
+{
+ unsigned int ms;
- /* Use microseconds for reasonable accuracy */
- for (ms = 1; order > 0; order--)
- ms *= 10;
+ might_sleep();
+ ms = rtas_busy_delay_time(status);
+ if (ms)
+ msleep(ms);
- return ms;
+ return ms;
}
+EXPORT_SYMBOL(rtas_busy_delay);
int rtas_error_rc(int rtas_rc)
{
@@ -434,82 +513,61 @@ int rtas_get_power_level(int powerdomain, int *level)
return rtas_error_rc(rc);
return rc;
}
+EXPORT_SYMBOL(rtas_get_power_level);
int rtas_set_power_level(int powerdomain, int level, int *setlevel)
{
int token = rtas_token("set-power-level");
- unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- while (1) {
+ do {
rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
- if (rc == RTAS_BUSY)
- udelay(1);
- else if (rtas_is_extended_busy(rc)) {
- wait_time = rtas_extended_busy_delay_time(rc);
- udelay(wait_time * 1000);
- } else
- break;
- }
+ } while (rtas_busy_delay(rc));
if (rc < 0)
return rtas_error_rc(rc);
return rc;
}
+EXPORT_SYMBOL(rtas_set_power_level);
int rtas_get_sensor(int sensor, int index, int *state)
{
int token = rtas_token("get-sensor-state");
- unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- while (1) {
+ do {
rc = rtas_call(token, 2, 2, state, sensor, index);
- if (rc == RTAS_BUSY)
- udelay(1);
- else if (rtas_is_extended_busy(rc)) {
- wait_time = rtas_extended_busy_delay_time(rc);
- udelay(wait_time * 1000);
- } else
- break;
- }
+ } while (rtas_busy_delay(rc));
if (rc < 0)
return rtas_error_rc(rc);
return rc;
}
+EXPORT_SYMBOL(rtas_get_sensor);
int rtas_set_indicator(int indicator, int index, int new_value)
{
int token = rtas_token("set-indicator");
- unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
return -ENOENT;
- while (1) {
+ do {
rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
- if (rc == RTAS_BUSY)
- udelay(1);
- else if (rtas_is_extended_busy(rc)) {
- wait_time = rtas_extended_busy_delay_time(rc);
- udelay(wait_time * 1000);
- }
- else
- break;
- }
+ } while (rtas_busy_delay(rc));
if (rc < 0)
return rtas_error_rc(rc);
return rc;
}
+EXPORT_SYMBOL(rtas_set_indicator);
void rtas_restart(char *cmd)
{
@@ -555,13 +613,11 @@ void rtas_os_term(char *str)
do {
status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
__pa(rtas_os_term_buf));
+ } while (rtas_busy_delay(status));
- if (status == RTAS_BUSY)
- udelay(1);
- else if (status != 0)
- printk(KERN_EMERG "ibm,os-term call failed %d\n",
+ if (status != 0)
+ printk(KERN_EMERG "ibm,os-term call failed %d\n",
status);
- } while (status == RTAS_BUSY);
}
static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
@@ -608,9 +664,31 @@ out:
static int rtas_ibm_suspend_me(struct rtas_args *args)
{
int i;
+ long state;
+ long rc;
+ unsigned long dummy;
struct rtas_suspend_me_data data;
+ /* Make sure the state is valid */
+ rc = plpar_hcall(H_VASI_STATE,
+ ((u64)args->args[0] << 32) | args->args[1],
+ 0, 0, 0,
+ &state, &dummy, &dummy);
+
+ if (rc) {
+ printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
+ return rc;
+ } else if (state == H_VASI_ENABLED) {
+ args->args[args->nargs] = RTAS_NOT_SUSPENDABLE;
+ return 0;
+ } else if (state != H_VASI_SUSPENDING) {
+ printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
+ state);
+ args->args[args->nargs] = -1;
+ return 0;
+ }
+
data.waiting = 1;
data.args = args;
@@ -784,13 +862,34 @@ void __init rtas_initialize(void)
#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_extended_busy_delay_time);
-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/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index aaf384c3f04..1442b63a75d 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -365,20 +365,12 @@ static int rtas_excl_release(struct inode *inode, struct file *file)
static void manage_flash(struct rtas_manage_flash_t *args_buf)
{
- unsigned int wait_time;
s32 rc;
- while (1) {
+ do {
rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1,
1, NULL, args_buf->op);
- if (rc == RTAS_RC_BUSY)
- udelay(1);
- else if (rtas_is_extended_busy(rc)) {
- wait_time = rtas_extended_busy_delay_time(rc);
- udelay(wait_time * 1000);
- } else
- break;
- }
+ } while (rtas_busy_delay(rc));
args_buf->status = rc;
}
@@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
static void validate_flash(struct rtas_validate_flash_t *args_buf)
{
int token = rtas_token("ibm,validate-flash-image");
- unsigned int wait_time;
int update_results;
s32 rc;
rc = 0;
- while(1) {
+ do {
spin_lock(&rtas_data_buf_lock);
memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE);
rc = rtas_call(token, 2, 2, &update_results,
(u32) __pa(rtas_data_buf), args_buf->buf_size);
memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE);
spin_unlock(&rtas_data_buf_lock);
-
- if (rc == RTAS_RC_BUSY)
- udelay(1);
- else if (rtas_is_extended_busy(rc)) {
- wait_time = rtas_extended_busy_delay_time(rc);
- udelay(wait_time * 1000);
- } else
- break;
- }
+ } while (rtas_busy_delay(rc));
args_buf->status = rc;
args_buf->update_results = update_results;
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 57b539a03fa..6eb7e49b394 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -313,7 +313,9 @@ unsigned long __init find_and_init_phbs(void)
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
- if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+ if (node->type == NULL || (strcmp(node->type, "pci") != 0 &&
+ strcmp(node->type, "pciex") != 0))
continue;
phb = pcibios_alloc_controller(node);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 684ab1d49c6..c6d7b98af7d 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -12,7 +12,6 @@
#undef DEBUG
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sched.h>
@@ -443,6 +442,7 @@ void __init smp_setup_cpu_maps(void)
}
#endif /* CONFIG_SMP */
+int __initdata do_early_xmon;
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
@@ -456,7 +456,7 @@ static int __init early_xmon(char *p)
return 0;
}
xmon_init(1);
- debugger(NULL);
+ do_early_xmon = 1;
return 0;
}
@@ -524,3 +524,20 @@ int check_legacy_ioport(unsigned long base_port)
return ppc_md.check_legacy_ioport(base_port);
}
EXPORT_SYMBOL(check_legacy_ioport);
+
+static int ppc_panic_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ ppc_md.panic(ptr); /* May not return */
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_panic_block = {
+ .notifier_call = ppc_panic_event,
+ .priority = INT_MIN /* may not return; must be done last */
+};
+
+void __init setup_panic(void)
+{
+ atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
+}
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
index 2ebba755272..4c67ad7fae0 100644
--- a/arch/powerpc/kernel/setup.h
+++ b/arch/powerpc/kernel/setup.h
@@ -2,5 +2,8 @@
#define _POWERPC_KERNEL_SETUP_H
void check_for_initrd(void);
+void do_init_bootmem(void);
+void setup_panic(void);
+extern int do_early_xmon;
#endif /* _POWERPC_KERNEL_SETUP_H */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 69ac2570134..ba7cd50d820 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -2,7 +2,6 @@
* Common prep/pmac/chrp boot and setup code.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sched.h>
@@ -131,12 +130,6 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
/* Do some early initialization based on the flat device tree */
early_init_devtree(__va(dt_ptr));
- /* Check default command line */
-#ifdef CONFIG_CMDLINE
- if (cmd_line[0] == 0)
- strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
probe_machine();
#ifdef CONFIG_6xx
@@ -221,7 +214,7 @@ int __init ppc_init(void)
/* register CPU devices */
for_each_possible_cpu(i)
- register_cpu(&cpu_devices[i], i, NULL);
+ register_cpu(&cpu_devices[i], i);
/* call platform init */
if (ppc_md.init != NULL) {
@@ -235,7 +228,7 @@ arch_initcall(ppc_init);
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
{
- extern void do_init_bootmem(void);
+ *cmdline_p = cmd_line;
/* so udelay does something sensible, assume <= 1000 bogomips */
loops_per_jiffy = 500000000 / HZ;
@@ -285,16 +278,16 @@ void __init setup_arch(char **cmdline_p)
/* reboot on panic */
panic_timeout = 180;
+ if (ppc_md.panic)
+ setup_panic();
+
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit;
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
- *cmdline_p = cmd_line;
-
- parse_early_param();
+ if (do_early_xmon)
+ debugger(NULL);
/* set up the bootmem stuff with available memory */
do_init_bootmem();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4467c49903b..ac7276c4068 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -12,7 +12,6 @@
#undef DEBUG
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sched.h>
@@ -100,12 +99,6 @@ unsigned long SYSRQ_KEY;
#endif /* CONFIG_MAGIC_SYSRQ */
-static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-static struct notifier_block ppc64_panic_block = {
- .notifier_call = ppc64_panic_event,
- .priority = INT_MIN /* may not return; must be done last */
-};
-
#ifdef CONFIG_SMP
static int smt_enabled_cmdline;
@@ -155,6 +148,13 @@ early_param("smt-enabled", early_smt_enabled);
#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
@@ -176,6 +176,9 @@ early_param("smt-enabled", early_smt_enabled);
void __init early_setup(unsigned long dt_ptr)
{
+ /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
+ setup_paca(0);
+
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
@@ -189,7 +192,7 @@ void __init early_setup(unsigned long dt_ptr)
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;
@@ -199,9 +202,7 @@ void __init early_setup(unsigned long dt_ptr)
/* Probe the machine type */
probe_machine();
-#ifdef CONFIG_CRASH_DUMP
- kdump_setup();
-#endif
+ setup_kdump_trampoline();
DBG("Found, Initializing memory management...\n");
@@ -353,27 +354,16 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");
-#ifdef CONFIG_KEXEC
- kdump_move_device_tree();
-#endif
/*
* Unflatten the device-tree passed by prom_init or kexec
*/
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();
@@ -420,10 +410,8 @@ void __init setup_system(void)
*/
register_early_udbg_console();
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
- parse_early_param();
+ if (do_early_xmon)
+ debugger(NULL);
check_smt_enabled();
smp_setup_cpu_maps();
@@ -456,13 +444,6 @@ void __init setup_system(void)
DBG(" <- setup_system()\n");
}
-static int ppc64_panic_event(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- ppc_md.panic((char *)ptr); /* May not return */
- return NOTIFY_DONE;
-}
-
#ifdef CONFIG_IRQSTACKS
static void __init irqstack_early_init(void)
{
@@ -517,8 +498,6 @@ static void __init emergency_stack_init(void)
*/
void __init setup_arch(char **cmdline_p)
{
- extern void do_init_bootmem(void);
-
ppc64_boot_msg(0x12, "Setup Arch");
*cmdline_p = cmd_line;
@@ -535,8 +514,7 @@ void __init setup_arch(char **cmdline_p)
panic_timeout = 180;
if (ppc_md.panic)
- atomic_notifier_chain_register(&panic_notifier_list,
- &ppc64_panic_block);
+ setup_panic();
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) _etext;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 8fdeca2d459..320353f0926 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -17,7 +17,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -419,9 +418,7 @@ static long restore_user_regs(struct pt_regs *regs,
{
long err;
unsigned int save_r2 = 0;
-#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
unsigned long msr;
-#endif
/*
* restore general registers but not including MSR or SOFTE. Also
@@ -430,11 +427,16 @@ static long restore_user_regs(struct pt_regs *regs,
if (!sig)
save_r2 = (unsigned int)regs->gpr[2];
err = restore_general_regs(regs, sr);
+ err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
if (!sig)
regs->gpr[2] = (unsigned long) save_r2;
if (err)
return 1;
+ /* if doing signal return, restore the previous little-endian mode */
+ if (sig)
+ regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
/*
* Do this before updating the thread state in
* current->thread.fpr/vr/evr. That way, if we get preempted
@@ -455,7 +457,7 @@ static long restore_user_regs(struct pt_regs *regs,
/* force the process to reload the altivec registers from
current->thread when it next does altivec instructions */
regs->msr &= ~MSR_VEC;
- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+ if (msr & MSR_VEC) {
/* restore altivec registers from the stack */
if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
sizeof(sr->mc_vregs)))
@@ -472,7 +474,7 @@ static long restore_user_regs(struct pt_regs *regs,
/* force the process to reload the spe registers from
current->thread when it next does spe instructions */
regs->msr &= ~MSR_SPE;
- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+ if (msr & MSR_SPE) {
/* restore spe registers from the stack */
if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
ELF_NEVRREG * sizeof(u32)))
@@ -757,10 +759,10 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
/* Save user registers on the stack */
frame = &rt_sf->uc.uc_mcontext;
- if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+ if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, frame, 0))
goto badframe;
- regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+ regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
} else {
if (save_user_regs(regs, frame, __NR_rt_sigreturn))
goto badframe;
@@ -777,6 +779,8 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
regs->gpr[5] = (unsigned long) &rt_sf->uc;
regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler;
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1;
@@ -1038,10 +1042,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|| __put_user(sig, &sc->signal))
goto badframe;
- if (vdso32_sigtramp && current->thread.vdso_base) {
+ if (vdso32_sigtramp && current->mm->context.vdso_base) {
if (save_user_regs(regs, &frame->mctx, 0))
goto badframe;
- regs->link = current->thread.vdso_base + vdso32_sigtramp;
+ regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
} else {
if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
goto badframe;
@@ -1056,6 +1060,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler;
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index c2db642f4cd..f72e8e823d7 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -12,7 +12,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -141,9 +140,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
unsigned long err = 0;
unsigned long save_r13 = 0;
elf_greg_t *gregs = (elf_greg_t *)regs;
-#ifdef CONFIG_ALTIVEC
unsigned long msr;
-#endif
int i;
/* If this is not a signal return, we preserve the TLS in r13 */
@@ -154,7 +151,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
err |= __copy_from_user(regs, &sc->gp_regs,
PT_MSR*sizeof(unsigned long));
- /* skip MSR and SOFTE */
+ /* get MSR separately, transfer the LE bit if doing signal return */
+ err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+ if (sig)
+ regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
+ /* skip SOFTE */
for (i = PT_MSR+1; i <= PT_RESULT; i++) {
if (i == PT_SOFTE)
continue;
@@ -179,7 +181,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
#ifdef CONFIG_ALTIVEC
err |= __get_user(v_regs, &sc->v_regs);
- err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
if (err)
return err;
if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
@@ -396,8 +397,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
current->thread.fpscr.val = 0;
/* Set up to return from userspace. */
- if (vdso64_rt_sigtramp && current->thread.vdso_base) {
- regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
+ regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
} else {
err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
if (err)
@@ -412,6 +413,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Set up "regs" so we "return" to the signal handler. */
err |= get_user(regs->nip, &funct_desc_ptr->entry);
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->gpr[1] = newsp;
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
regs->gpr[3] = signr;
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index 9adef3bddad..f19e2e0e61e 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -5,7 +5,6 @@
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 530f7dba0bd..46c56cfd1b2 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -17,7 +17,6 @@
#undef DEBUG
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -492,7 +491,7 @@ int __devinit __cpu_up(unsigned int cpu)
* -- Cort
*/
if (system_state < SYSTEM_RUNNING)
- for (c = 5000; c && !cpu_callin_map[cpu]; c--)
+ for (c = 50000; c && !cpu_callin_map[cpu]; c--)
udelay(100);
#ifdef CONFIG_HOTPLUG_CPU
else
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
index 69773cc1a85..7369f9a6ad2 100644
--- a/arch/powerpc/kernel/swsusp_32.S
+++ b/arch/powerpc/kernel/swsusp_32.S
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index ec274e68881..2e292863e98 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -14,7 +14,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 5bc2585c803..01043509555 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <linux/smp.h>
@@ -279,7 +278,7 @@ static void unregister_cpu_online(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static int sysfs_cpu_notify(struct notifier_block *self,
+static int __devinit sysfs_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,30 +296,19 @@ static int sysfs_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block sysfs_cpu_nb = {
+static struct notifier_block __devinitdata sysfs_cpu_nb = {
.notifier_call = sysfs_cpu_notify,
};
/* NUMA stuff */
#ifdef CONFIG_NUMA
-static struct node node_devices[MAX_NUMNODES];
-
static void register_nodes(void)
{
int i;
- for (i = 0; i < MAX_NUMNODES; i++) {
- if (node_online(i)) {
- int p_node = parent_node(i);
- struct node *parent = NULL;
-
- if (p_node != i)
- parent = &node_devices[p_node];
-
- register_node(&node_devices[i], i, parent);
- }
- }
+ for (i = 0; i < MAX_NUMNODES; i++)
+ register_one_node(i);
}
int sysfs_add_device_to_node(struct sys_device *dev, int nid)
@@ -359,23 +347,13 @@ static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL);
static int __init topology_init(void)
{
int cpu;
- struct node *parent = NULL;
register_nodes();
-
register_cpu_notifier(&sysfs_cpu_nb);
for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
-#ifdef CONFIG_NUMA
- /* The node to which a cpu belongs can't be known
- * until the cpu is made present.
- */
- parent = NULL;
- if (cpu_present(cpu))
- parent = &node_devices[cpu_to_node(cpu)];
-#endif
/*
* For now, we just see if the system supports making
* the RTAS calls for CPU hotplug. But, there may be a
@@ -387,7 +365,7 @@ static int __init topology_init(void)
c->no_control = 1;
if (cpu_online(cpu) || (c->no_control == 0)) {
- register_cpu(c, cpu, parent);
+ register_cpu(c, cpu);
sysdev_create_file(&c->sysdev, &attr_physical_id);
}
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 26ed1f5ef16..579de70e0b4 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -14,7 +14,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/ppc_asm.h>
#ifdef CONFIG_PPC64
@@ -32,6 +31,10 @@
#define SYS32ONLY(func) .long sys_##func
#define SYSX(f, f3264, f32) .long f32
#endif
+#define SYSCALL_SPU(func) SYSCALL(func)
+#define COMPAT_SYS_SPU(func) COMPAT_SYS(func)
+#define PPC_SYS_SPU(func) PPC_SYS(func)
+#define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32)
#ifdef CONFIG_PPC64
#define sys_sigpending sys_ni_syscall
@@ -39,309 +42,4 @@
#endif
_GLOBAL(sys_call_table)
-SYSCALL(restart_syscall)
-SYSCALL(exit)
-PPC_SYS(fork)
-SYSCALL(read)
-SYSCALL(write)
-COMPAT_SYS(open)
-SYSCALL(close)
-COMPAT_SYS(waitpid)
-COMPAT_SYS(creat)
-SYSCALL(link)
-SYSCALL(unlink)
-COMPAT_SYS(execve)
-SYSCALL(chdir)
-COMPAT_SYS(time)
-SYSCALL(mknod)
-SYSCALL(chmod)
-SYSCALL(lchown)
-SYSCALL(ni_syscall)
-OLDSYS(stat)
-SYSX(sys_lseek,ppc32_lseek,sys_lseek)
-SYSCALL(getpid)
-COMPAT_SYS(mount)
-SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
-SYSCALL(setuid)
-SYSCALL(getuid)
-COMPAT_SYS(stime)
-COMPAT_SYS(ptrace)
-SYSCALL(alarm)
-OLDSYS(fstat)
-COMPAT_SYS(pause)
-COMPAT_SYS(utime)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(access)
-COMPAT_SYS(nice)
-SYSCALL(ni_syscall)
-SYSCALL(sync)
-COMPAT_SYS(kill)
-SYSCALL(rename)
-COMPAT_SYS(mkdir)
-SYSCALL(rmdir)
-SYSCALL(dup)
-SYSCALL(pipe)
-COMPAT_SYS(times)
-SYSCALL(ni_syscall)
-SYSCALL(brk)
-SYSCALL(setgid)
-SYSCALL(getgid)
-SYSCALL(signal)
-SYSCALL(geteuid)
-SYSCALL(getegid)
-SYSCALL(acct)
-SYSCALL(umount)
-SYSCALL(ni_syscall)
-COMPAT_SYS(ioctl)
-COMPAT_SYS(fcntl)
-SYSCALL(ni_syscall)
-COMPAT_SYS(setpgid)
-SYSCALL(ni_syscall)
-SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
-COMPAT_SYS(umask)
-SYSCALL(chroot)
-SYSCALL(ustat)
-SYSCALL(dup2)
-SYSCALL(getppid)
-SYSCALL(getpgrp)
-SYSCALL(setsid)
-SYS32ONLY(sigaction)
-SYSCALL(sgetmask)
-COMPAT_SYS(ssetmask)
-SYSCALL(setreuid)
-SYSCALL(setregid)
-SYS32ONLY(sigsuspend)
-COMPAT_SYS(sigpending)
-COMPAT_SYS(sethostname)
-COMPAT_SYS(setrlimit)
-COMPAT_SYS(old_getrlimit)
-COMPAT_SYS(getrusage)
-COMPAT_SYS(gettimeofday)
-COMPAT_SYS(settimeofday)
-COMPAT_SYS(getgroups)
-COMPAT_SYS(setgroups)
-SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
-SYSCALL(symlink)
-OLDSYS(lstat)
-COMPAT_SYS(readlink)
-SYSCALL(uselib)
-SYSCALL(swapon)
-SYSCALL(reboot)
-SYSX(sys_ni_syscall,old32_readdir,old_readdir)
-SYSCALL(mmap)
-SYSCALL(munmap)
-SYSCALL(truncate)
-SYSCALL(ftruncate)
-SYSCALL(fchmod)
-SYSCALL(fchown)
-COMPAT_SYS(getpriority)
-COMPAT_SYS(setpriority)
-SYSCALL(ni_syscall)
-COMPAT_SYS(statfs)
-COMPAT_SYS(fstatfs)
-SYSCALL(ni_syscall)
-COMPAT_SYS(socketcall)
-COMPAT_SYS(syslog)
-COMPAT_SYS(setitimer)
-COMPAT_SYS(getitimer)
-COMPAT_SYS(newstat)
-COMPAT_SYS(newlstat)
-COMPAT_SYS(newfstat)
-SYSX(sys_ni_syscall,sys_uname,sys_uname)
-SYSCALL(ni_syscall)
-SYSCALL(vhangup)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(wait4)
-SYSCALL(swapoff)
-COMPAT_SYS(sysinfo)
-COMPAT_SYS(ipc)
-SYSCALL(fsync)
-SYS32ONLY(sigreturn)
-PPC_SYS(clone)
-COMPAT_SYS(setdomainname)
-PPC_SYS(newuname)
-SYSCALL(ni_syscall)
-COMPAT_SYS(adjtimex)
-SYSCALL(mprotect)
-SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
-SYSCALL(ni_syscall)
-SYSCALL(init_module)
-SYSCALL(delete_module)
-SYSCALL(ni_syscall)
-SYSCALL(quotactl)
-COMPAT_SYS(getpgid)
-SYSCALL(fchdir)
-SYSCALL(bdflush)
-COMPAT_SYS(sysfs)
-SYSX(ppc64_personality,ppc64_personality,sys_personality)
-SYSCALL(ni_syscall)
-SYSCALL(setfsuid)
-SYSCALL(setfsgid)
-SYSCALL(llseek)
-COMPAT_SYS(getdents)
-SYSX(sys_select,ppc32_select,ppc_select)
-SYSCALL(flock)
-SYSCALL(msync)
-COMPAT_SYS(readv)
-COMPAT_SYS(writev)
-COMPAT_SYS(getsid)
-SYSCALL(fdatasync)
-COMPAT_SYS(sysctl)
-SYSCALL(mlock)
-SYSCALL(munlock)
-SYSCALL(mlockall)
-SYSCALL(munlockall)
-COMPAT_SYS(sched_setparam)
-COMPAT_SYS(sched_getparam)
-COMPAT_SYS(sched_setscheduler)
-COMPAT_SYS(sched_getscheduler)
-SYSCALL(sched_yield)
-COMPAT_SYS(sched_get_priority_max)
-COMPAT_SYS(sched_get_priority_min)
-COMPAT_SYS(sched_rr_get_interval)
-COMPAT_SYS(nanosleep)
-SYSCALL(mremap)
-SYSCALL(setresuid)
-SYSCALL(getresuid)
-SYSCALL(ni_syscall)
-SYSCALL(poll)
-COMPAT_SYS(nfsservctl)
-SYSCALL(setresgid)
-SYSCALL(getresgid)
-COMPAT_SYS(prctl)
-COMPAT_SYS(rt_sigreturn)
-COMPAT_SYS(rt_sigaction)
-COMPAT_SYS(rt_sigprocmask)
-COMPAT_SYS(rt_sigpending)
-COMPAT_SYS(rt_sigtimedwait)
-COMPAT_SYS(rt_sigqueueinfo)
-COMPAT_SYS(rt_sigsuspend)
-COMPAT_SYS(pread64)
-COMPAT_SYS(pwrite64)
-SYSCALL(chown)
-SYSCALL(getcwd)
-SYSCALL(capget)
-SYSCALL(capset)
-COMPAT_SYS(sigaltstack)
-SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-PPC_SYS(vfork)
-COMPAT_SYS(getrlimit)
-COMPAT_SYS(readahead)
-SYS32ONLY(mmap2)
-SYS32ONLY(truncate64)
-SYS32ONLY(ftruncate64)
-SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
-SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
-SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
-SYSCALL(pciconfig_read)
-SYSCALL(pciconfig_write)
-SYSCALL(pciconfig_iobase)
-SYSCALL(ni_syscall)
-SYSCALL(getdents64)
-SYSCALL(pivot_root)
-SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
-SYSCALL(madvise)
-SYSCALL(mincore)
-SYSCALL(gettid)
-SYSCALL(tkill)
-SYSCALL(setxattr)
-SYSCALL(lsetxattr)
-SYSCALL(fsetxattr)
-SYSCALL(getxattr)
-SYSCALL(lgetxattr)
-SYSCALL(fgetxattr)
-SYSCALL(listxattr)
-SYSCALL(llistxattr)
-SYSCALL(flistxattr)
-SYSCALL(removexattr)
-SYSCALL(lremovexattr)
-SYSCALL(fremovexattr)
-COMPAT_SYS(futex)
-COMPAT_SYS(sched_setaffinity)
-COMPAT_SYS(sched_getaffinity)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-SYS32ONLY(sendfile64)
-COMPAT_SYS(io_setup)
-SYSCALL(io_destroy)
-COMPAT_SYS(io_getevents)
-COMPAT_SYS(io_submit)
-SYSCALL(io_cancel)
-SYSCALL(set_tid_address)
-SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
-SYSCALL(exit_group)
-SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
-SYSCALL(epoll_create)
-SYSCALL(epoll_ctl)
-SYSCALL(epoll_wait)
-SYSCALL(remap_file_pages)
-SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create)
-COMPAT_SYS(timer_settime)
-COMPAT_SYS(timer_gettime)
-SYSCALL(timer_getoverrun)
-SYSCALL(timer_delete)
-COMPAT_SYS(clock_settime)
-COMPAT_SYS(clock_gettime)
-COMPAT_SYS(clock_getres)
-COMPAT_SYS(clock_nanosleep)
-SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
-COMPAT_SYS(tgkill)
-COMPAT_SYS(utimes)
-COMPAT_SYS(statfs64)
-COMPAT_SYS(fstatfs64)
-SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
-PPC_SYS(rtas)
-OLDSYS(debug_setcontext)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(mbind)
-COMPAT_SYS(get_mempolicy)
-COMPAT_SYS(set_mempolicy)
-COMPAT_SYS(mq_open)
-SYSCALL(mq_unlink)
-COMPAT_SYS(mq_timedsend)
-COMPAT_SYS(mq_timedreceive)
-COMPAT_SYS(mq_notify)
-COMPAT_SYS(mq_getsetattr)
-COMPAT_SYS(kexec_load)
-COMPAT_SYS(add_key)
-COMPAT_SYS(request_key)
-COMPAT_SYS(keyctl)
-COMPAT_SYS(waitid)
-COMPAT_SYS(ioprio_set)
-COMPAT_SYS(ioprio_get)
-SYSCALL(inotify_init)
-SYSCALL(inotify_add_watch)
-SYSCALL(inotify_rm_watch)
-SYSCALL(spu_run)
-SYSCALL(spu_create)
-COMPAT_SYS(pselect6)
-COMPAT_SYS(ppoll)
-SYSCALL(unshare)
-SYSCALL(splice)
-SYSCALL(tee)
-SYSCALL(vmsplice)
-COMPAT_SYS(openat)
-SYSCALL(mkdirat)
-SYSCALL(mknodat)
-SYSCALL(fchownat)
-COMPAT_SYS(futimesat)
-SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
-SYSCALL(unlinkat)
-SYSCALL(renameat)
-SYSCALL(linkat)
-SYSCALL(symlinkat)
-SYSCALL(readlinkat)
-SYSCALL(fchmodat)
-SYSCALL(faccessat)
-COMPAT_SYS(get_robust_list)
-COMPAT_SYS(set_robust_list)
-
-/*
- * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
- * as well when appropriate.
- */
+#include <asm/systbl.h>
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c
index 26bd8ea35a4..368a4934f7e 100644
--- a/arch/powerpc/kernel/tau_6xx.c
+++ b/arch/powerpc/kernel/tau_6xx.c
@@ -11,7 +11,6 @@
* life in portables, and add a 'performance/watt' metric somewhere in /proc
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 24e3ad756de..774c0a3c501 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -32,7 +32,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -76,7 +75,6 @@
/* keep track of when we need to update the rtc */
time_t last_rtc_update;
-extern int piranha_simulator;
#ifdef CONFIG_PPC_ISERIES
unsigned long iSeries_recal_titan = 0;
unsigned long iSeries_recal_tb = 0;
@@ -103,7 +101,7 @@ EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */
u64 tb_to_xs;
unsigned tb_to_us;
-#define TICKLEN_SCALE (SHIFT_SCALE - 10)
+#define TICKLEN_SCALE TICK_LENGTH_SHIFT
u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */
u64 ticklen_to_xs; /* 0.64 fraction */
@@ -858,42 +856,50 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
-void __init generic_calibrate_decr(void)
+static int __init get_freq(char *name, int cells, unsigned long *val)
{
struct device_node *cpu;
unsigned int *fp;
- int node_found;
+ int found = 0;
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
+ /* The cpu node should have timebase and clock frequency properties */
cpu = of_find_node_by_type(NULL, "cpu");
- ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
- node_found = 0;
if (cpu) {
- fp = (unsigned int *)get_property(cpu, "timebase-frequency",
- NULL);
+ fp = (unsigned int *)get_property(cpu, name, NULL);
if (fp) {
- node_found = 1;
- ppc_tb_freq = *fp;
+ found = 1;
+ *val = 0;
+ while (cells--)
+ *val = (*val << 32) | *fp++;
}
+
+ of_node_put(cpu);
}
- if (!node_found)
+
+ return found;
+}
+
+void __init generic_calibrate_decr(void)
+{
+ ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
+
+ if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) &&
+ !get_freq("timebase-frequency", 1, &ppc_tb_freq)) {
+
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
+ }
- ppc_proc_freq = DEFAULT_PROC_FREQ;
- node_found = 0;
- if (cpu) {
- fp = (unsigned int *)get_property(cpu, "clock-frequency",
- NULL);
- if (fp) {
- node_found = 1;
- ppc_proc_freq = *fp;
- }
+ ppc_proc_freq = DEFAULT_PROC_FREQ; /* hardcoded default */
+
+ if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) &&
+ !get_freq("clock-frequency", 1, &ppc_proc_freq)) {
+
+ printk(KERN_ERR "WARNING: Estimating processor frequency "
+ "(not found)\n");
}
+
#ifdef CONFIG_BOOKE
/* Set the time base to zero */
mtspr(SPRN_TBWL, 0);
@@ -905,11 +911,6 @@ void __init generic_calibrate_decr(void)
/* Enable decrementer interrupt */
mtspr(SPRN_TCR, TCR_DIE);
#endif
- if (!node_found)
- printk(KERN_ERR "WARNING: Estimating processor frequency "
- "(not found)\n");
-
- of_node_put(cpu);
}
unsigned long get_boot_time(void)
@@ -945,9 +946,9 @@ void __init time_init(void)
} else {
/* Normal PowerPC with timebase register */
ppc_md.calibrate_decr();
- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n",
ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
+ printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n",
ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
tb_last_stamp = tb_last_jiffy = get_tb();
}
@@ -1010,10 +1011,7 @@ void __init time_init(void)
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
-#ifdef CONFIG_PPC_ISERIES
- if (!piranha_simulator)
-#endif
- tm = get_boot_time();
+ tm = get_boot_time();
write_seqlock_irqsave(&xtime_lock, flags);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 064a5256469..3c668078e52 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -14,7 +14,6 @@
* This file handles the architecture-dependent parts of hardware exceptions
*/
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -32,6 +31,7 @@
#include <linux/delay.h>
#include <linux/kprobes.h>
#include <linux/kexec.h>
+#include <linux/backlight.h>
#include <asm/kdebug.h>
#include <asm/pgtable.h>
@@ -51,9 +51,13 @@
#include <asm/firmware.h>
#include <asm/processor.h>
#endif
+#include <asm/kexec.h>
#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
@@ -96,7 +100,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;
@@ -105,10 +109,18 @@ int die(const char *str, struct pt_regs *regs, long err)
spin_lock_irq(&die_lock);
bust_spinlocks(1);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac)) {
- set_backlight_enable(1);
- set_backlight_level(BACKLIGHT_MAX);
+ mutex_lock(&pmac_backlight_mutex);
+ if (machine_is(powermac) && pmac_backlight) {
+ struct backlight_properties *props;
+
+ down(&pmac_backlight->sem);
+ props = pmac_backlight->props;
+ props->brightness = props->max_brightness;
+ props->power = FB_BLANK_UNBLANK;
+ props->update_status(pmac_backlight);
+ up(&pmac_backlight->sem);
}
+ mutex_unlock(&pmac_backlight_mutex);
#endif
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -128,21 +140,12 @@ int die(const char *str, struct pt_regs *regs, long err)
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");
@@ -206,6 +209,10 @@ void system_reset_exception(struct pt_regs *regs)
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 */
@@ -658,7 +665,7 @@ static int emulate_instruction(struct pt_regs *regs)
u32 instword;
u32 rd;
- if (!user_mode(regs))
+ if (!user_mode(regs) || (regs->msr & MSR_LE))
return -EINVAL;
CHECK_FULL_REGS(regs);
@@ -805,9 +812,11 @@ void __kprobes program_check_exception(struct pt_regs *regs)
void alignment_exception(struct pt_regs *regs)
{
- int fixed;
+ int fixed = 0;
- fixed = fix_alignment(regs);
+ /* we don't implement logging of alignment exceptions */
+ if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+ fixed = fix_alignment(regs);
if (fixed == 1) {
regs->nip += 4; /* skip over emulated instruction */
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 3774e80094f..5730906b23d 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -10,10 +10,10 @@
*/
#include <stdarg.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/console.h>
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/udbg.h>
@@ -33,9 +33,12 @@ void __init udbg_early_init(void)
#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();
@@ -141,12 +144,14 @@ static int early_console_initialized;
void __init disable_early_printk(void)
{
-#if 1
if (!early_console_initialized)
return;
+ if (strstr(saved_command_line, "udbg-immortal")) {
+ printk(KERN_INFO "early console immortal !\n");
+ return;
+ }
unregister_console(&udbg_console);
early_console_initialized = 0;
-#endif
}
/* called by setup_system */
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 5d29dcca523..0835b4841de 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -8,7 +8,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <asm/udbg.h>
#include <asm/io.h>
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 573afb68d69..1a7e19cdab3 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -8,7 +8,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -223,6 +222,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
struct vm_area_struct *vma;
unsigned long vdso_pages;
unsigned long vdso_base;
+ int rc;
#ifdef CONFIG_PPC64
if (test_thread_flag(TIF_32BIT)) {
@@ -237,20 +237,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
vdso_base = VDSO32_MBASE;
#endif
- current->thread.vdso_base = 0;
+ current->mm->context.vdso_base = 0;
/* vDSO has a problem and was disabled, just don't "enable" it for the
* process
*/
if (vdso_pages == 0)
return 0;
-
- vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
- if (vma == NULL)
- return -ENOMEM;
-
- memset(vma, 0, sizeof(*vma));
-
/* Add a page to the vdso size for the data page */
vdso_pages ++;
@@ -259,17 +252,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
* at vdso_base which is the "natural" base for it, but we might fail
* and end up putting it elsewhere.
*/
+ down_write(&mm->mmap_sem);
vdso_base = get_unmapped_area(NULL, vdso_base,
vdso_pages << PAGE_SHIFT, 0, 0);
- if (vdso_base & ~PAGE_MASK) {
- kmem_cache_free(vm_area_cachep, vma);
- return (int)vdso_base;
+ if (IS_ERR_VALUE(vdso_base)) {
+ rc = vdso_base;
+ goto fail_mmapsem;
}
- current->thread.vdso_base = vdso_base;
+ /* Allocate a VMA structure and fill it up */
+ vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma == NULL) {
+ rc = -ENOMEM;
+ goto fail_mmapsem;
+ }
vma->vm_mm = mm;
- vma->vm_start = current->thread.vdso_base;
+ vma->vm_start = vdso_base;
vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
/*
@@ -282,23 +281,38 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
* It's fine to use that for setting breakpoints in the vDSO code
* pages though
*/
- vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
vma->vm_flags |= mm->def_flags;
vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
vma->vm_ops = &vdso_vmops;
- down_write(&mm->mmap_sem);
- if (insert_vm_struct(mm, vma)) {
- up_write(&mm->mmap_sem);
- kmem_cache_free(vm_area_cachep, vma);
- return -ENOMEM;
- }
+ /* Insert new VMA */
+ rc = insert_vm_struct(mm, vma);
+ if (rc)
+ goto fail_vma;
+
+ /* Put vDSO base into mm struct and account for memory usage */
+ current->mm->context.vdso_base = vdso_base;
mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
up_write(&mm->mmap_sem);
-
return 0;
+
+ fail_vma:
+ kmem_cache_free(vm_area_cachep, vma);
+ fail_mmapsem:
+ up_write(&mm->mmap_sem);
+ return rc;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
+ return "[vdso]";
+ return NULL;
}
+
+
static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
unsigned long *size)
{
diff --git a/arch/powerpc/kernel/vdso32/cacheflush.S b/arch/powerpc/kernel/vdso32/cacheflush.S
index 09629aea3e4..9cb319992c3 100644
--- a/arch/powerpc/kernel/vdso32/cacheflush.S
+++ b/arch/powerpc/kernel/vdso32/cacheflush.S
@@ -9,7 +9,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S
index 4709f1d9542..dc21e891d2e 100644
--- a/arch/powerpc/kernel/vdso32/datapage.S
+++ b/arch/powerpc/kernel/vdso32/datapage.S
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index 7eebff03a04..05909f75430 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -10,7 +10,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S
index 0c6a37b29dd..68d49dd71dc 100644
--- a/arch/powerpc/kernel/vdso32/sigtramp.S
+++ b/arch/powerpc/kernel/vdso32/sigtramp.S
@@ -10,7 +10,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
diff --git a/arch/powerpc/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S
index cb4ae0a5edd..66a36d3cc6a 100644
--- a/arch/powerpc/kernel/vdso64/cacheflush.S
+++ b/arch/powerpc/kernel/vdso64/cacheflush.S
@@ -9,7 +9,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index 3b2dd7d0c1e..79796de1173 100644
--- a/arch/powerpc/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index 4ee871f1cad..56e76ff5498 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -11,7 +11,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/vdso.h>
diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S
index 7479edb101b..17a83fa6dc5 100644
--- a/arch/powerpc/kernel/vdso64/sigtramp.S
+++ b/arch/powerpc/kernel/vdso64/sigtramp.S
@@ -10,7 +10,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/processor.h>
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 66b3d03c5fa..49ac3d6e139 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <asm/ppc_asm.h>
#include <asm/reg.h>
@@ -53,12 +52,12 @@ fpenable:
stfd fr31,8(r1)
LDCONST(fr1, fpzero)
mffs fr31
- mtfsf 0xff,fr1
+ MTFSF_L(fr1)
blr
fpdisable:
mtlr r12
- mtfsf 0xff,fr31
+ MTFSF_L(fr31)
lfd fr31,8(r1)
lfd fr1,16(r1)
lfd fr0,24(r1)
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 971020cf3f7..cdf5867838a 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -13,27 +13,116 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/types.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
+#include <linux/kobject.h>
+
#include <asm/iommu.h>
#include <asm/dma.h>
#include <asm/vio.h>
#include <asm/prom.h>
-
-static const struct vio_device_id *vio_match_device(
- const struct vio_device_id *, const struct vio_dev *);
-
-struct vio_dev vio_bus_device = { /* fake "parent" device */
+#include <asm/firmware.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/hvcall.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/iommu.h>
+
+extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+
+static struct vio_dev vio_bus_device = { /* fake "parent" device */
.name = vio_bus_device.dev.bus_id,
.type = "",
.dev.bus_id = "vio",
.dev.bus = &vio_bus_type,
};
-static struct vio_bus_ops vio_bus_ops;
+#ifdef CONFIG_PPC_ISERIES
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
+EXPORT_SYMBOL(iSeries_vio_dev);
+
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+static void __init iommu_vio_init(void)
+{
+ iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+ veth_iommu_table.it_size /= 2;
+ vio_iommu_table = veth_iommu_table;
+ vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+ if (!iommu_init_table(&veth_iommu_table, -1))
+ printk("Virtual Bus VETH TCE table failed.\n");
+ if (!iommu_init_table(&vio_iommu_table, -1))
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+#endif
+
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+#ifdef CONFIG_PPC_ISERIES
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ if (strcmp(dev->type, "network") == 0)
+ return &veth_iommu_table;
+ return &vio_iommu_table;
+ } else
+#endif
+ {
+ unsigned char *dma_window;
+ struct iommu_table *tbl;
+ unsigned long offset, size;
+
+ dma_window = get_property(dev->dev.platform_data,
+ "ibm,my-dma-window", NULL);
+ if (!dma_window)
+ return NULL;
+
+ tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+ of_parse_dma_window(dev->dev.platform_data, dma_window,
+ &tbl->it_index, &offset, &size);
+
+ /* TCE table size - measured in tce entries */
+ tbl->it_size = size >> PAGE_SHIFT;
+ /* offset for VIO should always be 0 */
+ tbl->it_offset = offset >> PAGE_SHIFT;
+ tbl->it_busno = 0;
+ tbl->it_type = TCE_VB;
+
+ return iommu_init_table(tbl, -1);
+ }
+}
+
+/**
+ * vio_match_device: - Tell if a VIO device has a matching
+ * VIO device id structure.
+ * @ids: array of VIO device id structures to search in
+ * @dev: the VIO device structure to match against
+ *
+ * Used by a driver to check whether a VIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * vio_device_id structure or NULL if there is no match.
+ */
+static const struct vio_device_id *vio_match_device(
+ const struct vio_device_id *ids, const struct vio_dev *dev)
+{
+ while (ids->type[0] != '\0') {
+ if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
+ device_is_compatible(dev->dev.platform_data, ids->compat))
+ return ids;
+ ids++;
+ }
+ return NULL;
+}
/*
* Convert from struct device to struct vio_dev and pass to driver.
@@ -106,35 +195,110 @@ void vio_unregister_driver(struct vio_driver *viodrv)
}
EXPORT_SYMBOL(vio_unregister_driver);
+/* vio_dev refcount hit 0 */
+static void __devinit vio_dev_release(struct device *dev)
+{
+ if (dev->platform_data) {
+ /* XXX free TCE table */
+ of_node_put(dev->platform_data);
+ }
+ kfree(to_vio_dev(dev));
+}
+
/**
- * vio_match_device: - Tell if a VIO device has a matching
- * VIO device id structure.
- * @ids: array of VIO device id structures to search in
- * @dev: the VIO device structure to match against
+ * vio_register_device_node: - Register a new vio device.
+ * @of_node: The OF node for this device.
*
- * Used by a driver to check whether a VIO device present in the
- * system is in its list of supported devices. Returns the matching
- * vio_device_id structure or NULL if there is no match.
+ * Creates and initializes a vio_dev structure from the data in
+ * of_node (dev.platform_data) and adds it to the list of virtual devices.
+ * Returns a pointer to the created vio_dev or NULL if node has
+ * NULL device_type or compatible fields.
*/
-static const struct vio_device_id *vio_match_device(
- const struct vio_device_id *ids, const struct vio_dev *dev)
+struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
{
- while (ids->type[0] != '\0') {
- if (vio_bus_ops.match(ids, dev))
- return ids;
- ids++;
+ struct vio_dev *viodev;
+ unsigned int *unit_address;
+ unsigned int *irq_p;
+
+ /* we need the 'device_type' property, in order to match with drivers */
+ if (of_node->type == NULL) {
+ printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
+ __FUNCTION__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
}
- return NULL;
+
+ unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
+ if (unit_address == NULL) {
+ printk(KERN_WARNING "%s: node %s missing 'reg'\n",
+ __FUNCTION__,
+ of_node->name ? of_node->name : "<unknown>");
+ return NULL;
+ }
+
+ /* allocate a vio_dev for this node */
+ viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
+ if (viodev == NULL)
+ return NULL;
+
+ viodev->dev.platform_data = of_node_get(of_node);
+
+ viodev->irq = NO_IRQ;
+ irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
+ if (irq_p) {
+ int virq = virt_irq_create_mapping(*irq_p);
+ if (virq == NO_IRQ) {
+ printk(KERN_ERR "Unable to allocate interrupt "
+ "number for %s\n", of_node->full_name);
+ } else
+ viodev->irq = irq_offset_up(virq);
+ }
+
+ snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+ viodev->name = of_node->name;
+ viodev->type = of_node->type;
+ viodev->unit_address = *unit_address;
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ unit_address = (unsigned int *)get_property(of_node,
+ "linux,unit_address", NULL);
+ if (unit_address != NULL)
+ viodev->unit_address = *unit_address;
+ }
+ viodev->iommu_table = vio_build_iommu_table(viodev);
+
+ /* init generic 'struct device' fields: */
+ viodev->dev.parent = &vio_bus_device.dev;
+ viodev->dev.bus = &vio_bus_type;
+ viodev->dev.release = vio_dev_release;
+
+ /* register with generic device framework */
+ if (device_register(&viodev->dev)) {
+ printk(KERN_ERR "%s: failed to register device %s\n",
+ __FUNCTION__, viodev->dev.bus_id);
+ /* XXX free TCE table */
+ kfree(viodev);
+ return NULL;
+ }
+
+ return viodev;
}
+EXPORT_SYMBOL(vio_register_device_node);
/**
* vio_bus_init: - Initialize the virtual IO bus
*/
-int __init vio_bus_init(struct vio_bus_ops *ops)
+static int __init vio_bus_init(void)
{
int err;
+ struct device_node *node_vroot;
- vio_bus_ops = *ops;
+#ifdef CONFIG_PPC_ISERIES
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ iommu_vio_init();
+ vio_bus_device.iommu_table = &vio_iommu_table;
+ iSeries_vio_dev = &vio_bus_device.dev;
+ }
+#endif
err = bus_register(&vio_bus_type);
if (err) {
@@ -153,47 +317,48 @@ int __init vio_bus_init(struct vio_bus_ops *ops)
return err;
}
- return 0;
-}
+ node_vroot = find_devices("vdevice");
+ if (node_vroot) {
+ struct device_node *of_node;
+
+ /*
+ * Create struct vio_devices for each virtual device in
+ * the device tree. Drivers will associate with them later.
+ */
+ for (of_node = node_vroot->child; of_node != NULL;
+ of_node = of_node->sibling) {
+ printk(KERN_DEBUG "%s: processing %p\n",
+ __FUNCTION__, of_node);
+ vio_register_device_node(of_node);
+ }
+ }
-/* vio_dev refcount hit 0 */
-static void __devinit vio_dev_release(struct device *dev)
-{
- if (vio_bus_ops.release_device)
- vio_bus_ops.release_device(dev);
- kfree(to_vio_dev(dev));
+ return 0;
}
+__initcall(vio_bus_init);
-static ssize_t viodev_show_name(struct device *dev,
+static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
}
-DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
-struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
+static ssize_t devspec_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- /* init generic 'struct device' fields: */
- viodev->dev.parent = &vio_bus_device.dev;
- viodev->dev.bus = &vio_bus_type;
- viodev->dev.release = vio_dev_release;
-
- /* register with generic device framework */
- if (device_register(&viodev->dev)) {
- printk(KERN_ERR "%s: failed to register device %s\n",
- __FUNCTION__, viodev->dev.bus_id);
- return NULL;
- }
- device_create_file(&viodev->dev, &dev_attr_name);
+ struct device_node *of_node = dev->platform_data;
- return viodev;
+ return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
}
+static struct device_attribute vio_dev_attrs[] = {
+ __ATTR_RO(name),
+ __ATTR_RO(devspec),
+ __ATTR_NULL
+};
+
void __devinit vio_unregister_device(struct vio_dev *viodev)
{
- if (vio_bus_ops.unregister_device)
- vio_bus_ops.unregister_device(viodev);
- device_remove_file(&viodev->dev, &dev_attr_name);
device_unregister(&viodev->dev);
}
EXPORT_SYMBOL(vio_unregister_device);
@@ -229,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
- dma_handle, ~0ul, flag);
+ dma_handle, ~0ul, flag, -1);
}
static void vio_free_coherent(struct device *dev, size_t size,
@@ -267,22 +432,23 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
const struct vio_dev *vio_dev = to_vio_dev(dev);
+ struct device_node *dn = dev->platform_data;
char *cp;
int length;
if (!num_envp)
return -ENOMEM;
- if (!vio_dev->dev.platform_data)
+ if (!dn)
return -ENODEV;
- cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length);
+ cp = (char *)get_property(dn, "compatible", &length);
if (!cp)
return -ENODEV;
envp[0] = buffer;
length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
vio_dev->type, cp);
- if (buffer_size - length <= 0)
+ if ((buffer_size - length) <= 0)
return -ENOMEM;
envp[1] = NULL;
return 0;
@@ -290,9 +456,81 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
struct bus_type vio_bus_type = {
.name = "vio",
+ .dev_attrs = vio_dev_attrs,
.uevent = vio_hotplug,
.match = vio_bus_match,
.probe = vio_bus_probe,
.remove = vio_bus_remove,
.shutdown = vio_bus_shutdown,
};
+
+/**
+ * vio_get_attribute: - get attribute for virtual device
+ * @vdev: The vio device to get property.
+ * @which: The property/attribute to be extracted.
+ * @length: Pointer to length of returned data size (unused if NULL).
+ *
+ * Calls prom.c's get_property() to return the value of the
+ * attribute specified by @which
+*/
+const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
+{
+ return get_property(vdev->dev.platform_data, which, length);
+}
+EXPORT_SYMBOL(vio_get_attribute);
+
+#ifdef CONFIG_PPC_PSERIES
+/* vio_find_name() - internal because only vio.c knows how we formatted the
+ * kobject name
+ * XXX once vio_bus_type.devices is actually used as a kset in
+ * drivers/base/bus.c, this function should be removed in favor of
+ * "device_find(kobj_name, &vio_bus_type)"
+ */
+static struct vio_dev *vio_find_name(const char *kobj_name)
+{
+ struct kobject *found;
+
+ found = kset_find_obj(&devices_subsys.kset, kobj_name);
+ if (!found)
+ return NULL;
+
+ return to_vio_dev(container_of(found, struct device, kobj));
+}
+
+/**
+ * vio_find_node - find an already-registered vio_dev
+ * @vnode: device_node of the virtual device we're looking for
+ */
+struct vio_dev *vio_find_node(struct device_node *vnode)
+{
+ uint32_t *unit_address;
+ char kobj_name[BUS_ID_SIZE];
+
+ /* construct the kobject name from the device node */
+ unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
+ if (!unit_address)
+ return NULL;
+ snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+
+ return vio_find_name(kobj_name);
+}
+EXPORT_SYMBOL(vio_find_node);
+
+int vio_enable_interrupts(struct vio_dev *dev)
+{
+ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
+ if (rc != H_SUCCESS)
+ printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+ return rc;
+}
+EXPORT_SYMBOL(vio_enable_interrupts);
+
+int vio_disable_interrupts(struct vio_dev *dev)
+{
+ int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
+ if (rc != H_SUCCESS)
+ printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+ return rc;
+}
+EXPORT_SYMBOL(vio_disable_interrupts);
+#endif /* CONFIG_PPC_PSERIES */
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fe79c2584cb..02665a02130 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#ifdef CONFIG_PPC64
#include <asm/page.h>
#define PROVIDE32(x) PROVIDE(__unused__##x)
@@ -93,6 +92,11 @@ SECTIONS
__ptov_table_begin = .;
*(.ptov_fixup);
__ptov_table_end = .;
+#ifdef CONFIG_PPC_ISERIES
+ __dt_strings_start = .;
+ *(.dt_strings);
+ __dt_strings_end = .;
+#endif
}
. = ALIGN(16);