diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 14:27:45 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-14 14:27:45 -0800 |
commit | cebfa85eb86d92bf85d3b041c6b044184517a988 (patch) | |
tree | be0a374556fe335ce96dfdb296c89537750d5868 /drivers/edac/octeon_edac-pc.c | |
parent | d42b3a2906a10b732ea7d7f849d49be79d242ef0 (diff) | |
parent | 241738bd51cb0efe58e6c570223153e970afe3ae (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"The MIPS bits for 3.8. This also includes a bunch fixes that were
sitting in the linux-mips.org git tree for a long time. This pull
request contains updates to several OCTEON drivers and the board
support code for BCM47XX, BCM63XX, XLP, XLR, XLS, lantiq, Loongson1B,
updates to the SSB bus support, MIPS kexec code and adds support for
kdump.
When pulling this, there are two expected merge conflicts in
include/linux/bcma/bcma_driver_chipcommon.h which are trivial to
resolve, just remove the conflict markers and keep both alternatives."
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (90 commits)
MIPS: PMC-Sierra Yosemite: Remove support.
VIDEO: Newport Fix console crashes
MIPS: wrppmc: Fix build of PCI code.
MIPS: IP22/IP28: Fix build of EISA code.
MIPS: RB532: Fix build of prom code.
MIPS: PowerTV: Fix build.
MIPS: IP27: Correct fucked grammar in ops-bridge.c
MIPS: Highmem: Fix build error if CONFIG_DEBUG_HIGHMEM is disabled
MIPS: Fix potencial corruption
MIPS: Fix for warning from FPU emulation code
MIPS: Handle COP3 Unusable exception as COP1X for FP emulation
MIPS: Fix poweroff failure when HOTPLUG_CPU configured.
MIPS: MT: Fix build with CONFIG_UIDGID_STRICT_TYPE_CHECKS=y
MIPS: Remove unused smvp.h
MIPS/EDAC: Improve OCTEON EDAC support.
MIPS: OCTEON: Add definitions for OCTEON memory contoller registers.
MIPS: OCTEON: Add OCTEON family definitions to octeon-model.h
ata: pata_octeon_cf: Use correct byte order for DMA in when built little-endian.
MIPS/OCTEON/ata: Convert pata_octeon_cf.c to use device tree.
MIPS: Remove usage of CEVT_R4K_LIB config option.
...
Diffstat (limited to 'drivers/edac/octeon_edac-pc.c')
-rw-r--r-- | drivers/edac/octeon_edac-pc.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c new file mode 100644 index 000000000000..14a5e57f2b32 --- /dev/null +++ b/drivers/edac/octeon_edac-pc.c @@ -0,0 +1,143 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 Cavium, Inc. + * + * Copyright (C) 2009 Wind River Systems, + * written by Ralf Baechle <ralf@linux-mips.org> + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/edac.h> + +#include "edac_core.h" +#include "edac_module.h" + +#include <asm/octeon/cvmx.h> +#include <asm/mipsregs.h> + +extern int register_co_cache_error_notifier(struct notifier_block *nb); +extern int unregister_co_cache_error_notifier(struct notifier_block *nb); + +extern unsigned long long cache_err_dcache[NR_CPUS]; + +struct co_cache_error { + struct notifier_block notifier; + struct edac_device_ctl_info *ed; +}; + +/** + * EDAC CPU cache error callback + * + * @event: non-zero if unrecoverable. + */ +static int co_cache_error_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct co_cache_error *p = container_of(this, struct co_cache_error, + notifier); + + unsigned int core = cvmx_get_core_num(); + unsigned int cpu = smp_processor_id(); + u64 icache_err = read_octeon_c0_icacheerr(); + u64 dcache_err; + + if (event) { + dcache_err = cache_err_dcache[core]; + cache_err_dcache[core] = 0; + } else { + dcache_err = read_octeon_c0_dcacheerr(); + } + + if (icache_err & 1) { + edac_device_printk(p->ed, KERN_ERR, + "CacheErr (Icache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n", + (unsigned long long)icache_err, core, cpu, + read_c0_errorepc()); + write_octeon_c0_icacheerr(0); + edac_device_handle_ce(p->ed, cpu, 1, "icache"); + } + if (dcache_err & 1) { + edac_device_printk(p->ed, KERN_ERR, + "CacheErr (Dcache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n", + (unsigned long long)dcache_err, core, cpu, + read_c0_errorepc()); + if (event) + edac_device_handle_ue(p->ed, cpu, 0, "dcache"); + else + edac_device_handle_ce(p->ed, cpu, 0, "dcache"); + + /* Clear the error indication */ + if (OCTEON_IS_MODEL(OCTEON_FAM_2)) + write_octeon_c0_dcacheerr(1); + else + write_octeon_c0_dcacheerr(0); + } + + return NOTIFY_STOP; +} + +static int __devinit co_cache_error_probe(struct platform_device *pdev) +{ + struct co_cache_error *p = devm_kzalloc(&pdev->dev, sizeof(*p), + GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->notifier.notifier_call = co_cache_error_event; + platform_set_drvdata(pdev, p); + + p->ed = edac_device_alloc_ctl_info(0, "cpu", num_possible_cpus(), + "cache", 2, 0, NULL, 0, + edac_device_alloc_index()); + if (!p->ed) + goto err; + + p->ed->dev = &pdev->dev; + + p->ed->dev_name = dev_name(&pdev->dev); + + p->ed->mod_name = "octeon-cpu"; + p->ed->ctl_name = "cache"; + + if (edac_device_add_device(p->ed)) { + pr_err("%s: edac_device_add_device() failed\n", __func__); + goto err1; + } + + register_co_cache_error_notifier(&p->notifier); + + return 0; + +err1: + edac_device_free_ctl_info(p->ed); +err: + return -ENXIO; +} + +static int co_cache_error_remove(struct platform_device *pdev) +{ + struct co_cache_error *p = platform_get_drvdata(pdev); + + unregister_co_cache_error_notifier(&p->notifier); + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(p->ed); + return 0; +} + +static struct platform_driver co_cache_error_driver = { + .probe = co_cache_error_probe, + .remove = co_cache_error_remove, + .driver = { + .name = "octeon_pc_edac", + } +}; +module_platform_driver(co_cache_error_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); |