patch-2.4.21 linux-2.4.21/arch/alpha/kernel/sys_nautilus.c

Next file: linux-2.4.21/arch/alpha/kernel/sys_ruffian.c
Previous file: linux-2.4.21/arch/alpha/kernel/sys_mikasa.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/arch/alpha/kernel/sys_nautilus.c linux-2.4.21/arch/alpha/kernel/sys_nautilus.c
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/reboot.h>
+#include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -45,6 +46,7 @@
 #include <asm/hwrpb.h>
 
 #include "proto.h"
+#include "err_impl.h"
 #include "irq_impl.h"
 #include "pci_impl.h"
 #include "machvec_impl.h"
@@ -99,324 +101,12 @@
 	}
 }
 
-/* Machine check handler code
- *
- * Perform analysis of a machine check that was triggered by the EV6
- * CPU's fault-detection mechanism.
- */
-
-/* IPR structures for EV6, containing the necessary data for the
- * machine check handler to unpick the logout frame
- */
-
-/* I_STAT */
-
-#define EV6__I_STAT__PAR                ( 1 << 29 )
-
-/* MM_STAT */
-
-#define EV6__MM_STAT__DC_TAG_PERR       ( 1 << 10 )
-
-/* DC_STAT */
-
-#define EV6__DC_STAT__SEO               ( 1 << 4 )
-#define EV6__DC_STAT__ECC_ERR_LD        ( 1 << 3 )
-#define EV6__DC_STAT__ECC_ERR_ST        ( 1 << 2 )
-#define EV6__DC_STAT__TPERR_P1          ( 1 << 1 )
-#define EV6__DC_STAT__TPERR_P0          ( 1      )
-
-/* C_STAT */
-
-#define EV6__C_STAT__BC_PERR            ( 0x01 )
-#define EV6__C_STAT__DC_PERR            ( 0x02 )
-#define EV6__C_STAT__DSTREAM_MEM_ERR    ( 0x03 )
-#define EV6__C_STAT__DSTREAM_BC_ERR     ( 0x04 )
-#define EV6__C_STAT__DSTREAM_DC_ERR     ( 0x05 )
-#define EV6__C_STAT__PROBE_BC_ERR0      ( 0x06 )
-#define EV6__C_STAT__PROBE_BC_ERR1      ( 0x07 )
-#define EV6__C_STAT__ISTREAM_MEM_ERR    ( 0x0B )
-#define EV6__C_STAT__ISTREAM_BC_ERR     ( 0x0C )
-#define EV6__C_STAT__DSTREAM_MEM_DBL    ( 0x13 )
-#define EV6__C_STAT__DSTREAM_BC_DBL     ( 0x14 )
-#define EV6__C_STAT__ISTREAM_MEM_DBL    ( 0x1B )
-#define EV6__C_STAT__ISTREAM_BC_DBL     ( 0x1C )
-
-
-/* Take the two syndromes from the CBOX error chain and convert them
- * into a bit number.  */
-
-/* NOTE - since I don't know of any difference between C0 and C1 I
-   just ignore C1, since in all cases I've seen so far they are
-   identical.  */
-
-static const unsigned char ev6_bit_to_syndrome[72] =
-{
-	0xce, 0xcb, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc,     /* 0 */
-	0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,     /* 8 */
-	0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,     /* 16 */
-	0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xf1, 0xf4,     /* 24 */
-	0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,     /* 32 */
-	0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xb0, 0xb5,     /* 40 */
-	0x8f, 0x8a, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d,     /* 48 */
-	0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,     /* 56 */
-	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80      /* 64 */
-};
-
-
-static int ev6_syn2bit(unsigned long c0, unsigned long c1)
-{
-	int bit;
-
-	for (bit = 0; bit < 72; bit++)
-		if (ev6_bit_to_syndrome[bit] == c0)	return bit;
-	for (bit = 0; bit < 72; bit++)
-		if (ev6_bit_to_syndrome[bit] == c1)	return bit + 64;
-
-	return -1;                  /* not found */
-}
-
-
-/* Single bit ECC errors are categorized here.  */
-
-#if 0
-static const char *interr = "CPU internal error";
-static const char *slotb= "Slot-B error";
-static const char *membus= "Memory/EV6-bus error";
-#else
-static const char *interr = "";
-static const char *slotb = "";
-static const char *membus = "";
-#endif
-
-static void
-ev6_crd_interp(char *interp, struct el_common_EV6_mcheck * L)
-{
-	/* Icache data or tag parity error.  */
-	if (L->I_STAT & EV6__I_STAT__PAR) {
-		sprintf(interp, "%s: I_STAT[PAR]\n "
-			"Icache data or tag parity error", interr);
-		return;
-	}
-
-	/* Dcache tag parity error (on issue) (DFAULT).  */
-	if (L->MM_STAT & EV6__MM_STAT__DC_TAG_PERR) {
-		sprintf(interp, "%s: MM_STAT[DC_TAG_PERR]\n "
-			"Dcache tag parity error(on issue)", interr);
-		return;
-	}
-
-	/* Errors relating to D-stream set non-zero DC_STAT.
-	   Mask CRD bits.  */
-	switch (L->DC_STAT & (EV6__DC_STAT__ECC_ERR_ST
-			      | EV6__DC_STAT__ECC_ERR_LD)) {
-	case EV6__DC_STAT__ECC_ERR_ST:
-		/* Dcache single-bit ECC error on small store */
-		sprintf(interp, "%s: DC_STAT[ECC_ERR_ST]\n "
-			"Dcache single-bit ECC error on small store", interr);
-		return;
-
-	case EV6__DC_STAT__ECC_ERR_LD:
-		switch (L->C_STAT) {
-		case 0:
-			/* Dcache single-bit error on speculative load */
-			/* Bcache victim read on Dcache/Bcache miss */
-			sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT=0\n "
-				"Dcache single-bit ECC error on speculative load",
-				slotb);
-			return;
-
-		case EV6__C_STAT__DSTREAM_DC_ERR:
-			/* Dcache single bit error on load */
-			sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_DC_ERR]\n"
-				" Dcache single-bit ECC error on speculative load, bit %d",
-				interr, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
-			return;
-
-		case EV6__C_STAT__DSTREAM_BC_ERR:
-			/* Bcache single-bit error on Dcache fill */
-			sprintf(interp, "%s: DC_STAT[ECC_ERR_LD] C_STAT[DSTREAM_BC_ERR]\n"
-				" Bcache single-bit error on Dcache fill, bit %d",
-				slotb, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
-			return;
-
-		case EV6__C_STAT__DSTREAM_MEM_ERR:
-			/* Memory single-bit error on Dcache fill */
-			sprintf(interp, "%s (to Dcache): DC_STAT[ECC_ERR_LD] "
-				"C_STAT[DSTREAM_MEM_ERR]\n "
-				"Memory single-bit error on Dcache fill, "
-				"Address 0x%lX, bit %d",
-				membus, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
-							       L->DC1_SYNDROME));
-			return;
-		}
-	}
-
-	/* I-stream, other misc errors go on C_STAT alone */
-	switch (L->C_STAT) {
-	case EV6__C_STAT__ISTREAM_BC_ERR:
-		/* Bcache single-bit error on Icache fill (also MCHK) */
-		sprintf(interp, "%s: C_STAT[ISTREAM_BC_ERR]\n "
-			"Bcache single-bit error on Icache fill, bit %d",
-			slotb, ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
-		return;
-
-	case EV6__C_STAT__ISTREAM_MEM_ERR:
-		/* Memory single-bit error on Icache fill (also MCHK) */
-		sprintf(interp, "%s : C_STATISTREAM_MEM_ERR]\n "
-			"Memory single-bit error on Icache fill "
-			"addr 0x%lX, bit %d",
-			membus, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
-						       L->DC1_SYNDROME));
-		return;
-
-	case EV6__C_STAT__PROBE_BC_ERR0:
-	case EV6__C_STAT__PROBE_BC_ERR1:
-		/* Bcache single-bit error on a probe hit */
-		sprintf(interp, "%s: C_STAT[PROBE_BC_ERR]\n "
-			"Bcache single-bit error on a probe hit, "
-			"addr 0x%lx, bit %d",
-			slotb, L->C_ADDR, ev6_syn2bit(L->DC0_SYNDROME,
-						      L->DC1_SYNDROME));
-		return;
-	}
-}
-
-static void
-ev6_mchk_interp(char *interp, struct el_common_EV6_mcheck * L)
-{
-	/* Machine check errors described by DC_STAT */
-	switch (L->DC_STAT) {
-	case EV6__DC_STAT__TPERR_P0:
-	case EV6__DC_STAT__TPERR_P1:
-		/* Dcache tag parity error (on retry) */
-		sprintf(interp, "%s: DC_STAT[TPERR_P0|TPERR_P1]\n "
-			"Dcache tag parity error(on retry)", interr);
-		return;
-
-	case EV6__DC_STAT__SEO:
-		/* Dcache second error on store */
-		sprintf(interp, "%s: DC_STAT[SEO]\n "
-			"Dcache second error during mcheck", interr);
-		return;
-	}
-
-	/* Machine check errors described by C_STAT */
-	switch (L->C_STAT) {
-	case EV6__C_STAT__DC_PERR:
-		/* Dcache duplicate tag parity error */
-		sprintf(interp, "%s: C_STAT[DC_PERR]\n "
-			"Dcache duplicate tag parity error at 0x%lX",
-			interr, L->C_ADDR);
-		return;
-
-	case EV6__C_STAT__BC_PERR:
-		/* Bcache tag parity error */
-		sprintf(interp, "%s: C_STAT[BC_PERR]\n "
-			"Bcache tag parity error at 0x%lX",
-			slotb, L->C_ADDR);
-		return;
-
-	case EV6__C_STAT__ISTREAM_BC_ERR:
-		/* Bcache single-bit error on Icache fill (also CRD) */
-		sprintf(interp, "%s: C_STAT[ISTREAM_BC_ERR]\n "
-			"Bcache single-bit error on Icache fill 0x%lX bit %d",
-			slotb, L->C_ADDR,
-			ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
-		return;
-
-
-	case EV6__C_STAT__ISTREAM_MEM_ERR:
-		/* Memory single-bit error on Icache fill (also CRD) */
-		sprintf(interp, "%s: C_STAT[ISTREAM_MEM_ERR]\n "
-			"Memory single-bit error on Icache fill 0x%lX, bit %d",
-			membus, L->C_ADDR,
-			ev6_syn2bit(L->DC0_SYNDROME, L->DC1_SYNDROME));
-		return;
-
-
-	case EV6__C_STAT__ISTREAM_BC_DBL:
-		/* Bcache double-bit error on Icache fill */
-		sprintf(interp, "%s: C_STAT[ISTREAM_BC_DBL]\n "
-			"Bcache double-bit error on Icache fill at 0x%lX",
-			slotb, L->C_ADDR);
-		return;
-	case EV6__C_STAT__DSTREAM_BC_DBL:
-		/* Bcache double-bit error on Dcache fill */
-		sprintf(interp, "%s: C_STAT[DSTREAM_BC_DBL]\n "
-			"Bcache double-bit error on Dcache fill at 0x%lX",
-			slotb, L->C_ADDR);
-		return;
-
-	case EV6__C_STAT__ISTREAM_MEM_DBL:
-		/* Memory double-bit error on Icache fill */
-		sprintf(interp, "%s: C_STAT[ISTREAM_MEM_DBL]\n "
-			"Memory double-bit error on Icache fill at 0x%lX",
-			membus, L->C_ADDR);
-		return;
-
-	case EV6__C_STAT__DSTREAM_MEM_DBL:
-		/* Memory double-bit error on Dcache fill */
-		sprintf(interp, "%s: C_STAT[DSTREAM_MEM_DBL]\n "
-			"Memory double-bit error on Dcache fill at 0x%lX",
-			membus, L->C_ADDR);
-		return;
-	}
-}
-
-static void
-ev6_cpu_machine_check(unsigned long vector, struct el_common_EV6_mcheck *L,
-		      struct pt_regs *regs)
-{
-	char interp[80];
-
-	/* This is verbose and looks intimidating.  Should it be printed for
-	   corrected (CRD) machine checks? */
-
-	printk(KERN_CRIT "PALcode logout frame:  "
-	       "MCHK_Code       %d  "
-	       "MCHK_Frame_Rev  %d\n"
-	       "I_STAT  %016lx  "
-	       "DC_STAT %016lx  "
-	       "C_ADDR  %016lx\n"
-	       "SYND1   %016lx  "
-	       "SYND0   %016lx  "
-	       "C_STAT  %016lx\n"
-	       "C_STS   %016lx  "
-	       "RES     %016lx  "
-	       "EXC_ADDR%016lx\n"
-	       "IER_CM  %016lx  "
-	       "ISUM    %016lx  "
-	       "MM_STAT %016lx\n"
-	       "PALBASE %016lx  "
-	       "I_CTL   %016lx  "
-	       "PCTX    %016lx\n"
-	       "CPU registers: "
-	       "PC      %016lx  "
-	       "Return  %016lx\n",
-	       L->MCHK_Code, L->MCHK_Frame_Rev, L->I_STAT, L->DC_STAT,
-	       L->C_ADDR, L->DC1_SYNDROME, L->DC0_SYNDROME, L->C_STAT,
-	       L->C_STS, L->RESERVED0, L->EXC_ADDR, L->IER_CM, L->ISUM,
-	       L->MM_STAT, L->PAL_BASE, L->I_CTL, L->PCTX,
-	       regs->pc, regs->r26);
-
-	/* Attempt an interpretation on the meanings of the fields above.  */
-	sprintf(interp, "No interpretation available!" );
-	if (vector == SCB_Q_PROCERR)
-		ev6_crd_interp(interp, L);
-	else if (vector == SCB_Q_PROCMCHK)
-		ev6_mchk_interp(interp, L);
-
-	printk(KERN_CRIT "interpretation: %s\n\n", interp);
-}
-
-
 /* Perform analysis of a machine check that arrived from the system (NMI) */
 
 static void
 naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
 		       struct pt_regs *regs)
 {
-	printk("xtime %lx\n", CURRENT_TIME);
 	printk("PC %lx RA %lx\n", regs->pc, regs->r26);
 	irongate_pci_clr_err();
 }
