aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2012-11-15 13:58:59 -0800
committerRalf Baechle <ralf@linux-mips.org>2012-12-13 18:15:26 +0100
commite1ced09797776dfd4a2a7b04b9ee7e97ab1e64be (patch)
tree473934ca424e0e10f235bcd9ae97781349af5495 /arch
parentabe105a4d8c5ee2aa2acef33c5d163e5d187598f (diff)
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')
-rw-r--r--arch/mips/cavium-octeon/setup.c30
-rw-r--r--arch/mips/mm/c-octeon.c39
-rw-r--r--arch/mips/pci/pci-octeon.c3
3 files changed, 58 insertions, 14 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 7c2b7aab77b..d7e0a09f77c 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 9f67553762d..6ec04daf423 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 8eb2ee345d0..5b5ed76c6f4 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();