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
- Lines: 371
- Date:
Tue Jan 4 10:12:11 2000
- Orig file:
v2.2.13/linux/arch/alpha/kernel/core_mcpcia.c
- Orig date:
Tue Oct 19 17:10:36 1999
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)