LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] powerpc: Add udbg-immortal kernel option
From: Olof Johansson @ 2006-06-07  2:24 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1149645981.27572.96.camel@localhost.localdomain>

On Wed, Jun 07, 2006 at 12:06:20PM +1000, Benjamin Herrenschmidt wrote:
>  		return;
> +	if (strstr(saved_command_line, "udbg-immortal")) {
> +		printk(KERN_INFO "early console immortal !\n");
> +		return;
> +	}

So it's YOU who add spaces before punctuation all over arch/powerpc!
Please fix. ;-)


-Olof

^ permalink raw reply

* Re: [PATCH] powerpc: Add udbg-immortal kernel option
From: Benjamin Herrenschmidt @ 2006-06-07  4:19 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <20060607022412.GA5661@pb15.lixom.net>

On Tue, 2006-06-06 at 19:24 -0700, Olof Johansson wrote:
> On Wed, Jun 07, 2006 at 12:06:20PM +1000, Benjamin Herrenschmidt wrote:
> >  		return;
> > +	if (strstr(saved_command_line, "udbg-immortal")) {
> > +		printk(KERN_INFO "early console immortal !\n");
> > +		return;
> > +	}
> 
> So it's YOU who add spaces before punctuation all over arch/powerpc!
> Please fix. ;-)

No way :) Besides, that's how it should be done in french :)

Ben.

^ permalink raw reply

* Problem in PCI with MPC5200B
From: Ram Prasad H L @ 2006-06-07  5:35 UTC (permalink / raw)
  To: linuxppc-embedded

