On Thu, Jun 27, 2002 at 02:21:30PM +0200, Maciej W. Rozycki wrote:
> On Wed, 26 Jun 2002, Ladislav Michl wrote:
>
> > +int be_ip22_handler(struct pt_regs *regs, int is_fixup)
> > +{
> > + save_and_clear_buserr();
> > + if (nofault) {
> > + nofault = 0;
> > + compute_return_epc(regs);
> > + return MIPS_BE_DISCARD;
> > + }
> > + return MIPS_BE_FIXUP;
> > +}
>
> I wouldn't use nofault -- it leads to reentrancy problems and I don't
> think you really need it. You probably need to code it like this:
>
> {
> save_and_clear_buserr();
>
> return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
> }
>
> unless:
>
> 1. There is a condition when for is_fixup true you should ignore the fixup
> anyway (e.g. what the bus error logic reports is irrelevant to fixups).
> You should choose between MIPS_BE_FATAL and MIPS_BE_DISCARD then.
>
> 2. There is a condition when for is_fixup false, an error is not fatal and
> execution should get restarted. You should return MIPS_BE_DISCARD then.
You are probably right. Unfortunately I cannot verify following patch
(my Indy is currently dead). I hope there is enough brave men for this
dirty job :-)
ladis
--- linux/arch/mips/sgi-ip22/ip22-berr.c.orig Thu Aug 1 23:26:10 2002
+++ linux/arch/mips/sgi-ip22/ip22-berr.c Sun Aug 4 23:03:34 2002
@@ -20,8 +20,6 @@
unsigned int cpu_err_addr; /* Error address reg for CPU */
unsigned int gio_err_addr; /* Error address reg for GIO */
-volatile int nofault;
-
static void save_and_clear_buserr(void)
{
/* save memory controler's error status registers */
@@ -33,6 +31,35 @@
mcmisc_regs->cstat = mcmisc_regs->gstat = 0;
}
+#define GIO_ERRMASK 0xff00
+#define CPU_ERRMASK 0x3f00
+
+static void print_buserr(void)
+{
+ if (cpu_err_stat & CPU_ERRMASK)
+ printk(KERN_ALERT "CPU Error/Addr 0x%x<%s%s%s%s%s%s> 0x%08x\n",
+ cpu_err_stat,
+ cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "",
+ cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "",
+ cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "",
+ cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "",
+ cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "",
+ cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "",
+ cpu_err_addr);
+ if (gio_err_stat & GIO_ERRMASK)
+ printk(KERN_ALERT "GIO Error/Addr 0x%x:<%s%s%s%s%s%s%s%s>
0x08%x\n",
+ gio_err_stat,
+ gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "",
+ gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "",
+ gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "",
+ gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "",
+ gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "",
+ gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "",
+ gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "",
+ gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "",
+ gio_err_addr);
+}
+
/*
* MC sends an interrupt whenever bus or parity errors occur. In addition,
* if the error happened during a CPU read, it also asserts the bus error
@@ -43,6 +70,7 @@
void be_ip22_interrupt(int irq, struct pt_regs *regs)
{
save_and_clear_buserr();
+ print_buserr();
printk(KERN_ALERT "Bus error, epc == %08lx, ra == %08lx\n",
regs->cp0_epc, regs->regs[31]);
die_if_kernel("Oops", regs);
@@ -52,24 +80,10 @@
int be_ip22_handler(struct pt_regs *regs, int is_fixup)
{
save_and_clear_buserr();
- if (nofault) {
- nofault = 0;
- compute_return_epc(regs);
- return MIPS_BE_DISCARD;
- }
- return MIPS_BE_FIXUP;
-}
-
-int ip22_baddr(unsigned int *val, unsigned long addr)
-{
- nofault = 1;
- *val = *(volatile unsigned int *) addr;
- __asm__ __volatile__("nop;nop;nop;nop");
- if (nofault) {
- nofault = 0;
- return 0;
- }
- return -EFAULT;
+ if (is_fixup)
+ return MIPS_BE_FIXUP;
+ print_buserr();
+ return MIPS_BE_FATAL;
}
void __init bus_error_init(void)
--- linux/arch/mips/sgi-ip22/ip22-gio.c.orig Thu Aug 1 23:26:23 2002
+++ linux/arch/mips/sgi-ip22/ip22-gio.c Sun Aug 4 23:43:35 2002
@@ -11,6 +11,7 @@
#include <linux/proc_fs.h>
#include <asm/addrspace.h>
+#include <asm/paccess.h>
#include <asm/sgi/sgimc.h>
#include <asm/sgi/sgigio.h>
@@ -118,8 +119,6 @@
#define GIO_ROM_PRESENT 0x20000
#define GIO_VENDOR_CODE(x) ((x >> 18) & 0x3fff)
-extern int ip22_baddr(unsigned int *val, unsigned long addr);
-
/**
* sgigio_init - scan the GIO space and figure out what hardware is actually
* present.
@@ -128,9 +127,10 @@
{
unsigned int i, id, found = 0;
- printk("GIO: Scanning for GIO cards...\n");
+ printk("GIO: Probing bus...\n");
for (i = 0; i < GIO_NUM_SLOTS; i++) {
- if (ip22_baddr(&id, KSEG1ADDR(gio_slot[i].base_addr)))
+ if (get_dbe(id, (volatile unsigned int *)
+ KSEG1ADDR(gio_slot[i].base_addr)))
continue;
found = 1;
--- linux/include/asm-mips/sgi/sgimc.h.orig Sun Aug 4 22:16:03 2002
+++ linux/include/asm-mips/sgi/sgimc.h Sun Aug 4 22:34:43 2002
@@ -128,11 +128,29 @@
volatile u32 cerr; /* Error address reg for CPU */
u32 _unused22;
volatile u32 cstat; /* Status reg for CPU */
+#define SGIMC_CSTAT_RD 0x00000100 /* read parity error */
+#define SGIMC_CSTAT_PAR 0x00000200 /* CPU parity error */
+#define SGIMC_CSTAT_ADDR 0x00000400 /* memory bus error bad
addr */
+#define SGIMC_CSTAT_SYSAD_PAR 0x00000800 /* sysad parity error */
+#define SGIMC_CSTAT_SYSCMD_PAR 0x00001000 /* syscmd parity error
*/
+#define SGIMC_CSTAT_BAD_DATA 0x00002000 /* bad data identifier
*/
+#define SGIMC_CSTAT_PAR_MASK 0x00001f00 /* parity error mask */
+#define SGIMC_CSTAT_RD_PAR (SGIMC_CSTAT_RD | SGIMC_CSTAT_PAR)
u32 _unused23;
volatile u32 gerr; /* Error address reg for GIO */
u32 _unused24;
volatile u32 gstat; /* Status reg for GIO */
-
+#define SGIMC_GSTAT_RD 0x00000100 /* read parity error */
+#define SGIMC_GSTAT_WR 0x00000200 /* write parity error */
+#define SGIMC_GSTAT_TIME 0x00000400 /* GIO bus timed out */
+#define SGIMC_GSTAT_PROM 0x00000800 /* write to PROM when
PROM_EN
+ not set */
+#define SGIMC_GSTAT_ADDR 0x00001000 /* parity error on addr
+ cycle */
+#define SGIMC_GSTAT_BC 0x00002000 /* parity error on byte
count
+ cycle */
+#define SGIMC_GSTAT_PIO_RD 0x00004000 /* read data parity on pio */
+#define SGIMC_GSTAT_PIO_WR 0x00008000 /* write data parity on pio */
/* Special hard bus locking registers. */
u32 _unused25;
volatile unsigned char syssembit; /* Uni-bit system semaphore */
@@ -146,13 +164,13 @@
/* GIO dma control registers. */
unsigned char _unused30[3];
u32 _unused31[14];
- volatile u32 gio_dma_trans;/* DMA mask to translation GIO addrs */
+ volatile u32 gio_dma_trans; /* DMA mask to translation GIO addrs */
u32 _unused32;
- volatile u32 gio_dma_sbits;/* DMA GIO addr substitution bits */
+ volatile u32 gio_dma_sbits; /* DMA GIO addr substitution bits */
u32 _unused33;
volatile u32 dma_intr_cause; /* DMA IRQ cause indicator bits */
u32 _unused34;
- volatile u32 dma_ctrl; /* Main DMA control reg */
+ volatile u32 dma_ctrl; /* Main DMA control reg */
/* DMA TLB entry 0 */
u32 _unused35;
@@ -181,29 +199,29 @@
/* MC misc control registers live at physical 0x1fa00000. */
extern struct sgimc_misc_ctrl *mcmisc_regs;
-extern u32 *rpsscounter; /* Chirps at 100ns */
+extern u32 *rpsscounter; /* Chirps at 100ns */
struct sgimc_dma_ctrl {
u32 _unused1;
- volatile u32 maddronly; /* Address DMA goes at */
+ volatile u32 maddronly; /* Address DMA goes at */
u32 _unused2;
volatile u32 maddrpdeflts; /* Same as above, plus set defaults */
u32 _unused3;
- volatile u32 dmasz; /* DMA count */
+ volatile u32 dmasz; /* DMA count */
u32 _unused4;
- volatile u32 ssize; /* DMA stride size */
+ volatile u32 ssize; /* DMA stride size */
u32 _unused5;
- volatile u32 gmaddronly; /* Set GIO DMA but do not start trans */
+ volatile u32 gmaddronly; /* Set GIO DMA but do not start trans */
u32 _unused6;
- volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
+ volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
u32 _unused7;
- volatile u32 dmamode; /* DMA mode config bit settings */
+ volatile u32 dmamode; /* DMA mode config bit settings */
u32 _unused8;
volatile u32 dmaccount; /* Zoom and byte count for DMA */
u32 _unused9;
- volatile u32 dmastart; /* Pedal to the metal. */
+ volatile u32 dmastart; /* Pedal to the metal. */
u32 _unused10;
- volatile u32 dmarunning; /* DMA op is in progress */
+ volatile u32 dmarunning; /* DMA op is in progress */
u32 _unused11;
/* Set dma addr, defaults, and kick it */
--- linux/include/asm-mips64/sgi/sgimc.h.orig Sun Aug 4 22:40:27 2002
+++ linux/include/asm-mips64/sgi/sgimc.h Sun Aug 4 22:40:40 2002
@@ -128,11 +128,29 @@
volatile u32 cerr; /* Error address reg for CPU */
u32 _unused22;
volatile u32 cstat; /* Status reg for CPU */
+#define SGIMC_CSTAT_RD 0x00000100 /* read parity error */
+#define SGIMC_CSTAT_PAR 0x00000200 /* CPU parity error */
+#define SGIMC_CSTAT_ADDR 0x00000400 /* memory bus error bad
addr */
+#define SGIMC_CSTAT_SYSAD_PAR 0x00000800 /* sysad parity error */
+#define SGIMC_CSTAT_SYSCMD_PAR 0x00001000 /* syscmd parity error
*/
+#define SGIMC_CSTAT_BAD_DATA 0x00002000 /* bad data identifier
*/
+#define SGIMC_CSTAT_PAR_MASK 0x00001f00 /* parity error mask */
+#define SGIMC_CSTAT_RD_PAR (SGIMC_CSTAT_RD | SGIMC_CSTAT_PAR)
u32 _unused23;
volatile u32 gerr; /* Error address reg for GIO */
u32 _unused24;
volatile u32 gstat; /* Status reg for GIO */
-
+#define SGIMC_GSTAT_RD 0x00000100 /* read parity error */
+#define SGIMC_GSTAT_WR 0x00000200 /* write parity error */
+#define SGIMC_GSTAT_TIME 0x00000400 /* GIO bus timed out */
+#define SGIMC_GSTAT_PROM 0x00000800 /* write to PROM when
PROM_EN
+ not set */
+#define SGIMC_GSTAT_ADDR 0x00001000 /* parity error on addr
+ cycle */
+#define SGIMC_GSTAT_BC 0x00002000 /* parity error on byte
count
+ cycle */
+#define SGIMC_GSTAT_PIO_RD 0x00004000 /* read data parity on pio */
+#define SGIMC_GSTAT_PIO_WR 0x00008000 /* write data parity on pio */
/* Special hard bus locking registers. */
u32 _unused25;
volatile unsigned char syssembit; /* Uni-bit system semaphore */
@@ -146,13 +164,13 @@
/* GIO dma control registers. */
unsigned char _unused30[3];
u32 _unused31[14];
- volatile u32 gio_dma_trans;/* DMA mask to translation GIO addrs */
+ volatile u32 gio_dma_trans; /* DMA mask to translation GIO addrs */
u32 _unused32;
- volatile u32 gio_dma_sbits;/* DMA GIO addr substitution bits */
+ volatile u32 gio_dma_sbits; /* DMA GIO addr substitution bits */
u32 _unused33;
volatile u32 dma_intr_cause; /* DMA IRQ cause indicator bits */
u32 _unused34;
- volatile u32 dma_ctrl; /* Main DMA control reg */
+ volatile u32 dma_ctrl; /* Main DMA control reg */
/* DMA TLB entry 0 */
u32 _unused35;
@@ -181,29 +199,29 @@
/* MC misc control registers live at physical 0x1fa00000. */
extern struct sgimc_misc_ctrl *mcmisc_regs;
-extern u32 *rpsscounter; /* Chirps at 100ns */
+extern u32 *rpsscounter; /* Chirps at 100ns */
struct sgimc_dma_ctrl {
u32 _unused1;
- volatile u32 maddronly; /* Address DMA goes at */
+ volatile u32 maddronly; /* Address DMA goes at */
u32 _unused2;
volatile u32 maddrpdeflts; /* Same as above, plus set defaults */
u32 _unused3;
- volatile u32 dmasz; /* DMA count */
+ volatile u32 dmasz; /* DMA count */
u32 _unused4;
- volatile u32 ssize; /* DMA stride size */
+ volatile u32 ssize; /* DMA stride size */
u32 _unused5;
- volatile u32 gmaddronly; /* Set GIO DMA but do not start trans */
+ volatile u32 gmaddronly; /* Set GIO DMA but do not start trans */
u32 _unused6;
- volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
+ volatile u32 dmaddnpgo; /* Set GIO DMA addr + start transfer */
u32 _unused7;
- volatile u32 dmamode; /* DMA mode config bit settings */
+ volatile u32 dmamode; /* DMA mode config bit settings */
u32 _unused8;
- volatile u32 dmacount; /* Zoom and byte count for DMA */
+ volatile u32 dmaccount; /* Zoom and byte count for DMA */
u32 _unused9;
- volatile u32 dmastart; /* Pedal to the metal. */
+ volatile u32 dmastart; /* Pedal to the metal. */
u32 _unused10;
- volatile u32 dmarunning; /* DMA op is in progress */
+ volatile u32 dmarunning; /* DMA op is in progress */
u32 _unused11;
/* Set dma addr, defaults, and kick it */
|