Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1821

kernel-2.6.18-128.1.10.el5.src.rpm

From: Scott Moser <smoser@redhat.com>
Date: Tue, 20 Nov 2007 17:17:06 -0500
Subject: [ppc64] cell: support pinhole-reset on blades
Message-id: 1195597029193-do-send-email-smoser@redhat.com
O-Subject: [PATCH RHEL5u2] bz253208 Cell/B.E. Kernel Maintenance [1/4]
Bugzilla: 253208

commit 3addf55c9415f9da039947b33d064332137e49fe
Author: Arnd Bergmann <arnd@arndb.de>
Date:   Thu Aug 23 03:01:26 2007 +1000

 [POWERPC] cell: Support pinhole-reset on IBM cell blades

 The Cell Broadband Engine has a method of injecting a
 system-reset-exception from an external source into the
 operating system, which should trigger the regular behaviour
 of entering xmon or kdump.

 Unfortunately, the exception handler cannot distinguish it from
 other interrupt causes by the SRR1 register, which gets used
 for this on Power 6 and others.

 IBM Blade servers that want to support triggering the
 system reset exception using a pinhole button in the front
 panel therefore use an extra register to determine the
 reset cause.

--
 arch/powerpc/platforms/cell/cbe_regs.h  |    8 ++++--
 arch/powerpc/platforms/cell/pervasive.c |   33 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)

Acked-by: David Howells <dhowells@redhat.com>

diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
index a030c69..a7f2866 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -111,10 +111,14 @@ struct cbe_pmd_regs {
 	u64	checkstop_fir;					/* 0x0c00 */
 	u64	recoverable_fir;				/* 0x0c08 */
 	u64	spec_att_mchk_fir;				/* 0x0c10 */
-	u64	fir_mode_reg;					/* 0x0c18 */
+	u32	fir_mode_reg;					/* 0x0c18 */
+	u8	pad_0x0c1c_0x0c20 [4];				/* 0x0c1c */
+#define CBE_PMD_FIR_MODE_M8		0x00800
 	u64	fir_enable_mask;				/* 0x0c20 */
 
-	u8	pad_0x0c28_0x1000 [0x1000 - 0x0c28];		/* 0x0c28 */
+	u8	pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28];		/* 0x0c28 */
+	u64	ras_esc_0;					/* 0x0ca8 */
+	u8	pad_0x0cb0_0x1000 [0x1000 - 0x0cb0];		/* 0x0cb0 */
 };
 
 extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 9f2e4ed..3312b19 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,6 +38,8 @@
 #include "pervasive.h"
 #include "cbe_regs.h"
 
+static int sysreset_hack;
+
 static DEFINE_SPINLOCK(cbe_pervasive_lock);
 
 static void __init cbe_enable_pause_zero(void)
@@ -131,6 +133,9 @@ static void cbe_idle(void)
 
 static int cbe_system_reset_exception(struct pt_regs *regs)
 {
+	int cpu;
+	struct cbe_pmd_regs __iomem *pmd;
+
 	switch (regs->msr & SRR1_WAKEMASK) {
 	case SRR1_WAKEEE:
 		do_IRQ(regs);
@@ -139,6 +144,18 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
 		timer_interrupt(regs);
 		break;
 	case SRR1_WAKEMT:
+		/*
+		 * The BMC can inject user triggered system reset exceptions,
+		 * but cannot set the system reset reason in srr1,
+		 * so check an extra register here.
+		 */
+		if (sysreset_hack && (cpu = smp_processor_id()) == 0) {
+			pmd = cbe_get_cpu_pmd_regs(cpu);
+			if (in_be64(&pmd->ras_esc_0) & 0xffff) {
+				out_be64(&pmd->ras_esc_0, 0);
+				return 0;
+			}
+		}
 		break;
 #ifdef CONFIG_CBE_RAS
 	case SRR1_WAKESYSERR:
@@ -158,9 +175,25 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
 
 void __init cbe_pervasive_init(void)
 {
+	int cpu;
+
 	if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
 		return;
 
+	sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
+
+	for_each_possible_cpu(cpu) {
+		struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
+		if (!regs)
+			continue;
+
+		/* Enable JTAG system-reset hack */
+		if (sysreset_hack)
+			out_be32(&regs->fir_mode_reg,
+				in_be32(&regs->fir_mode_reg) |
+				CBE_PMD_FIR_MODE_M8);
+	}
+
 	ppc_md.idle_loop = cbe_idle;
 	ppc_md.system_reset_exception = cbe_system_reset_exception;
 }