patch-2.2.14 linux/arch/alpha/kernel/core_mcpcia.c

Next file: linux/arch/alpha/kernel/core_pyxis.c
Previous file: linux/arch/alpha/kernel/core_irongate.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.13/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c
@@ -24,6 +24,7 @@
 #include <asm/core_mcpcia.h>
 #undef __EXTERN_INLINE
 
+#include "machvec.h"
 #include "proto.h"
 #include "bios32.h"
 
@@ -51,9 +52,12 @@
 static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
 static volatile unsigned int MCPCIA_mcheck_hose[NR_CPUS];
 static unsigned int MCPCIA_jd[NR_CPUS];
+static unsigned int MCPCIA_mcheck_enable_print = 1;
+static unsigned int MCPCIA_mcheck_probing_hose = 0;
 
-#define MCPCIA_MAX_HOSES 2
+#define MCPCIA_MAX_HOSES	4
 
+static struct linux_hose_info *mcpcia_hoses[MCPCIA_MAX_HOSES];
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -297,24 +301,65 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static void
+mcpcia_pci_clr_err(int cpu, int hose)
+{
+	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(hose);
+	*(vuip)MCPCIA_CAP_ERR(hose) = 0xffffffff; mb(); /* clear them all */
+	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(hose); /* read to force write */
+}
+
 void __init
 mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-	extern asmlinkage void entInt(void);
 	struct linux_hose_info *hose;
-	unsigned int mcpcia_err;
-	unsigned int pci_rev;
-	int h, cpu;
-
-	/* Ho hum.. init_arch is called before init_IRQ, but we need to be
-	   able to handle machine checks.  So install the handler now.  */
-	wrent(entInt, 0);
+	int h;
 
 	/* Align memory to cache line; we'll be allocating from it.  */
 	*mem_start = (*mem_start | 31) + 1;
 
+	/* First, allocate for the maximum number of hoses we might have.  */
+	for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
+
+		hose = (struct linux_hose_info *)*mem_start;
+		*mem_start = (unsigned long)(hose + 1);
+
+		memset(hose, 0, sizeof(*hose));
+
+		mcpcia_hoses[h] = hose;
+
+		hose->pci_io_space = MCPCIA_IO(h);
+		hose->pci_mem_space = MCPCIA_DENSE(h);
+		hose->pci_config_space = MCPCIA_CONF(h);
+		hose->pci_sparse_space = MCPCIA_SPARSE(h);
+		hose->pci_hose_index = h;
+		hose->pci_first_busno = 255;
+		hose->pci_last_busno = 0;
+	}
+
+#if 1
+	printk("mcpcia_init_arch: allocating for %d hoses\n",
+	       MCPCIA_MAX_HOSES);
+#endif
+}
+
+/*
+ * This is called from init_IRQ, since we cannot take interrupts
+ * before then, so we cannot do this in init_arch.
+ */
+void __init
+mcpcia_init_hoses(void)
+{
+	struct linux_hose_info *hose;
+	unsigned int mcpcia_err;
+	unsigned int pci_rev;
+	int h, cpu;
+
 	cpu = smp_processor_id();
 
+	MCPCIA_mcheck_enable_print = 0;
+	MCPCIA_mcheck_probing_hose = 1;
+
 	/* First, find how many hoses we have.  */
 	for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
 
@@ -324,50 +369,49 @@
 		mb();
 		mb();
 		draina();
+		wrmces(7);
 		MCPCIA_mcheck_expected[cpu] = 1;
 		MCPCIA_mcheck_taken[cpu]    = 0;
+		MCPCIA_mcheck_hose[cpu] = h;
+		pci_rev = 0xffffffff;
 		mb();
 
 		/* Access the bus revision word. */
 		pci_rev = *(vuip)MCPCIA_REV(h);
 
+#if 0
+		draina(); /* huh? */
+#endif
+
 		mb();
 		mb();  /* magic */
 		if (MCPCIA_mcheck_taken[cpu]) {
 			MCPCIA_mcheck_taken[cpu] = 0;
 			pci_rev = 0xffffffff;
 			mb();
+			break;
 		}
 		MCPCIA_mcheck_expected[cpu] = 0;
 		mb();
 
-#if 0
-		printk("mcpcia_init_arch: got 0x%x for PCI_REV for hose %d\n",
-		       pci_rev, h);
-#endif
 		if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
+
 			hose_count++;
 
-			hose = (struct linux_hose_info *)*mem_start;
-			*mem_start = (unsigned long)(hose + 1);
+			mcpcia_pci_clr_err(cpu, h);
 
-			memset(hose, 0, sizeof(*hose));
+			hose = mcpcia_hoses[h];
 
 			*hose_tail = hose;
 			hose_tail = &hose->next;
-
-			hose->pci_io_space = MCPCIA_IO(h);
-			hose->pci_mem_space = MCPCIA_DENSE(h);
-			hose->pci_config_space = MCPCIA_CONF(h);
-			hose->pci_sparse_space = MCPCIA_SPARSE(h);
-			hose->pci_hose_index = h;
-			hose->pci_first_busno = 255;
-			hose->pci_last_busno = 0;
 		}
 	}
 
