diff options
author | David Daney <david.daney@cavium.com> | 2012-11-16 01:58:59 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-12-13 21:15:26 +0400 |
commit | e1ced09797776dfd4a2a7b04b9ee7e97ab1e64be (patch) | |
tree | 473934ca424e0e10f235bcd9ae97781349af5495 /arch/mips | |
parent | abe105a4d8c5ee2aa2acef33c5d163e5d187598f (diff) | |
download | linux-e1ced09797776dfd4a2a7b04b9ee7e97ab1e64be.tar.xz |
MIPS/EDAC: Improve OCTEON EDAC support.
Some initialization errors are reported with the existing OCTEON EDAC
support patch. Also some parts have more than one memory controller.
Fix the errors and add multiple controllers if present.
Signed-off-by: David Daney <david.daney@cavium.com>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 30 | ||||
-rw-r--r-- | arch/mips/mm/c-octeon.c | 39 | ||||
-rw-r--r-- | arch/mips/pci/pci-octeon.c | 3 |
3 files changed, 58 insertions, 14 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 7c2b7aab77ba..d7e0a09f77c2 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -1112,18 +1112,30 @@ void __init device_tree_init(void) unflatten_device_tree(); } +static int __initdata disable_octeon_edac_p; + +static int __init disable_octeon_edac(char *str) +{ + disable_octeon_edac_p = 1; + return 0; +} +early_param("disable_octeon_edac", disable_octeon_edac); + static char *edac_device_names[] = { - "co_l2c_edac", - "co_lmc_edac", - "co_pc_edac", + "octeon_l2c_edac", + "octeon_pc_edac", }; static int __init edac_devinit(void) { struct platform_device *dev; int i, err = 0; + int num_lmc; char *name; + if (disable_octeon_edac_p) + return 0; + for (i = 0; i < ARRAY_SIZE(edac_device_names); i++) { name = edac_device_names[i]; dev = platform_device_register_simple(name, -1, NULL, 0); @@ -1133,7 +1145,17 @@ static int __init edac_devinit(void) } } + num_lmc = OCTEON_IS_MODEL(OCTEON_CN68XX) ? 4 : + (OCTEON_IS_MODEL(OCTEON_CN56XX) ? 2 : 1); + for (i = 0; i < num_lmc; i++) { + dev = platform_device_register_simple("octeon_lmc_edac", + i, NULL, 0); + if (IS_ERR(dev)) { + pr_err("Registation of octeon_lmc_edac %d failed!\n", i); + err = PTR_ERR(dev); + } + } + return err; } - device_initcall(edac_devinit); 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) board_cache_error_setup = octeon_cache_error_setup; } -/** +/* * Handle a cache error exception */ - static RAW_NOTIFIER_HEAD(co_cache_error_chain); int register_co_cache_error_notifier(struct notifier_block *nb) @@ -304,14 +303,39 @@ int unregister_co_cache_error_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier); -static inline int co_cache_error_call_notifiers(unsigned long val) +static void co_cache_error_call_notifiers(unsigned long val) { - return raw_notifier_call_chain(&co_cache_error_chain, val, NULL); + int rv = raw_notifier_call_chain(&co_cache_error_chain, val, NULL); + if ((rv & ~NOTIFY_STOP_MASK) != NOTIFY_OK) { + u64 dcache_err; + unsigned long coreid = cvmx_get_core_num(); + u64 icache_err = read_octeon_c0_icacheerr(); + + if (val) { + dcache_err = cache_err_dcache[coreid]; + cache_err_dcache[coreid] = 0; + } else { + dcache_err = read_octeon_c0_dcacheerr(); + } + + pr_err("Core%lu: Cache error exception:\n", coreid); + pr_err("cp0_errorepc == %lx\n", read_c0_errorepc()); + if (icache_err & 1) { + pr_err("CacheErr (Icache) == %llx\n", + (unsigned long long)icache_err); + write_octeon_c0_icacheerr(0); + } + if (dcache_err & 1) { + pr_err("CacheErr (Dcache) == %llx\n", + (unsigned long long)dcache_err); + } + } } -/** +/* * Called when the the exception is recoverable */ + asmlinkage void cache_parity_error_octeon_recoverable(void) { co_cache_error_call_notifiers(0); @@ -319,11 +343,8 @@ asmlinkage void cache_parity_error_octeon_recoverable(void) /** * Called when the the exception is not recoverable - * - * The issue not that the cache error exception itself was non-recoverable - * but that due to nesting of exception may have lost some state so can't - * continue. */ + asmlinkage void cache_parity_error_octeon_non_recoverable(void) { co_cache_error_call_notifiers(1); diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index 8eb2ee345d03..5b5ed76c6f47 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -705,7 +705,8 @@ static int __init octeon_pci_setup(void) */ cvmx_write_csr(CVMX_NPI_PCI_INT_SUM2, -1); - if (IS_ERR(platform_device_register_simple("co_pci_edac", 0, NULL, 0))) + if (IS_ERR(platform_device_register_simple("octeon_pci_edac", + -1, NULL, 0))) pr_err("Registation of co_pci_edac failed!\n"); octeon_pci_dma_init(); |