Commit 0dbdce6f authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://are.twiddle.net/axp-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents c987cb10 0b1afd0f
......@@ -693,9 +693,13 @@ menu "Kernel hacking"
config ALPHA_LEGACY_START_ADDRESS
bool "Legacy kernel start address"
depends on ALPHA_GENERIC
default n
---help---
The 2.4 kernel changed the kernel start address from 0x310000
to 0x810000 to make room for the Wildfire's larger SRM console.
Recent consoles on Titan and Marvel machines also require the
extra room.
If you're using aboot 0.7 or later, the bootloader will examine the
ELF headers to determine where to transfer control. Unfortunately,
......@@ -704,7 +708,12 @@ config ALPHA_LEGACY_START_ADDRESS
hard lockup.
Say Y if you have a broken bootloader. Say N if you do not, or if
you wish to run on Wildfire.
you wish to run on Wildfire, Titan, or Marvel.
config ALPHA_LEGACY_START_ADDRESS
bool
depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
default y
config DEBUG_KERNEL
bool "Kernel debugging"
......
......@@ -108,7 +108,7 @@ all boot: $(boot)/vmlinux.gz
$(boot)/vmlinux.gz: vmlinux
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(boot) $@
bootimage bootpfile: vmlinux
bootimage bootpfile bootpzfile: vmlinux
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(boot) $(boot)/$@
......@@ -129,4 +129,5 @@ define archhelp
echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
echo ' bootimage - SRM bootable image (arch/alpha/boot/bootimage)'
echo ' bootpfile - BOOTP bootable image (arch/alpha/boot/bootpfile)'
echo ' bootpzfile - compressed kernel BOOTP image (arch/alpha/boot/bootpzfile)'
endef
......@@ -11,7 +11,7 @@
host-progs := tools/mkbb tools/objstrip
targets := vmlinux.gz vmlinux \
vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
bootloader bootpheader
tools/bootpzh bootloader bootpheader bootpzheader
OBJSTRIP := $(obj)/tools/objstrip
# SRM bootable image. Copy to offset 512 of a partition.
......@@ -27,6 +27,14 @@ ifdef INITRD
cat $(INITRD) >> $@
endif
# Compressed kernel BOOTP bootable image.
# Define INITRD during make to append initrd image.
$(obj)/bootpzfile: $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz
cat $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz > $@
ifdef INITRD
cat $(INITRD) >> $@
endif
# Compressed kernel image
$(obj)/vmlinux.gz: $(obj)/vmlinux FORCE
$(call if_changed,gzip)
......@@ -34,6 +42,7 @@ $(obj)/vmlinux.gz: $(obj)/vmlinux FORCE
$(obj)/main.o: $(obj)/ksize.h
$(obj)/bootp.o: $(obj)/ksize.h
$(obj)/bootpz.o: $(obj)/kzsize.h
$(obj)/ksize.h: $(obj)/vmlinux.nh FORCE
echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
......@@ -44,8 +53,19 @@ endif
cmp -s $@T $@ || mv -f $@T $@
rm -f $@T
$(obj)/kzsize.h: $(obj)/vmlinux.nh.gz FORCE
echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
echo "#define KERNEL_Z_SIZE `ls -l $(obj)/vmlinux.nh.gz | awk '{print $$5}'`" >> $@T
ifdef INITRD
[ -f $(INITRD) ] || exit 1
echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
endif
cmp -s $@T $@ || mv -f $@T $@
rm -f $@T
quiet_cmd_strip = STRIP $@
cmd_strip = $(STRIP) -o $@ $<
$(obj)/vmlinux: vmlinux FORCE
$(call if_changed,strip)
......@@ -56,10 +76,14 @@ OSFLAGS_vmlinux.nh := -v
OSFLAGS_lxboot := -p
OSFLAGS_bootlx := -vb
OSFLAGS_bootph := -vb
OSFLAGS_bootpzh := -vb
$(obj)/vmlinux.nh: vmlinux $(OBJSTRIP) FORCE
$(call if_changed,objstrip)
$(obj)/vmlinux.nh.gz: $(obj)/vmlinux.nh FORCE
$(call if_changed,gzip)
$(obj)/tools/lxboot: $(obj)/bootloader $(OBJSTRIP) FORCE
$(call if_changed,objstrip)
......@@ -69,14 +93,24 @@ $(obj)/tools/bootlx: $(obj)/bootloader $(OBJSTRIP) FORCE
$(obj)/tools/bootph: $(obj)/bootpheader $(OBJSTRIP) FORCE
$(call if_changed,objstrip)
LDFLAGS_bootloader := -static -uvsprintf -T #-N -relax
LDFLAGS_bootpheader := -static -uvsprintf -T #-N -relax
$(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE
$(call if_changed,objstrip)
LDFLAGS_bootloader := -static -uvsprintf -T #-N -relax
LDFLAGS_bootpheader := -static -uvsprintf -T #-N -relax
LDFLAGS_bootpzheader := -static -uvsprintf -T #-N -relax
OBJ_bootlx := $(obj)/head.o $(obj)/main.o
OBJ_bootph := $(obj)/head.o $(obj)/bootp.o
OBJ_bootpzh := $(obj)/head.o $(obj)/bootpz.o $(obj)/misc.o
$(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) FORCE
$(call if_changed,ld)
$(obj)/bootpheader: $(obj)/bootloader.lds $(OBJ_bootph) $(LIBS_Y) FORCE
$(call if_changed,ld)
$(obj)/bootpzheader: $(obj)/bootloader.lds $(OBJ_bootpzh) $(LIBS_Y) FORCE
$(call if_changed,ld)
$(obj)/misc.o: lib/inflate.c
/*
* arch/alpha/boot/bootpz.c
*
* Copyright (C) 1997 Jay Estabrook
*
* This file is used for creating a compressed BOOTP file for the
* Linux/AXP kernel
*
* based significantly on the arch/alpha/boot/main.c of Linus Torvalds
* and the decompression code from MILO.
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/version.h>
#include <linux/mm.h>
#include <asm/system.h>
#include <asm/console.h>
#include <asm/hwrpb.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <stdarg.h>
#include "kzsize.h"
/* FIXME FIXME FIXME */
#define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */
/* FIXME FIXME FIXME */
#undef DEBUG_CHECK_RANGE
#define DEBUG_ADDRESSES
#define DEBUG_SP(x) \
{register long sp asm("30"); srm_printk("%s (sp=%lx)\n", x, sp);}
extern unsigned long switch_to_osf_pal(unsigned long nr,
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
unsigned long *vptb);
extern int decompress_kernel(void* destination, void *source,
size_t ksize, size_t kzsize);
struct hwrpb_struct *hwrpb = INIT_HWRPB;
static struct pcb_struct pcb_va[1];
/*
* Find a physical address of a virtual object..
*
* This is easy using the virtual page table address.
*/
#define VPTB ((unsigned long *) 0x200000000)
static inline unsigned long
find_pa(unsigned long address)
{
unsigned long result;
result = VPTB[address >> 13];
result >>= 32;
result <<= 13;
result |= address & 0x1fff;
return result;
}
int
check_range(unsigned long vstart, unsigned long vend,
unsigned long kstart, unsigned long kend)
{
unsigned long vaddr, kaddr;
#ifdef DEBUG_CHECK_RANGE
srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
vstart, vend, kstart, kend);
#endif
/* do some range checking for detecting an overlap... */
for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
{
kaddr = (find_pa(vaddr) | PAGE_OFFSET);
if (kaddr >= kstart && kaddr <= kend)
{
#ifdef DEBUG_CHECK_RANGE
srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
" [0x%lx:0x%lx]\n",
vaddr, kaddr, kstart, kend);
#endif
return 1;
}
}
return 0;
}
/*
* This function moves into OSF/1 pal-code, and has a temporary
* PCB for that. The kernel proper should replace this PCB with
* the real one as soon as possible.
*
* The page table muckery in here depends on the fact that the boot
* code has the L1 page table identity-map itself in the second PTE
* in the L1 page table. Thus the L1-page is virtually addressable
* itself (through three levels) at virtual address 0x200802000.
*/
#define L1 ((unsigned long *) 0x200802000)
void
pal_init(void)
{
unsigned long i, rev;
struct percpu_struct * percpu;
struct pcb_struct * pcb_pa;
/* Create the dummy PCB. */
pcb_va->ksp = 0;
pcb_va->usp = 0;
pcb_va->ptbr = L1[1] >> 32;
pcb_va->asn = 0;
pcb_va->pcc = 0;
pcb_va->unique = 0;
pcb_va->flags = 1;
pcb_va->res1 = 0;
pcb_va->res2 = 0;
pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
/*
* a0 = 2 (OSF)
* a1 = return address, but we give the asm the vaddr of the PCB
* a2 = physical addr of PCB
* a3 = new virtual page table pointer
* a4 = KSP (but the asm sets it)
*/
srm_printk("Switching to OSF PAL-code... ");
i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
if (i) {
srm_printk("failed, code %ld\n", i);
__halt();
}
percpu = (struct percpu_struct *)
(INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
rev = percpu->pal_revision = percpu->palcode_avail[2];
srm_printk("OK (rev %lx)\n", rev);
tbia(); /* do it directly in case we are SMP */
}
/*
* Start the kernel.
*/
static inline void
runkernel(void)
{
__asm__ __volatile__(
"bis %1,%1,$30\n\t"
"bis %0,%0,$27\n\t"
"jmp ($27)"
: /* no outputs: it doesn't even return */
: "r" (START_ADDR),
"r" (PAGE_SIZE + INIT_STACK));
}
/* Must record the SP (it is virtual) on entry, so we can make sure
not to overwrite it during movement or decompression. */
unsigned long SP_on_entry;
/* Calculate the kernel image address based on the end of the BOOTP
bootstrapper (ie this program).
*/
extern char _end;
#define KERNEL_ORIGIN \
((((unsigned long)&_end) + 511) & ~511)
/* Round address to next higher page boundary. */
#define NEXT_PAGE(a) (((a) | (PAGE_SIZE - 1)) + 1)
#ifdef INITRD_IMAGE_SIZE
# define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
#else
# define REAL_INITRD_SIZE 0
#endif
/* Defines from include/asm-alpha/system.h
BOOT_ADDR Virtual address at which the consoles loads
the BOOTP image.
KERNEL_START KSEG address at which the kernel is built to run,
which includes some initial data pages before the
code.
START_ADDR KSEG address of the entry point of kernel code.
ZERO_PGE KSEG address of page full of zeroes, but
upon entry to kerne cvan be expected
to hold the parameter list and possible
INTRD information.
These are used in the local defines below.
*/
/* Virtual addresses for the BOOTP image. Note that this includes the
bootstrapper code as well as the compressed kernel image, and
possibly the INITRD image.
Oh, and do NOT forget the STACK, which appears to be placed virtually
beyond the end of the loaded image.
*/
#define V_BOOT_IMAGE_START BOOT_ADDR
#define V_BOOT_IMAGE_END SP_on_entry
/* Virtual addresses for just the bootstrapper part of the BOOTP image. */
#define V_BOOTSTRAPPER_START BOOT_ADDR
#define V_BOOTSTRAPPER_END KERNEL_ORIGIN
/* Virtual addresses for just the data part of the BOOTP
image. This may also include the INITRD image, but always
includes the STACK.
*/
#define V_DATA_START KERNEL_ORIGIN
#define V_INITRD_START (KERNEL_ORIGIN + KERNEL_Z_SIZE)
#define V_INTRD_END (V_INITRD_START + REAL_INITRD_SIZE)
#define V_DATA_END V_BOOT_IMAGE_END
/* KSEG addresses for the uncompressed kernel.
Note that the end address includes workspace for the decompression.
Note also that the DATA_START address is ZERO_PGE, to which we write
just before jumping to the kernel image at START_ADDR.
*/
#define K_KERNEL_DATA_START ZERO_PGE
#define K_KERNEL_IMAGE_START START_ADDR
#define K_KERNEL_IMAGE_END (START_ADDR + KERNEL_SIZE)
/* Define to where we may have to decompress the kernel image, before
we move it to the final position, in case of overlap. This will be
above the final position of the kernel.
Regardless of overlap, we move the INITRD image to the end of this
copy area, because there needs to be a buffer area after the kernel
for "bootmem" anyway.
*/
#define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END)
#define K_INITRD_START NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE)
#define K_COPY_IMAGE_END \
(K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
#define K_COPY_IMAGE_SIZE \
NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
void
start_kernel(void)
{
int must_move = 0;
/* Initialize these for the decompression-in-place situation,
which is the smallest amount of work and most likely to
occur when using the normal START_ADDR of the kernel
(currently set to 16MB, to clear all console code.
*/
unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
unsigned long initrd_image_start = K_INITRD_START;
/*
* Note that this crufty stuff with static and envval
* and envbuf is because:
*
* 1. Frequently, the stack is short, and we don't want to overrun;
* 2. Frequently the stack is where we are going to copy the kernel to;
* 3. A certain SRM console required the GET_ENV output to stack.
* ??? A comment in the aboot sources indicates that the GET_ENV
* destination must be quadword aligned. Might this explain the
* behaviour, rather than requiring output to the stack, which
* seems rather far-fetched.
*/
static long nbytes;
static char envval[256] __attribute__((aligned(8)));
register unsigned long asm_sp asm("30");
SP_on_entry = asm_sp;
srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
/* Validity check the HWRPB. */
if (INIT_HWRPB->pagesize != 8192) {
srm_printk("Expected 8kB pages, got %ldkB\n",
INIT_HWRPB->pagesize >> 10);
return;
}
if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
srm_printk("Expected vptb at %p, got %p\n",
VPTB, (void *)INIT_HWRPB->vptb);
return;
}
/* PALcode (re)initialization. */
pal_init();
/* Get the parameter list from the console environment variable. */
nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
if (nbytes < 0 || nbytes >= sizeof(envval)) {
nbytes = 0;
}
envval[nbytes] = '\0';
#ifdef DEBUG_ADDRESSES
srm_printk("START_ADDR 0x%lx\n", START_ADDR);
srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
#endif
/* Since all the SRM consoles load the BOOTP image at virtual
* 0x20000000, we have to ensure that the physical memory
* pages occupied by that image do NOT overlap the physical
* address range where the kernel wants to be run. This
* causes real problems when attempting to cdecompress the
* former into the latter... :-(
*
* So, we may have to decompress/move the kernel/INITRD image
* virtual-to-physical someplace else first before moving
* kernel /INITRD to their final resting places... ;-}
*
* Sigh...
*/
/* First, check to see if the range of addresses occupied by
the bootstrapper part of the BOOTP image include any of the
physical pages into which the kernel will be placed for
execution.
We only need check on the final kernel image range, since we
will put the INITRD someplace that we can be sure is not
in conflict.
*/
if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
{
srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
__halt();
}
/* Next, check to see if the range of addresses occupied by
the compressed kernel/INITRD/stack portion of the BOOTP
image include any of the physical pages into which the
decompressed kernel or the INITRD will be placed for
execution.
*/
if (check_range(V_DATA_START, V_DATA_END,
K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
{
#ifdef DEBUG_ADDRESSES
srm_printk("OVERLAP: cannot decompress in place\n");
#endif
uncompressed_image_start = K_COPY_IMAGE_START;
uncompressed_image_end = K_COPY_IMAGE_END;
must_move = 1;
/* Finally, check to see if the range of addresses
occupied by the compressed kernel/INITRD part of
the BOOTP image include any of the physical pages
into which that part is to be copied for
decompression.
*/
while (check_range(V_DATA_START, V_DATA_END,
uncompressed_image_start,
uncompressed_image_end))
{
#if 0
uncompressed_image_start += K_COPY_IMAGE_SIZE;
uncompressed_image_end += K_COPY_IMAGE_SIZE;
initrd_image_start += K_COPY_IMAGE_SIZE;
#else
/* Keep as close as possible to end of BOOTP image. */
uncompressed_image_start += PAGE_SIZE;
uncompressed_image_end += PAGE_SIZE;
initrd_image_start += PAGE_SIZE;
#endif
}
}
srm_printk("Starting to load the kernel with args '%s'\n", envval);
#ifdef DEBUG_ADDRESSES
srm_printk("Decompressing the kernel...\n"
"...from 0x%lx to 0x%lx size 0x%x\n",
V_DATA_START,
uncompressed_image_start,
KERNEL_SIZE);
#endif
decompress_kernel((void *)uncompressed_image_start,
(void *)V_DATA_START,
KERNEL_SIZE, KERNEL_Z_SIZE);
/*
* Now, move things to their final positions, if/as required.
*/
#ifdef INITRD_IMAGE_SIZE
/* First, we always move the INITRD image, if present. */
#ifdef DEBUG_ADDRESSES
srm_printk("Moving the INITRD image...\n"
" from 0x%lx to 0x%lx size 0x%x\n",
V_INITRD_START,
initrd_image_start,
INITRD_IMAGE_SIZE);
#endif
memcpy((void *)initrd_image_start,
(void *)V_INITRD_START,
INITRD_IMAGE_SIZE);
#endif /* INITRD_IMAGE_SIZE */
/* Next, we may have to move the uncompressed kernel to the
final destination.
*/
if (must_move) {
#ifdef DEBUG_ADDRESSES
srm_printk("Moving the uncompressed kernel...\n"
"...from 0x%lx to 0x%lx size 0x%x\n",
uncompressed_image_start,
K_KERNEL_IMAGE_START,
(unsigned)KERNEL_SIZE);
#endif
memcpy((void *)K_KERNEL_IMAGE_START,
(void *)uncompressed_image_start,
KERNEL_SIZE);
}
/* Clear the zero page, then move the argument list in. */
memset((char*)ZERO_PGE, 0, PAGE_SIZE);
strcpy((char*)ZERO_PGE, envval);
#ifdef INITRD_IMAGE_SIZE
/* Finally, set the INITRD paramenters for the kernel. */
((long *)(ZERO_PGE+256))[0] = initrd_image_start;
((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
#endif /* INITRD_IMAGE_SIZE */
runkernel();
}
/*
* misc.c
*
* This is a collection of several routines from gzip-1.0.3
* adapted for Linux.
*
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
*
* Modified for ARM Linux by Russell King
*
* Nicolas Pitre <nico@visuaide.com> 1999/04/14 :
* For this code to run directly from Flash, all constant variables must
* be marked with 'const' and all other variables initialized at run-time
* only. This way all non constant variables will end up in the bss segment,
* which should point to addresses in RAM and cleared to 0 on start.
* This allows for a much quicker boot time.
*
* Modified for Alpha, from the ARM version, by Jay Estabrook 2003.
*/
#include <linux/kernel.h>
#include <asm/uaccess.h>
#define memzero(s,n) memset ((s),0,(n))
#define puts srm_printk
extern long srm_printk(const char *, ...)
__attribute__ ((format (printf, 1, 2)));;
/*
* gzip delarations
*/
#define OF(args) args
#define STATIC static
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#define WSIZE 0x8000 /* Window size must be at least 32k, */
/* and a power of two */
static uch *inbuf; /* input buffer */
static uch *window; /* Sliding window buffer */
static unsigned insize; /* valid bytes in inbuf */
static unsigned inptr; /* index of next byte to be processed in inbuf */
static unsigned outcnt; /* bytes in output buffer */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
/* Diagnostic functions */
#ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) error(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
static int fill_inbuf(void);
static void flush_window(void);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
static char *input_data;
static int input_data_size;
static uch *output_data;
static ulg output_ptr;
static ulg bytes_out;
static void *malloc(int size);
static void free(void *where);
static void error(char *m);
static void gzip_mark(void **);
static void gzip_release(void **);
extern int end;
static ulg free_mem_ptr;
static ulg free_mem_ptr_end;
#define HEAP_SIZE 0x2000
#include "../../../lib/inflate.c"
static void *malloc(int size)
{
void *p;
if (size <0) error("Malloc error\n");
if (free_mem_ptr <= 0) error("Memory error\n");
free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
p = (void *)free_mem_ptr;
free_mem_ptr += size;
if (free_mem_ptr >= free_mem_ptr_end)
error("Out of memory");
return p;
}
static void free(void *where)
{ /* gzip_mark & gzip_release do the free */
}
static void gzip_mark(void **ptr)
{
*ptr = (void *) free_mem_ptr;
}
static void gzip_release(void **ptr)
{
free_mem_ptr = (long) *ptr;
}
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
*/
int fill_inbuf(void)
{
if (insize != 0)
error("ran out of input data\n");
inbuf = input_data;
insize = input_data_size;
inptr = 1;
return inbuf[0];
}
/* ===========================================================================
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
void flush_window(void)
{
ulg c = crc;
unsigned n;
uch *in, *out, ch;
in = window;
out = &output_data[output_ptr];
for (n = 0; n < outcnt; n++) {
ch = *out++ = *in++;
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
}
crc = c;
bytes_out += (ulg)outcnt;
output_ptr += (ulg)outcnt;
outcnt = 0;
/* puts("."); */
}
static void error(char *x)
{
puts("\n\n");
puts(x);
puts("\n\n -- System halted");
while(1); /* Halt */
}
unsigned int
decompress_kernel(void *output_start,
void *input_start,
size_t ksize,
size_t kzsize)
{
output_data = (uch *)output_start;
input_data = (uch *)input_start;
input_data_size = kzsize; /* use compressed size */
/* FIXME FIXME FIXME */
free_mem_ptr = (ulg)output_start + ksize;
free_mem_ptr_end = (ulg)output_start + ksize + 0x200000;
/* FIXME FIXME FIXME */
/* put in temp area to reduce initial footprint */
window = malloc(WSIZE);
makecrc();
/* puts("Uncompressing Linux..."); */
gunzip();
/* puts(" done, booting the kernel.\n"); */
return output_ptr;
}
......@@ -27,7 +27,6 @@
#include <linux/param.h>
#include <linux/string.h>
#ifdef __ELF__
# include <asm/elf.h>
# include <linux/elf.h>
#endif
......
......@@ -19,20 +19,23 @@ obj-$(CONFIG_MODULES) += module.o
ifdef CONFIG_ALPHA_GENERIC
obj-y += core_apecs.o core_cia.o core_irongate.o core_lca.o \
core_marvel.o core_mcpcia.o core_polaris.o core_t2.o \
core_tsunami.o core_titan.o core_wildfire.o
core_mcpcia.o core_polaris.o core_t2.o \
core_tsunami.o
obj-y += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
sys_jensen.o sys_marvel.o sys_miata.o sys_mikasa.o sys_nautilus.o \
sys_titan.o sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_wildfire.o
sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
sys_sable.o sys_sio.o sys_sx164.o sys_takara.o
obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
obj-y += err_titan.o err_marvel.o
ifndef CONFIG_ALPHA_LEGACY_START_ADDRESS
obj-y += core_marvel.o core_titan.o core_wildfire.o
obj-y += sys_marvel.o sys_titan.o sys_wildfire.o
obj-y += err_ev7.o err_titan.o err_marvel.o
endif
obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
obj-y += err_ev6.o
obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
obj-y += srmcons.o
else
......@@ -67,13 +70,12 @@ obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
smc37c93x.o
obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o \
err_titan.o
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o
obj-$(CONFIG_ALPHA_EB64P) += sys_eb64p.o irq_i8259.o
obj-$(CONFIG_ALPHA_EB66) += sys_eb64p.o irq_i8259.o
obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o irq_i8259.o
obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o irq_i8259.o
obj-$(CONFIG_ALPHA_MARVEL) += sys_marvel.o err_marvel.o
obj-$(CONFIG_ALPHA_MARVEL) += sys_marvel.o
obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o irq_pyxis.o irq_i8259.o \
es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o irq_i8259.o irq_srm.o
......@@ -94,4 +96,9 @@ obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o irq_pyxis.o irq_i8259.o \
obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o ns87312.o
obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o irq_i8259.o
# Error support
obj-$(CONFIG_ALPHA_MARVEL) += err_ev7.o err_marvel.o
obj-$(CONFIG_ALPHA_NAUTILUS) += err_ev6.o
obj-$(CONFIG_ALPHA_TITAN) += err_ev6.o err_titan.o
endif # GENERIC
......@@ -524,7 +524,7 @@ mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where)
if (!io7_port->enabled)
return addr;
if (hose->first_busno == bus) {
if (hose->bus == pbus) {
/* Don't support idsel > 20 on primary bus. */
if (devfn >= PCI_DEVFN(21, 0))
return addr;
......
......@@ -185,7 +185,7 @@ mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where,
/* Type 1 configuration cycle for *ALL* busses. */
*type1 = 1;
if (bus == hose->first_busno)
if (hose->bus == pbus)
bus = 0;
addr = (bus << 16) | (devfn << 8) | (where);
addr <<= 5; /* swizzle for SPARSE */
......
......@@ -123,7 +123,7 @@ mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
"pci_addr=0x%p, type1=0x%p)\n",
bus, device_fn, where, pci_addr, type1));
if (hose->first_busno == bus)
if (hose->bus == pbus)
bus = 0;
*type1 = (bus != 0);
......
......@@ -101,7 +101,7 @@ mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
"pci_addr=0x%p, type1=0x%p)\n",
bus, device_fn, where, pci_addr, type1));
if (hose->first_busno == bus)
if (hose->bus == pbus)
bus = 0;
*type1 = (bus != 0);
......
......@@ -367,7 +367,7 @@ mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
"pci_addr=0x%p, type1=0x%p)\n",
bus, device_fn, where, pci_addr, type1));
if (hose->first_busno == bus)
if (hose->bus == pbus)
bus = 0;
*type1 = (bus != 0);
......
......@@ -13,6 +13,7 @@
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include <asm/err_common.h>
#include "err_impl.h"
#include "proto.h"
......@@ -23,12 +24,6 @@
*/
char *err_print_prefix = KERN_NOTICE;
/*
* Forward references
*/
static void el_print_timestamp(union el_timestamp);
static void el_process_subpackets(struct el_subpacket *, int);
/*
* Generic
......@@ -82,452 +77,6 @@ mchk_dump_logout_frame(struct el_common *mchk_header)
printk("%s -- End of Frame --\n", err_print_prefix);
}
/*
* EV7 generic
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV7)
void
ev7_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
/*
* Sync the processor
*/
mb();
draina();
/*
* Parse the logout frame without printing first. If the only error(s)
* found are have a disposition of "dismiss", then just dismiss them
* and don't print any message
*/
printk("%sEV7 MACHINE CHECK vector %lx\n", err_print_prefix, vector);
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
struct ev7_pal_subpacket {
union {
struct {
u32 mchk_code;
u32 subpacket_count;
u64 whami;
u64 rbox_whami;
u64 rbox_int;
u64 exc_addr;
union el_timestamp timestamp;
u64 halt_code;
u64 reserved;
} logout;
} by_type;
};
static char *el_ev7_processor_subpacket_annotation[] = {
"Subpacket Header", "I_STAT", "DC_STAT",
"C_ADDR", "C_SYNDROME_1", "C_SYNDROME_0",
"C_STAT", "C_STS", "MM_STAT",
"EXC_ADDR", "IER_CM", "ISUM",
"PAL_BASE", "I_CTL", "PROCESS_CONTEXT",
"CBOX_CTL", "CBOX_STP_CTL", "CBOX_ACC_CTL",
"CBOX_LCL_SET", "CBOX_GLB_SET", "BBOX_CTL",
"BBOX_ERR_STS", "BBOX_ERR_IDX", "CBOX_DDP_ERR_STS",
"BBOX_DAT_RMP", NULL
};
static char *el_ev7_zbox_subpacket_annotation[] = {
"Subpacket Header",
"ZBOX(0): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
"ZBOX(0): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
"ZBOX(0): DIFT_TIMEOUT / DRAM_ERR_ADR",
"ZBOX(0): FRC_ERR_ADR / DRAM_MAPPER_CTL",
"ZBOX(0): reserved / DIFT_ERR_STATUS",
"ZBOX(1): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
"ZBOX(1): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
"ZBOX(1): DIFT_TIMEOUT / DRAM_ERR_ADR",
"ZBOX(1): FRC_ERR_ADR / DRAM_MAPPER_CTL",
"ZBOX(1): reserved / DIFT_ERR_STATUS",
"CBOX_CTL", "CBOX_STP_CTL",
"ZBOX(0)_ERROR_PA", "ZBOX(1)_ERROR_PA",
"ZBOX(0)_ORED_SYNDROME","ZBOX(1)_ORED_SYNDROME",
NULL
};
static char *el_ev7_rbox_subpacket_annotation[] = {
"Subpacket Header", "RBOX_CFG", "RBOX_N_CFG",
"RBOX_S_CFG", "RBOX_E_CFG", "RBOX_W_CFG",
"RBOX_N_ERR", "RBOX_S_ERR", "RBOX_E_ERR",
"RBOX_W_ERR", "RBOX_IO_CFG", "RBOX_IO_ERR",
"RBOX_L_ERR", "RBOX_WHOAMI", "RBOX_IMASL",
"RBOX_INTQ", "RBOX_INT", NULL
};
static char *el_ev7_io_subpacket_annotation[] = {
"Subpacket Header", "IO_ASIC_REV", "IO_SYS_REV",
"IO7_UPH", "HPI_CTL", "CRD_CTL",
"HEI_CTL", "PO7_ERROR_SUM","PO7_UNCRR_SYM",
"PO7_CRRCT_SYM", "PO7_UGBGE_SYM","PO7_ERR_PKT0",
"PO7_ERR_PKT1", "reserved", "reserved",
"PO0_ERR_SUM", "PO0_TLB_ERR", "PO0_SPL_COMPLT",
"PO0_TRANS_SUM", "PO0_FIRST_ERR","PO0_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO1_ERR_SUM", "PO1_TLB_ERR", "PO1_SPL_COMPLT",
"PO1_TRANS_SUM", "PO1_FIRST_ERR","PO1_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO2_ERR_SUM", "PO2_TLB_ERR", "PO2_SPL_COMPLT",
"PO2_TRANS_SUM", "PO2_FIRST_ERR","PO2_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO3_ERR_SUM", "PO3_TLB_ERR", "PO3_SPL_COMPLT",
"PO3_TRANS_SUM", "PO3_FIRST_ERR","PO3_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
NULL
};
static struct el_subpacket_annotation el_ev7_pal_annotations[] = {
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_PROCESSOR,
1,
"EV7 Processor Subpacket",
el_ev7_processor_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_ZBOX,
1,
"EV7 ZBOX Subpacket",
el_ev7_zbox_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_RBOX,
1,
"EV7 RBOX Subpacket",
el_ev7_rbox_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_IO,
1,
"EV7 IO Subpacket",
el_ev7_io_subpacket_annotation)
};
static struct el_subpacket *
ev7_process_pal_subpacket(struct el_subpacket *header)
{
struct ev7_pal_subpacket *packet;
if (header->class != EL_CLASS__PAL) {
printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
err_print_prefix,
header->class, header->type);
return NULL;
}
packet = (struct ev7_pal_subpacket *)header->by_type.raw.data_start;
switch(header->type) {
case EL_TYPE__PAL__LOGOUT_FRAME:
printk("%s*** MCHK occurred on LPID %ld (RBOX %lx)\n",
err_print_prefix,
packet->by_type.logout.whami,
packet->by_type.logout.rbox_whami);
el_print_timestamp(packet->by_type.logout.timestamp);
printk("%s EXC_ADDR: %016lx\n"
" HALT_CODE: %lx\n",
err_print_prefix,
packet->by_type.logout.exc_addr,
packet->by_type.logout.halt_code);
el_process_subpackets(header,
packet->by_type.logout.subpacket_count);
break;
default:
printk("%s ** PAL TYPE %d SUBPACKET\n",
err_print_prefix,
header->type);
el_annotate_subpacket(header);
break;
}
return (struct el_subpacket *)((unsigned long)header + header->length);
}
struct el_subpacket_handler ev7_pal_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
void
ev7_register_error_handlers(void)
{
int i;
for(i = 0;
i<sizeof(el_ev7_pal_annotations)/sizeof(el_ev7_pal_annotations[1]);
i++) {
cdl_register_subpacket_annotation(&el_ev7_pal_annotations[i]);
}
cdl_register_subpacket_handler(&ev7_pal_subpacket_handler);
}
#endif /* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_EV7 */
/*
* EV6 generic
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6)
static int
ev6_parse_ibox(u64 i_stat, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#define EV6__I_STAT__PAR (1UL << 29)
#define EV6__I_STAT__ERRMASK (EV6__I_STAT__PAR)
if (!(i_stat & EV6__I_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
if (i_stat & EV6__I_STAT__PAR)
printk("%s Icache parity error\n", err_print_prefix);
return status;
}
static int
ev6_parse_mbox(u64 mm_stat, u64 d_stat, u64 c_stat, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#define EV6__MM_STAT__DC_TAG_PERR (1UL << 10)
#define EV6__MM_STAT__ERRMASK (EV6__MM_STAT__DC_TAG_PERR)
#define EV6__D_STAT__TPERR_P0 (1UL << 0)
#define EV6__D_STAT__TPERR_P1 (1UL << 1)
#define EV6__D_STAT__ECC_ERR_ST (1UL << 2)
#define EV6__D_STAT__ECC_ERR_LD (1UL << 3)
#define EV6__D_STAT__SEO (1UL << 4)
#define EV6__D_STAT__ERRMASK (EV6__D_STAT__TPERR_P0 | \
EV6__D_STAT__TPERR_P1 | \
EV6__D_STAT__ECC_ERR_ST | \
EV6__D_STAT__ECC_ERR_LD | \
EV6__D_STAT__SEO)
if (!(d_stat & EV6__D_STAT__ERRMASK) &&
!(mm_stat & EV6__MM_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
if (mm_stat & EV6__MM_STAT__DC_TAG_PERR)
printk("%s Dcache tag parity error on probe\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__TPERR_P0)
printk("%s Dcache tag parity error - pipe 0\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__TPERR_P1)
printk("%s Dcache tag parity error - pipe 1\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__ECC_ERR_ST)
printk("%s ECC error occurred on a store\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__ECC_ERR_LD)
printk("%s ECC error occurred on a %s load\n",
err_print_prefix,
c_stat ? "" : "speculative ");
if (d_stat & EV6__D_STAT__SEO)
printk("%s Dcache second error\n", err_print_prefix);
return status;
}
static int
ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn,
u64 c_stat, u64 c_sts, int print)
{
char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN",
"MEMORY", "BCACHE", "DCACHE",
"BCACHE PROBE", "BCACHE PROBE" };
char *streamname[] = { "D", "I" };
char *bitsname[] = { "SINGLE", "DOUBLE" };
int status = MCHK_DISPOSITION_REPORT;
int source = -1, stream = -1, bits = -1;
#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) /* both 6 and 7 indicate... */
#define EV6__C_STAT__PROBE_BC_ERR1 (0x07) /* ...probe bc error. */
#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)
#define EV6__C_STAT__SOURCE_MEMORY (0x03)
#define EV6__C_STAT__SOURCE_BCACHE (0x04)
#define EV6__C_STAT__SOURCE__S (0)
#define EV6__C_STAT__SOURCE__M (0x07)
#define EV6__C_STAT__ISTREAM__S (3)
#define EV6__C_STAT__ISTREAM__M (0x01)
#define EV6__C_STAT__DOUBLE__S (4)
#define EV6__C_STAT__DOUBLE__M (0x01)
#define EV6__C_STAT__ERRMASK (0x1F)
#define EV6__C_STS__SHARED (1 << 0)
#define EV6__C_STS__DIRTY (1 << 1)
#define EV6__C_STS__VALID (1 << 2)
#define EV6__C_STS__PARITY (1 << 3)
if (!(c_stat & EV6__C_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
source = EXTRACT(c_stat, EV6__C_STAT__SOURCE);
stream = EXTRACT(c_stat, EV6__C_STAT__ISTREAM);
bits = EXTRACT(c_stat, EV6__C_STAT__DOUBLE);
if (c_stat & EV6__C_STAT__BC_PERR) {
printk("%s Bcache tag parity error\n", err_print_prefix);
source = -1;
}
if (c_stat & EV6__C_STAT__DC_PERR) {
printk("%s Dcache tag parity error\n", err_print_prefix);
source = -1;
}
if (c_stat == EV6__C_STAT__PROBE_BC_ERR0 ||
c_stat == EV6__C_STAT__PROBE_BC_ERR1) {
printk("%s Bcache single-bit error on a probe hit\n",
err_print_prefix);
source = -1;
}
if (source != -1)
printk("%s %s-STREAM %s-BIT ECC error from %s\n",
err_print_prefix,
streamname[stream], bitsname[bits], sourcename[source]);
printk("%s Address: 0x%016lx\n"
" Syndrome[upper.lower]: %02lx.%02lx\n",
err_print_prefix,
c_addr,
c2_syn, c1_syn);
if (source == EV6__C_STAT__SOURCE_MEMORY ||
source == EV6__C_STAT__SOURCE_BCACHE)
printk("%s Block status: %s%s%s%s\n",
err_print_prefix,
(c_sts & EV6__C_STS__SHARED) ? "SHARED " : "",
(c_sts & EV6__C_STS__DIRTY) ? "DIRTY " : "",
(c_sts & EV6__C_STS__VALID) ? "VALID " : "",
(c_sts & EV6__C_STS__PARITY) ? "PARITY " : "");
return status;
}
int
ev6_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_common_EV6_mcheck *ev6mchk =
(struct el_common_EV6_mcheck *)mchk_header;
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= ev6_parse_ibox(ev6mchk->I_STAT, print);
status |= ev6_parse_mbox(ev6mchk->MM_STAT, ev6mchk->DC_STAT,
ev6mchk->C_STAT, print);
status |= ev6_parse_cbox(ev6mchk->C_ADDR, ev6mchk->DC1_SYNDROME,
ev6mchk->DC0_SYNDROME, ev6mchk->C_STAT,
ev6mchk->C_STS, print);
if (!print)
return status;
if (status != MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
/*
* Dump some additional information from the frame
*/
printk("%s EXC_ADDR: 0x%016lx IER_CM: 0x%016lx"
" ISUM: 0x%016lx\n"
" PAL_BASE: 0x%016lx I_CTL: 0x%016lx"
" PCTX: 0x%016lx\n",
err_print_prefix,
ev6mchk->EXC_ADDR, ev6mchk->IER_CM, ev6mchk->ISUM,
ev6mchk->PAL_BASE, ev6mchk->I_CTL, ev6mchk->PCTX);
if (status == MCHK_DISPOSITION_UNKNOWN_ERROR) {
printk("%s UNKNOWN error, frame follows:\n",
err_print_prefix);
} else {
/* had decode -- downgrade print level for frame */
err_print_prefix = KERN_NOTICE;
}
mchk_dump_logout_frame(mchk_header);
err_print_prefix = saved_err_prefix;
}
return status;
}
void
ev6_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
/*
* Sync the processor
*/
mb();
draina();
/*
* Parse the logout frame without printing first. If the only error(s)
* found are have a disposition of "dismiss", then just dismiss them
* and don't print any message
*/
if (ev6_process_logout_frame(mchk_header, 0) !=
MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
err_print_prefix = KERN_CRIT;
/*
* Either a nondismissable error was detected or no
* recognized error was detected in the logout frame
* -- report the error in either case
*/
printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(vector == SCB_Q_PROCERR)?"Correctable":"Uncorrectable",
(unsigned int)vector, (int)smp_processor_id());
ev6_process_logout_frame(mchk_header, 1);
dik_show_regs(regs, NULL);
err_print_prefix = saved_err_prefix;
}
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
#endif /* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_EV6 */
/*
* Console Data Log
......@@ -536,17 +85,6 @@ ev6_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
static struct el_subpacket_handler *subpacket_handler_list = NULL;
static struct el_subpacket_annotation *subpacket_annotation_list = NULL;
static void
el_print_timestamp(union el_timestamp timestamp)
{
if (timestamp.as_int)
printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
err_print_prefix,
timestamp.b.month, timestamp.b.day,
timestamp.b.year, timestamp.b.hour,
timestamp.b.minute, timestamp.b.second);
}
static struct el_subpacket *
el_process_header_subpacket(struct el_subpacket *header)
{
......@@ -602,7 +140,7 @@ el_process_header_subpacket(struct el_subpacket *header)
err_print_prefix,
name,
header->class, header->type);
el_print_timestamp(timestamp);
el_print_timestamp(&timestamp);
/*
* Process the subpackets
......@@ -615,7 +153,30 @@ el_process_header_subpacket(struct el_subpacket *header)
return header;
}
static void
static struct el_subpacket *
el_process_subpacket_reg(struct el_subpacket *header)
{
struct el_subpacket *next = NULL;
struct el_subpacket_handler *h = subpacket_handler_list;
for (; h && h->class != header->class; h = h->next);
if (h) next = h->handler(header);
return next;
}
void
el_print_timestamp(union el_timestamp *timestamp)
{
if (timestamp->as_int)
printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
err_print_prefix,
timestamp->b.month, timestamp->b.day,
timestamp->b.year, timestamp->b.hour,
timestamp->b.minute, timestamp->b.second);
}
void
el_process_subpackets(struct el_subpacket *header, int packet_count)
{
struct el_subpacket *subpacket;
......@@ -630,18 +191,6 @@ el_process_subpackets(struct el_subpacket *header, int packet_count)
}
}
static struct el_subpacket *
el_process_subpacket_reg(struct el_subpacket *header)
{
struct el_subpacket *next = NULL;
struct el_subpacket_handler *h = subpacket_handler_list;
for (; h && h->class != header->class; h = h->next);
if (h) next = h->handler(header);
return next;
}
struct el_subpacket *
el_process_subpacket(struct el_subpacket *header)
{
......
/*
* linux/arch/alpha/kernel/err_ev6.c
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Error handling code supporting Alpha systems
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include <asm/err_common.h>
#include <asm/err_ev6.h>
#include "err_impl.h"
#include "proto.h"
static int
ev6_parse_ibox(u64 i_stat, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#define EV6__I_STAT__PAR (1UL << 29)
#define EV6__I_STAT__ERRMASK (EV6__I_STAT__PAR)
if (!(i_stat & EV6__I_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
if (i_stat & EV6__I_STAT__PAR)
printk("%s Icache parity error\n", err_print_prefix);
return status;
}
static int
ev6_parse_mbox(u64 mm_stat, u64 d_stat, u64 c_stat, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#define EV6__MM_STAT__DC_TAG_PERR (1UL << 10)
#define EV6__MM_STAT__ERRMASK (EV6__MM_STAT__DC_TAG_PERR)
#define EV6__D_STAT__TPERR_P0 (1UL << 0)
#define EV6__D_STAT__TPERR_P1 (1UL << 1)
#define EV6__D_STAT__ECC_ERR_ST (1UL << 2)
#define EV6__D_STAT__ECC_ERR_LD (1UL << 3)
#define EV6__D_STAT__SEO (1UL << 4)
#define EV6__D_STAT__ERRMASK (EV6__D_STAT__TPERR_P0 | \
EV6__D_STAT__TPERR_P1 | \
EV6__D_STAT__ECC_ERR_ST | \
EV6__D_STAT__ECC_ERR_LD | \
EV6__D_STAT__SEO)
if (!(d_stat & EV6__D_STAT__ERRMASK) &&
!(mm_stat & EV6__MM_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
if (mm_stat & EV6__MM_STAT__DC_TAG_PERR)
printk("%s Dcache tag parity error on probe\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__TPERR_P0)
printk("%s Dcache tag parity error - pipe 0\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__TPERR_P1)
printk("%s Dcache tag parity error - pipe 1\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__ECC_ERR_ST)
printk("%s ECC error occurred on a store\n",
err_print_prefix);
if (d_stat & EV6__D_STAT__ECC_ERR_LD)
printk("%s ECC error occurred on a %s load\n",
err_print_prefix,
c_stat ? "" : "speculative ");
if (d_stat & EV6__D_STAT__SEO)
printk("%s Dcache second error\n", err_print_prefix);
return status;
}
static int
ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn,
u64 c_stat, u64 c_sts, int print)
{
char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN",
"MEMORY", "BCACHE", "DCACHE",
"BCACHE PROBE", "BCACHE PROBE" };
char *streamname[] = { "D", "I" };
char *bitsname[] = { "SINGLE", "DOUBLE" };
int status = MCHK_DISPOSITION_REPORT;
int source = -1, stream = -1, bits = -1;
#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) /* both 6 and 7 indicate... */
#define EV6__C_STAT__PROBE_BC_ERR1 (0x07) /* ...probe bc error. */
#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)
#define EV6__C_STAT__SOURCE_MEMORY (0x03)
#define EV6__C_STAT__SOURCE_BCACHE (0x04)
#define EV6__C_STAT__SOURCE__S (0)
#define EV6__C_STAT__SOURCE__M (0x07)
#define EV6__C_STAT__ISTREAM__S (3)
#define EV6__C_STAT__ISTREAM__M (0x01)
#define EV6__C_STAT__DOUBLE__S (4)
#define EV6__C_STAT__DOUBLE__M (0x01)
#define EV6__C_STAT__ERRMASK (0x1F)
#define EV6__C_STS__SHARED (1 << 0)
#define EV6__C_STS__DIRTY (1 << 1)
#define EV6__C_STS__VALID (1 << 2)
#define EV6__C_STS__PARITY (1 << 3)
if (!(c_stat & EV6__C_STAT__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
if (!print)
return status;
source = EXTRACT(c_stat, EV6__C_STAT__SOURCE);
stream = EXTRACT(c_stat, EV6__C_STAT__ISTREAM);
bits = EXTRACT(c_stat, EV6__C_STAT__DOUBLE);
if (c_stat & EV6__C_STAT__BC_PERR) {
printk("%s Bcache tag parity error\n", err_print_prefix);
source = -1;
}
if (c_stat & EV6__C_STAT__DC_PERR) {
printk("%s Dcache tag parity error\n", err_print_prefix);
source = -1;
}
if (c_stat == EV6__C_STAT__PROBE_BC_ERR0 ||
c_stat == EV6__C_STAT__PROBE_BC_ERR1) {
printk("%s Bcache single-bit error on a probe hit\n",
err_print_prefix);
source = -1;
}
if (source != -1)
printk("%s %s-STREAM %s-BIT ECC error from %s\n",
err_print_prefix,
streamname[stream], bitsname[bits], sourcename[source]);
printk("%s Address: 0x%016lx\n"
" Syndrome[upper.lower]: %02lx.%02lx\n",
err_print_prefix,
c_addr,
c2_syn, c1_syn);
if (source == EV6__C_STAT__SOURCE_MEMORY ||
source == EV6__C_STAT__SOURCE_BCACHE)
printk("%s Block status: %s%s%s%s\n",
err_print_prefix,
(c_sts & EV6__C_STS__SHARED) ? "SHARED " : "",
(c_sts & EV6__C_STS__DIRTY) ? "DIRTY " : "",
(c_sts & EV6__C_STS__VALID) ? "VALID " : "",
(c_sts & EV6__C_STS__PARITY) ? "PARITY " : "");
return status;
}
void
ev6_register_error_handlers(void)
{
/* None right now. */
}
int
ev6_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_common_EV6_mcheck *ev6mchk =
(struct el_common_EV6_mcheck *)mchk_header;
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= ev6_parse_ibox(ev6mchk->I_STAT, print);
status |= ev6_parse_mbox(ev6mchk->MM_STAT, ev6mchk->DC_STAT,
ev6mchk->C_STAT, print);
status |= ev6_parse_cbox(ev6mchk->C_ADDR, ev6mchk->DC1_SYNDROME,
ev6mchk->DC0_SYNDROME, ev6mchk->C_STAT,
ev6mchk->C_STS, print);
if (!print)
return status;
if (status != MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
/*
* Dump some additional information from the frame
*/
printk("%s EXC_ADDR: 0x%016lx IER_CM: 0x%016lx"
" ISUM: 0x%016lx\n"
" PAL_BASE: 0x%016lx I_CTL: 0x%016lx"
" PCTX: 0x%016lx\n",
err_print_prefix,
ev6mchk->EXC_ADDR, ev6mchk->IER_CM, ev6mchk->ISUM,
ev6mchk->PAL_BASE, ev6mchk->I_CTL, ev6mchk->PCTX);
if (status == MCHK_DISPOSITION_UNKNOWN_ERROR) {
printk("%s UNKNOWN error, frame follows:\n",
err_print_prefix);
} else {
/* had decode -- downgrade print level for frame */
err_print_prefix = KERN_NOTICE;
}
mchk_dump_logout_frame(mchk_header);
err_print_prefix = saved_err_prefix;
}
return status;
}
void
ev6_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
/*
* Sync the processor
*/
mb();
draina();
/*
* Parse the logout frame without printing first. If the only error(s)
* found are have a disposition of "dismiss", then just dismiss them
* and don't print any message
*/
if (ev6_process_logout_frame(mchk_header, 0) !=
MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
err_print_prefix = KERN_CRIT;
/*
* Either a nondismissable error was detected or no
* recognized error was detected in the logout frame
* -- report the error in either case
*/
printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(vector == SCB_Q_PROCERR)?"Correctable":"Uncorrectable",
(unsigned int)vector, (int)smp_processor_id());
ev6_process_logout_frame(mchk_header, 1);
dik_show_regs(regs, NULL);
err_print_prefix = saved_err_prefix;
}
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
/*
* linux/arch/alpha/kernel/err_ev7.c
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Error handling code supporting Alpha systems
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include <asm/err_common.h>
#include <asm/err_ev7.h>
#include "err_impl.h"
#include "proto.h"
struct ev7_lf_subpackets *
ev7_collect_logout_frame_subpackets(struct el_subpacket *el_ptr,
struct ev7_lf_subpackets *lf_subpackets)
{
struct el_subpacket *subpacket;
int i;
/*
* A Marvel machine check frame is always packaged in an
* el_subpacket of class HEADER, type LOGOUT_FRAME.
*/
if (el_ptr->class != EL_CLASS__HEADER ||
el_ptr->type != EL_TYPE__HEADER__LOGOUT_FRAME)
return NULL;
/*
* It is a logout frame header. Look at the one subpacket.
*/
el_ptr = (struct el_subpacket *)
((unsigned long)el_ptr + el_ptr->length);
/*
* It has to be class PAL, type LOGOUT_FRAME.
*/
if (el_ptr->class != EL_CLASS__PAL ||
el_ptr->type != EL_TYPE__PAL__LOGOUT_FRAME)
return NULL;
lf_subpackets->logout = (struct ev7_pal_logout_subpacket *)
el_ptr->by_type.raw.data_start;
/*
* Process the subpackets.
*/
subpacket = (struct el_subpacket *)
((unsigned long)el_ptr + el_ptr->length);
for (i = 0;
subpacket && i < lf_subpackets->logout->subpacket_count;
subpacket = (struct el_subpacket *)
((unsigned long)subpacket + subpacket->length), i++) {
/*
* All subpackets should be class PAL.
*/
if (subpacket->class != EL_CLASS__PAL) {
printk("%s**UNEXPECTED SUBPACKET CLASS %d "
"IN LOGOUT FRAME (packet %d\n",
err_print_prefix, subpacket->class, i);
return NULL;
}
/*
* Remember the subpacket.
*/
switch(subpacket->type) {
case EL_TYPE__PAL__EV7_PROCESSOR:
lf_subpackets->ev7 =
(struct ev7_pal_processor_subpacket *)
subpacket->by_type.raw.data_start;
break;
case EL_TYPE__PAL__EV7_RBOX:
lf_subpackets->rbox = (struct ev7_pal_rbox_subpacket *)
subpacket->by_type.raw.data_start;
break;
case EL_TYPE__PAL__EV7_ZBOX:
lf_subpackets->zbox = (struct ev7_pal_zbox_subpacket *)
subpacket->by_type.raw.data_start;
break;
case EL_TYPE__PAL__EV7_IO:
lf_subpackets->io = (struct ev7_pal_io_subpacket *)
subpacket->by_type.raw.data_start;
break;
case EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE:
case EL_TYPE__PAL__ENV__AIRMOVER_FAN:
case EL_TYPE__PAL__ENV__VOLTAGE:
case EL_TYPE__PAL__ENV__INTRUSION:
case EL_TYPE__PAL__ENV__POWER_SUPPLY:
case EL_TYPE__PAL__ENV__LAN:
case EL_TYPE__PAL__ENV__HOT_PLUG:
lf_subpackets->env[ev7_lf_env_index(subpacket->type)] =
(struct ev7_pal_environmental_subpacket *)
subpacket->by_type.raw.data_start;
break;
default:
/*
* Don't know what kind of frame this is.
*/
return NULL;
}
}
return lf_subpackets;
}
void
ev7_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
char *saved_err_prefix = err_print_prefix;
/*
* Sync the processor
*/
mb();
draina();
err_print_prefix = KERN_CRIT;
printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d\n",
err_print_prefix,
(vector == SCB_Q_PROCERR) ? "Correctable" : "Uncorrectable",
(unsigned int)vector, (int)smp_processor_id());
el_process_subpacket(el_ptr);
err_print_prefix = saved_err_prefix;
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
static char *el_ev7_processor_subpacket_annotation[] = {
"Subpacket Header", "I_STAT", "DC_STAT",
"C_ADDR", "C_SYNDROME_1", "C_SYNDROME_0",
"C_STAT", "C_STS", "MM_STAT",
"EXC_ADDR", "IER_CM", "ISUM",
"PAL_BASE", "I_CTL", "PROCESS_CONTEXT",
"CBOX_CTL", "CBOX_STP_CTL", "CBOX_ACC_CTL",
"CBOX_LCL_SET", "CBOX_GLB_SET", "BBOX_CTL",
"BBOX_ERR_STS", "BBOX_ERR_IDX", "CBOX_DDP_ERR_STS",
"BBOX_DAT_RMP", NULL
};
static char *el_ev7_zbox_subpacket_annotation[] = {
"Subpacket Header",
"ZBOX(0): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
"ZBOX(0): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
"ZBOX(0): DIFT_TIMEOUT / DRAM_ERR_ADR",
"ZBOX(0): FRC_ERR_ADR / DRAM_MAPPER_CTL",
"ZBOX(0): reserved / DIFT_ERR_STATUS",
"ZBOX(1): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
"ZBOX(1): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
"ZBOX(1): DIFT_TIMEOUT / DRAM_ERR_ADR",
"ZBOX(1): FRC_ERR_ADR / DRAM_MAPPER_CTL",
"ZBOX(1): reserved / DIFT_ERR_STATUS",
"CBOX_CTL", "CBOX_STP_CTL",
"ZBOX(0)_ERROR_PA", "ZBOX(1)_ERROR_PA",
"ZBOX(0)_ORED_SYNDROME","ZBOX(1)_ORED_SYNDROME",
NULL
};
static char *el_ev7_rbox_subpacket_annotation[] = {
"Subpacket Header", "RBOX_CFG", "RBOX_N_CFG",
"RBOX_S_CFG", "RBOX_E_CFG", "RBOX_W_CFG",
"RBOX_N_ERR", "RBOX_S_ERR", "RBOX_E_ERR",
"RBOX_W_ERR", "RBOX_IO_CFG", "RBOX_IO_ERR",
"RBOX_L_ERR", "RBOX_WHOAMI", "RBOX_IMASL",
"RBOX_INTQ", "RBOX_INT", NULL
};
static char *el_ev7_io_subpacket_annotation[] = {
"Subpacket Header", "IO_ASIC_REV", "IO_SYS_REV",
"IO7_UPH", "HPI_CTL", "CRD_CTL",
"HEI_CTL", "PO7_ERROR_SUM","PO7_UNCRR_SYM",
"PO7_CRRCT_SYM", "PO7_UGBGE_SYM","PO7_ERR_PKT0",
"PO7_ERR_PKT1", "reserved", "reserved",
"PO0_ERR_SUM", "PO0_TLB_ERR", "PO0_SPL_COMPLT",
"PO0_TRANS_SUM", "PO0_FIRST_ERR","PO0_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO1_ERR_SUM", "PO1_TLB_ERR", "PO1_SPL_COMPLT",
"PO1_TRANS_SUM", "PO1_FIRST_ERR","PO1_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO2_ERR_SUM", "PO2_TLB_ERR", "PO2_SPL_COMPLT",
"PO2_TRANS_SUM", "PO2_FIRST_ERR","PO2_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
"PO3_ERR_SUM", "PO3_TLB_ERR", "PO3_SPL_COMPLT",
"PO3_TRANS_SUM", "PO3_FIRST_ERR","PO3_MULT_ERR",
"DM CSR PH", "DM CSR PH", "DM CSR PH",
"DM CSR PH", "reserved",
NULL
};
static struct el_subpacket_annotation el_ev7_pal_annotations[] = {
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_PROCESSOR,
1,
"EV7 Processor Subpacket",
el_ev7_processor_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_ZBOX,
1,
"EV7 ZBOX Subpacket",
el_ev7_zbox_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_RBOX,
1,
"EV7 RBOX Subpacket",
el_ev7_rbox_subpacket_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__PAL,
EL_TYPE__PAL__EV7_IO,
1,
"EV7 IO Subpacket",
el_ev7_io_subpacket_annotation)
};
static struct el_subpacket *
ev7_process_pal_subpacket(struct el_subpacket *header)
{
struct ev7_pal_subpacket *packet;
if (header->class != EL_CLASS__PAL) {
printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
err_print_prefix,
header->class, header->type);
return NULL;
}
packet = (struct ev7_pal_subpacket *)header->by_type.raw.data_start;
switch(header->type) {
case EL_TYPE__PAL__LOGOUT_FRAME:
printk("%s*** MCHK occurred on LPID %ld (RBOX %lx)\n",
err_print_prefix,
packet->by_type.logout.whami,
packet->by_type.logout.rbox_whami);
el_print_timestamp(&packet->by_type.logout.timestamp);
printk("%s EXC_ADDR: %016lx\n"
" HALT_CODE: %lx\n",
err_print_prefix,
packet->by_type.logout.exc_addr,
packet->by_type.logout.halt_code);
el_process_subpackets(header,
packet->by_type.logout.subpacket_count);
break;
default:
printk("%s ** PAL TYPE %d SUBPACKET\n",
err_print_prefix,
header->type);
el_annotate_subpacket(header);
break;
}
return (struct el_subpacket *)((unsigned long)header + header->length);
}
struct el_subpacket_handler ev7_pal_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
void
ev7_register_error_handlers(void)
{
int i;
for(i = 0;
i<sizeof(el_ev7_pal_annotations)/sizeof(el_ev7_pal_annotations[1]);
i++) {
cdl_register_subpacket_annotation(&el_ev7_pal_annotations[i]);
}
cdl_register_subpacket_handler(&ev7_pal_subpacket_handler);
}
......@@ -7,103 +7,9 @@
* implementations.
*/
/*
* SCB Vector definitions
*/
#define SCB_Q_SYSERR 0x620
#define SCB_Q_PROCERR 0x630
#define SCB_Q_SYSMCHK 0x660
#define SCB_Q_PROCMCHK 0x670
#define SCB_Q_SYSEVENT 0x680
/*
* Disposition definitions for logout frame parser
*/
#define MCHK_DISPOSITION_UNKNOWN_ERROR 0x00
#define MCHK_DISPOSITION_REPORT 0x01
#define MCHK_DISPOSITION_DISMISS 0x02
/*
* Error Log definitions
*/
/*
* Types
*/
#define EL_CLASS__TERMINATION (0)
# define EL_TYPE__TERMINATION__TERMINATION (0)
#define EL_CLASS__HEADER (5)
# define EL_TYPE__HEADER__SYSTEM_ERROR_FRAME (1)
# define EL_TYPE__HEADER__SYSTEM_EVENT_FRAME (2)
# define EL_TYPE__HEADER__HALT_FRAME (3)
# define EL_TYPE__HEADER__LOGOUT_FRAME (19)
#define EL_CLASS__GENERAL_NOTIFICATION (9)
#define EL_CLASS__PCI_ERROR_FRAME (11)
#define EL_CLASS__REGATTA_FAMILY (12)
# define EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME (1)
# define EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME (2)
# define EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME (3)
# define EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED (8)
# define EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED (9)
# define EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED (10)
# define EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT (11)
# define EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT (12)
#define EL_CLASS__PAL (14)
# define EL_TYPE__PAL__LOGOUT_FRAME (1)
# define EL_TYPE__PAL__EV7_PROCESSOR (4)
# define EL_TYPE__PAL__EV7_ZBOX (5)
# define EL_TYPE__PAL__EV7_RBOX (6)
# define EL_TYPE__PAL__EV7_IO (7)
union el_timestamp {
struct {
u8 second;
u8 minute;
u8 hour;
u8 day;
u8 month;
u8 year;
} b;
u64 as_int;
};
struct el_subpacket {
u16 length; /* length of header (in bytes) */
u16 class; /* header class and type... */
u16 type; /* ...determine content */
u16 revision; /* header revision */
union {
struct { /* Class 5, Type 1 - System Error */
u32 frame_length;
u32 frame_packet_count;
} sys_err;
struct { /* Class 5, Type 2 - System Event */
union el_timestamp timestamp;
u32 frame_length;
u32 frame_packet_count;
} sys_event;
struct { /* Class 5, Type 3 - Double Error Halt */
u16 halt_code;
u16 reserved;
union el_timestamp timestamp;
u32 frame_length;
u32 frame_packet_count;
} err_halt;
struct { /* Clasee 5, Type 19 - Logout Frame Header */
u32 frame_length;
u32 frame_flags;
u32 cpu_offset;
u32 system_offset;
} logout_header;
struct { /* Class 12 - Regatta */
u64 cpuid;
u64 data_start[1];
} regatta_frame;
struct { /* Raw */
u64 data_start[1];
} raw;
} by_type;
};
union el_timestamp;
struct el_subpacket;
struct ev7_lf_subpackets;
struct el_subpacket_annotation {
struct el_subpacket_annotation *next;
......@@ -123,10 +29,14 @@ struct el_subpacket_handler {
#define SUBPACKET_HANDLER_INIT(c, h) {NULL, (c), (h)}
/*
* Extract a field from a register given it's name. defines
* Manipulate a field from a register given it's name. defines
* for the LSB (__S - shift count) and bitmask (__M) are required
*
* EXTRACT(u, f) - extracts the field and places it at bit position 0
* GEN_MASK(f) - creates an in-position mask for the field
*/
#define EXTRACT(u, f) (((u) >> f##__S) & f##__M)
#define GEN_MASK(f) ((u64)f##__M << f##__S)
/*
* err_common.c
......@@ -135,17 +45,30 @@ extern char *err_print_prefix;
extern void mchk_dump_mem(void *, size_t, char **);
extern void mchk_dump_logout_frame(struct el_common *);
extern void ev7_register_error_handlers(void);
extern void ev7_machine_check(u64, u64, struct pt_regs *);
extern void ev6_register_error_handlers(void);
extern int ev6_process_logout_frame(struct el_common *, int);
extern void ev6_machine_check(u64, u64, struct pt_regs *);
extern void el_print_timestamp(union el_timestamp *);
extern void el_process_subpackets(struct el_subpacket *, int);
extern struct el_subpacket *el_process_subpacket(struct el_subpacket *);
extern void el_annotate_subpacket(struct el_subpacket *);
extern void cdl_check_console_data_log(void);
extern int cdl_register_subpacket_annotation(struct el_subpacket_annotation *);
extern int cdl_register_subpacket_handler(struct el_subpacket_handler *);
/*
* err_ev7.c
*/
extern struct ev7_lf_subpackets *
ev7_collect_logout_frame_subpackets(struct el_subpacket *,
struct ev7_lf_subpackets *);
extern void ev7_register_error_handlers(void);
extern void ev7_machine_check(u64, u64, struct pt_regs *);
/*
* err_ev6.c
*/
extern void ev6_register_error_handlers(void);
extern int ev6_process_logout_frame(struct el_common *, int);
extern void ev6_machine_check(u64, u64, struct pt_regs *);
/*
* err_marvel.c
*/
......
......@@ -14,15 +14,1044 @@
#include <asm/core_marvel.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include <asm/err_common.h>
#include <asm/err_ev7.h>
#include "err_impl.h"
#include "proto.h"
static void
marvel_print_680_frame(struct ev7_lf_subpackets *lf_subpackets)
{
#ifdef CONFIG_VERBOSE_MCHECK
struct ev7_pal_environmental_subpacket *env;
struct { int type; char *name; } ev_packets[] = {
{ EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE,
"Ambient Temperature" },
{ EL_TYPE__PAL__ENV__AIRMOVER_FAN,
"AirMover / Fan" },
{ EL_TYPE__PAL__ENV__VOLTAGE,
"Voltage" },
{ EL_TYPE__PAL__ENV__INTRUSION,
"Intrusion" },
{ EL_TYPE__PAL__ENV__POWER_SUPPLY,
"Power Supply" },
{ EL_TYPE__PAL__ENV__LAN,
"LAN" },
{ EL_TYPE__PAL__ENV__HOT_PLUG,
"Hot Plug" },
{ 0, NULL }
};
int i;
for (i = 0; ev_packets[i].type != 0; i++) {
env = lf_subpackets->env[ev7_lf_env_index(ev_packets[i].type)];
if (!env)
continue;
printk("%s**%s event (cabinet %d, drawer %d)\n",
err_print_prefix,
ev_packets[i].name,
env->cabinet,
env->drawer);
printk("%s Module Type: 0x%x - Unit ID 0x%x - "
"Condition 0x%x\n",
err_print_prefix,
env->module_type,
env->unit_id,
env->condition);
}
#endif /* CONFIG_VERBOSE_MCHECK */
}
static int
marvel_process_680_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
{
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
int i;
for (i = ev7_lf_env_index(EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE);
i <= ev7_lf_env_index(EL_TYPE__PAL__ENV__HOT_PLUG);
i++) {
if (lf_subpackets->env[i])
status = MCHK_DISPOSITION_REPORT;
}
if (print)
marvel_print_680_frame(lf_subpackets);
return status;
}
#ifdef CONFIG_VERBOSE_MCHECK
static void
marvel_print_err_cyc(u64 err_cyc)
{
static char *packet_desc[] = {
"No Error",
"UNKNOWN",
"1 cycle (1 or 2 flit packet)",
"2 cycles (3 flit packet)",
"9 cycles (18 flit packet)",
"10 cycles (19 flit packet)",
"UNKNOWN",
"UNKNOWN",
"UNKNOWN"
};
#define IO7__ERR_CYC__ODD_FLT (1UL << 0)
#define IO7__ERR_CYC__EVN_FLT (1UL << 1)
#define IO7__ERR_CYC__PACKET__S (6)
#define IO7__ERR_CYC__PACKET__M (0x7)
#define IO7__ERR_CYC__LOC (1UL << 5)
#define IO7__ERR_CYC__CYCLE__S (2)
#define IO7__ERR_CYC__CYCLE__M (0x7)
printk("%s Packet In Error: %s\n"
"%s Error in %s, cycle %ld%s%s\n",
err_print_prefix,
packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)],
err_print_prefix,
(err_cyc & IO7__ERR_CYC__LOC) ? "DATA" : "HEADER",
EXTRACT(err_cyc, IO7__ERR_CYC__CYCLE),
(err_cyc & IO7__ERR_CYC__ODD_FLT) ? " [ODD Flit]": "",
(err_cyc & IO7__ERR_CYC__EVN_FLT) ? " [Even Flit]": "");
}
static void
marvel_print_po7_crrct_sym(u64 crrct_sym)
{
#define IO7__PO7_CRRCT_SYM__SYN__S (0)
#define IO7__PO7_CRRCT_SYM__SYN__M (0x7f)
#define IO7__PO7_CRRCT_SYM__ERR_CYC__S (7) /* ERR_CYC + ODD_FLT + EVN_FLT */
#define IO7__PO7_CRRCT_SYM__ERR_CYC__M (0x1ff)
printk("%s Correctable Error Symptoms:\n"
"%s Syndrome: 0x%lx\n",
err_print_prefix,
err_print_prefix, EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__SYN));
marvel_print_err_cyc(EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__ERR_CYC));
}
static void
marvel_print_po7_uncrr_sym(u64 uncrr_sym, u64 valid_mask)
{
static char *clk_names[] = { "_h[0]", "_h[1]", "_n[0]", "_n[1]" };
static char *clk_decode[] = {
"No Error",
"One extra rising edge",
"Two extra rising edges",
"Lost one clock"
};
static char *port_names[] = { "Port 0", "Port 1",
"Port 2", "Port 3",
"Unknown Port", "Unknown Port",
"Unknown Port", "Port 7" };
int scratch, i;
#define IO7__PO7_UNCRR_SYM__SYN__S (0)
#define IO7__PO7_UNCRR_SYM__SYN__M (0x7f)
#define IO7__PO7_UNCRR_SYM__ERR_CYC__S (7) /* ERR_CYC + ODD_FLT... */
#define IO7__PO7_UNCRR_SYM__ERR_CYC__M (0x1ff) /* ... + EVN_FLT */
#define IO7__PO7_UNCRR_SYM__CLK__S (16)
#define IO7__PO7_UNCRR_SYM__CLK__M (0xff)
#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ (1UL << 24)
#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO (1UL << 25)
#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO (1UL << 26)
#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK (1UL << 27)
#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK (1UL << 28)
#define IO7__PO7_UNCRR_SYM__OVF__READIO (1UL << 29)
#define IO7__PO7_UNCRR_SYM__OVF__WRITEIO (1UL << 30)
#define IO7__PO7_UNCRR_SYM__OVF__FWD (1UL << 31)
#define IO7__PO7_UNCRR_SYM__VICTIM_SP__S (32)
#define IO7__PO7_UNCRR_SYM__VICTIM_SP__M (0xff)
#define IO7__PO7_UNCRR_SYM__DETECT_SP__S (40)
#define IO7__PO7_UNCRR_SYM__DETECT_SP__M (0xff)
#define IO7__PO7_UNCRR_SYM__STRV_VTR__S (48)
#define IO7__PO7_UNCRR_SYM__STRV_VTR__M (0x3ff)
#define IO7__STRV_VTR__LSI__INTX__S (0)
#define IO7__STRV_VTR__LSI__INTX__M (0x3)
#define IO7__STRV_VTR__LSI__SLOT__S (2)
#define IO7__STRV_VTR__LSI__SLOT__M (0x7)
#define IO7__STRV_VTR__LSI__BUS__S (5)
#define IO7__STRV_VTR__LSI__BUS__M (0x3)
#define IO7__STRV_VTR__MSI__INTNUM__S (0)
#define IO7__STRV_VTR__MSI__INTNUM__M (0x1ff)
#define IO7__STRV_VTR__IS_MSI (1UL << 9)
printk("%s Uncorrectable Error Symptoms:\n", err_print_prefix);
uncrr_sym &= valid_mask;
if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__SYN))
printk("%s Syndrome: 0x%lx\n",
err_print_prefix,
EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__SYN));
if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__ERR_CYC))
marvel_print_err_cyc(EXTRACT(uncrr_sym,
IO7__PO7_UNCRR_SYM__ERR_CYC));
scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__CLK);
for (i = 0; i < 4; i++, scratch >>= 2) {
if (scratch & 0x3)
printk("%s Clock %s: %s\n",
err_print_prefix,
clk_names[i], clk_decode[scratch & 0x3]);
}
if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ)
printk("%s REQ Credit Timeout or Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO)
printk("%s RIO Credit Timeout or Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO)
printk("%s WIO Credit Timeout or Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK)
printk("%s BLK Credit Timeout or Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK)
printk("%s NBK Credit Timeout or Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__READIO)
printk("%s Read I/O Buffer Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__WRITEIO)
printk("%s Write I/O Buffer Overflow\n",
err_print_prefix);
if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__FWD)
printk("%s FWD Buffer Overflow\n",
err_print_prefix);
if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__VICTIM_SP))) {
int lost = scratch & (1UL << 4);
scratch &= ~lost;
for (i = 0; i < 8; i++, scratch >>= 1) {
if (!(scratch & 1))
continue;
printk("%s Error Response sent to %s",
err_print_prefix, port_names[i]);
}
if (lost)
printk("%s Lost Error sent somewhere else\n",
err_print_prefix);
}
if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__DETECT_SP))) {
for (i = 0; i < 8; i++, scratch >>= 1) {
if (!(scratch & 1))
continue;
printk("%s Error Reported by %s",
err_print_prefix, port_names[i]);
}
}
if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__STRV_VTR)) {
char starvation_message[80];
scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__STRV_VTR);
if (scratch & IO7__STRV_VTR__IS_MSI)
sprintf(starvation_message,
"MSI Interrupt 0x%x",
EXTRACT(scratch, IO7__STRV_VTR__MSI__INTNUM));
else
sprintf(starvation_message,
"LSI INT%c for Bus:Slot (%d:%d)\n",
'A' + EXTRACT(scratch,
IO7__STRV_VTR__LSI__INTX),
EXTRACT(scratch, IO7__STRV_VTR__LSI__BUS),
EXTRACT(scratch, IO7__STRV_VTR__LSI__SLOT));
printk("%s Starvation Int Trigger By: %s\n",
err_print_prefix, starvation_message);
}
}
static void
marvel_print_po7_ugbge_sym(u64 ugbge_sym)
{
char opcode_str[10];
#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__S (6)
#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__M (0xfffffffful)
#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__S (40)
#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__M (0xff)
#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__S (48)
#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__M (0xf)
#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__S (52)
#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__M (0x7ff)
#define IO7__PO7_UGBGE_SYM__VALID (1UL << 63)
if (!(ugbge_sym & IO7__PO7_UGBGE_SYM__VALID))
return;
switch(EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)) {
case 0x51:
sprintf(opcode_str, "Wr32");
break;
case 0x50:
sprintf(opcode_str, "WrQW");
break;
case 0x54:
sprintf(opcode_str, "WrIPR");
break;
case 0xD8:
sprintf(opcode_str, "Victim");
break;
case 0xC5:
sprintf(opcode_str, "BlkIO");
break;
default:
sprintf(opcode_str, "0x%lx\n",
EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE));
break;
}
printk("%s Up Hose Garbage Symptom:\n"
"%s Source Port: %ld - Dest PID: %ld - OpCode: %s\n",
err_print_prefix,
err_print_prefix,
EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT),
EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_DEST_PID),
opcode_str);
if (0xC5 != EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE))
printk("%s Packet Offset 0x%08lx\n",
err_print_prefix,
EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_PKT_OFF));
}
static void
marvel_print_po7_err_sum(struct ev7_pal_io_subpacket *io)
{
u64 uncrr_sym_valid = 0;
#define IO7__PO7_ERRSUM__CR_SBE (1UL << 32)
#define IO7__PO7_ERRSUM__CR_SBE2 (1UL << 33)
#define IO7__PO7_ERRSUM__CR_PIO_WBYTE (1UL << 34)
#define IO7__PO7_ERRSUM__CR_CSR_NXM (1UL << 35)
#define IO7__PO7_ERRSUM__CR_RPID_ACV (1UL << 36)
#define IO7__PO7_ERRSUM__CR_RSP_NXM (1UL << 37)
#define IO7__PO7_ERRSUM__CR_ERR_RESP (1UL << 38)
#define IO7__PO7_ERRSUM__CR_CLK_DERR (1UL << 39)
#define IO7__PO7_ERRSUM__CR_DAT_DBE (1UL << 40)
#define IO7__PO7_ERRSUM__CR_DAT_GRBG (1UL << 41)
#define IO7__PO7_ERRSUM__MAF_TO (1UL << 42)
#define IO7__PO7_ERRSUM__UGBGE (1UL << 43)
#define IO7__PO7_ERRSUM__UN_MAF_LOST (1UL << 44)
#define IO7__PO7_ERRSUM__UN_PKT_OVF (1UL << 45)
#define IO7__PO7_ERRSUM__UN_CDT_OVF (1UL << 46)
#define IO7__PO7_ERRSUM__UN_DEALLOC (1UL << 47)
#define IO7__PO7_ERRSUM__BH_CDT_TO (1UL << 51)
#define IO7__PO7_ERRSUM__BH_CLK_HDR (1UL << 52)
#define IO7__PO7_ERRSUM__BH_DBE_HDR (1UL << 53)
#define IO7__PO7_ERRSUM__BH_GBG_HDR (1UL << 54)
#define IO7__PO7_ERRSUM__BH_BAD_CMD (1UL << 55)
#define IO7__PO7_ERRSUM__HLT_INT (1UL << 56)
#define IO7__PO7_ERRSUM__HP_INT (1UL << 57)
#define IO7__PO7_ERRSUM__CRD_INT (1UL << 58)
#define IO7__PO7_ERRSUM__STV_INT (1UL << 59)
#define IO7__PO7_ERRSUM__HRD_INT (1UL << 60)
#define IO7__PO7_ERRSUM__BH_SUM (1UL << 61)
#define IO7__PO7_ERRSUM__ERR_LST (1UL << 62)
#define IO7__PO7_ERRSUM__ERR_VALID (1UL << 63)
#define IO7__PO7_ERRSUM__ERR_MASK (IO7__PO7_ERRSUM__ERR_VALID | \
IO7__PO7_ERRSUM__CR_SBE)
/*
* Single bit errors aren't covered by ERR_VALID.
*/
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE) {
printk("%s %sSingle Bit Error(s) detected/corrected\n",
err_print_prefix,
(io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE2)
? "Multiple " : "");
marvel_print_po7_crrct_sym(io->po7_crrct_sym);
}
/*
* Neither are the interrupt status bits
*/
if (io->po7_error_sum & IO7__PO7_ERRSUM__HLT_INT)
printk("%s Halt Interrupt posted", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__HP_INT) {
printk("%s Hot Plug Event Interrupt posted",
err_print_prefix);
uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
}
if (io->po7_error_sum & IO7__PO7_ERRSUM__CRD_INT)
printk("%s Correctable Error Interrupt posted",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__STV_INT) {
printk("%s Starvation Interrupt posted", err_print_prefix);
uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__STRV_VTR);
}
if (io->po7_error_sum & IO7__PO7_ERRSUM__HRD_INT) {
printk("%s Hard Error Interrupt posted", err_print_prefix);
uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
}
/*
* Everything else is valid only with ERR_VALID, so skip to the end
* (uncrr_sym check) unless ERR_VALID is set.
*/
if (!(io->po7_error_sum & IO7__PO7_ERRSUM__ERR_VALID))
goto check_uncrr_sym;
/*
* Since ERR_VALID is set, VICTIM_SP in uncrr_sym is valid.
* For bits [29:0] to also be valid, the following bits must
* not be set:
* CR_PIO_WBYTE CR_CSR_NXM CR_RSP_NXM
* CR_ERR_RESP MAF_TO
*/
uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__VICTIM_SP);
if (!(io->po7_error_sum & (IO7__PO7_ERRSUM__CR_PIO_WBYTE |
IO7__PO7_ERRSUM__CR_CSR_NXM |
IO7__PO7_ERRSUM__CR_RSP_NXM |
IO7__PO7_ERRSUM__CR_ERR_RESP |
IO7__PO7_ERRSUM__MAF_TO)))
uncrr_sym_valid |= 0x3ffffffful;
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_PIO_WBYTE)
printk("%s Write byte into IO7 CSR\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CSR_NXM)
printk("%s PIO to non-existent CSR\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RPID_ACV)
printk("%s Bus Requester PID (Access Violation)\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RSP_NXM)
printk("%s Received NXM response from EV7\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_ERR_RESP)
printk("%s Received ERROR RESPONSE\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CLK_DERR)
printk("%s Clock error on data flit\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_DBE)
printk("%s Double Bit Error Data Error Detected\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_GRBG)
printk("%s Garbage Encoding Detected on the data\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__UGBGE) {
printk("%s Garbage Encoding sent up hose\n",
err_print_prefix);
marvel_print_po7_ugbge_sym(io->po7_ugbge_sym);
}
if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_MAF_LOST)
printk("%s Orphan response (unexpected response)\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_PKT_OVF)
printk("%s Down hose packet overflow\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_CDT_OVF)
printk("%s Down hose credit overflow\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_DEALLOC)
printk("%s Unexpected or bad dealloc field\n",
err_print_prefix);
/*
* The black hole events.
*/
if (io->po7_error_sum & IO7__PO7_ERRSUM__MAF_TO)
printk("%s BLACK HOLE: Timeout for all responses\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CDT_TO)
printk("%s BLACK HOLE: Credit Timeout\n", err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CLK_HDR)
printk("%s BLACK HOLE: Clock check on header\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_DBE_HDR)
printk("%s BLACK HOLE: Uncorrectable Error on header\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_GBG_HDR)
printk("%s BLACK HOLE: Garbage on header\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_BAD_CMD)
printk("%s BLACK HOLE: Bad EV7 command\n",
err_print_prefix);
if (io->po7_error_sum & IO7__PO7_ERRSUM__ERR_LST)
printk("%s Lost Error\n", err_print_prefix);
printk("%s Failing Packet:\n"
"%s Cycle 1: %016lx\n"
"%s Cycle 2: %016lx\n",
err_print_prefix,
err_print_prefix, io->po7_err_pkt0,
err_print_prefix, io->po7_err_pkt1);
/*
* If there are any valid bits in UNCRR sym for this err,
* print UNCRR_SYM as well.
*/
check_uncrr_sym:
if (uncrr_sym_valid)
marvel_print_po7_uncrr_sym(io->po7_uncrr_sym, uncrr_sym_valid);
}
static void
marvel_print_pox_tlb_err(u64 tlb_err)
{
static char *tlb_errors[] = {
"No Error",
"North Port Signaled Error fetching TLB entry",
"PTE invalid or UCC or GBG error on this entry",
"Address did not hit any DMA window"
};
#define IO7__POX_TLBERR__ERR_VALID (1UL << 63)
#define IO7__POX_TLBERR__ERRCODE__S (0)
#define IO7__POX_TLBERR__ERRCODE__M (0x3)
#define IO7__POX_TLBERR__ERR_TLB_PTR__S (3)
#define IO7__POX_TLBERR__ERR_TLB_PTR__M (0x7)
#define IO7__POX_TLBERR__FADDR__S (6)
#define IO7__POX_TLBERR__FADDR__M (0x3fffffffffful)
if (!(tlb_err & IO7__POX_TLBERR__ERR_VALID))
return;
printk("%s TLB Error on index 0x%lx:\n"
"%s - %s\n"
"%s - Addr: 0x%016lx\n",
err_print_prefix,
EXTRACT(tlb_err, IO7__POX_TLBERR__ERR_TLB_PTR),
err_print_prefix,
tlb_errors[EXTRACT(tlb_err, IO7__POX_TLBERR__ERRCODE)],
err_print_prefix,
EXTRACT(tlb_err, IO7__POX_TLBERR__FADDR) << 6);
}
static void
marvel_print_pox_spl_cmplt(u64 spl_cmplt)
{
char message[80];
#define IO7__POX_SPLCMPLT__MESSAGE__S (0)
#define IO7__POX_SPLCMPLT__MESSAGE__M (0x0fffffffful)
#define IO7__POX_SPLCMPLT__SOURCE_BUS__S (40)
#define IO7__POX_SPLCMPLT__SOURCE_BUS__M (0xfful)
#define IO7__POX_SPLCMPLT__SOURCE_DEV__S (35)
#define IO7__POX_SPLCMPLT__SOURCE_DEV__M (0x1ful)
#define IO7__POX_SPLCMPLT__SOURCE_FUNC__S (32)
#define IO7__POX_SPLCMPLT__SOURCE_FUNC__M (0x07ul)
#define IO7__POX_SPLCMPLT__MSG_CLASS__S (28)
#define IO7__POX_SPLCMPLT__MSG_CLASS__M (0xf)
#define IO7__POX_SPLCMPLT__MSG_INDEX__S (20)
#define IO7__POX_SPLCMPLT__MSG_INDEX__M (0xff)
#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__S (20)
#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__M (0xfff)
#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__S (12)
#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__M (0x7f)
#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__S (0)
#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M (0xfff)
printk("%s Split Completion Error:\n"
"%s Source (Bus:Dev:Func): %ld:%ld:%ld\n",
err_print_prefix,
err_print_prefix,
EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS),
EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_DEV),
EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_FUNC));
switch(EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MSG_CLASSINDEX)) {
case 0x000:
sprintf(message, "Normal completion");
break;
case 0x100:
sprintf(message, "Bridge - Master Abort");
break;
case 0x101:
sprintf(message, "Bridge - Target Abort");
break;
case 0x102:
sprintf(message, "Bridge - Uncorrectable Write Data Error");
break;
case 0x200:
sprintf(message, "Byte Count Out of Range");
break;
case 0x201:
sprintf(message, "Uncorrectable Split Write Data Error");
break;
default:
sprintf(message, "%08lx\n",
EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MESSAGE));
break;
}
printk("%s Message: %s\n", err_print_prefix, message);
}
static void
marvel_print_pox_trans_sum(u64 trans_sum)
{
char *pcix_cmd[] = { "Interrupt Acknowledge",
"Special Cycle",
"I/O Read",
"I/O Write",
"Reserved",
"Reserved / Device ID Message",
"Memory Read",
"Memory Write",
"Reserved / Alias to Memory Read Block",
"Reserved / Alias to Memory Write Block",
"Configuration Read",
"Configuration Write",
"Memory Read Multiple / Split Completion",
"Dual Address Cycle",
"Memory Read Line / Memory Read Block",
"Memory Write and Invalidate / Memory Write Block"
};
#define IO7__POX_TRANSUM__PCI_ADDR__S (0)
#define IO7__POX_TRANSUM__PCI_ADDR__M (0x3fffffffffffful)
#define IO7__POX_TRANSUM__DAC (1UL << 50)
#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__S (52)
#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__M (0xf)
#define IO7__POX_TRANSUM__PCIX_CMD__S (56)
#define IO7__POX_TRANSUM__PCIX_CMD__M (0xf)
#define IO7__POX_TRANSUM__ERR_VALID (1UL << 63)
if (!(trans_sum & IO7__POX_TRANSUM__ERR_VALID))
return;
printk("%s Transaction Summary:\n"
"%s Command: 0x%lx - %s\n"
"%s Address: 0x%016lx%s\n"
"%s PCI-X Master Slot: 0x%lx\n",
err_print_prefix,
err_print_prefix,
EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD),
pcix_cmd[EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD)],
err_print_prefix,
EXTRACT(trans_sum, IO7__POX_TRANSUM__PCI_ADDR),
(trans_sum & IO7__POX_TRANSUM__DAC) ? " (DAC)" : "",
err_print_prefix,
EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_MASTER_SLOT));
}
static void
marvel_print_pox_err(u64 err_sum, struct ev7_pal_io_one_port *port)
{
#define IO7__POX_ERRSUM__AGP_REQQ_OVFL (1UL << 4)
#define IO7__POX_ERRSUM__AGP_SYNC_ERR (1UL << 5)
#define IO7__POX_ERRSUM__MRETRY_TO (1UL << 6)
#define IO7__POX_ERRSUM__PCIX_UX_SPL (1UL << 7)
#define IO7__POX_ERRSUM__PCIX_SPLIT_TO (1UL << 8)
#define IO7__POX_ERRSUM__PCIX_DISCARD_SPL (1UL << 9)
#define IO7__POX_ERRSUM__DMA_RD_TO (1UL << 10)
#define IO7__POX_ERRSUM__CSR_NXM_RD (1UL << 11)
#define IO7__POX_ERRSUM__CSR_NXM_WR (1UL << 12)
#define IO7__POX_ERRSUM__DMA_TO (1UL << 13)
#define IO7__POX_ERRSUM__ALL_MABORTS (1UL << 14)
#define IO7__POX_ERRSUM__MABORT (1UL << 15)
#define IO7__POX_ERRSUM__MABORT_MASK (IO7__POX_ERRSUM__ALL_MABORTS|\
IO7__POX_ERRSUM__MABORT)
#define IO7__POX_ERRSUM__PT_TABORT (1UL << 16)
#define IO7__POX_ERRSUM__PM_TABORT (1UL << 17)
#define IO7__POX_ERRSUM__TABORT_MASK (IO7__POX_ERRSUM__PT_TABORT | \
IO7__POX_ERRSUM__PM_TABORT)
#define IO7__POX_ERRSUM__SERR (1UL << 18)
#define IO7__POX_ERRSUM__ADDRERR_STB (1UL << 19)
#define IO7__POX_ERRSUM__DETECTED_SERR (1UL << 20)
#define IO7__POX_ERRSUM__PERR (1UL << 21)
#define IO7__POX_ERRSUM__DATAERR_STB_NIOW (1UL << 22)
#define IO7__POX_ERRSUM__DETECTED_PERR (1UL << 23)
#define IO7__POX_ERRSUM__PM_PERR (1UL << 24)
#define IO7__POX_ERRSUM__PT_SCERROR (1UL << 26)
#define IO7__POX_ERRSUM__HUNG_BUS (1UL << 28)
#define IO7__POX_ERRSUM__UPE_ERROR__S (51)
#define IO7__POX_ERRSUM__UPE_ERROR__M (0xffUL)
#define IO7__POX_ERRSUM__UPE_ERROR GEN_MASK(IO7__POX_ERRSUM__UPE_ERROR)
#define IO7__POX_ERRSUM__TLB_ERR (1UL << 59)
#define IO7__POX_ERRSUM__ERR_VALID (1UL << 63)
#define IO7__POX_ERRSUM__TRANS_SUM__MASK (IO7__POX_ERRSUM__MRETRY_TO | \
IO7__POX_ERRSUM__PCIX_UX_SPL | \
IO7__POX_ERRSUM__PCIX_SPLIT_TO | \
IO7__POX_ERRSUM__DMA_TO | \
IO7__POX_ERRSUM__MABORT_MASK | \
IO7__POX_ERRSUM__TABORT_MASK | \
IO7__POX_ERRSUM__SERR | \
IO7__POX_ERRSUM__ADDRERR_STB | \
IO7__POX_ERRSUM__PERR | \
IO7__POX_ERRSUM__DATAERR_STB_NIOW |\
IO7__POX_ERRSUM__DETECTED_PERR | \
IO7__POX_ERRSUM__PM_PERR | \
IO7__POX_ERRSUM__PT_SCERROR | \
IO7__POX_ERRSUM__UPE_ERROR)
if (!(err_sum & IO7__POX_ERRSUM__ERR_VALID))
return;
/*
* First the transaction summary errors
*/
if (err_sum & IO7__POX_ERRSUM__MRETRY_TO)
printk("%s IO7 Master Retry Timeout expired\n",
err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PCIX_UX_SPL)
printk("%s Unexpected Split Completion\n",
err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PCIX_SPLIT_TO)
printk("%s IO7 Split Completion Timeout expired\n",
err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__DMA_TO)
printk("%s Hung bus during DMA transaction\n",
err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__MABORT_MASK)
printk("%s Master Abort\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PT_TABORT)
printk("%s IO7 Asserted Target Abort\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PM_TABORT)
printk("%s IO7 Received Target Abort\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__ADDRERR_STB) {
printk("%s Address or PCI-X Attribute Parity Error\n",
err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__SERR)
printk("%s IO7 Asserted SERR\n", err_print_prefix);
}
if (err_sum & IO7__POX_ERRSUM__PERR) {
if (err_sum & IO7__POX_ERRSUM__DATAERR_STB_NIOW)
printk("%s IO7 Detected Data Parity Error\n",
err_print_prefix);
else
printk("%s Split Completion Response with "
"Parity Error\n", err_print_prefix);
}
if (err_sum & IO7__POX_ERRSUM__DETECTED_PERR)
printk("%s PERR detected\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PM_PERR)
printk("%s PERR while IO7 is master\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PT_SCERROR) {
printk("%s IO7 Received Split Completion Error message\n",
err_print_prefix);
marvel_print_pox_spl_cmplt(port->pox_spl_cmplt);
}
if (err_sum & IO7__POX_ERRSUM__UPE_ERROR) {
unsigned int upe_error = EXTRACT(err_sum,
IO7__POX_ERRSUM__UPE_ERROR);
int i;
static char *upe_errors[] = {
"Parity Error on MSI write data",
"MSI read (MSI window is write only",
"TLB - Invalid WR transaction",
"TLB - Invalid RD transaction",
"DMA - WR error (see north port)",
"DMA - RD error (see north port)",
"PPR - WR error (see north port)",
"PPR - RD error (see north port)"
};
printk("%s UPE Error:\n", err_print_prefix);
for (i = 0; i < 8; i++) {
if (upe_error & (1 << i))
printk("%s %s\n", err_print_prefix,
upe_errors[i]);
}
}
/*
* POx_TRANS_SUM, if appropriate.
*/
if (err_sum & IO7__POX_ERRSUM__TRANS_SUM__MASK)
marvel_print_pox_trans_sum(port->pox_trans_sum);
/*
* Then TLB_ERR.
*/
if (err_sum & IO7__POX_ERRSUM__TLB_ERR) {
printk("%s TLB ERROR\n", err_print_prefix);
marvel_print_pox_tlb_err(port->pox_tlb_err);
}
/*
* And the single bit status errors.
*/
if (err_sum & IO7__POX_ERRSUM__AGP_REQQ_OVFL)
printk("%s AGP Request Queue Overflow\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__AGP_SYNC_ERR)
printk("%s AGP Sync Error\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__PCIX_DISCARD_SPL)
printk("%s Discarded split completion\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__DMA_RD_TO)
printk("%s DMA Read Timeout\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__CSR_NXM_RD)
printk("%s CSR NXM READ\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__CSR_NXM_WR)
printk("%s CSR NXM WRITE\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__DETECTED_SERR)
printk("%s SERR detected\n", err_print_prefix);
if (err_sum & IO7__POX_ERRSUM__HUNG_BUS)
printk("%s HUNG BUS detected\n", err_print_prefix);
}
#endif /* CONFIG_VERBOSE_MCHECK */
static struct ev7_pal_io_subpacket *
marvel_find_io7_with_error(struct ev7_lf_subpackets *lf_subpackets)
{
struct ev7_pal_io_subpacket *io = lf_subpackets->io;
struct io7 *io7;
int i;
/*
* Caller must provide the packet to fill
*/
if (!io)
return NULL;
/*
* Fill the subpacket with the console's standard fill pattern
*/
memset(io, 0x55, sizeof(*io));
for (io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); ) {
unsigned long err_sum = 0;
err_sum |= io7->csrs->PO7_ERROR_SUM.csr;
for (i = 0; i < IO7_NUM_PORTS; i++) {
if (!io7->ports[i].enabled)
continue;
err_sum |= io7->ports[i].csrs->POx_ERR_SUM.csr;
}
/*
* Is there at least one error?
*/
if (err_sum & (1UL << 63))
break;
}
/*
* Did we find an IO7 with an error?
*/
if (!io7)
return NULL;
/*
* We have an IO7 with an error.
*
* Fill in the IO subpacket.
*/
io->io_asic_rev = io7->csrs->IO_ASIC_REV.csr;
io->io_sys_rev = io7->csrs->IO_SYS_REV.csr;
io->io7_uph = io7->csrs->IO7_UPH.csr;
io->hpi_ctl = io7->csrs->HPI_CTL.csr;
io->crd_ctl = io7->csrs->CRD_CTL.csr;
io->hei_ctl = io7->csrs->HEI_CTL.csr;
io->po7_error_sum = io7->csrs->PO7_ERROR_SUM.csr;
io->po7_uncrr_sym = io7->csrs->PO7_UNCRR_SYM.csr;
io->po7_crrct_sym = io7->csrs->PO7_CRRCT_SYM.csr;
io->po7_ugbge_sym = io7->csrs->PO7_UGBGE_SYM.csr;
io->po7_err_pkt0 = io7->csrs->PO7_ERR_PKT[0].csr;
io->po7_err_pkt1 = io7->csrs->PO7_ERR_PKT[1].csr;
for (i = 0; i < IO7_NUM_PORTS; i++) {
io7_ioport_csrs *csrs = io7->ports[i].csrs;
if (!io7->ports[i].enabled)
continue;
io->ports[i].pox_err_sum = csrs->POx_ERR_SUM.csr;
io->ports[i].pox_tlb_err = csrs->POx_TLB_ERR.csr;
io->ports[i].pox_spl_cmplt = csrs->POx_SPL_COMPLT.csr;
io->ports[i].pox_trans_sum = csrs->POx_TRANS_SUM.csr;
io->ports[i].pox_first_err = csrs->POx_FIRST_ERR.csr;
io->ports[i].pox_mult_err = csrs->POx_MULT_ERR.csr;
io->ports[i].pox_dm_source = csrs->POx_DM_SOURCE.csr;
io->ports[i].pox_dm_dest = csrs->POx_DM_DEST.csr;
io->ports[i].pox_dm_size = csrs->POx_DM_SIZE.csr;
io->ports[i].pox_dm_ctrl = csrs->POx_DM_CTRL.csr;
/*
* Ack this port's errors, if any. POx_ERR_SUM must be last.
*
* Most of the error registers get cleared and unlocked when
* the associated bits in POx_ERR_SUM are cleared (by writing
* 1). POx_TLB_ERR is an exception and must be explicitly
* cleared.
*/
csrs->POx_TLB_ERR.csr = io->ports[i].pox_tlb_err;
csrs->POx_ERR_SUM.csr = io->ports[i].pox_err_sum;
mb();
csrs->POx_ERR_SUM.csr;
}
/*
* Ack any port 7 error(s).
*/
io7->csrs->PO7_ERROR_SUM.csr = io->po7_error_sum;
mb();
io7->csrs->PO7_ERROR_SUM.csr;
/*
* Correct the io7_pid.
*/
lf_subpackets->io_pid = io7->pe;
return io;
}
static int
marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print)
{
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
struct ev7_pal_io_subpacket *io = lf_subpackets->io;
int i;
#endif /* CONFIG_VERBOSE_MCHECK */
#define MARVEL_IO_ERR_VALID(x) ((x) & (1UL << 63))
if (!lf_subpackets->logout || !lf_subpackets->io)
return status;
/*
* The PALcode only builds an IO subpacket if there is a
* locally connected IO7. In the cases of
* 1) a uniprocessor kernel
* 2) an mp kernel before the local secondary has called in
* error interrupts are all directed to the primary processor.
* In that case, we may not have an IO subpacket at all and, event
* if we do, it may not be the right now.
*
* If the RBOX indicates an I/O error interrupt, make sure we have
* the correct IO7 information. If we don't have an IO subpacket
* or it's the wrong one, try to find the right one.
*
* RBOX I/O error interrupts are indicated by RBOX_INT<29> and
* RBOX_INT<10>.
*/
if ((lf_subpackets->io->po7_error_sum & (1UL << 32)) ||
((lf_subpackets->io->po7_error_sum |
lf_subpackets->io->ports[0].pox_err_sum |
lf_subpackets->io->ports[1].pox_err_sum |
lf_subpackets->io->ports[2].pox_err_sum |
lf_subpackets->io->ports[3].pox_err_sum) & (1UL << 63))) {
/*
* Either we have no IO subpacket or no error is
* indicated in the one we do have. Try find the
* one with the error.
*/
if (!marvel_find_io7_with_error(lf_subpackets))
return status;
}
/*
* We have an IO7 indicating an error - we're going to report it
*/
status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
printk("%s*Error occurred on IO7 at PID %u\n",
err_print_prefix, lf_subpackets->io_pid);
/*
* Check port 7 first
*/
if (lf_subpackets->io->po7_error_sum & IO7__PO7_ERRSUM__ERR_MASK) {
marvel_print_po7_err_sum(io);
#if 0
printk("%s PORT 7 ERROR:\n"
"%s PO7_ERROR_SUM: %016lx\n"
"%s PO7_UNCRR_SYM: %016lx\n"
"%s PO7_CRRCT_SYM: %016lx\n"
"%s PO7_UGBGE_SYM: %016lx\n"
"%s PO7_ERR_PKT0: %016lx\n"
"%s PO7_ERR_PKT1: %016lx\n",
err_print_prefix,
err_print_prefix, io->po7_error_sum,
err_print_prefix, io->po7_uncrr_sym,
err_print_prefix, io->po7_crrct_sym,
err_print_prefix, io->po7_ugbge_sym,
err_print_prefix, io->po7_err_pkt0,
err_print_prefix, io->po7_err_pkt1);
#endif
}
/*
* Then loop through the ports
*/
for (i = 0; i < IO7_NUM_PORTS; i++) {
if (!MARVEL_IO_ERR_VALID(io->ports[i].pox_err_sum))
continue;
printk("%s PID %u PORT %d POx_ERR_SUM: %016lx\n",
err_print_prefix,
lf_subpackets->io_pid, i, io->ports[i].pox_err_sum);
marvel_print_pox_err(io->ports[i].pox_err_sum, &io->ports[i]);
printk("%s [ POx_FIRST_ERR: %016lx ]\n",
err_print_prefix, io->ports[i].pox_first_err);
marvel_print_pox_err(io->ports[i].pox_first_err,
&io->ports[i]);
}
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
{
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
/*
* I/O error?
*/
#define EV7__RBOX_INT__IO_ERROR__MASK 0x20000400ul
if (lf_subpackets->logout &&
(lf_subpackets->logout->rbox_int & 0x20000400ul))
status = marvel_process_io_error(lf_subpackets, print);
/*
* Probing behind PCI-X bridges can cause machine checks on
* Marvel when the probe is handled by the bridge as a split
* completion transaction. The symptom is an ERROR_RESPONSE
* to a CONFIG address. Since these errors will happen in
* normal operation, dismiss them.
*
* Dismiss if:
* C_STAT = 0x14 (Error Reponse)
* C_STS<3> = 0 (C_ADDR valid)
* C_ADDR<42> = 1 (I/O)
* C_ADDR<31:22> = 111110xxb (PCI Config space)
*/
if (lf_subpackets->ev7 &&
(lf_subpackets->ev7->c_stat == 0x14) &&
!(lf_subpackets->ev7->c_sts & 0x8) &&
((lf_subpackets->ev7->c_addr & 0x400ff000000ul)
== 0x400fe000000ul))
status = MCHK_DISPOSITION_DISMISS;
return status;
}
void
marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
struct ev7_lf_subpackets subpacket_collection = { NULL, };
struct ev7_pal_io_subpacket scratch_io_packet = { 0, };
struct ev7_lf_subpackets *lf_subpackets = NULL;
int disposition = MCHK_DISPOSITION_UNKNOWN_ERROR;
char *saved_err_prefix = err_print_prefix;
char *error_type = NULL;
/*
* Sync the processor
......@@ -30,21 +1059,93 @@ marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
mb();
draina();
el_process_subpacket(el_ptr);
switch(vector) {
case SCB_Q_SYSEVENT:
printk(KERN_CRIT "MARVEL SYSEVENT %ld\n", vector);
process_frame = marvel_process_680_frame;
error_type = "System Event";
break;
case SCB_Q_SYSMCHK:
process_frame = marvel_process_logout_frame;
error_type = "System Uncorrectable Error";
break;
case SCB_Q_SYSERR:
printk(KERN_CRIT "MARVEL SYSMCHK/ERR %ld\n", vector);
process_frame = marvel_process_logout_frame;
error_type = "System Correctable Error";
break;
default:
/* Don't know it - pass it up. */
return ev7_machine_check(vector, la_ptr, regs);
}
/*
* A system event or error has occured, handle it here.
*
* Any errors in the logout frame have already been cleared by the
* PALcode, so just parse it.
*/
err_print_prefix = KERN_CRIT;
/*
* Parse the logout frame without printing first. If the only error(s)
* found are classified as "dismissable", then just dismiss them and
* don't print any message
*/
lf_subpackets =
ev7_collect_logout_frame_subpackets(el_ptr,
&subpacket_collection);
if (process_frame && lf_subpackets && lf_subpackets->logout) {
/*
* We might not have the correct (or any) I/O subpacket.
* [ See marvel_process_io_error() for explanation. ]
* If we don't have one, point the io subpacket in
* lf_subpackets at scratch_io_packet so that
* marvel_find_io7_with_error() will have someplace to
* store the info.
*/
if (!lf_subpackets->io)
lf_subpackets->io = &scratch_io_packet;
/*
* Default io_pid to the processor reporting the error
* [this will get changed in marvel_find_io7_with_error()
* if a different one is needed]
*/
lf_subpackets->io_pid = lf_subpackets->logout->whami;
/*
* Evaluate the frames.
*/
disposition = process_frame(lf_subpackets, 0);
}
switch(disposition) {
case MCHK_DISPOSITION_DISMISS:
/* Nothing to do. */
break;
case MCHK_DISPOSITION_REPORT:
/* Recognized error, report it. */
printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
err_print_prefix, error_type,
(unsigned int)vector, (int)smp_processor_id());
el_print_timestamp(&lf_subpackets->logout->timestamp);
process_frame(lf_subpackets, 1);
break;
default:
/* Unknown - dump the annotated subpackets. */
printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
err_print_prefix, error_type,
(unsigned int)vector, (int)smp_processor_id());
el_process_subpacket(el_ptr);
break;
}
err_print_prefix = saved_err_prefix;
/* Release the logout frame. */
wrmces(0x7);
mb();
......
......@@ -14,6 +14,8 @@
#include <asm/core_titan.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include <asm/err_common.h>
#include <asm/err_ev6.h>
#include "err_impl.h"
#include "proto.h"
......@@ -567,6 +569,8 @@ titan_register_error_handlers(void)
cdl_register_subpacket_annotation(&el_titan_annotations[i]);
cdl_register_subpacket_handler(&titan_subpacket_handler);
ev6_register_error_handlers();
}
......
......@@ -167,6 +167,9 @@ setup_irq(unsigned int irq, struct irqaction * new)
unsigned long flags;
irq_desc_t *desc = irq_desc + irq;
if (desc->handler == &no_irq_type)
return -ENOSYS;
/*
* Some drivers like serial.c use request_irq() heavily,
* so we have to be careful not to interfere with a
......@@ -208,7 +211,8 @@ setup_irq(unsigned int irq, struct irqaction * new)
if (!shared) {
desc->depth = 0;
desc->status &= ~IRQ_DISABLED;
desc->status &=
~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS);
desc->handler->startup(irq);
}
spin_unlock_irqrestore(&desc->lock,flags);
......@@ -353,12 +357,10 @@ prof_cpu_mask_write_proc(struct file *file, const char *buffer,
static void
register_irq_proc (unsigned int irq)
{
#ifdef CONFIG_SMP
struct proc_dir_entry *entry;
#endif
char name [MAX_NAMELEN];
if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
irq_dir[irq])
return;
memset(name, 0, MAX_NAMELEN);
......@@ -369,13 +371,16 @@ register_irq_proc (unsigned int irq)
#ifdef CONFIG_SMP
if (irq_desc[irq].handler->set_affinity) {
struct proc_dir_entry *entry;
/* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
entry->nlink = 1;
entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc;
if (entry) {
entry->nlink = 1;
entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc;
}
smp_affinity_entry[irq] = entry;
}
......
......@@ -280,7 +280,7 @@ common_swizzle(struct pci_dev *dev, u8 *pinp)
{
struct pci_controller *hose = dev->sysdata;
if (dev->bus->number != hose->first_busno) {
if (dev->bus != hose->bus) {
u8 pin = *pinp;
do {
pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
......@@ -398,15 +398,20 @@ common_init_pci(void)
struct pci_controller *hose;
struct pci_bus *bus;
int next_busno;
int need_domain_info = 0;
/* Scan all of the recorded PCI controllers. */
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
hose->first_busno = next_busno;
hose->last_busno = 0xff;
bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose);
hose->bus = bus;
next_busno = hose->last_busno = bus->subordinate;
next_busno += 1;
hose->need_domain_info = need_domain_info;
next_busno = bus->subordinate + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */
if (next_busno > 224) {
next_busno = 0;
need_domain_info = 1;
}
}
if (pci_probe_only)
......
......@@ -463,7 +463,7 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
struct pci_controller *hose = dev->sysdata;
int slot, pin = *pinp;
if (hose->first_busno == dev->bus->number) {
if (hose->bus == dev->bus) {
slot = PCI_SLOT(dev->devfn);
}
/* Check for the built-in bridge on hose 1. */
......
......@@ -200,7 +200,6 @@ nautilus_init_pci(void)
/* Scan our single hose. */
bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
hose->bus = bus;
hose->last_busno = bus->subordinate;
irongate = pci_find_slot(0, 0);
bus->self = irongate;
......
......@@ -149,7 +149,9 @@ common_init_rtc(void)
/* Reset periodic interrupt frequency. */
x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
if (x != 0x26 && x != 0x19 && x != 0x06) {
/* Test includes known working values on various platforms
where 0x26 is wrong; we refuse to change those. */
if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
CMOS_WRITE(0x26, RTC_FREQ_SELECT);
}
......
......@@ -80,10 +80,10 @@ typedef struct {
io7_csr POx_MEM_ADR_EXT; /* 0x0100 */
io7_csr POx_XCAL_CTRL;
io7_csr rsvd1[2]; /* ?? spec doesn't show 0x180 */
io7_csr POx_DM_SOURCE; /* ox0200 */
io7_csr POx_DM_SOURCE; /* 0x0200 */
io7_csr POx_DM_DEST;
io7_csr POx_DM_SIZE;
io7_csr POx_DM_STATE;
io7_csr POx_DM_CTRL;
io7_csr rsvd2[4]; /* 0x0300 */
/* AGP Control Registers -- port 3 only */
......
/*
* linux/include/asm-alpha/err_common.h
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Contains declarations and macros to support Alpha error handling
* implementations.
*/
#ifndef __ALPHA_ERR_COMMON_H
#define __ALPHA_ERR_COMMON_H 1
/*
* SCB Vector definitions
*/
#define SCB_Q_SYSERR 0x620
#define SCB_Q_PROCERR 0x630
#define SCB_Q_SYSMCHK 0x660
#define SCB_Q_PROCMCHK 0x670
#define SCB_Q_SYSEVENT 0x680
/*
* Disposition definitions for logout frame parser
*/
#define MCHK_DISPOSITION_UNKNOWN_ERROR 0x00
#define MCHK_DISPOSITION_REPORT 0x01
#define MCHK_DISPOSITION_DISMISS 0x02
/*
* Error Log definitions
*/
/*
* Types
*/
#define EL_CLASS__TERMINATION (0)
# define EL_TYPE__TERMINATION__TERMINATION (0)
#define EL_CLASS__HEADER (5)
# define EL_TYPE__HEADER__SYSTEM_ERROR_FRAME (1)
# define EL_TYPE__HEADER__SYSTEM_EVENT_FRAME (2)
# define EL_TYPE__HEADER__HALT_FRAME (3)
# define EL_TYPE__HEADER__LOGOUT_FRAME (19)
#define EL_CLASS__GENERAL_NOTIFICATION (9)
#define EL_CLASS__PCI_ERROR_FRAME (11)
#define EL_CLASS__REGATTA_FAMILY (12)
# define EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME (1)
# define EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME (2)
# define EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME (3)
# define EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED (8)
# define EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED (9)
# define EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED (10)
# define EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT (11)
# define EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT (12)
#define EL_CLASS__PAL (14)
# define EL_TYPE__PAL__LOGOUT_FRAME (1)
# define EL_TYPE__PAL__EV7_PROCESSOR (4)
# define EL_TYPE__PAL__EV7_ZBOX (5)
# define EL_TYPE__PAL__EV7_RBOX (6)
# define EL_TYPE__PAL__EV7_IO (7)
# define EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE (10)
# define EL_TYPE__PAL__ENV__AIRMOVER_FAN (11)
# define EL_TYPE__PAL__ENV__VOLTAGE (12)
# define EL_TYPE__PAL__ENV__INTRUSION (13)
# define EL_TYPE__PAL__ENV__POWER_SUPPLY (14)
# define EL_TYPE__PAL__ENV__LAN (15)
# define EL_TYPE__PAL__ENV__HOT_PLUG (16)
union el_timestamp {
struct {
u8 second;
u8 minute;
u8 hour;
u8 day;
u8 month;
u8 year;
} b;
u64 as_int;
};
struct el_subpacket {
u16 length; /* length of header (in bytes) */
u16 class; /* header class and type... */
u16 type; /* ...determine content */
u16 revision; /* header revision */
union {
struct { /* Class 5, Type 1 - System Error */
u32 frame_length;
u32 frame_packet_count;
} sys_err;
struct { /* Class 5, Type 2 - System Event */
union el_timestamp timestamp;
u32 frame_length;
u32 frame_packet_count;
} sys_event;
struct { /* Class 5, Type 3 - Double Error Halt */
u16 halt_code;
u16 reserved;
union el_timestamp timestamp;
u32 frame_length;
u32 frame_packet_count;
} err_halt;
struct { /* Clasee 5, Type 19 - Logout Frame Header */
u32 frame_length;
u32 frame_flags;
u32 cpu_offset;
u32 system_offset;
} logout_header;
struct { /* Class 12 - Regatta */
u64 cpuid;
u64 data_start[1];
} regatta_frame;
struct { /* Raw */
u64 data_start[1];
} raw;
} by_type;
};
#endif /* __ALPHA_ERR_COMMON_H */
#ifndef __ALPHA_ERR_EV6_H
#define __ALPHA_ERR_EV6_H 1
/* Dummy include for now. */
#endif /* __ALPHA_ERR_EV6_H */
#ifndef __ALPHA_ERR_EV7_H
#define __ALPHA_ERR_EV7_H 1
/*
* Data for el packet class PAL (14), type LOGOUT_FRAME (1)
*/
struct ev7_pal_logout_subpacket {
u32 mchk_code;
u32 subpacket_count;
u64 whami;
u64 rbox_whami;
u64 rbox_int;
u64 exc_addr;
union el_timestamp timestamp;
u64 halt_code;
u64 reserved;
};
/*
* Data for el packet class PAL (14), type EV7_PROCESSOR (4)
*/
struct ev7_pal_processor_subpacket {
u64 i_stat;
u64 dc_stat;
u64 c_addr;
u64 c_syndrome_1;
u64 c_syndrome_0;
u64 c_stat;
u64 c_sts;
u64 mm_stat;
u64 exc_addr;
u64 ier_cm;
u64 isum;
u64 pal_base;
u64 i_ctl;
u64 process_context;
u64 cbox_ctl;
u64 cbox_stp_ctl;
u64 cbox_acc_ctl;
u64 cbox_lcl_set;
u64 cbox_gbl_set;
u64 bbox_ctl;
u64 bbox_err_sts;
u64 bbox_err_idx;
u64 cbox_ddp_err_sts;
u64 bbox_dat_rmp;
u64 reserved[2];
};
/*
* Data for el packet class PAL (14), type EV7_ZBOX (5)
*/
struct ev7_pal_zbox_subpacket {
u32 zbox0_dram_err_status_1;
u32 zbox0_dram_err_status_2;
u32 zbox0_dram_err_status_3;
u32 zbox0_dram_err_ctl;
u32 zbox0_dram_err_adr;
u32 zbox0_dift_timeout;
u32 zbox0_dram_mapper_ctl;
u32 zbox0_frc_err_adr;
u32 zbox0_dift_err_status;
u32 reserved1;
u32 zbox1_dram_err_status_1;
u32 zbox1_dram_err_status_2;
u32 zbox1_dram_err_status_3;
u32 zbox1_dram_err_ctl;
u32 zbox1_dram_err_adr;
u32 zbox1_dift_timeout;
u32 zbox1_dram_mapper_ctl;
u32 zbox1_frc_err_adr;
u32 zbox1_dift_err_status;
u32 reserved2;
u64 cbox_ctl;
u64 cbox_stp_ctl;
u64 zbox0_error_pa;
u64 zbox1_error_pa;
u64 zbox0_ored_syndrome;
u64 zbox1_ored_syndrome;
u64 reserved3[2];
};
/*
* Data for el packet class PAL (14), type EV7_RBOX (6)
*/
struct ev7_pal_rbox_subpacket {
u64 rbox_cfg;
u64 rbox_n_cfg;
u64 rbox_s_cfg;
u64 rbox_e_cfg;
u64 rbox_w_cfg;
u64 rbox_n_err;
u64 rbox_s_err;
u64 rbox_e_err;
u64 rbox_w_err;
u64 rbox_io_cfg;
u64 rbox_io_err;
u64 rbox_l_err;
u64 rbox_whoami;
u64 rbox_imask;
u64 rbox_intq;
u64 rbox_int;
u64 reserved[2];
};
/*
* Data for el packet class PAL (14), type EV7_IO (7)
*/
struct ev7_pal_io_one_port {
u64 pox_err_sum;
u64 pox_tlb_err;
u64 pox_spl_cmplt;
u64 pox_trans_sum;
u64 pox_first_err;
u64 pox_mult_err;
u64 pox_dm_source;
u64 pox_dm_dest;
u64 pox_dm_size;
u64 pox_dm_ctrl;
u64 reserved;
};
struct ev7_pal_io_subpacket {
u64 io_asic_rev;
u64 io_sys_rev;
u64 io7_uph;
u64 hpi_ctl;
u64 crd_ctl;
u64 hei_ctl;
u64 po7_error_sum;
u64 po7_uncrr_sym;
u64 po7_crrct_sym;
u64 po7_ugbge_sym;
u64 po7_err_pkt0;
u64 po7_err_pkt1;
u64 reserved[2];
struct ev7_pal_io_one_port ports[4];
};
/*
* Environmental subpacket. Data used for el packets:
* class PAL (14), type AMBIENT_TEMPERATURE (10)
* class PAL (14), type AIRMOVER_FAN (11)
* class PAL (14), type VOLTAGE (12)
* class PAL (14), type INTRUSION (13)
* class PAL (14), type POWER_SUPPLY (14)
* class PAL (14), type LAN (15)
* class PAL (14), type HOT_PLUG (16)
*/
struct ev7_pal_environmental_subpacket {
u16 cabinet;
u16 drawer;
u16 reserved1[2];
u8 module_type;
u8 unit_id; /* unit reporting condition */
u8 reserved2;
u8 condition; /* condition reported */
};
/*
* Convert environmental type to index
*/
static inline int ev7_lf_env_index(int type)
{
BUG_ON((type < EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE)
|| (type > EL_TYPE__PAL__ENV__HOT_PLUG));
return type - EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE;
}
/*
* Data for generic el packet class PAL.
*/
struct ev7_pal_subpacket {
union {
struct ev7_pal_logout_subpacket logout; /* Type 1 */
struct ev7_pal_processor_subpacket ev7; /* Type 4 */
struct ev7_pal_zbox_subpacket zbox; /* Type 5 */
struct ev7_pal_rbox_subpacket rbox; /* Type 6 */
struct ev7_pal_io_subpacket io; /* Type 7 */
struct ev7_pal_environmental_subpacket env; /* Type 10-16 */
u64 as_quad[1]; /* Raw u64 */
} by_type;
};
/*
* Struct to contain collected logout from subpackets.
*/
struct ev7_lf_subpackets {
struct ev7_pal_logout_subpacket *logout; /* Type 1 */
struct ev7_pal_processor_subpacket *ev7; /* Type 4 */
struct ev7_pal_zbox_subpacket *zbox; /* Type 5 */
struct ev7_pal_rbox_subpacket *rbox; /* Type 6 */
struct ev7_pal_io_subpacket *io; /* Type 7 */
struct ev7_pal_environmental_subpacket *env[7]; /* Type 10-16 */
unsigned int io_pid;
};
#endif /* __ALPHA_ERR_EV7_H */
......@@ -16,7 +16,20 @@
many places throughout the kernel to size static arrays. That's ok,
we'll use alpha_mv.nr_irqs when we want the real thing. */
# define NR_IRQS (32768 + 16) /* marvel - 32 pids*/
/* When LEGACY_START_ADDRESS is selected, we leave out:
TITAN
WILDFIRE
MARVEL
This helps keep the kernel object size reasonable for the majority
of machines.
*/
# if defined(CONFIG_ALPHA_LEGACY_START_ADDRESS)
# define NR_IRQS (128) /* max is RAWHIDE/TAKARA */
# else
# define NR_IRQS (32768 + 16) /* marvel - 32 pids */
# endif
#elif defined(CONFIG_ALPHA_CABRIOLET) || \
defined(CONFIG_ALPHA_EB66P) || \
......
......@@ -37,8 +37,9 @@ struct pci_controller {
unsigned long config_space_base;
unsigned int index;
unsigned int first_busno;
unsigned int last_busno;
/* For compatibility with current (as of July 2003) pciutils
and XFree86. Eventually will be removed. */
unsigned int need_domain_info;
struct pci_iommu_arena *sg_pci;
struct pci_iommu_arena *sg_isa;
......@@ -194,15 +195,14 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
/* Bus number == domain number until we get above 256 busses */
static inline int pci_name_bus(char *name, struct pci_bus *bus)
{
int domain = pci_domain_nr(bus);
struct pci_controller *hose = bus->sysdata;
if (domain < 256) {
sprintf(name, "%02x", domain);
if (likely(hose->need_domain_info == 0)) {
sprintf(name, "%02x", bus->number);
} else {
sprintf(name, "%04x:%02x", domain, bus->number);
sprintf(name, "%04x:%02x", hose->index, bus->number);
}
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment