diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-25 01:08:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-25 01:08:34 -0400 |
commit | 881d021ab0d675f519b68df916fde969940ef988 (patch) | |
tree | b4b60a1d2a0a25c8b1f1fbf322a44d89817a22da /arch/sparc64/kernel/traps.c | |
parent | 83ef64b9dea6e3ed287a45d56166913bffcd2497 (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.c | 62 |
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 | ||
132 | static DEFINE_SPINLOCK(dimm_handler_lock); | ||
133 | static dimm_printer_t dimm_handler; | ||
134 | |||
135 | static 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 | |||
155 | int 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 | |||
170 | void 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 | |||
131 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 181 | void 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 | ||
1064 | extern int chmc_getunumber(int, unsigned long, char *, int); | ||
1065 | |||
1066 | static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, | 1112 | static 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), |