hi all,
	We are using a customised board which is based on
	the reference design of lite5200B. But our board is customised by adding
	a PCI-PCI Bridge on the primary bus. On the secondary bus we have added
	a DSP(DM642) along with 2 PCI slots, which are routed through
	bridge (PCI2250) to MPC5200B.

	As far as software is concerned we are using "mpc5200_lite_K26-BSP-b30"
	BSP downloaded from freescale's website for lite5200B. This BSP has a
	u-boot-1.1.3 and linux kernel-2.6.11.7. As far as u-boot is concerned
	the PCI devices are allocated and assigned with proper resources (BAR's)
	which come under the range for Mem region(40000000 - 4fffffff) and I/O
	region (50000000 - 50ffffff). But during the boot process of linux we
	are getting the following errors:


****************************************************************************
***
	PCI: Probing PCI hardware
	PCI: Cannot allocate resource region 1 of PCI bridge 1
	PCI: bridge 1 resource 1 moved to 4ff00000..4fffffff
	PCI: Cannot allocate resource region 2 of PCI bridge 1
	PCI: bridge 1 resource 2 moved to 4fe00000..4fefffff
	PCI: Failed to allocate mem resource #0: 400000 @ 50000000 for 0000:01:08.0
	PCI: Failed to allocate mem resource #1: 800000 @ 50000000 for 0000:01:08.0
	PCI: Failed to allocate I/O resource #2: 10 @ 1000 for 0000:01:08.0

****************************************************************************
****

	where 0000:01:08.0 is the dev function address for DM642(DSP).

	I'm stuck up with this problem since long time. Plz help me in giving some
pointers
	for overcoming this problem as i'm a newbie to linux-pci. Any patches for
the kernel
	2.6.11.7 which can resolve the above problem would be of great help.


Thanks and regards,
Ramprasad



The information contained in this electronic message and any attachments to this message are intended for the exclusive use of the addressee(s)and may contain confidential or privileged information. If you are not the intended recipient, please notify the sender or administrator@tataelxsi.co.in

^ permalink raw reply

* [PATCH 1/3] Add a prctl to change the endianness of a process.
From: Paul Mackerras @ 2006-06-07  6:10 UTC (permalink / raw)
  To: akpm, linux-kernel, linuxppc-dev

From: Anton Blanchard <anton@samba.org>

This new prctl is intended for changing the execution mode of the
processor, on processors that support both a little-endian mode and a
big-endian mode.  It is intended for use by programs such as
instruction set emulators (for example an x86 emulator on PowerPC),
which may find it convenient to use the processor in an alternate
endianness mode when executing translated instructions.

Note that this does not imply the existence of a fully-fledged ABI for
both endiannesses, or of compatibility code for converting system
calls done in the non-native endianness mode.  The program is expected
to arrange for all of its system call arguments to be presented in the
native endianness.

Switching between big and little-endian mode will require some care in
constructing the instruction sequence for the switch.  Generally the
instructions up to the instruction that invokes the prctl system call
will have to be in the old endianness, and subsequent instructions
will have to be in the new endianness.

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
Andrew: if you are OK with this patch, I will put it in the
powerpc.git tree along with the next 2 patches in this series, and
merge them to Linus after 2.6.17 is released.

diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index bf022c4..52a9be4 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -52,4 +52,11 @@ # define PR_TIMING_TIMESTAMP    1       
 #define PR_SET_NAME    15		/* Set process name */
 #define PR_GET_NAME    16		/* Get process name */
 
+/* Get/set process endian */
+#define PR_GET_ENDIAN	19
+#define PR_SET_ENDIAN	20
+# define PR_ENDIAN_BIG		0
+# define PR_ENDIAN_LITTLE	1	/* True little endian mode */
+# define PR_ENDIAN_PPC_LITTLE	2	/* "PowerPC" pseudo little endian */
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 0b6ec0e..12d2d75 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -57,6 +57,12 @@ #endif
 #ifndef GET_FPEXC_CTL
 # define GET_FPEXC_CTL(a,b)	(-EINVAL)
 #endif
+#ifndef GET_ENDIAN
+# define GET_ENDIAN(a,b)	(-EINVAL)
+#endif
+#ifndef SET_ENDIAN
+# define SET_ENDIAN(a,b)	(-EINVAL)
+#endif
 
 /*
  * this is where the system-wide overflow UID and GID are defined, for
@@ -2057,6 +2063,13 @@ asmlinkage long sys_prctl(int option, un
 				return -EFAULT;
 			return 0;
 		}
+		case PR_GET_ENDIAN:
+			error = GET_ENDIAN(current, arg2);
+			break;
+		case PR_SET_ENDIAN:
+			error = SET_ENDIAN(current, arg2);
+			break;
+
 		default:
 			error = -EINVAL;
 			break;

^ permalink raw reply related

* [PATCH 2/3] powerpc: Implement support for setting little-endian mode via prctl
From: Paul Mackerras @ 2006-06-07  6:14 UTC (permalink / raw)
  To: akpm, linuxppc-dev

This adds the PowerPC part of the code to allow processes to change
their endian mode via prctl.

This also extends the alignment exception handler to be able to fix up
alignment exceptions that occur in little-endian mode, both for
"PowerPC" little-endian and true little-endian.

We always enter signal handlers in big-endian mode -- the support for
little-endian mode does not amount to the creation of a little-endian
user/kernel ABI.  If the signal handler returns, the endian mode is
restored to what it was when the signal was delivered.

We have two new kernel CPU feature bits, one for PPC little-endian and
one for true little-endian.  Most of the classic 32-bit processors
support PPC little-endian, and this is reflected in the CPU feature
table.  There are two corresponding feature bits reported to userland
in the AT_HWCAP aux vector entry.

This is based on an earlier patch by Anton Blanchard.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index faaec9c..4734b5d 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -35,17 +35,19 @@ #define IS_DSFORM(inst)	(((inst) >> 26) 
 
 #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 @@ #else
 #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_re
 			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_re
 		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_re
 			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 @@ #else
 		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/cputable.c b/arch/powerpc/kernel/cputable.c
index 0c487ee..2a62d99 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -54,7 +54,8 @@ #define COMMON_USER_POWER5	(COMMON_USER_
 #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)
 
@@ -74,7 +75,7 @@ #ifdef CONFIG_PPC64
 		.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,
@@ -87,7 +88,7 @@ #ifdef CONFIG_PPC64
 		.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,
@@ -306,7 +307,7 @@ #if CLASSIC_PPC
 		.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,
@@ -317,7 +318,7 @@ #if CLASSIC_PPC
 		.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,
@@ -328,7 +329,7 @@ #if CLASSIC_PPC
 		.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,
@@ -339,7 +340,7 @@ #if CLASSIC_PPC
 		.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,
@@ -351,7 +352,7 @@ #if CLASSIC_PPC
 		.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,
@@ -363,7 +364,7 @@ #if CLASSIC_PPC
 		.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,
@@ -375,7 +376,7 @@ #if CLASSIC_PPC
 		.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,
@@ -387,7 +388,7 @@ #if CLASSIC_PPC
 		.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,
@@ -399,7 +400,7 @@ #if CLASSIC_PPC
 		.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,
@@ -411,7 +412,7 @@ #if CLASSIC_PPC
 		.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,
@@ -423,7 +424,7 @@ #if CLASSIC_PPC
 		.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,
@@ -435,7 +436,7 @@ #if CLASSIC_PPC
 		.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,
@@ -447,7 +448,7 @@ #if CLASSIC_PPC
 		.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,
@@ -459,7 +460,7 @@ #if CLASSIC_PPC
 		.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,
@@ -471,7 +472,7 @@ #if CLASSIC_PPC
 		.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,
@@ -483,7 +484,7 @@ #if CLASSIC_PPC
 		.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,
@@ -495,7 +496,7 @@ #if CLASSIC_PPC
 		.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,
@@ -507,7 +508,7 @@ #if CLASSIC_PPC
 		.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,
@@ -519,7 +520,8 @@ #if CLASSIC_PPC
 		.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,
@@ -531,7 +533,8 @@ #if CLASSIC_PPC
 		.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,
@@ -543,7 +546,8 @@ #if CLASSIC_PPC
 		.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,
@@ -555,7 +559,8 @@ #if CLASSIC_PPC
 		.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,
@@ -569,7 +574,8 @@ #if CLASSIC_PPC
 		.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,
@@ -583,7 +589,8 @@ #if CLASSIC_PPC
 		.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,
@@ -597,7 +604,8 @@ #if CLASSIC_PPC
 		.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,
@@ -611,7 +619,8 @@ #if CLASSIC_PPC
 		.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,
@@ -625,7 +634,8 @@ #if CLASSIC_PPC
 		.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,
@@ -639,7 +649,8 @@ #if CLASSIC_PPC
 		.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,
@@ -653,7 +664,8 @@ #if CLASSIC_PPC
 		.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,
@@ -667,7 +679,7 @@ #if CLASSIC_PPC
 		.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,
@@ -681,7 +693,8 @@ #if CLASSIC_PPC
 		.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,
@@ -695,7 +708,8 @@ #if CLASSIC_PPC
 		.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/process.c b/arch/powerpc/kernel/process.c
index 2dd47d2..e473245 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -708,6 +708,50 @@ #endif
 	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);
+}
+
 #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/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 01e3c08..a885e25 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_
 {
 	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 +428,16 @@ #endif
 	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 +458,7 @@ #ifdef CONFIG_ALTIVEC
 	/* 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 +475,7 @@ #ifdef CONFIG_SPE
 	/* 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)))
@@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned lon
 	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;
 
@@ -1047,6 +1052,8 @@ #endif
 	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 27f65b9..6801b19 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -141,9 +141,7 @@ #endif
 	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 +152,12 @@ #endif
 	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 +182,6 @@ #endif
 
 #ifdef CONFIG_ALTIVEC
 	err |= __get_user(v_regs, &sc->v_regs);
-	err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
 	if (err)
 		return err;
 	/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
@@ -410,6 +412,8 @@ static int setup_rt_frame(int signr, str
 
 	/* 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/traps.c b/arch/powerpc/kernel/traps.c
index 064a525..91a6e04 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -658,7 +658,7 @@ static int emulate_instruction(struct pt
 	u32 instword;
 	u32 rd;
 
-	if (!user_mode(regs))
+	if (!user_mode(regs) || (regs->msr & MSR_LE))
 		return -EINVAL;
 	CHECK_FULL_REGS(regs);
 
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 9fcf016..72ded03 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -24,6 +24,9 @@ #define PPC_FEATURE_SMT			0x00004000
 #define PPC_FEATURE_ICACHE_SNOOP	0x00002000
 #define PPC_FEATURE_ARCH_2_05		0x00001000
 
+#define PPC_FEATURE_TRUE_LE		0x00000002
+#define PPC_FEATURE_PPC_LE		0x00000001
+
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
@@ -104,6 +107,8 @@ #define CPU_FTR_NEED_COHERENT		ASM_CONST
 #define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
 #define CPU_FTR_BIG_PHYS		ASM_CONST(0x0000000000080000)
 #define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
+#define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
+#define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
 
 #ifdef __powerpc64__
 /* Add the 64b processor unique features in the top half of the word */
@@ -136,6 +141,7 @@ #define CPU_FTR_COHERENT_ICACHE		ASM_CON
 #define CPU_FTR_LOCKLESS_TLBIE		ASM_CONST(0x0)
 #define CPU_FTR_MMCRA_SIHV		ASM_CONST(0x0)
 #define CPU_FTR_CI_LARGE_PAGE		ASM_CONST(0x0)
+#define CPU_FTR_PAUSE_ZERO              ASM_CONST(0x0)
 #define CPU_FTR_PURR			ASM_CONST(0x0)
 #endif
 
@@ -192,92 +198,95 @@ #define CLASSIC_PPC (!defined(CONFIG_8xx
 #define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_603	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_604	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_740	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_750	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX2	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_NO_DPM)
+	    CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750GX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7400	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_21	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_23	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455_1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447_10	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447A	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
 #define CPU_FTRS_G2_LE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
@@ -307,7 +316,7 @@ #define CPU_FTRS_E500_2	(CPU_FTR_SPLIT_I
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 #ifdef __powerpc64__
 #define CPU_FTRS_POWER3	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
 #define CPU_FTRS_RS64	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
@@ -325,7 +334,7 @@ #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_I
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE)
+	    CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE)
 #define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 93f83ef..02b56f2 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -212,6 +212,12 @@ #define SET_FPEXC_CTL(tsk, val) set_fpex
 extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
 extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
 
