summaryrefslogtreecommitdiff
path: root/arch/blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/cpu/cpu.h1
-rw-r--r--arch/blackfin/cpu/traps.c76
2 files changed, 49 insertions, 28 deletions
diff --git a/arch/blackfin/cpu/cpu.h b/arch/blackfin/cpu/cpu.h
index 0a13c285e0e..c8bec115a13 100644
--- a/arch/blackfin/cpu/cpu.h
+++ b/arch/blackfin/cpu/cpu.h
@@ -29,6 +29,7 @@
void board_reset(void) __attribute__((__weak__));
void bfin_reset_or_hang(void) __attribute__((__noreturn__));
+void bfin_dump(struct pt_regs *reg);
void bfin_panic(struct pt_regs *reg);
void dump(struct pt_regs *regs);
diff --git a/arch/blackfin/cpu/traps.c b/arch/blackfin/cpu/traps.c
index caaea94106a..09388aa3d53 100644
--- a/arch/blackfin/cpu/traps.c
+++ b/arch/blackfin/cpu/traps.c
@@ -29,14 +29,26 @@
#include <asm/deferred.h>
#include "cpu.h"
+#ifdef CONFIG_DEBUG_DUMP
+# define ENABLE_DUMP 1
+#else
+# define ENABLE_DUMP 0
+#endif
+
#define trace_buffer_save(x) \
do { \
+ if (!ENABLE_DUMP) \
+ break; \
(x) = bfin_read_TBUFCTL(); \
bfin_write_TBUFCTL((x) & ~TBUFEN); \
} while (0)
#define trace_buffer_restore(x) \
- bfin_write_TBUFCTL((x))
+ do { \
+ if (!ENABLE_DUMP) \
+ break; \
+ bfin_write_TBUFCTL((x)); \
+ } while (0);
/* The purpose of this map is to provide a mapping of address<->cplb settings
* rather than an exact map of what is actually addressable on the part. This
@@ -82,8 +94,16 @@ int trap_c(struct pt_regs *regs, uint32_t level)
{
uint32_t ret = 0;
uint32_t trapnr = (regs->seqstat & EXCAUSE);
+ unsigned long tflags;
bool data = false;
+ /*
+ * Keep the trace buffer so that a miss here points people
+ * to the right place (their code). Crashes here rarely
+ * happen. If they do, only the Blackfin maintainer cares.
+ */
+ trace_buffer_save(tflags);
+
switch (trapnr) {
/* 0x26 - Data CPLB Miss */
case VEC_CPLB_M:
@@ -97,7 +117,7 @@ int trap_c(struct pt_regs *regs, uint32_t level)
*/
if (last_cplb_fault_retx != regs->retx) {
last_cplb_fault_retx = regs->retx;
- return ret;
+ break;
}
}
@@ -110,7 +130,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
uint32_t new_cplb_addr = 0, new_cplb_data = 0;
static size_t last_evicted;
size_t i;
- unsigned long tflags;
#ifdef CONFIG_EXCEPTION_DEFER
/* This should never happen */
@@ -118,13 +137,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
bfin_panic(regs);
#endif
- /*
- * Keep the trace buffer so that a miss here points people
- * to the right place (their code). Crashes here rarely
- * happen. If they do, only the Blackfin maintainer cares.
- */
- trace_buffer_save(tflags);
-
new_cplb_addr = (data ? bfin_read_DCPLB_FAULT_ADDR() : bfin_read_ICPLB_FAULT_ADDR()) & ~(4 * 1024 * 1024 - 1);
for (i = 0; i < ARRAY_SIZE(bfin_memory_map); ++i) {
@@ -180,7 +192,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
for (i = 0; i < 16; ++i)
debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++);
- trace_buffer_restore(tflags);
break;
}
#ifdef CONFIG_CMD_KGDB
@@ -208,23 +219,21 @@ int trap_c(struct pt_regs *regs, uint32_t level)
#ifdef CONFIG_CMD_KGDB
if (level == 3) {
/* We need to handle this at EVT5, so try again */
+ bfin_dump(regs);
ret = 1;
break;
}
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
- return 0;
+ break;
#endif
bfin_panic(regs);
}
+
+ trace_buffer_restore(tflags);
+
return ret;
}
-#ifdef CONFIG_DEBUG_DUMP
-# define ENABLE_DUMP 1
-#else
-# define ENABLE_DUMP 0
-#endif
-
#ifndef CONFIG_KALLSYMS
const char *symbol_lookup(unsigned long addr, unsigned long *caddr)
{
@@ -364,17 +373,14 @@ void dump(struct pt_regs *fp)
printf("\n");
}
-void dump_bfin_trace_buffer(void)
+static void _dump_bfin_trace_buffer(void)
{
char buf[150];
- unsigned long tflags;
int i = 0;
if (!ENABLE_DUMP)
return;
- trace_buffer_save(tflags);
-
printf("Hardware Trace:\n");
if (bfin_read_TBUFSTAT() & TBUFCNT) {
@@ -385,16 +391,21 @@ void dump_bfin_trace_buffer(void)
printf(" Source : %s\n", buf);
}
}
+}
+void dump_bfin_trace_buffer(void)
+{
+ unsigned long tflags;
+ trace_buffer_save(tflags);
+ _dump_bfin_trace_buffer();
trace_buffer_restore(tflags);
}
-void bfin_panic(struct pt_regs *regs)
+void bfin_dump(struct pt_regs *regs)
{
- if (ENABLE_DUMP) {
- unsigned long tflags;
- trace_buffer_save(tflags);
- }
+ unsigned long tflags;
+
+ trace_buffer_save(tflags);
puts(
"\n"
@@ -404,7 +415,16 @@ void bfin_panic(struct pt_regs *regs)
"\n"
);
dump(regs);
- dump_bfin_trace_buffer();
+ _dump_bfin_trace_buffer();
puts("\n");
+
+ trace_buffer_restore(tflags);
+}
+
+void bfin_panic(struct pt_regs *regs)
+{
+ unsigned long tflags;
+ trace_buffer_save(tflags);
+ bfin_dump(regs);
bfin_reset_or_hang();
}