[PATCH] IP28 fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



- ISA DMA is broken on IP28
- bus error handler improved to not issue bus errors for
  speculative accesses to CPU and GIO addresses. We now
  treat CSTAT_ADDR and GSTAT_TIME errors as non fatal, when
  they are issues via MC error interrupt. For real (non
  speculative) bus errors a DBE will be issued, which is
  lethal as before. Handling the issue this way gets rid
  of decoding instructions

Signed-off-by: Thomas Bogendoerfer <tsbogend@xxxxxxxxxxxxxxxx>
---

 arch/mips/Kconfig              |    1 +
 arch/mips/sgi-ip22/ip28-berr.c |  203 +---------------------------------------
 2 files changed, 4 insertions(+), 200 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 3541402..2996b9f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -457,6 +457,7 @@ config SGI_IP28
 	select CSRC_R4K
 	select DEFAULT_SGI_PARTITION
 	select DMA_NONCOHERENT
+	select GENERIC_ISA_DMA_SUPPORT_BROKEN
 	select IRQ_CPU
 	select HW_HAS_EISA
 	select I8253
diff --git a/arch/mips/sgi-ip22/ip28-berr.c b/arch/mips/sgi-ip22/ip28-berr.c
index 0ee5be8..b09d7d5 100644
--- a/arch/mips/sgi-ip22/ip28-berr.c
+++ b/arch/mips/sgi-ip22/ip28-berr.c
@@ -299,198 +299,6 @@ static void print_buserr(const struct pt_regs *regs)
 }
 
 /*
- * Try to find out, whether the bus error is caused by the instruction
- * at EPC, otherwise we have an asynchronous error.
- *
- * Doc1: "MIPS IV Instruction Set", Rev 3.2 (SGI 007-2597-001)
- * Doc2: "MIPS R10000 Microporcessor User's Manual", Ver 2.0 (SGI 007-2490-001)
- * Doc3: "MIPS R4000 Microporcessor User's Manual", 2nd Ed. (SGI 007-2489-001)
- */
-
-#define JMP_INDEX26_OP 1
-#define JMP_REGISTER_OP 2
-#define JMP_PCREL16_OP 3
-#define BASE_OFFSET_OP 4
-#define BASE_IDXREG_OP 5
-
-/* Match virtual address in an insn with physical error address */
-
-static int match_addr(unsigned paddr, unsigned long vaddr)
-{
-	unsigned long uaddr;
-
-	if ((vaddr & 0xffffffff80000000L) == 0xffffffff80000000L)
-		uaddr = (unsigned) CPHYSADDR(vaddr);
-	else if ((vaddr >> 62) == 2)
-		uaddr = (unsigned) XPHYSADDR(vaddr);
-	else {
-		unsigned long eh = vaddr & ~0x1fffL;
-
-		eh |= read_c0_entryhi() & 0xff;
-		write_c0_entryhi(eh);
-		tlb_probe();
-		if (read_c0_index() & 0x80000000)
-			return 0;
-		tlb_read();
-		if (vaddr & (1L << PAGE_SHIFT))
-			uaddr = (unsigned) read_c0_entrylo1();
-		else
-			uaddr = (unsigned) read_c0_entrylo0();
-		uaddr <<= 6;
-		uaddr &= ~PAGE_MASK;
-		uaddr |= vaddr & PAGE_MASK;
-	}
-	return ((uaddr & ~0x7f) == (paddr & ~0x7f));
-}
-
-/* Check, which kind of memory reference is triggered by `insn' */
-
-static int check_special(unsigned insn)
-{
-	/* See Doc1, page A-180 */
-	unsigned func = insn & 0x3f;
-
-	if (8 == func || 8+1 == func) /* JR, JALR */
-		return JMP_REGISTER_OP;
-
-	return 0;
-}
-
-static int check_regimm(unsigned insn)
-{
-	/* See Doc1, page A-180 */
-	unsigned rt = (insn >> 19) & 3; /* bits 20..19[..16] */
-
-	/* BLTZ, BGEZ, BLTZL, BBGEZL || BLTZAL, BGEZAL, BLTZALL, BBGEZALL */
-	if (!rt || 2 == rt)
-		return JMP_PCREL16_OP;
-
-	return 0;
-}
-
-static int check_cop0(unsigned insn)
-{
-	/* See Doc2, pages 287 ff., 187 ff. */
-	if ((insn >> 26) == 5*8+7) /* CACHE */
-		switch ((insn >> 16) & 0x1f) {
-		case Index_Writeback_Inv_D:
-		case Hit_Writeback_Inv_D:
-		case Index_Writeback_Inv_S:
-		case Hit_Writeback_Inv_S:
-			return BASE_OFFSET_OP;
-		}
-	return 0;
-}
-
-static int check_cop1(unsigned insn)
-{
-	/* See Doc1, pages B-108 ff. */
-	unsigned fmt = (insn >> 21) & 0x1f; /* bits 25..21 */
-
-	if (8 == fmt) /* BC1* */
-		return JMP_PCREL16_OP;
-
-	return 0;
-}
-
-static int check_cop1x(unsigned insn)
-{
-	/* See Doc1, pages B-108 ff. */
-	switch (insn & 0x3f) {
-	case 0:   /* LWXC1 */
-	case 1:   /* LDXC1 */
-	case 8:   /* SWXC1 */
-	case 8+1: /* SDXC1 */
-		return BASE_IDXREG_OP;
-	}
-	return 0;
-}
-
-static int check_plain(unsigned insn)
-{
-	/* See Doc1, page A-180 */
-	unsigned opcode = insn >> 26;
-
-	if (2 == opcode || 3 == opcode) /* J, JAL */
-		return JMP_INDEX26_OP;
-
-	if ((4     <= opcode && opcode <= 7) ||   /* BEQ, BNE, BLEZ, BGTZ */
-	    (4+2*8 <= opcode && opcode <= 7+2*8)) /* BEQL, BNEL, BLEZL, BGTZL */
-		return JMP_PCREL16_OP;
-
-	if (6*8+3 == opcode) /* PREF */
-		return 0;
-
-	if (3*8+2 == opcode || 3*8+3 == opcode || /* LDL, LDR */
-	    4*8 <= opcode) /* misc. LOAD, STORE */
-		return BASE_OFFSET_OP;
-
-	return 0;
-}
-
-/* Check, whether the insn at EPC causes a memory access at `paddr' */
-
-static int check_addr_in_insn(unsigned paddr, const struct pt_regs *regs)
-{
-	unsigned long epc;
-	unsigned insn;
-	unsigned long a;
-	int typ;
-
-	epc = regs->cp0_cause & CAUSEF_BD ? regs->cp0_epc:regs->cp0_epc+4;
-
-	/* show_code() from kernel/traps.c */
-	if (__get_user(insn, (u32 *)epc))
-		return 1;
-
-	/* See Doc1, pages A-180, B-108 ff. */
-	switch (insn >> 26) {
-	case 0:
-		typ = check_special(insn);
-		break;
-	case 1:
-		typ = check_regimm(insn);
-		break;
-	case 2*8:   /* COP0 */
-	case 5*8+7: /* CACHE */
-		typ = check_cop0(insn);
-		break;
-	case 2*8+1:
-		typ = check_cop1(insn);
-		break;
-	case 2*8+3:
-		typ = check_cop1x(insn);
-		break;
-	default:
-		typ = check_plain(insn);
-		break;
-	}
-	switch (typ) {
-	case JMP_INDEX26_OP:
-		a = (regs->cp0_epc + 4) & ~0xfffffff;
-		a |= (insn & 0x3ffffff) << 2;
-		return match_addr(paddr, a);
-	case JMP_REGISTER_OP:
-		a = regs->regs[(insn >> 21) & 0x1f];
-		return match_addr(paddr, a);
-	case JMP_PCREL16_OP:
-		a = regs->cp0_epc + 4 + ((insn & 0xffff) << 2);
-		return match_addr(paddr, a);
-	case BASE_OFFSET_OP:
-		a = regs->regs[(insn >> 21) & 0x1f] + (insn & 0xffff);
-		return match_addr(paddr, a);
-	case BASE_IDXREG_OP:
-		a = regs->regs[(insn >> 21) & 0x1f];
-		a += regs->regs[(insn >> 16) & 0x1f];
-		return match_addr(paddr, a);
-	case 0:
-		return 0;
-	}
-	/* Assume it would be too dangerous to continue ... */
-	return 1;
-}
-
-/*
  * Check, whether MC's (virtual) DMA address caused the bus error.
  * See "Virtual DMA Specification", Draft 1.5, Feb 13 1992, SGI
  */
@@ -594,16 +402,11 @@ static int ip28_be_interrupt(const struct pt_regs *regs)
 
 	/* Any state other than "Memory bus error" is fatal. */
 	if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR)
-			goto mips_be_fatal;
-
-	/* GIO errors are fatal */
-	if (gio_err_stat & GIO_ERRMASK)
 		goto mips_be_fatal;
 
-	/* Finding `cpu_err_addr' in the insn at EPC is fatal. */
-	if ((cpu_err_stat & CPU_ERRMASK) &&
-	     check_addr_in_insn(cpu_err_addr, regs))
-			goto mips_be_fatal;
+	/* GIO errors other than timeouts are fatal */
+	if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME)
+		goto mips_be_fatal;
 
 	/*
 	 * Now we have an asynchronous bus error, speculatively or DMA caused.


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux