diff --git a/arch/blackfin/cpu/cpu.h b/arch/blackfin/cpu/cpu.h
index 0a13c285e0e468601be51a6206e5b830f1fa0f86..c8bec115a13580b496f6c2867180f67855837347 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 caaea94106a556d2095a85847967743a3eabfd19..09388aa3d53a15ed8b34d188732ee31eded5499f 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();
 }