+#define GET_ENDIAN(tsk, adr) get_endian((tsk), (adr))
+#define SET_ENDIAN(tsk, val) set_endian((tsk), (val))
+
+extern int get_endian(struct task_struct *tsk, unsigned long adr);
+extern int set_endian(struct task_struct *tsk, unsigned int val);
+
 static inline unsigned int __unpack_fe01(unsigned long msr_bits)
 {
 	return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);

^ permalink raw reply related

* [PATCH 3/3] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc
From: Paul Mackerras @ 2006-06-07  6:15 UTC (permalink / raw)
  To: akpm, linuxppc-dev

This gives the ability to control whether alignment exceptions get
fixed up or reported to the process as a SIGBUS, using the existing
PR_SET_UNALIGN and PR_GET_UNALIGN prctls.  We do not implement the
option of logging a message on alignment exceptions.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -805,9 +805,11 @@ #endif /* CONFIG_MATH_EMULATION */
 
 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 a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -752,6 +752,17 @@
 	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 a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -149,6 +149,7 @@ #endif
 		unsigned int val;	/* Floating point status */
 	} fpscr;
 	int		fpexc_mode;	/* floating-point exception mode */
+	unsigned int	align_ctl;	/* alignment handling control */
 #ifdef CONFIG_PPC64
 	unsigned long	start_tb;	/* Start purr when proc switched in */
 	unsigned long	accum_tb;	/* Total accumilated purr for process */
@@ -218,6 +219,12 @@ #define SET_FPEXC_CTL(tsk, val) set_fpex
 extern int get_endian(struct task_struct *tsk, unsigned long adr);
 extern int set_endian(struct task_struct *tsk, unsigned int val);
 
+#define GET_UNALIGN_CTL(tsk, adr)	get_unalign_ctl((tsk), (adr))
+#define SET_UNALIGN_CTL(tsk, val)	set_unalign_ctl((tsk), (val))
+
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
 static inline unsigned int __unpack_fe01(unsigned long msr_bits)
 {
 	return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);

^ permalink raw reply

* [PATCH 1/2] powerpc: Make rtas console _much_ faster
From: Michael Ellerman @ 2006-06-07  7:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann

Currently the hvc_rtas driver is painfully slow to use. Our "benchmark" is
ls -R /etc, which spits out about 27866 characters. The theoretical maximum
speed would be about 2.2 seconds, the current code takes ~50 seconds.

The core of the problem is that sometimes when the tty layer asks us to push
characters the firmware isn't able to handle some or all of them, and so
returns an error. The current code sees this and just returns to the tty code
with the buffer half sent.

The khvcd thread will eventually wake up and try to push more characters, which
will usually work because by then the firmware's had time to make room. But
the khvcd thread only wakes up every 10 milliseconds, which isn't fast enough.

So change the khvcd thread logic so that if there's an incomplete write we
yield() and then immediately try writing again. Doing so makes POLL_QUICK and
POLL_WRITE synonymous, so remove POLL_QUICK.

With this patch our "benchmark" takes ~2.8 seconds.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 drivers/char/hvc_console.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: to-merge/drivers/char/hvc_console.c
===================================================================
--- to-merge.orig/drivers/char/hvc_console.c
+++ to-merge/drivers/char/hvc_console.c
@@ -553,7 +553,6 @@ static int hvc_chars_in_buffer(struct tt
 
 #define HVC_POLL_READ	0x00000001
 #define HVC_POLL_WRITE	0x00000002
-#define HVC_POLL_QUICK	0x00000004
 
 static int hvc_poll(struct hvc_struct *hp)
 {
@@ -568,6 +567,7 @@ static int hvc_poll(struct hvc_struct *h
 	/* Push pending writes */
 	if (hp->n_outbuf > 0)
 		hvc_push(hp);
+
 	/* Reschedule us if still some write pending */
 	if (hp->n_outbuf > 0)
 		poll_mask |= HVC_POLL_WRITE;
@@ -680,7 +680,7 @@ int khvcd(void *unused)
 			poll_mask |= HVC_POLL_READ;
 		if (hvc_kicked)
 			continue;
-		if (poll_mask & HVC_POLL_QUICK) {
+		if (poll_mask & HVC_POLL_WRITE) {
 			yield();
 			continue;
 		}

^ permalink raw reply

* [PATCH 2/2] powerpc: Cleanup hvc_rtas.c a little
From: Michael Ellerman @ 2006-06-07  7:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann

A few cleanups in hvc_rtas.c:
 1. Remove unused RTASCONS_PUT_ATTEMPTS
 2. Remove unused rtascons_put_delay.
 3. Use i as a loop counter like everyone else on earth.
 4. Remove pointless variables, eg. x = foo; if (x) return something_else;
 5. Whitespace cleanups and formatting.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 drivers/char/hvc_rtas.c |   37 ++++++++++++++++---------------------
 1 file changed, 16 insertions(+), 21 deletions(-)

Index: cell/drivers/char/hvc_rtas.c
===================================================================
--- cell.orig/drivers/char/hvc_rtas.c
+++ cell/drivers/char/hvc_rtas.c
@@ -41,37 +41,28 @@
 #define hvc_rtas_cookie 0x67781e15
 struct hvc_struct *hvc_rtas_dev;
 
-#define RTASCONS_PUT_ATTEMPTS  16
-
 static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
 static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
-static int rtascons_put_delay = 100;
-module_param_named(put_delay, rtascons_put_delay, int, 0644);
 
-static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count)
+static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf,
+		int count)
 {
-	int done;
+	int i;
 
-	/* if there is more than one character to be displayed, wait a bit */
-	for (done = 0; done < count; done++) {
-		int result;
-		result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]);
-		if (result)
+	for (i = 0; i < count; i++) {
+		if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i]))
 			break;
 	}
