aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-25 01:08:34 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-25 01:08:34 -0400
commit881d021ab0d675f519b68df916fde969940ef988 (patch)
treeb4b60a1d2a0a25c8b1f1fbf322a44d89817a22da /arch/sparc64/kernel/traps.c
parent83ef64b9dea6e3ed287a45d56166913bffcd2497 (diff)
sparc64: Add generic interface for registering a dimm printing handler.
The way to do this varies by platform type and the exact memory controller the cpu uses. For Spitfire cpus we currently just use prom_getunumber() and hope that works. For Cheetah cpus we have a memory controller driver that can compute this information. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r--arch/sparc64/kernel/traps.c62
1 files changed, 54 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 3d924121c796..17880ccfa3cd 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -37,6 +37,7 @@
37#include <asm/timer.h> 37#include <asm/timer.h>
38#include <asm/head.h> 38#include <asm/head.h>
39#include <asm/prom.h> 39#include <asm/prom.h>
40#include <asm/memctrl.h>
40 41
41#include "entry.h" 42#include "entry.h"
42#include "kstack.h" 43#include "kstack.h"
@@ -128,6 +129,55 @@ void do_BUG(const char *file, int line)
128} 129}
129#endif 130#endif
130 131
132static DEFINE_SPINLOCK(dimm_handler_lock);
133static dimm_printer_t dimm_handler;
134
135static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen)
136{
137 unsigned long flags;
138 int ret = -ENODEV;
139
140 spin_lock_irqsave(&dimm_handler_lock, flags);
141 if (dimm_handler) {
142 ret = dimm_handler(synd_code, paddr, buf, buflen);
143 } else if (tlb_type == spitfire) {
144 if (prom_getunumber(synd_code, paddr, buf, buflen) == -1)
145 ret = -EINVAL;
146 else
147 ret = 0;
148 } else
149 ret = -ENODEV;
150 spin_unlock_irqrestore(&dimm_handler_lock, flags);
151
152 return ret;
153}
154
155int register_dimm_printer(dimm_printer_t func)
156{
157 unsigned long flags;
158 int ret = 0;
159
160 spin_lock_irqsave(&dimm_handler_lock, flags);
161 if (!dimm_handler)
162 dimm_handler = func;
163 else
164 ret = -EEXIST;
165 spin_unlock_irqrestore(&dimm_handler_lock, flags);
166
167 return ret;
168}
169
170void unregister_dimm_printer(dimm_printer_t func)
171{
172 unsigned long flags;
173
174 spin_lock_irqsave(&dimm_handler_lock, flags);
175 if (dimm_handler == func)
176 dimm_handler = NULL;
177 spin_unlock_irqrestore(&dimm_handler_lock, flags);
178}
179
180
131void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) 181void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
132{ 182{
133 siginfo_t info; 183 siginfo_t info;
@@ -375,8 +425,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un
375 425
376 if (udbl & bit) { 426 if (udbl & bit) {
377 scode = ecc_syndrome_table[udbl & 0xff]; 427 scode = ecc_syndrome_table[udbl & 0xff];
378 if (prom_getunumber(scode, afar, 428 if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
379 memmod_str, sizeof(memmod_str)) == -1)
380 p = syndrome_unknown; 429 p = syndrome_unknown;
381 else 430 else
382 p = memmod_str; 431 p = memmod_str;
@@ -387,8 +436,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un
387 436
388 if (udbh & bit) { 437 if (udbh & bit) {
389 scode = ecc_syndrome_table[udbh & 0xff]; 438 scode = ecc_syndrome_table[udbh & 0xff];
390 if (prom_getunumber(scode, afar, 439 if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0)
391 memmod_str, sizeof(memmod_str)) == -1)
392 p = syndrome_unknown; 440 p = syndrome_unknown;
393 else 441 else
394 p = memmod_str; 442 p = memmod_str;
@@ -1061,8 +1109,6 @@ static const char *cheetah_get_string(unsigned long bit)
1061 return "???"; 1109 return "???";
1062} 1110}
1063 1111
1064extern int chmc_getunumber(int, unsigned long, char *, int);
1065
1066static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, 1112static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info,
1067 unsigned long afsr, unsigned long afar, int recoverable) 1113 unsigned long afsr, unsigned long afar, int recoverable)
1068{ 1114{
@@ -1104,7 +1150,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
1104 1150
1105 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; 1151 syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT;
1106 syndrome = cheetah_ecc_syntab[syndrome]; 1152 syndrome = cheetah_ecc_syntab[syndrome];
1107 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1153 ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
1108 if (ret != -1) 1154 if (ret != -1)
1109 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", 1155 printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n",
1110 (recoverable ? KERN_WARNING : KERN_CRIT), 1156 (recoverable ? KERN_WARNING : KERN_CRIT),
@@ -1115,7 +1161,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
1115 1161
1116 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; 1162 syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT;
1117 syndrome = cheetah_mtag_syntab[syndrome]; 1163 syndrome = cheetah_mtag_syntab[syndrome];
1118 ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); 1164 ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum));
1119 if (ret != -1) 1165 if (ret != -1)
1120 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", 1166 printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n",
1121 (recoverable ? KERN_WARNING : KERN_CRIT), 1167 (recoverable ? KERN_WARNING : KERN_CRIT),