@@ -429,7 +119,6 @@
 		       struct pt_regs *regs)
 {
 	char *mchk_class;
-	unsigned cpu_analysis=0, sys_analysis=0;
 
 	/* Now for some analysis.  Machine checks fall into two classes --
 	   those picked up by the system, and those picked up by the CPU.
@@ -462,39 +151,20 @@
 		return;
 	}
 
-	switch (vector) {
-	case SCB_Q_SYSERR:
-		mchk_class = "Correctable System Machine Check (NMI)";
-		sys_analysis = 1;
-		break;
-	case SCB_Q_SYSMCHK:
-		mchk_class = "Fatal System Machine Check (NMI)";
-		sys_analysis = 1;
-		break;
-
-	case SCB_Q_PROCERR:
-		mchk_class = "Correctable Processor Machine Check";
-		cpu_analysis = 1;
-		break;
-	case SCB_Q_PROCMCHK:
-		mchk_class = "Fatal Processor Machine Check";
-		cpu_analysis = 1;
-		break;
-
-	default:
-		mchk_class = "Unknown vector!";
-		break;
+	if (vector == SCB_Q_SYSERR)
+		mchk_class = "Correctable";
+	else if (vector == SCB_Q_SYSMCHK)
+		mchk_class = "Fatal";
+	else {
+		ev6_machine_check(vector, la_ptr, regs);
+		return;
 	}
 
-	printk(KERN_CRIT "NAUTILUS Machine check 0x%lx [%s]\n",
+	printk(KERN_CRIT "NAUTILUS Machine check 0x%lx "
+			 "[%s System Machine Check (NMI)]\n",
 	       vector, mchk_class);
 
-	if (cpu_analysis)
-		ev6_cpu_machine_check(vector,
-				      (struct el_common_EV6_mcheck *)la_ptr,
-				      regs);
-	if (sys_analysis)
-		naut_sys_machine_check(vector, la_ptr, regs);
+	naut_sys_machine_check(vector, la_ptr, regs);
 
 	/* Tell the PALcode to clear the machine check */
 	draina();
@@ -503,6 +173,69 @@
 }
 
 