-	/* the calling routine expects to receive the number of bytes sent */
-	return done;
+
+	return i;
 }
 
 static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
 {
-	int i;
+	int i, c;
 
 	for (i = 0; i < count; i++) {
-		int c, err;
-
-		err = rtas_call(rtascons_get_char_token, 0, 2, &c);
-		if (err)
+		if (rtas_call(rtascons_get_char_token, 0, 2, &c))
 			break;
 
 		buf[i] = c;
@@ -106,7 +97,9 @@ static int hvc_rtas_init(void)
 	hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops);
 	if (IS_ERR(hp))
 		return PTR_ERR(hp);
+
 	hvc_rtas_dev = hp;
+
 	return 0;
 }
 module_init(hvc_rtas_init);
@@ -114,8 +107,8 @@ module_init(hvc_rtas_init);
 /* This will tear down the tty portion of the driver */
 static void __exit hvc_rtas_exit(void)
 {
-	/* Really the fun isn't over until the worker thread breaks down and the
-	 * tty cleans up */
+	/* Really the fun isn't over until the worker thread breaks down and
+	 * the tty cleans up */
 	if (hvc_rtas_dev)
 		hvc_remove(hvc_rtas_dev);
 }
@@ -127,12 +120,14 @@ static int hvc_rtas_console_init(void)
 	rtascons_put_char_token = rtas_token("put-term-char");
 	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
 		return -EIO;
+
 	rtascons_get_char_token = rtas_token("get-term-char");
 	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
 		return -EIO;
 
-	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops );
+	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
 	add_preferred_console("hvc", 0, NULL);
+
 	return 0;
 }
 console_initcall(hvc_rtas_console_init);

^ permalink raw reply

* Re: [PATCH] powerpc: Add udbg-immortal kernel option
From: Arnd Bergmann @ 2006-06-07  9:31 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Olof Johansson, Benjamin Herrenschmidt, Paul Mackerras
In-Reply-To: <1149653947.27572.113.camel@localhost.localdomain>

On Wednesday 07 June 2006 06:19, Benjamin Herrenschmidt wrote:
> No way :) Besides, that's how it should be done in french :)
>=20
So you mean, like this?

Index: linux-work/arch/powerpc/kernel/udbg.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=2D-- linux-work.orig/arch/powerpc/kernel/udbg.c	2006-05-31 14:13:59.000000=
000 +1000
+++ linux-work/arch/powerpc/kernel/udbg.c	2006-05-31 14:48:07.000000000 +10=
00
@@ -141,12 +142,14 @@ static int early_console_initialized;
=20
 void __init disable_early_printk(void)
 {
=2D#if 1
 	if (!early_console_initialized)
 		return;
+	if (strstr(saved_command_line, "udbg-immortel")) {
+		printk(KERN_INFO "console t=F4t immortel !\n");
+		return;
+	}
 	unregister_console(&udbg_console);
 	early_console_initialized =3D 0;
=2D#endif
 }
=20
 /* called by setup_system */

^ permalink raw reply

* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Mel Gorman @ 2006-06-07  9:42 UTC (permalink / raw)
  To: Andrew Morton
  Cc: davej, tony.luck, linux-mm, ak, bob.picco, linux-kernel,
	linuxppc-dev
In-Reply-To: <20060606164311.27d4af98.akpm@osdl.org>

On Tue, 6 Jun 2006, Andrew Morton wrote:

> On Tue,  6 Jun 2006 14:47:10 +0100 (IST)
> Mel Gorman <mel@csn.ul.ie> wrote:
>
>> This is V7 of the patchset to size zones and memory holes in an
>> architecture-independent manner.
>
> I hope this won't deprive me of my 4 kbyte highmem zone.
>

heh, I think I found the thread you are on about, including your 4kb 
zone.

For future reference, the memory present in zones should be the same 
before and after the patches. Spanned pages and holes will be different on 
x86_64 because I don't account the kernel image and memmap as holes. 
Spanned pages may be different on ia64 as I start nodes on the first real 
page frame, not pfn 0 there and end them at the last real pfn. However, 
present pages should be the same before and after the patch :)

> I won't merge these patches for rc6-mm1 - we already have a few problems in
> this area which I don't think anyone understands yet.
>

I can't argue with that logic as it makes sense with the current 
uncertainties. I'll keep it rebased and resubmit later. In the meantime, 
I'll keep an eye out for issues in -mm that I can hit a kick or two.

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply

* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Andi Kleen @ 2006-06-07  9:45 UTC (permalink / raw)
  To: Mel Gorman
  Cc: Andrew Morton, davej, tony.luck, linux-mm, linux-kernel,
	bob.picco, linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0606071030100.20653@skynet.skynet.ie>

> Spanned pages and holes will be different on 
> x86_64 because I don't account the kernel image and memmap as holes. 

That's a significant inaccuracy and may give worse VM results.

-Andi

^ permalink raw reply

* Re: Problem in PCI with MPC5200B
From: Sylvain Munaut @ 2006-06-07 10:02 UTC (permalink / raw)
  To: Ram Prasad H L; +Cc: linuxppc-embedded
In-Reply-To: <000d01c689f4$281750c0$4129320a@telxsi.com>

Hi,

> 	As far as software is concerned we are using "mpc5200_lite_K26-BSP-b30"
> 	BSP downloaded from freescale's website for lite5200B. This BSP has a
> 	u-boot-1.1.3 and linux kernel-2.6.11.7.