+	MCPCIA_mcheck_enable_print = 1;
+	MCPCIA_mcheck_probing_hose = 0;
+
 #if 1
-	printk("mcpcia_init_arch: found %d hoses\n", hose_count);
+	printk("mcpcia_init_hoses: found %d hoses\n", hose_count);
 #endif
 
 	/* Now do init for each hose.  */
@@ -390,22 +434,16 @@
 		printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
 #endif
 
+#if 1
 		/* 
-		 * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+		 * Set up error reporting.
 		 */
-#if 0
-		mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
-		mcpcia_err &= ~4;   
-		*(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
-		mb();
-		mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
-#endif
-
 		mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
 		mcpcia_err |= 0x0006;   /* master/target abort */
 		*(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
 		mb() ;
 		mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
+#endif
 
 		switch (alpha_use_srm_setup)
 		{
@@ -486,11 +524,10 @@
 		case 0:
 			/*
 			 * Set up the PCI->physical memory translation windows.
-			 * For now, windows 1,2 and 3 are disabled.  In the
-			 * future, we may want to use them to do scatter/
-			 * gather DMA.
+			 * For now, windows 2 and 3 are disabled. 
 			 *
 			 * Window 0 goes at 2 GB and is 2 GB large.
+			 * Window 1 goes at ? MB and is ? MB large, S/G.
 			 */
 
 			*(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
@@ -551,14 +588,6 @@
 }
 
 static void
-mcpcia_pci_clr_err(int cpu, int hose)
-{
-	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(hose);
-	*(vuip)MCPCIA_CAP_ERR(hose) = 0xffffffff; mb(); /* clear them all */
-	MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(hose); /* read to force write */
-}
-
-static void
 mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
 {
 	struct el_common_EV5_uncorrectable_mcheck *frame;
@@ -568,65 +597,64 @@
 
 	/* Print PAL fields */
 	for (i = 0; i < 24; i += 2) {
-		printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n",
+		printk("  paltmp[%2d-%2d]    = %16lx %16lx\n",
 		       i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
 	}
 	for (i = 0; i < 8; i += 2) {
-		printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n",
+		printk("  shadow[%2d-%2d]     = %16lx %16lx\n",
 		       i, i+1, frame->shadow[i], 
 		       frame->shadow[i+1]);
 	}
-	printk("\tAddr of excepting instruction\t= %16lx\n",
+	printk("  Addr of excepting instruction  = %16lx\n",
 	       frame->exc_addr);
-	printk("\tSummary of arithmetic traps\t= %16lx\n",
+	printk("  Summary of arithmetic traps    = %16lx\n",
 	       frame->exc_sum);
-	printk("\tException mask\t\t\t= %16lx\n",
+	printk("  Exception mask                 = %16lx\n",
 	       frame->exc_mask);
-	printk("\tBase address for PALcode\t= %16lx\n",
+	printk("  Base address for PALcode       = %16lx\n",
 	       frame->pal_base);
-	printk("\tInterrupt Status Reg\t\t= %16lx\n",
+	printk("  Interrupt Status Reg           = %16lx\n",
 	       frame->isr);
-	printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n",
+	printk("  CURRENT SETUP OF EV5 IBOX      = %16lx\n",
 	       frame->icsr);
-	printk("\tI-CACHE Reg %s parity error\t= %16lx\n",
-	       (frame->ic_perr_stat & 0x800L) ? 
-	       "Data" : "Tag", 
+	printk("  I-CACHE Reg %s parity error    = %16lx\n",
+	       (frame->ic_perr_stat & 0x800L) ? "Data" : "Tag", 
 	       frame->ic_perr_stat); 
-	printk("\tD-CACHE error Reg\t\t= %16lx\n",
+	printk("  D-CACHE error Reg              = %16lx\n",
 	       frame->dc_perr_stat);
 	if (frame->dc_perr_stat & 0x2) {
 		switch (frame->dc_perr_stat & 0x03c) {
 		case 8:
-			printk("\t\tData error in bank 1\n");
+			printk("    Data error in bank 1\n");
 			break;
 		case 4:
-			printk("\t\tData error in bank 0\n");
+			printk("    Data error in bank 0\n");
 			break;
 		case 20:
-			printk("\t\tTag error in bank 1\n");
+			printk("    Tag error in bank 1\n");
 			break;
 		case 10:
-			printk("\t\tTag error in bank 0\n");
+			printk("    Tag error in bank 0\n");
 			break;
 		}
 	}
-	printk("\tEffective VA\t\t\t= %16lx\n",
+	printk("  Effective VA                   = %16lx\n",
 	       frame->va);
-	printk("\tReason for D-stream\t\t= %16lx\n",
+	printk("  Reason for D-stream            = %16lx\n",
 	       frame->mm_stat);
-	printk("\tEV5 SCache address\t\t= %16lx\n",
+	printk("  EV5 SCache address             = %16lx\n",
 	       frame->sc_addr);
-	printk("\tEV5 SCache TAG/Data parity\t= %16lx\n",
+	printk("  EV5 SCache TAG/Data parity     = %16lx\n",
 	       frame->sc_stat);
-	printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n",
+	printk("  EV5 BC_TAG_ADDR                = %16lx\n",
 	       frame->bc_tag_addr);
-	printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n",
+	printk("  EV5 EI_ADDR: Phys addr of Xfer = %16lx\n",
 	       frame->ei_addr);
-	printk("\tFill Syndrome\t\t\t= %16lx\n",
+	printk("  Fill Syndrome                  = %16lx\n",
 	       frame->fill_syndrome);
-	printk("\tEI_STAT reg\t\t\t= %16lx\n",
+	printk("  EI_STAT reg                    = %16lx\n",
 	       frame->ei_stat);
-	printk("\tLD_LOCK\t\t\t\t= %16lx\n",
+	printk("  LD_LOCK                        = %16lx\n",
 	       frame->ld_lock);
 }
 
@@ -636,32 +664,53 @@
 {
 	struct el_common *mchk_header;
 	struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+#if 0
+halt();
+#endif
+	mb();
+	mb();  /* magic */
+#if 0
+	draina();
+#endif
 
 	mchk_header = (struct el_common *)la_ptr;
 	mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
 
-	mb();
-	mb();  /* magic */
-	draina();
-	if (MCPCIA_mcheck_expected[cpu])
+	cpu = smp_processor_id();
+
+	if (!MCPCIA_mcheck_probing_hose) {
+
+	    if (MCPCIA_mcheck_expected[cpu])
 		mcpcia_pci_clr_err(cpu, MCPCIA_mcheck_hose[cpu]);
-	else {
+	    else {
 		/* FIXME: how do we figure out which hose the error was on? */
 		mcpcia_pci_clr_err(cpu, 0);
 		mcpcia_pci_clr_err(cpu, 1);
+	    }
+
+	} else {
+		/* FIXME: clear out known always good hoses */
+		mcpcia_pci_clr_err(cpu, 0);
+		mcpcia_pci_clr_err(cpu, 1);
 	}
+
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "MCPCIA",
-			    DEBUG_MCHECK, MCPCIA_mcheck_expected[cpu]);
+	if (MCPCIA_mcheck_enable_print) {
+
+	    process_mcheck_info(vector, la_ptr, regs, "MCPCIA",
+				DEBUG_MCHECK, MCPCIA_mcheck_expected[cpu]);
 
-	if (vector != 0x620 && vector != 0x630
-	    && ! MCPCIA_mcheck_expected[cpu]) {
+	    if (vector != 0x620 && vector != 0x630
+		&& ! MCPCIA_mcheck_expected[cpu]) {
 		mcpcia_print_uncorrectable(mchk_logout);
+	    }
 	}
 
+#if 0
 	MCPCIA_mcheck_expected[cpu] = 0;
+#endif
 	MCPCIA_mcheck_taken[cpu] = 1;
 }

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