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
- Lines: 478
- Date:
2003-06-13 07:51:29.000000000 -0700
- Orig file:
linux-2.4.20/arch/alpha/kernel/sys_nautilus.c
- Orig date:
2001-05-21 13:40:39.000000000 -0700
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)