I'm not familiar with that BSP and then without knowing
exactly what's in that kernel and what's not it's hard
to answer.

Can you provide a link to it ?


      Sylvain


----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.

^ permalink raw reply

* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Mel Gorman @ 2006-06-07 10:11 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andrew Morton, davej, tony.luck, linux-mm, linux-kernel,
	bob.picco, linuxppc-dev
In-Reply-To: <200606071145.04938.ak@suse.de>

On Wed, 7 Jun 2006, Andi Kleen wrote:

>> Spanned pages and holes will be different on
>> x86_64 because I don't account the kernel image and memmap as holes.
>
> That's a significant inaccuracy and may give worse VM results.
>

Right now, x86_64 seems to be the only arch that accounts for the kernel 
image and memmap as holes so I would consider it to be unusual. For memory 
hot-add, new memmaps are allocated using kmalloc() and are not accounted 
for as holes. So, on x86_64, some memmaps are holes and others are not.

Why is it a performance regression if the image and memmap is accounted 
for as holes? How are those regions different from any other kernel 
allocation or bootmem allocations for example which are not accounted as 
holes? Bear in mind that when I said "I don't account the kernel image and 
memmap as holes", the spanned_pages value remains the same, the value of 
present_pages is greater but the starting number of free pages should be 
more or less the same.

If you are sure that it makes a measurable difference to performance, I 
can work on adding a new call unregister_active_region() that allows an 
arch to account for arbitrary pfn ranges as holes. This could be used for 
kernel images, memmaps and probably the first contiguous allocated block 
used by the bootmem allocator. However, I'm not sure it is worth the 
effort. That said, if it *is* worth the effort, all architectures using 
the arch-independent zone-sizing would benefit, not just x86_64.

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply

* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Andi Kleen @ 2006-06-07 10:16 UTC (permalink / raw)
  To: Mel Gorman
  Cc: Andrew Morton, davej, tony.luck, linux-mm, linux-kernel,
	bob.picco, linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0606071059480.20653@skynet.skynet.ie>


> Right now, x86_64 seems to be the only arch that accounts for the kernel 
> image and memmap as holes so I would consider it to be unusual.

s/unusual/more advanced/

> For memory  
> hot-add, new memmaps are allocated using kmalloc() and are not accounted 
> for as holes. 

At least in the standard (non sparsemem) hotadd they are accounted afaik.

> So, on x86_64, some memmaps are holes and others are not. 
> 
> Why is it a performance regression if the image and memmap is accounted 
> for as holes? How are those regions different from any other kernel 
> allocation or bootmem allocations for example which are not accounted as 
> holes? 

They are comparatively big and cannot be freed.

>If you are sure that it makes a measurable difference to performance,

There was at least one benchmark/use case where it made a significant
difference, can't remember the exact numbers though.

-Andi

^ permalink raw reply

* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Mel Gorman @ 2006-06-07 10:54 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andrew Morton, davej, tony.luck, linux-mm, linux-kernel,
	bob.picco, linuxppc-dev
In-Reply-To: <200606071216.24640.ak@suse.de>

On Wed, 7 Jun 2006, Andi Kleen wrote:

>
>> Right now, x86_64 seems to be the only arch that accounts for the kernel
>> image and memmap as holes so I would consider it to be unusual.
>
> s/unusual/more advanced/
>

Ok, debatable, but lets assume that to be true. On the same assumption, it 
would be desirable for all other architectures.

>> For memory
>> hot-add, new memmaps are allocated using kmalloc() and are not accounted
>> for as holes.
>
> At least in the standard (non sparsemem) hotadd they are accounted afaik.
>

Indirectly, yes, and again only on x86_64 I *think*. On x86_64, I believe 
what you do is setup a memmap for a region that will be later used for 
hotplug but is not backed by real memory at boottime. In that case, you 
have extra memmap that is not backed by real pages and the spare memmap 
gets accounted for as a hole.

>> So, on x86_64, some memmaps are holes and others are not.
>>
>> Why is it a performance regression if the image and memmap is accounted
>> for as holes? How are those regions different from any other kernel
>> allocation or bootmem allocations for example which are not accounted as
>> holes?
>
> They are comparatively big and cannot be freed.
>

Ok, while true, I'm not sure how it affects performance. The only "real" 
value affected by present_pages is the number of patches that are 
allocated in batches to the per-cpu allocator. If the following held true;

1. Many CPUs are using one one node
2. The node was mainly consumed by memmap
3. ((present_pages - pages_in_memmap) / 1024) < (NUM_CPUS)

Then we would probably see free pages been left on per-cpu lists and 
remote nodes been used that accounting for memmap as holes might have 
helped. But in that case, there are so few free pages on the node anyway, 
you are going to see regressions unless the workload is fairly small.

page reclaim *used* to use present_pages for some decisions but it was 
really concerned with present_pages == 0. Not sure how I would trigger a 
regression there.

>> If you are sure that it makes a measurable difference to performance,
>
> There was at least one benchmark/use case where it made a significant
> difference, can't remember the exact numbers though.
>

If this case can be resurrected, I will check it out and report if the 
difference can be measured. If it is, I will write support for 
unregister_active_range() which will be used during boot to account for 
PFN ranges as holes. alloc_node_mem_map() could use it to account for 
memmaps and architectures can account for the kernel image if they want. 
Then the benefit will be for many architectures, not just a poorly 
understood feature buried in x86_64.

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply

* [snd-aoa] looking for layout-id 41
From: Johannes Berg @ 2006-06-06 18:15 UTC (permalink / raw)
  To: debian-powerpc; +Cc: linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 829 bytes --]

Hey,

I found all the other layout IDs (that is to say those that snd-powermac
supports) and except the powermac7,2/3 they are supported and have been
tested but this one is still missing. If you have such a machine, please
try out snd-aoa and report if it works, I think it should. Also, please
tell me if you have any platform-* properties in your device tree
(contact me privately if you need help with that).

Again, here's how to get your layout-id:

find /proc/device-tree -name layout-id | xargs hexdump -e '1/4 "%d\n"'