+extern void free_reserved_mem(void *, void *);
+extern void pbus_size_bridges(struct pci_bus *);
+extern void pbus_assign_resources(struct pci_bus *);
+
+static struct resource irongate_mem = {
+	.name	= "Irongate PCI MEM",
+	.flags	= IORESOURCE_MEM,
+};
+
+void __init
+nautilus_init_pci(void)
+{
+	struct pci_controller *hose = hose_head;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	unsigned long bus_align, bus_size, pci_mem;
+	unsigned long memtop = max_low_pfn << PAGE_SHIFT;
+
+	/* Scan our single hose.  */
+	bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
+	hose->bus = bus;
+	hose->last_busno = bus->subordinate;
+
+	bus->self = pci_find_slot(0, 0);
+	bus->resource[1] = &irongate_mem;
+
+	pbus_size_bridges(bus);
+
+	/* IO port range. */
+	bus->resource[0]->start = 0;
+	bus->resource[0]->end = 0xffff;
+
+	/* Set up PCI memory range - limit is hardwired to 0xffffffff,
+	   base must be at aligned to 16Mb. */
+	bus_align = bus->resource[1]->start;
+	bus_size = bus->resource[1]->end + 1 - bus_align;
+	if (bus_align < 0x1000000UL)
+		bus_align = 0x1000000UL;
+
+	pci_mem = (0x100000000UL - bus_size) & -bus_align;
+
+	bus->resource[1]->start = pci_mem;
+	bus->resource[1]->end = 0xffffffffUL;
+	if (request_resource(&iomem_resource, bus->resource[1]) < 0)
+		printk(KERN_ERR "Failed to request MEM on hose 0\n");
+
+	if (pci_mem < memtop && pci_mem > alpha_mv.min_mem_address) {
+		free_reserved_mem(__va(alpha_mv.min_mem_address),
+				  __va(pci_mem));
+		printk("nautilus_init_pci: %ldk freed\n",
+			(pci_mem - alpha_mv.min_mem_address) >> 10);
+	}
+
+	if ((IRONGATE0->dev_vendor >> 16) > 0x7006)	/* Albacore? */
+		IRONGATE0->pci_mem = pci_mem;
+
+	pbus_assign_resources(bus);
+
+	pci_for_each_dev(dev) {
+		pdev_enable_device(dev);
+	}
+	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+}
 
 /*
  * The System Vectors
@@ -525,7 +258,7 @@
 	init_arch:		irongate_init_arch,
 	init_irq:		nautilus_init_irq,
 	init_rtc:		common_init_rtc,
-	init_pci:		common_init_pci,
+	init_pci:		nautilus_init_pci,
 	kill_arch:		nautilus_kill_arch,
 	pci_map_irq:		nautilus_map_irq,
 	pci_swizzle:		common_swizzle,

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)