diff options
Diffstat (limited to 'arch/mips/mm/c-octeon.c')
-rw-r--r-- | arch/mips/mm/c-octeon.c | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 9f67553762d5..6ec04daf4231 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c | |||
@@ -286,10 +286,9 @@ void __cpuinit octeon_cache_init(void) | |||
286 | board_cache_error_setup = octeon_cache_error_setup; | 286 | board_cache_error_setup = octeon_cache_error_setup; |
287 | } | 287 | } |
288 | 288 | ||
289 | /** | 289 | /* |
290 | * Handle a cache error exception | 290 | * Handle a cache error exception |
291 | */ | 291 | */ |
292 | |||
293 | static RAW_NOTIFIER_HEAD(co_cache_error_chain); | 292 | static RAW_NOTIFIER_HEAD(co_cache_error_chain); |
294 | 293 | ||
295 | int register_co_cache_error_notifier(struct notifier_block *nb) | 294 | int register_co_cache_error_notifier(struct notifier_block *nb) |
@@ -304,14 +303,39 @@ int unregister_co_cache_error_notifier(struct notifier_block *nb) | |||
304 | } | 303 | } |
305 | EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier); | 304 | EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier); |
306 | 305 | ||
307 | static inline int co_cache_error_call_notifiers(unsigned long val) | 306 | static void co_cache_error_call_notifiers(unsigned long val) |
308 | { | 307 | { |
309 | return raw_notifier_call_chain(&co_cache_error_chain, val, NULL); | 308 | int rv = raw_notifier_call_chain(&co_cache_error_chain, val, NULL); |
309 | if ((rv & ~NOTIFY_STOP_MASK) != NOTIFY_OK) { | ||
310 | u64 dcache_err; | ||
311 | unsigned long coreid = cvmx_get_core_num(); | ||
312 | u64 icache_err = read_octeon_c0_icacheerr(); | ||
313 | |||
314 | if (val) { | ||
315 | dcache_err = cache_err_dcache[coreid]; | ||
316 | cache_err_dcache[coreid] = 0; | ||
317 | } else { | ||
318 | dcache_err = read_octeon_c0_dcacheerr(); | ||
319 | } | ||
320 | |||
321 | pr_err("Core%lu: Cache error exception:\n", coreid); | ||
322 | pr_err("cp0_errorepc == %lx\n", read_c0_errorepc()); | ||
323 | if (icache_err & 1) { | ||
324 | pr_err("CacheErr (Icache) == %llx\n", | ||
325 | (unsigned long long)icache_err); | ||
326 | write_octeon_c0_icacheerr(0); | ||
327 | } | ||
328 | if (dcache_err & 1) { | ||
329 | pr_err("CacheErr (Dcache) == %llx\n", | ||
330 | (unsigned long long)dcache_err); | ||
331 | } | ||
332 | } | ||
310 | } | 333 | } |
311 | 334 | ||
312 | /** | 335 | /* |
313 | * Called when the the exception is recoverable | 336 | * Called when the the exception is recoverable |
314 | */ | 337 | */ |
338 | |||
315 | asmlinkage void cache_parity_error_octeon_recoverable(void) | 339 | asmlinkage void cache_parity_error_octeon_recoverable(void) |
316 | { | 340 | { |
317 | co_cache_error_call_notifiers(0); | 341 | co_cache_error_call_notifiers(0); |
@@ -319,11 +343,8 @@ asmlinkage void cache_parity_error_octeon_recoverable(void) | |||
319 | 343 | ||
320 | /** | 344 | /** |
321 | * Called when the the exception is not recoverable | 345 | * Called when the the exception is not recoverable |
322 | * | ||
323 | * The issue not that the cache error exception itself was non-recoverable | ||
324 | * but that due to nesting of exception may have lost some state so can't | ||
325 | * continue. | ||
326 | */ | 346 | */ |
347 | |||
327 | asmlinkage void cache_parity_error_octeon_non_recoverable(void) | 348 | asmlinkage void cache_parity_error_octeon_non_recoverable(void) |
328 | { | 349 | { |
329 | co_cache_error_call_notifiers(1); | 350 | co_cache_error_call_notifiers(1); |