(in decimal, if nothing is printed out you don't have one, snd-aoa
doesn't handle that yet)

Even if no one shows up with this machine I'll probably go ahead with
the snd-powermac deprecation for layout-id based machines as soon as we
have the pm72/3 thing figured out.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* [snd-aoa] more layout IDs
From: Johannes Berg @ 2006-06-06 20:19 UTC (permalink / raw)
  To: debian-powerpc; +Cc: linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 585 bytes --]

I have tentatively added support for these layout-IDs to snd-aoa:

36	tas
47 48	onyx/topaz
49 50	onyx/topaz
56 57	onyx/topaz
62	onyx/topaz on a single bus
66 67	onyx/topaz
76	tas/topaz on a single bus
90	tas
94	onyx
96	onyx
98	toonie
100	onyx/topaz on a single bus

If you have one of those, please test :) I based the info on the
Info.plist from Apple (thanks to xsltproc & python), so this should be
all possible layout IDs that Apple ever had.

Again, to find your layout-id:
  find /proc/device-tree -name layout-id | xargs hexdump -e '1/4 "%d\n"'

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* [PATCH] convert powermac ide blink to new led infrastructure
From: Johannes Berg @ 2006-06-06 23:05 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list

Ben, all, do you have any further objections to this patch? Otherwise,
I'd like to see it queued for 2.6.18 through whoever should do that.

---

This patch removes the old pmac ide led blink code and adds generic LED
subsystem support for the LED.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- wireless-dev.orig/drivers/ide/Kconfig	2006-05-26 15:42:45.292052079 +0200
+++ wireless-dev/drivers/ide/Kconfig	2006-06-07 00:50:11.021517067 +0200
@@ -773,13 +773,6 @@ config BLK_DEV_IDEDMA_PMAC
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 
-config BLK_DEV_IDE_PMAC_BLINK
-	bool "Blink laptop LED on drive activity"
-	depends on BLK_DEV_IDE_PMAC && ADB_PMU
-	help
-	  This option enables the use of the sleep LED as a hard drive
-	  activity LED.
-
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"
 	depends on SIBYTE_SB1xxx_SOC
--- wireless-dev.orig/drivers/ide/ppc/pmac.c	2006-05-26 15:42:45.322052079 +0200
+++ wireless-dev/drivers/ide/ppc/pmac.c	2006-06-07 00:50:11.231517067 +0200
@@ -421,107 +421,6 @@ static void pmac_ide_kauai_selectproc(id
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 /*
- * Below is the code for blinking the laptop LED along with hard
- * disk activity.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-
-/* Set to 50ms minimum led-on time (also used to limit frequency
- * of requests sent to the PMU
- */
-#define PMU_HD_BLINK_TIME	(HZ/50)
-
-static struct adb_request pmu_blink_on, pmu_blink_off;
-static spinlock_t pmu_blink_lock;
-static unsigned long pmu_blink_stoptime;
-static int pmu_blink_ledstate;
-static struct timer_list pmu_blink_timer;
-static int pmu_ide_blink_enabled;
-
-
-static void
-pmu_hd_blink_timeout(unsigned long data)
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-
-	/* We may have been triggered again in a racy way, check
-	 * that we really want to switch it off
-	 */
-	if (time_after(pmu_blink_stoptime, jiffies))
-		goto done;
-
-	/* Previous req. not complete, try 100ms more */
-	if (pmu_blink_off.complete == 0)
-		mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME);
-	else if (pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0);
-		pmu_blink_ledstate = 0;
-	}
-done:
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static void
-pmu_hd_kick_blink(void *data, int rw)
-{
-	unsigned long flags;
-	
-	pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME;
-	wmb();
-	mod_timer(&pmu_blink_timer, pmu_blink_stoptime);
-	/* Fast path when LED is already ON */
-	if (pmu_blink_ledstate == 1)
-		return;
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-	if (pmu_blink_on.complete && !pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1);
-		pmu_blink_ledstate = 1;
-	}
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static int
-pmu_hd_blink_init(void)
-{
-	struct device_node *dt;
-	const char *model;
-
-	/* Currently, I only enable this feature on KeyLargo based laptops,
-	 * older laptops may support it (at least heathrow/paddington) but
-	 * I don't feel like loading those venerable old machines with so
-	 * much additional interrupt & PMU activity...
-	 */
-	if (pmu_get_model() != PMU_KEYLARGO_BASED)
-		return 0;
-	
-	dt = of_find_node_by_path("/");
-	if (dt == NULL)
-		return 0;
-	model = (const char *)get_property(dt, "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
-	    strncmp(model, "iBook", strlen("iBook")) != 0) {
-		of_node_put(dt);
-	    	return 0;
-	}
-	of_node_put(dt);
-
-	pmu_blink_on.complete = 1;
-	pmu_blink_off.complete = 1;
-	spin_lock_init(&pmu_blink_lock);
-	init_timer(&pmu_blink_timer);
-	pmu_blink_timer.function = pmu_hd_blink_timeout;
-
-	return 1;
-}
-
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
-/*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
@@ -1190,23 +1089,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
 	pmif->timings[0] = 0;
 	pmif->timings[1] = 0;
 	
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	/* Note: This code will be called for every hwif, thus we'll
-	 * try several time to stop the LED blinker timer,  but that
-	 * should be harmless
-	 */
-	if (pmu_ide_blink_enabled) {
-		unsigned long flags;
-
-		/* Make sure we don't hit the PMU blink */
-		spin_lock_irqsave(&pmu_blink_lock, flags);
-		if (pmu_blink_ledstate)
-			del_timer(&pmu_blink_timer);
-		pmu_blink_ledstate = 0;
-		spin_unlock_irqrestore(&pmu_blink_lock, flags);
-	}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 	disable_irq(pmif->irq);
 
 	/* The media bay will handle itself just fine */
@@ -1374,13 +1256,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *p
 		hwif->selectproc = pmac_ide_selectproc;
 	hwif->speedproc = pmac_ide_tune_chipset;
 
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	pmu_ide_blink_enabled = pmu_hd_blink_init();
-
-	if (pmu_ide_blink_enabled)
-		hwif->led_act = pmu_hd_kick_blink;
-#endif
-
 	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
 	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
 	       pmif->mediabay ? " (mediabay)" : "", hwif->irq);
--- wireless-dev.orig/drivers/macintosh/Kconfig	2006-05-26 15:42:45.382052079 +0200
+++ wireless-dev/drivers/macintosh/Kconfig	2006-06-07 00:50:11.341517067 +0200
@@ -78,6 +78,17 @@ config ADB_PMU
 	  this device; you should do so if your machine is one of those
 	  mentioned above.
 
+config ADB_PMU_LED
+	bool "Support for the Power/iBook front LED"
+	depends on ADB_PMU
+	select LEDS_CLASS
+	help
+	  Support the front LED on Power/iBooks as a generic LED that can
+	  be triggered by any of the supported triggers. To get the
+	  behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this
+	  and the ide-disk LED trigger and configure appropriately through
+	  sysfs.
+
 config PMAC_SMU
 	bool "Support for SMU  based PowerMacs"
 	depends on PPC_PMAC64
--- wireless-dev.orig/drivers/macintosh/Makefile	2006-05-26 15:42:45.442052079 +0200
+++ wireless-dev/drivers/macintosh/Makefile	2006-06-07 00:58:49.861517067 +0200
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
 obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
 obj-$(CONFIG_PMAC_SMU)		+= smu.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-dev/drivers/macintosh/via-pmu-led.c	2006-06-07 01:01:15.521517067 +0200
@@ -0,0 +1,141 @@
+/*
+ * via-pmu LED class device
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+
+static spinlock_t pmu_blink_lock;
+static struct adb_request pmu_blink_req;
+/* -1: no change, 0: request off, 1: request on */
+static int requested_change;
+static int sleeping;
+
+static void pmu_req_done(struct adb_request * req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	/* if someone requested a change in the meantime
+	 * (we only see the last one which is fine)
+	 * then apply it now */
+	if (requested_change != -1 && !sleeping)
+		pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+	/* reset requested change */
+	requested_change = -1;
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_set(struct led_classdev *led_cdev,
+			enum led_brightness brightness)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	switch (brightness) {
+	case LED_OFF:
+		requested_change = 0;
+		break;
+	case LED_FULL:
+		requested_change = 1;
+		break;
+	default:
+		goto out;
+		break;
+	}
+	/* if request isn't done, then don't do anything */
+	if (pmu_blink_req.complete && !sleeping)
+		pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+ out:
+ 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static struct led_classdev pmu_led = {
+	.name = "pmu-front-led",
+	.brightness_set = pmu_led_set,
+};
+
+#ifdef CONFIG_PM
+static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+
+	switch (when) {
+	case PBOOK_SLEEP_REQUEST:
+		sleeping = 1;
+		break;
+	case PBOOK_WAKE:
+		sleeping = 0;
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+
+	return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
+	.notifier_call = pmu_led_sleep_call,
+};
+#endif
+
+static int __init via_pmu_led_init(void)
+{
+	struct device_node *dt;
+	const char *model;
+
+	/* only do this on keylargo based models */
+	if (pmu_get_model() != PMU_KEYLARGO_BASED)
+		return -ENODEV;
+
+	dt = of_find_node_by_path("/");
+	if (dt == NULL)
+		return -ENODEV;
+	model = (const char *)get_property(dt, "model", NULL);
+	if (model == NULL)
+		return -ENODEV;
+	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
+	    strncmp(model, "iBook", strlen("iBook")) != 0) {
+		of_node_put(dt);
+		/* silently ignore */
+		return 0;
+	}
+	of_node_put(dt);
+
+	spin_lock_init(&pmu_blink_lock);
+	/* no outstanding req */
+	pmu_blink_req.complete = 1;
+	pmu_blink_req.done = pmu_req_done;
+#ifdef CONFIG_PM
+	pmu_register_sleep_notifier(&via_pmu_led_sleep_notif);
+#endif
+	return led_classdev_register(NULL, &pmu_led);
+}
+
+late_initcall(via_pmu_led_init);

^ permalink raw reply

* [PATCH] via-pmu: add input device
From: Johannes Berg @ 2006-06-06 22:58 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: akpm, mjg59, linuxppc-dev list, pavel, rpurdie, linux-input
In-Reply-To: <1149245659.11092.1.camel@johannes.berg>

Almost forgot to make a new patch. Bah. Here it is, also containing the
cleanups by Andrew, thanks.
---
This patch adds an input device for the button and lid switch
so that userspace gets notified about the user pressing them
via the standard input layer.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- wireless-dev.orig/drivers/macintosh/Makefile	2006-06-07 00:50:11.351517067 +0200
+++ wireless-dev/drivers/macintosh/Makefile	2006-06-07 00:50:11.531517067 +0200
@@ -11,7 +11,7 @@ obj-$(CONFIG_MAC_EMUMOUSEBTN)	+= mac_hid
 obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
-obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU)		+= via-pmu.o via-pmu-event.o
 obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-dev/drivers/macintosh/via-pmu-event.c	2006-06-07 00:52:40.821517067 +0200
@@ -0,0 +1,80 @@
+/*
+ * via-pmu event device for reporting some events that come through the PMU
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include "via-pmu-event.h"
+
+static struct input_dev *pmu_input_dev;
+
+static int __init via_pmu_event_init(void)
+{
+	int err;
+
+	/* do other models report button/lid status? */
+	if (pmu_get_model() != PMU_KEYLARGO_BASED)
+		return -ENODEV;
+
+	pmu_input_dev = input_allocate_device();
+	if (!pmu_input_dev)
+		return -ENOMEM;
+
+	pmu_input_dev->name = "PMU";
+	pmu_input_dev->id.bustype = BUS_HOST;
+	pmu_input_dev->id.vendor = 0x0001;
+	pmu_input_dev->id.product = 0x0001;
+	pmu_input_dev->id.version = 0x0100;
+
+	set_bit(EV_KEY, pmu_input_dev->evbit);
+	set_bit(EV_SW, pmu_input_dev->evbit);
+	set_bit(KEY_POWER, pmu_input_dev->keybit);
+	set_bit(SW_LID, pmu_input_dev->swbit);
+
+	err = input_register_device(pmu_input_dev);
+	if (err)
+		input_free_device(pmu_input_dev);
+	return err;
+}
+
+void via_pmu_event(int key, int down)
+{
+
+	if (unlikely(!pmu_input_dev))
+		return;
+
+	switch (key) {
+	case PMU_EVT_POWER:
+		input_report_key(pmu_input_dev, KEY_POWER, down);
+		break;
+	case PMU_EVT_LID:
+		input_report_switch(pmu_input_dev, SW_LID, down);
+		break;
+	default:
+		/* no such key handled */
+		return;
+	}
+
+	input_sync(pmu_input_dev);
+}
+
+late_initcall(via_pmu_event_init);
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-dev/drivers/macintosh/via-pmu-event.h	2006-06-07 00:51:09.821517067 +0200
@@ -0,0 +1,8 @@
+#ifndef __VIA_PMU_EVENT_H
+#define __VIA_PMU_EVENT_H
+
+#define PMU_EVT_POWER	0
+#define PMU_EVT_LID	1
+extern void via_pmu_event(int key, int down);
+
+#endif /* __VIA_PMU_EVENT_H */
--- wireless-dev.orig/drivers/macintosh/via-pmu.c	2006-05-26 15:42:44.622052079 +0200
+++ wireless-dev/drivers/macintosh/via-pmu.c	2006-06-07 00:51:01.991517067 +0200
@@ -69,6 +69,8 @@
 #include <asm/open_pic.h>
 #endif
 
+#include "via-pmu-event.h"
+
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
@@ -1441,6 +1443,12 @@ next:
 		if (pmu_battery_count)
 			query_battery_state();
 		pmu_pass_intr(data, len);
+		/* len == 6 is probably a bad check. But how do I
+		 * know what PMU versions send what events here? */
+		if (len == 6) {
+			via_pmu_event(PMU_EVT_POWER, !!(data[1]&8));
+			via_pmu_event(PMU_EVT_LID, data[1]&1);
+		}
 	} else {
 	       pmu_pass_intr(data, len);
 	}

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Johannes Berg @ 2006-06-07 11:40 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5h8xoamliv.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 707 bytes --]

On Tue, 2006-06-06 at 16:00 +0200, Takashi Iwai wrote:

> > Yeah, I guess, never really thought about that, just wrote it down the
> > way I thought to do it :) That said, I think it's more readable if
> > written that way, do you want me to change it regardless?
> 
> I found a single if is more readable (and good for compiler).

Heh ok, I'll change it, it isn't really hard to read either way.


> No, the only requirement is that you have to call snd_pcm_lib_malloc()
> with proper type and assigned device pointer if you use
> snd_pcm_lib_malloc() function.  (If not called, you've got an error
> when compiled with debug option.)

Ok, but how do I set the device pointer?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* CPM_UART should allocate DPRAM for SMCx parameter RAM on MPC82xx
From: Laurent Pinchart @ 2006-06-07 12:34 UTC (permalink / raw)
  To: linuxppc-embedded

Hi everybody,

the move to platform devices introduced a bug in the CPM_UART SMC driver.

Unlike SCC and FCC, the SMC parameter ram is not at a fixed location. A 
pointer to the parameter ram is instead stored at PROFF_SMCx_BASE.

The SMC platform device resources (in arch/ppc/syslib/pq2_devices.c) reserves 
the memory resource PROFF_SMCx_BASE - PROFF_SMCx_BASE+1. The CPM UART driver 
considers that value as the SMC parameter ram offset. It should instead 
allocate 64 bytes (on a 64 bytes boundary) of DPRAM for its parameter ram, 
and store the offset at PROFF_SMCx_BASE. 

I'm not sure how to fix the problem as it seems that the platform device 
support is not complete yet (cpm_uart_init_portdesc is still used to 
initialize the console). A possible workaround is to set the pram resource to 
0x0000-0x003f and 0x0040-0x007f instead of 0x87fc-0x87fd and 0x88fc-0x88fd 
for SMC1 and SMC2. This will not work if cpm_uart_init_portdesc is not 
called.

Laurent Pinchart

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Takashi Iwai @ 2006-06-07 12:41 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <1149680421.3999.4.camel@johannes>

At Wed, 07 Jun 2006 13:40:21 +0200,
Johannes Berg wrote:
> 
> On Tue, 2006-06-06 at 16:00 +0200, Takashi Iwai wrote:
> 
> > > Yeah, I guess, never really thought about that, just wrote it down the
> > > way I thought to do it :) That said, I think it's more readable if
> > > written that way, do you want me to change it regardless?
> > 
> > I found a single if is more readable (and good for compiler).
> 
> Heh ok, I'll change it, it isn't really hard to read either way.
> 
> 
> > No, the only requirement is that you have to call snd_pcm_lib_malloc()
> > with proper type and assigned device pointer if you use
> > snd_pcm_lib_malloc() function.  (If not called, you've got an error
> > when compiled with debug option.)
> 
> Ok, but how do I set the device pointer?

Your code already does it.  The macro pci_to_dev() retrieves struct
device pointer (it's just for compatibility with older kernels).


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Johannes Berg @ 2006-06-07 12:45 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5hwtbt5ea8.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 392 bytes --]

On Wed, 2006-06-07 at 14:41 +0200, Takashi Iwai wrote:
> > Ok, but how do I set the device pointer?
> 
> Your code already does it.

Where? Am I just missing something? I don't see where I use pci_to_dev
nor setting any device pointer.

The thing the comment noted was that if I left out the call to
snd_pcm_lib_preallocate_pages_for_all, it would later oops somewhere.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Takashi Iwai @ 2006-06-07 12:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <1149684301.3999.21.camel@johannes>

At Wed, 07 Jun 2006 14:45:00 +0200,
Johannes Berg wrote:
> 
> On Wed, 2006-06-07 at 14:41 +0200, Takashi Iwai wrote:
> > > Ok, but how do I set the device pointer?
> > 
> > Your code already does it.
> 
> Where? Am I just missing something? I don't see where I use pci_to_dev
> nor setting any device pointer.

Sorry, s/pci_to_dev/snd_dma_pci_data/


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC 4/8] snd-aoa: add i2sbus
From: Johannes Berg @ 2006-06-07 12:52 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev, alsa-devel
In-Reply-To: <s5hslmh5dwl.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 536 bytes --]

On Wed, 2006-06-07 at 14:49 +0200, Takashi Iwai wrote:

> Sorry, s/pci_to_dev/snd_dma_pci_data/

So then you're saying that indeed, snd_pcm_lib_preallocate_pages_for_all
has the side effect of setting a pointer somewhere else?

I just don't understand why it all blows up when I leave off the
preallocate call. From the function name that says 'preallocate pages'
it seemed to me that I should be allowed to just leave it off, risking
that later an open() or prepare() fails because no pages could be
allocated.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox