diff options
Diffstat (limited to 'drivers/edac')
36 files changed, 802 insertions, 144 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index bb82d6be793..66719925970 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -4,10 +4,13 @@ # Licensed and distributed under the GPL # +config EDAC_SUPPORT + bool + menuconfig EDAC bool "EDAC (Error Detection And Correction) reporting" depends on HAS_IOMEM - depends on X86 || PPC || TILE || ARM + depends on X86 || PPC || TILE || ARM || EDAC_SUPPORT help EDAC is designed to report errors in the core system. These are low-level errors that are reported in the CPU or @@ -29,8 +32,6 @@ menuconfig EDAC if EDAC -comment "Reporting subsystems" - config EDAC_LEGACY_SYSFS bool "EDAC legacy sysfs" default y @@ -316,4 +317,32 @@ config EDAC_HIGHBANK_L2 Support for error detection and correction on the Calxeda Highbank memory controller. +config EDAC_OCTEON_PC + tristate "Cavium Octeon Primary Caches" + depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON + help + Support for error detection and correction on the primary caches of + the cnMIPS cores of Cavium Octeon family SOCs. + +config EDAC_OCTEON_L2C + tristate "Cavium Octeon Secondary Caches (L2C)" + depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON + help + Support for error detection and correction on the + Cavium Octeon family of SOCs. + +config EDAC_OCTEON_LMC + tristate "Cavium Octeon DRAM Memory Controller (LMC)" + depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON + help + Support for error detection and correction on the + Cavium Octeon family of SOCs. + +config EDAC_OCTEON_PCI + tristate "Cavium Octeon PCI Controller" + depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON + help + Support for error detection and correction on the + Cavium Octeon family of SOCs. + endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 7e5129a733f..5608a9ba61b 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -58,3 +58,8 @@ obj-$(CONFIG_EDAC_TILE) += tile_edac.o obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o + +obj-$(CONFIG_EDAC_OCTEON_PC) += octeon_edac-pc.o +obj-$(CONFIG_EDAC_OCTEON_L2C) += octeon_edac-l2c.o +obj-$(CONFIG_EDAC_OCTEON_LMC) += octeon_edac-lmc.o +obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index f74a684269f..ad8bf2aa629 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2563,8 +2563,8 @@ err_ret: return ret; } -static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, - const struct pci_device_id *mc_type) +static int amd64_probe_one_instance(struct pci_dev *pdev, + const struct pci_device_id *mc_type) { u8 nid = get_node_id(pdev); struct pci_dev *F3 = node_to_amd_nb(nid)->misc; @@ -2612,7 +2612,7 @@ err_out: return ret; } -static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) +static void amd64_remove_one_instance(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct amd64_pvt *pvt; @@ -2686,7 +2686,7 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table); static struct pci_driver amd64_pci_driver = { .name = EDAC_MOD_STR, .probe = amd64_probe_one_instance, - .remove = __devexit_p(amd64_remove_one_instance), + .remove = amd64_remove_one_instance, .id_table = amd64_pci_table, }; diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 29eeb68a200..96e3ee3460a 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -301,8 +301,8 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit amd76x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int amd76x_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { edac_dbg(0, "\n"); @@ -318,7 +318,7 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, * structure for the device then delete the mci and free the * resources. */ -static void __devexit amd76x_remove_one(struct pci_dev *pdev) +static void amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl); static struct pci_driver amd76x_driver = { .name = EDAC_MOD_STR, .probe = amd76x_init_one, - .remove = __devexit_p(amd76x_remove_one), + .remove = amd76x_remove_one, .id_table = amd76x_pci_tbl, }; diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index a1bbd8edd25..c2eaf334b90 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -124,7 +124,7 @@ static void cell_edac_check(struct mem_ctl_info *mci) } } -static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) +static void cell_edac_init_csrows(struct mem_ctl_info *mci) { struct csrow_info *csrow = mci->csrows[0]; struct dimm_info *dimm; @@ -164,7 +164,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit cell_edac_probe(struct platform_device *pdev) +static int cell_edac_probe(struct platform_device *pdev) { struct cbe_mic_tm_regs __iomem *regs; struct mem_ctl_info *mci; @@ -233,7 +233,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) return 0; } -static int __devexit cell_edac_remove(struct platform_device *pdev) +static int cell_edac_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev); if (mci) @@ -247,7 +247,7 @@ static struct platform_driver cell_edac_driver = { .owner = THIS_MODULE, }, .probe = cell_edac_probe, - .remove = __devexit_p(cell_edac_remove), + .remove = cell_edac_remove, }; static int __init cell_edac_init(void) diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index c2ef1349587..7f3c57113ba 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -932,7 +932,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase) return dual; } -static int __devinit cpc925_probe(struct platform_device *pdev) +static int cpc925_probe(struct platform_device *pdev) { static int edac_mc_idx; struct mem_ctl_info *mci; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index a5ed6b795fd..644fec54681 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1390,8 +1390,7 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit e752x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { edac_dbg(0, "\n"); @@ -1402,7 +1401,7 @@ static int __devinit e752x_init_one(struct pci_dev *pdev, return e752x_probe1(pdev, ent->driver_data); } -static void __devexit e752x_remove_one(struct pci_dev *pdev) +static void e752x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct e752x_pvt *pvt; @@ -1445,7 +1444,7 @@ MODULE_DEVICE_TABLE(pci, e752x_pci_tbl); static struct pci_driver e752x_driver = { .name = EDAC_MOD_STR, .probe = e752x_init_one, - .remove = __devexit_p(e752x_remove_one), + .remove = e752x_remove_one, .id_table = e752x_pci_tbl, }; diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 9ff57f361a4..1c4056a5038 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -528,8 +528,7 @@ fail0: } /* returns count (>= 0), or negative on error */ -static int __devinit e7xxx_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { edac_dbg(0, "\n"); @@ -538,7 +537,7 @@ static int __devinit e7xxx_init_one(struct pci_dev *pdev, -EIO : e7xxx_probe1(pdev, ent->driver_data); } -static void __devexit e7xxx_remove_one(struct pci_dev *pdev) +static void e7xxx_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct e7xxx_pvt *pvt; @@ -579,7 +578,7 @@ MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); static struct pci_driver e7xxx_driver = { .name = EDAC_MOD_STR, .probe = e7xxx_init_one, - .remove = __devexit_p(e7xxx_remove_one), + .remove = e7xxx_remove_one, .id_table = e7xxx_pci_tbl, }; diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 281f566a551..d1e9eb191f2 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -340,7 +340,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* * Alocate and fill the csrow/channels structs */ - mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); + mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL); if (!mci->csrows) goto error; for (row = 0; row < tot_csrows; row++) { @@ -351,7 +351,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, csr->csrow_idx = row; csr->mci = mci; csr->nr_channels = tot_channels; - csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, + csr->channels = kcalloc(tot_channels, sizeof(*csr->channels), GFP_KERNEL); if (!csr->channels) goto error; @@ -369,7 +369,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* * Allocate and fill the dimm structs */ - mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); + mci->dimms = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL); if (!mci->dimms) goto error; diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index de2df92f9c7..0ca1ca71157 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -472,8 +472,7 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) device_remove_file(&csrow->dev, dynamic_csrow_ce_count_attr[chan]); } - put_device(&mci->csrows[i]->dev); - device_del(&mci->csrows[i]->dev); + device_unregister(&mci->csrows[i]->dev); } } #endif @@ -1055,11 +1054,9 @@ fail: struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; - put_device(&dimm->dev); - device_del(&dimm->dev); + device_unregister(&dimm->dev); } - put_device(&mci->dev); - device_del(&mci->dev); + device_unregister(&mci->dev); bus_unregister(&mci->bus); kfree(mci->bus.name); return err; @@ -1086,16 +1083,14 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) if (dimm->nr_pages == 0) continue; edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev)); - put_device(&dimm->dev); - device_del(&dimm->dev); + device_unregister(&dimm->dev); } } void edac_unregister_sysfs(struct mem_ctl_info *mci) { edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); - put_device(&mci->dev); - device_del(&mci->dev); + device_unregister(&mci->dev); bus_unregister(&mci->bus); kfree(mci->bus.name); } @@ -1159,8 +1154,6 @@ int __init edac_mc_sysfs_init(void) void __exit edac_mc_sysfs_exit(void) { - put_device(mci_pdev); - device_del(mci_pdev); + device_unregister(mci_pdev); edac_put_sysfs_subsys(); - kfree(mci_pdev); } diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index dc6e905ee1a..0056c4dae9d 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -256,7 +256,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; - if (edac_pci_dev->show) + if (edac_pci_dev->store) return edac_pci_dev->store(edac_pci_dev->value, buffer, count); return -EIO; } diff --git a/drivers/edac/highbank_l2_edac.c b/drivers/edac/highbank_l2_edac.c index e599b00c05a..c2bd8c6a434 100644 --- a/drivers/edac/highbank_l2_edac.c +++ b/drivers/edac/highbank_l2_edac.c @@ -50,7 +50,7 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit highbank_l2_err_probe(struct platform_device *pdev) +static int highbank_l2_err_probe(struct platform_device *pdev) { struct edac_device_ctl_info *dci; struct hb_l2_drvdata *drvdata; diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 7ea4cc2e8bd..4695dd2d71f 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c @@ -119,7 +119,7 @@ static const struct file_operations highbank_mc_debug_inject_fops = { .llseek = generic_file_llseek, }; -static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) +static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) { if (mci->debugfs) debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci, @@ -127,11 +127,11 @@ static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) ; } #else -static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) +static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) {} #endif -static int __devinit highbank_mc_probe(struct platform_device *pdev) +static int highbank_mc_probe(struct platform_device *pdev) { struct edac_mc_layer layers[2]; struct mem_ctl_info *mci; diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index d3d19cc4e9a..694efcbf19c 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -455,8 +455,7 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit i3000_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i3000_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; @@ -472,7 +471,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i3000_remove_one(struct pci_dev *pdev) +static void i3000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -502,7 +501,7 @@ MODULE_DEVICE_TABLE(pci, i3000_pci_tbl); static struct pci_driver i3000_driver = { .name = EDAC_MOD_STR, .probe = i3000_init_one, - .remove = __devexit_p(i3000_remove_one), + .remove = i3000_remove_one, .id_table = i3000_pci_tbl, }; diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index b6653a6fc5d..4e8337602e7 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -419,8 +419,7 @@ fail: return rc; } -static int __devinit i3200_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i3200_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; @@ -436,7 +435,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i3200_remove_one(struct pci_dev *pdev) +static void i3200_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct i3200_priv *priv; @@ -467,7 +466,7 @@ MODULE_DEVICE_TABLE(pci, i3200_pci_tbl); static struct pci_driver i3200_driver = { .name = EDAC_MOD_STR, .probe = i3200_init_one, - .remove = __devexit_p(i3200_remove_one), + .remove = i3200_remove_one, .id_table = i3200_pci_tbl, }; diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 6a49dd00b81..63b2194e8c2 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1489,8 +1489,7 @@ fail0: * negative on error * count (>= 0) */ -static int __devinit i5000_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i5000_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; @@ -1509,7 +1508,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, * i5000_remove_one destructor for one instance of device * */ -static void __devexit i5000_remove_one(struct pci_dev *pdev) +static void i5000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -1547,7 +1546,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl); static struct pci_driver i5000_driver = { .name = KBUILD_BASENAME, .probe = i5000_init_one, - .remove = __devexit_p(i5000_remove_one), + .remove = i5000_remove_one, .id_table = i5000_pci_tbl, }; diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index c4b5e5f868e..d6955b2cc99 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -638,8 +638,7 @@ static struct pci_dev *pci_get_device_func(unsigned vendor, return ret; } -static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci, - int csrow) +static unsigned long i5100_npages(struct mem_ctl_info *mci, int csrow) { struct i5100_priv *priv = mci->pvt_info; const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow); @@ -660,7 +659,7 @@ static unsigned long __devinit i5100_npages(struct mem_ctl_info *mci, ((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE); } -static void __devinit i5100_init_mtr(struct mem_ctl_info *mci) +static void i5100_init_mtr(struct mem_ctl_info *mci) { struct i5100_priv *priv = mci->pvt_info; struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; @@ -732,7 +731,7 @@ static int i5100_read_spd_byte(const struct mem_ctl_info *mci, * o not the only way to may chip selects to dimm slots * o investigate if there is some way to obtain this map from the bios */ -static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci) +static void i5100_init_dimm_csmap(struct mem_ctl_info *mci) { struct i5100_priv *priv = mci->pvt_info; int i; @@ -762,8 +761,8 @@ static void __devinit i5100_init_dimm_csmap(struct mem_ctl_info *mci) } } -static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev, - struct mem_ctl_info *mci) +static void i5100_init_dimm_layout(struct pci_dev *pdev, + struct mem_ctl_info *mci) { struct i5100_priv *priv = mci->pvt_info; int i; @@ -784,8 +783,8 @@ static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev, i5100_init_dimm_csmap(mci); } -static void __devinit i5100_init_interleaving(struct pci_dev *pdev, - struct mem_ctl_info *mci) +static void i5100_init_interleaving(struct pci_dev *pdev, + struct mem_ctl_info *mci) { u16 w; u32 dw; @@ -830,7 +829,7 @@ static void __devinit i5100_init_interleaving(struct pci_dev *pdev, i5100_init_mtr(mci); } -static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) +static void i5100_init_csrows(struct mem_ctl_info *mci) { int i; struct i5100_priv *priv = mci->pvt_info; @@ -864,8 +863,7 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit i5100_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; struct mem_ctl_info *mci; @@ -1020,7 +1018,7 @@ bail: return ret; } -static void __devexit i5100_remove_one(struct pci_dev *pdev) +static void i5100_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct i5100_priv *priv; @@ -1054,7 +1052,7 @@ MODULE_DEVICE_TABLE(pci, i5100_pci_tbl); static struct pci_driver i5100_driver = { .name = KBUILD_BASENAME, .probe = i5100_init_one, - .remove = __devexit_p(i5100_remove_one), + .remove = i5100_remove_one, .id_table = i5100_pci_tbl, }; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 277246998b8..0a05bbceb08 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -1373,8 +1373,7 @@ fail0: * negative on error * count (>= 0) */ -static int __devinit i5400_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i5400_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; @@ -1393,7 +1392,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, * i5400_remove_one destructor for one instance of device * */ -static void __devexit i5400_remove_one(struct pci_dev *pdev) +static void i5400_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -1431,7 +1430,7 @@ MODULE_DEVICE_TABLE(pci, i5400_pci_tbl); static struct pci_driver i5400_driver = { .name = "i5400_edac", .probe = i5400_init_one, - .remove = __devexit_p(i5400_remove_one), + .remove = i5400_remove_one, .id_table = i5400_pci_tbl, }; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 9d669cd4361..087c27bc5d4 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -923,7 +923,7 @@ static void i7300_put_devices(struct mem_ctl_info *mci) * Device 21 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 * Device 22 function 0: PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 */ -static int __devinit i7300_get_devices(struct mem_ctl_info *mci) +static int i7300_get_devices(struct mem_ctl_info *mci) { struct i7300_pvt *pvt; struct pci_dev *pdev; @@ -1008,8 +1008,7 @@ error: * @pdev: struct pci_dev pointer * @id: struct pci_device_id pointer - currently unused */ -static int __devinit i7300_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i7300_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { struct mem_ctl_info *mci; struct edac_mc_layer layers[3]; @@ -1122,7 +1121,7 @@ fail0: * i7300_remove_one() - Remove the driver * @pdev: struct pci_dev pointer */ -static void __devexit i7300_remove_one(struct pci_dev *pdev) +static void i7300_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; char *tmp; @@ -1163,7 +1162,7 @@ MODULE_DEVICE_TABLE(pci, i7300_pci_tbl); static struct pci_driver i7300_driver = { .name = "i7300_edac", .probe = i7300_init_one, - .remove = __devexit_p(i7300_remove_one), + .remove = i7300_remove_one, .id_table = i7300_pci_tbl, }; diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 10c8c00d646..e213d030b0d 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -2305,8 +2305,7 @@ fail0: * < 0 for error code */ -static int __devinit i7core_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i7core_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int rc, count = 0; struct i7core_dev *i7core_dev; @@ -2368,7 +2367,7 @@ fail0: * i7core_remove destructor for one instance of device * */ -static void __devexit i7core_remove(struct pci_dev *pdev) +static void i7core_remove(struct pci_dev *pdev) { struct i7core_dev *i7core_dev; @@ -2409,7 +2408,7 @@ MODULE_DEVICE_TABLE(pci, i7core_pci_tbl); static struct pci_driver i7core_driver = { .name = "i7core_edac", .probe = i7core_probe, - .remove = __devexit_p(i7core_remove), + .remove = i7core_remove, .id_table = i7core_pci_tbl, }; diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 90f303db5d1..57fdb77903b 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -353,8 +353,8 @@ fail: EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1); /* returns count (>= 0), or negative on error */ -static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc; @@ -369,7 +369,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) +static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -399,7 +399,7 @@ MODULE_DEVICE_TABLE(pci, i82443bxgx_pci_tbl); static struct pci_driver i82443bxgx_edacmc_driver = { .name = EDAC_MOD_STR, .probe = i82443bxgx_edacmc_init_one, - .remove = __devexit_p(i82443bxgx_edacmc_remove_one), + .remove = i82443bxgx_edacmc_remove_one, .id_table = i82443bxgx_pci_tbl, }; diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 1faa7497151..3e3e431c830 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -254,8 +254,8 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit i82860_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i82860_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc; @@ -273,7 +273,7 @@ static int __devinit i82860_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i82860_remove_one(struct pci_dev *pdev) +static void i82860_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); static struct pci_driver i82860_driver = { .name = EDAC_MOD_STR, .probe = i82860_init_one, - .remove = __devexit_p(i82860_remove_one), + .remove = i82860_remove_one, .id_table = i82860_pci_tbl, }; diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 3e416b1a6b5..2f8535fc451 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -479,8 +479,8 @@ fail0: } /* returns count (>= 0), or negative on error */ -static int __devinit i82875p_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i82875p_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc; @@ -498,7 +498,7 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i82875p_remove_one(struct pci_dev *pdev) +static void i82875p_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct i82875p_pvt *pvt = NULL; @@ -541,7 +541,7 @@ MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); static struct pci_driver i82875p_driver = { .name = EDAC_MOD_STR, .probe = i82875p_init_one, - .remove = __devexit_p(i82875p_remove_one), + .remove = i82875p_remove_one, .id_table = i82875p_pci_tbl, }; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index a98020409fa..0c8d4b0eaa3 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -592,8 +592,8 @@ fail0: } /* returns count (>= 0), or negative on error */ -static int __devinit i82975x_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int i82975x_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { int rc; @@ -610,7 +610,7 @@ static int __devinit i82975x_init_one(struct pci_dev *pdev, return rc; } -static void __devexit i82975x_remove_one(struct pci_dev *pdev) +static void i82975x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; struct i82975x_pvt *pvt; @@ -643,7 +643,7 @@ MODULE_DEVICE_TABLE(pci, i82975x_pci_tbl); static struct pci_driver i82975x_driver = { .name = EDAC_MOD_STR, .probe = i82975x_init_one, - .remove = __devexit_p(i82975x_remove_one), + .remove = i82975x_remove_one, .id_table = i82975x_pci_tbl, }; diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 4fe66fa183e..42a840d530a 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -212,7 +212,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) return IRQ_HANDLED; } -int __devinit mpc85xx_pci_err_probe(struct platform_device *op) +int mpc85xx_pci_err_probe(struct platform_device *op) { struct edac_pci_ctl_info *pci; struct mpc85xx_pci_pdata *pdata; @@ -504,7 +504,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) +static int mpc85xx_l2_err_probe(struct platform_device *op) { struct edac_device_ctl_info *edac_dev; struct mpc85xx_l2_pdata *pdata; @@ -885,7 +885,7 @@ static irqreturn_t mpc85xx_mc_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) +static void mpc85xx_init_csrows(struct mem_ctl_info *mci) { struct mpc85xx_mc_pdata *pdata = mci->pvt_info; struct csrow_info *csrow; @@ -964,7 +964,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) +static int mpc85xx_mc_err_probe(struct platform_device *op) { struct mem_ctl_info *mci; struct edac_mc_layer layers[2]; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 2b315c2edc3..542fad70e36 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -100,7 +100,7 @@ static int __init mv64x60_pci_fixup(struct platform_device *pdev) return 0; } -static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) +static int mv64x60_pci_err_probe(struct platform_device *pdev) { struct edac_pci_ctl_info *pci; struct mv64x60_pci_pdata *pdata; @@ -221,7 +221,7 @@ static int mv64x60_pci_err_remove(struct platform_device *pdev) static struct platform_driver mv64x60_pci_err_driver = { .probe = mv64x60_pci_err_probe, - .remove = __devexit_p(mv64x60_pci_err_remove), + .remove = mv64x60_pci_err_remove, .driver = { .name = "mv64x60_pci_err", } @@ -271,7 +271,7 @@ static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) +static int mv64x60_sram_err_probe(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev; struct mv64x60_sram_pdata *pdata; @@ -439,7 +439,7 @@ static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) +static int mv64x60_cpu_err_probe(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev; struct resource *r; @@ -697,7 +697,7 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, dimm->edac_mode = EDAC_SECDED; } -static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) +static int mv64x60_mc_err_probe(struct platform_device *pdev) { struct mem_ctl_info *mci; struct edac_mc_layer layers[2]; diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c new file mode 100644 index 00000000000..7e98084d364 --- /dev/null +++ b/drivers/edac/octeon_edac-l2c.c @@ -0,0 +1,208 @@ +/* + * 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/io.h> +#include <linux/edac.h> + +#include <asm/octeon/cvmx.h> + +#include "edac_core.h" +#include "edac_module.h" + +#define EDAC_MOD_STR "octeon-l2c" + +static void octeon_l2c_poll_oct1(struct edac_device_ctl_info *l2c) +{ + union cvmx_l2t_err l2t_err, l2t_err_reset; + union cvmx_l2d_err l2d_err, l2d_err_reset; + + l2t_err_reset.u64 = 0; + l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); + if (l2t_err.s.sec_err) { + edac_device_handle_ce(l2c, 0, 0, + "Tag Single bit error (corrected)"); + l2t_err_reset.s.sec_err = 1; + } + if (l2t_err.s.ded_err) { + edac_device_handle_ue(l2c, 0, 0, + "Tag Double bit error (detected)"); + l2t_err_reset.s.ded_err = 1; + } + if (l2t_err_reset.u64) + cvmx_write_csr(CVMX_L2T_ERR, l2t_err_reset.u64); + + l2d_err_reset.u64 = 0; + l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR); + if (l2d_err.s.sec_err) { + edac_device_handle_ce(l2c, 0, 1, + "Data Single bit error (corrected)"); + l2d_err_reset.s.sec_err = 1; + } + if (l2d_err.s.ded_err) { + edac_device_handle_ue(l2c, 0, 1, + "Data Double bit error (detected)"); + l2d_err_reset.s.ded_err = 1; + } + if (l2d_err_reset.u64) + cvmx_write_csr(CVMX_L2D_ERR, l2d_err_reset.u64); + +} + +static void _octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c, int tad) +{ + union cvmx_l2c_err_tdtx err_tdtx, err_tdtx_reset; + union cvmx_l2c_err_ttgx err_ttgx, err_ttgx_reset; + char buf1[64]; + char buf2[80]; + + err_tdtx_reset.u64 = 0; + err_tdtx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TDTX(tad)); + if (err_tdtx.s.dbe || err_tdtx.s.sbe || + err_tdtx.s.vdbe || err_tdtx.s.vsbe) + snprintf(buf1, sizeof(buf1), + "type:%d, syn:0x%x, way:%d", + err_tdtx.s.type, err_tdtx.s.syn, err_tdtx.s.wayidx); + + if (err_tdtx.s.dbe) { + snprintf(buf2, sizeof(buf2), + "L2D Double bit error (detected):%s", buf1); + err_tdtx_reset.s.dbe = 1; + edac_device_handle_ue(l2c, tad, 1, buf2); + } + if (err_tdtx.s.sbe) { + snprintf(buf2, sizeof(buf2), + "L2D Single bit error (corrected):%s", buf1); + err_tdtx_reset.s.sbe = 1; + edac_device_handle_ce(l2c, tad, 1, buf2); + } + if (err_tdtx.s.vdbe) { + snprintf(buf2, sizeof(buf2), + "VBF Double bit error (detected):%s", buf1); + err_tdtx_reset.s.vdbe = 1; + edac_device_handle_ue(l2c, tad, 1, buf2); + } + if (err_tdtx.s.vsbe) { + snprintf(buf2, sizeof(buf2), + "VBF Single bit error (corrected):%s", buf1); + err_tdtx_reset.s.vsbe = 1; + edac_device_handle_ce(l2c, tad, 1, buf2); + } + if (err_tdtx_reset.u64) + cvmx_write_csr(CVMX_L2C_ERR_TDTX(tad), err_tdtx_reset.u64); + + err_ttgx_reset.u64 = 0; + err_ttgx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TTGX(tad)); + + if (err_ttgx.s.dbe || err_ttgx.s.sbe) + snprintf(buf1, sizeof(buf1), + "type:%d, syn:0x%x, way:%d", + err_ttgx.s.type, err_ttgx.s.syn, err_ttgx.s.wayidx); + + if (err_ttgx.s.dbe) { + snprintf(buf2, sizeof(buf2), + "Tag Double bit error (detected):%s", buf1); + err_ttgx_reset.s.dbe = 1; + edac_device_handle_ue(l2c, tad, 0, buf2); + } + if (err_ttgx.s.sbe) { + snprintf(buf2, sizeof(buf2), + "Tag Single bit error (corrected):%s", buf1); + err_ttgx_reset.s.sbe = 1; + edac_device_handle_ce(l2c, tad, 0, buf2); + } + if (err_ttgx_reset.u64) + cvmx_write_csr(CVMX_L2C_ERR_TTGX(tad), err_ttgx_reset.u64); +} + +static void octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c) +{ + int i; + for (i = 0; i < l2c->nr_instances; i++) + _octeon_l2c_poll_oct2(l2c, i); +} + +static int octeon_l2c_probe(struct platform_device *pdev) +{ + struct edac_device_ctl_info *l2c; + + int num_tads = OCTEON_IS_MODEL(OCTEON_CN68XX) ? 4 : 1; + + /* 'Tags' are block 0, 'Data' is block 1*/ + l2c = edac_device_alloc_ctl_info(0, "l2c", num_tads, "l2c", 2, 0, + NULL, 0, edac_device_alloc_index()); + if (!l2c) + return -ENOMEM; + + l2c->dev = &pdev->dev; + platform_set_drvdata(pdev, l2c); + l2c->dev_name = dev_name(&pdev->dev); + + l2c->mod_name = "octeon-l2c"; + l2c->ctl_name = "octeon_l2c_err"; + + + if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) { + union cvmx_l2t_err l2t_err; + union cvmx_l2d_err l2d_err; + + l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); + l2t_err.s.sec_intena = 0; /* We poll */ + l2t_err.s.ded_intena = 0; + cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64); + + l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR); + l2d_err.s.sec_intena = 0; /* We poll */ + l2d_err.s.ded_intena = 0; + cvmx_write_csr(CVMX_L2T_ERR, l2d_err.u64); + + l2c->edac_check = octeon_l2c_poll_oct1; + } else { + /* OCTEON II */ + l2c->edac_check = octeon_l2c_poll_oct2; + } + + if (edac_device_add_device(l2c) > 0) { + pr_err("%s: edac_device_add_device() failed\n", __func__); + goto err; + } + + + return 0; + +err: + edac_device_free_ctl_info(l2c); + + return -ENXIO; +} + +static int octeon_l2c_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *l2c = platform_get_drvdata(pdev); + + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(l2c); + + return 0; +} + +static struct platform_driver octeon_l2c_driver = { + .probe = octeon_l2c_probe, + .remove = octeon_l2c_remove, + .driver = { + .name = "octeon_l2c_edac", + } +}; +module_platform_driver(octeon_l2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c new file mode 100644 index 00000000000..93412d6b3af --- /dev/null +++ b/drivers/edac/octeon_edac-lmc.c @@ -0,0 +1,186 @@ +/* + * 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) 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/io.h> +#include <linux/edac.h> + +#include <asm/octeon/octeon.h> +#include <asm/octeon/cvmx-lmcx-defs.h> + +#include "edac_core.h" +#include "edac_module.h" + +#define OCTEON_MAX_MC 4 + +static void octeon_lmc_edac_poll(struct mem_ctl_info *mci) +{ + union cvmx_lmcx_mem_cfg0 cfg0; + bool do_clear = false; + char msg[64]; + + cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx)); + if (cfg0.s.sec_err || cfg0.s.ded_err) { + union cvmx_lmcx_fadr fadr; + fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx)); + snprintf(msg, sizeof(msg), + "DIMM %d rank %d bank %d row %d col %d", + fadr.cn30xx.fdimm, fadr.cn30xx.fbunk, + fadr.cn30xx.fbank, fadr.cn30xx.frow, fadr.cn30xx.fcol); + } + + if (cfg0.s.sec_err) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, msg, ""); + cfg0.s.sec_err = -1; /* Done, re-arm */ + do_clear = true; + } + + if (cfg0.s.ded_err) { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, msg, ""); + cfg0.s.ded_err = -1; /* Done, re-arm */ + do_clear = true; + } + if (do_clear) + cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx), cfg0.u64); +} + +static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci) +{ + union cvmx_lmcx_int int_reg; + bool do_clear = false; + char msg[64]; + + int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx)); + if (int_reg.s.sec_err || int_reg.s.ded_err) { + union cvmx_lmcx_fadr fadr; + fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx)); + snprintf(msg, sizeof(msg), + "DIMM %d rank %d bank %d row %d col %d", + fadr.cn61xx.fdimm, fadr.cn61xx.fbunk, + fadr.cn61xx.fbank, fadr.cn61xx.frow, fadr.cn61xx.fcol); + } + + if (int_reg.s.sec_err) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, msg, ""); + int_reg.s.sec_err = -1; /* Done, re-arm */ + do_clear = true; + } + + if (int_reg.s.ded_err) { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, msg, ""); + int_reg.s.ded_err = -1; /* Done, re-arm */ + do_clear = true; + } + if (do_clear) + cvmx_write_csr(CVMX_LMCX_INT(mci->mc_idx), int_reg.u64); +} + +static int octeon_lmc_edac_probe(struct platform_device *pdev) +{ + struct mem_ctl_info *mci; + struct edac_mc_layer layers[1]; + int mc = pdev->id; + + layers[0].type = EDAC_MC_LAYER_CHANNEL; + layers[0].size = 1; + layers[0].is_virt_csrow = false; + + if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) { + union cvmx_lmcx_mem_cfg0 cfg0; + + cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); + if (!cfg0.s.ecc_ena) { + dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); + return 0; + } + + mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0); + if (!mci) + return -ENXIO; + + mci->pdev = &pdev->dev; + mci->dev_name = dev_name(&pdev->dev); + + mci->mod_name = "octeon-lmc"; + mci->ctl_name = "octeon-lmc-err"; + mci->edac_check = octeon_lmc_edac_poll; + + if (edac_mc_add_mc(mci)) { + dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); + edac_mc_free(mci); + return -ENXIO; + } + + cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); + cfg0.s.intr_ded_ena = 0; /* We poll */ + cfg0.s.intr_sec_ena = 0; + cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), cfg0.u64); + } else { + /* OCTEON II */ + union cvmx_lmcx_int_en en; + union cvmx_lmcx_config config; + + config.u64 = cvmx_read_csr(CVMX_LMCX_CONFIG(0)); + if (!config.s.ecc_ena) { + dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); + return 0; + } + + mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0); + if (!mci) + return -ENXIO; + + mci->pdev = &pdev->dev; + mci->dev_name = dev_name(&pdev->dev); + + mci->mod_name = "octeon-lmc"; + mci->ctl_name = "co_lmc_err"; + mci->edac_check = octeon_lmc_edac_poll_o2; + + if (edac_mc_add_mc(mci)) { + dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); + edac_mc_free(mci); + return -ENXIO; + } + + en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); + en.s.intr_ded_ena = 0; /* We poll */ + en.s.intr_sec_ena = 0; + cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), en.u64); + } + platform_set_drvdata(pdev, mci); + + return 0; +} + +static int octeon_lmc_edac_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + return 0; +} + +static struct platform_driver octeon_lmc_edac_driver = { + .probe = octeon_lmc_edac_probe, + .remove = octeon_lmc_edac_remove, + .driver = { + .name = "octeon_lmc_edac", + } +}; +module_platform_driver(octeon_lmc_edac_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c new file mode 100644 index 00000000000..0f83c33a7d1 --- /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 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>"); diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c new file mode 100644 index 00000000000..9ca73cec74e --- /dev/null +++ b/drivers/edac/octeon_edac-pci.c @@ -0,0 +1,111 @@ +/* + * 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/io.h> +#include <linux/edac.h> + +#include <asm/octeon/cvmx.h> +#include <asm/octeon/cvmx-npi-defs.h> +#include <asm/octeon/cvmx-pci-defs.h> +#include <asm/octeon/octeon.h> + +#include "edac_core.h" +#include "edac_module.h" + +static void octeon_pci_poll(struct edac_pci_ctl_info *pci) +{ + union cvmx_pci_cfg01 cfg01; + + cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01); + if (cfg01.s.dpe) { /* Detected parity error */ + edac_pci_handle_pe(pci, pci->ctl_name); + cfg01.s.dpe = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } + if (cfg01.s.sse) { + edac_pci_handle_npe(pci, "Signaled System Error"); + cfg01.s.sse = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } + if (cfg01.s.rma) { + edac_pci_handle_npe(pci, "Received Master Abort"); + cfg01.s.rma = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } + if (cfg01.s.rta) { + edac_pci_handle_npe(pci, "Received Target Abort"); + cfg01.s.rta = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } + if (cfg01.s.sta) { + edac_pci_handle_npe(pci, "Signaled Target Abort"); + cfg01.s.sta = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } + if (cfg01.s.mdpe) { + edac_pci_handle_npe(pci, "Master Data Parity Error"); + cfg01.s.mdpe = 1; /* Reset */ + octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); + } +} + +static int octeon_pci_probe(struct platform_device *pdev) +{ + struct edac_pci_ctl_info *pci; + int res = 0; + + pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err"); + if (!pci) + return -ENOMEM; + + pci->dev = &pdev->dev; + platform_set_drvdata(pdev, pci); + pci->dev_name = dev_name(&pdev->dev); + + pci->mod_name = "octeon-pci"; + pci->ctl_name = "octeon_pci_err"; + pci->edac_check = octeon_pci_poll; + + if (edac_pci_add_device(pci, 0) > 0) { + pr_err("%s: edac_pci_add_device() failed\n", __func__); + goto err; + } + + return 0; + +err: + edac_pci_free_ctl_info(pci); + + return res; +} + +static int octeon_pci_remove(struct platform_device *pdev) +{ + struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); + + edac_pci_del_device(&pdev->dev); + edac_pci_free_ctl_info(pci); + + return 0; +} + +static struct platform_driver octeon_pci_driver = { + .probe = octeon_pci_probe, + .remove = octeon_pci_remove, + .driver = { + .name = "octeon_pci_edac", + } +}; +module_platform_driver(octeon_pci_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index 2d35b78ada3..9c971b57553 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -188,8 +188,8 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, return 0; } -static int __devinit pasemi_edac_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int pasemi_edac_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct mem_ctl_info *mci = NULL; struct edac_mc_layer layers[2]; @@ -266,7 +266,7 @@ fail: return -ENODEV; } -static void __devexit pasemi_edac_remove(struct pci_dev *pdev) +static void pasemi_edac_remove(struct pci_dev *pdev) { struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev); @@ -287,7 +287,7 @@ MODULE_DEVICE_TABLE(pci, pasemi_edac_pci_tbl); static struct pci_driver pasemi_edac_driver = { .name = MODULE_NAME, .probe = pasemi_edac_probe, - .remove = __devexit_p(pasemi_edac_remove), + .remove = pasemi_edac_remove, .id_table = pasemi_edac_pci_tbl, }; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index bf095763599..ef6b7e08f48 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -838,8 +838,7 @@ ppc4xx_edac_isr(int irq, void *dev_id) * * Returns a device type width enumeration. */ -static enum dev_type __devinit -ppc4xx_edac_get_dtype(u32 mcopt1) +static enum dev_type ppc4xx_edac_get_dtype(u32 mcopt1) { switch (mcopt1 & SDRAM_MCOPT1_WDTH_MASK) { case SDRAM_MCOPT1_WDTH_16: @@ -862,8 +861,7 @@ ppc4xx_edac_get_dtype(u32 mcopt1) * * Returns a memory type enumeration. */ -static enum mem_type __devinit -ppc4xx_edac_get_mtype(u32 mcopt1) +static enum mem_type ppc4xx_edac_get_mtype(u32 mcopt1) { bool rden = ((mcopt1 & SDRAM_MCOPT1_RDEN_MASK) == SDRAM_MCOPT1_RDEN); @@ -893,8 +891,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1) * Returns 0 if OK; otherwise, -EINVAL if the memory bank size * configuration cannot be determined. */ -static int __devinit -ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) +static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) { const struct ppc4xx_edac_pdata *pdata = mci->pvt_info; int status = 0; @@ -1011,11 +1008,9 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) * * Returns 0 if OK; otherwise, < 0 on error. */ -static int __devinit -ppc4xx_edac_mc_init(struct mem_ctl_info *mci, - struct platform_device *op, - const dcr_host_t *dcr_host, - u32 mcopt1) +static int ppc4xx_edac_mc_init(struct mem_ctl_info *mci, + struct platform_device *op, + const dcr_host_t *dcr_host, u32 mcopt1) { int status = 0; const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK); @@ -1105,8 +1100,8 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, * Returns 0 if OK; otherwise, -ENODEV if the interrupts could not be * mapped and assigned. */ -static int __devinit -ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) +static int ppc4xx_edac_register_irq(struct platform_device *op, + struct mem_ctl_info *mci) { int status = 0; int ded_irq, sec_irq; @@ -1183,8 +1178,8 @@ ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) * Returns 0 if the DCRs were successfully mapped; otherwise, < 0 on * error. */ -static int __devinit -ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) +static int ppc4xx_edac_map_dcrs(const struct device_node *np, + dcr_host_t *dcr_host) { unsigned int dcr_base, dcr_len; @@ -1232,7 +1227,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) * Returns 0 if the controller instance was successfully bound to the * driver; otherwise, < 0 on error. */ -static int __devinit ppc4xx_edac_probe(struct platform_device *op) +static int ppc4xx_edac_probe(struct platform_device *op) { int status = 0; u32 mcopt1, memcheck; diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index f854debd553..2fd6a549090 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -359,8 +359,8 @@ fail: } /* returns count (>= 0), or negative on error */ -static int __devinit r82600_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int r82600_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { edac_dbg(0, "\n"); @@ -368,7 +368,7 @@ static int __devinit r82600_init_one(struct pci_dev *pdev, return r82600_probe1(pdev, ent->driver_data); } -static void __devexit r82600_remove_one(struct pci_dev *pdev) +static void r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -397,7 +397,7 @@ MODULE_DEVICE_TABLE(pci, r82600_pci_tbl); static struct pci_driver r82600_driver = { .name = EDAC_MOD_STR, .probe = r82600_init_one, - .remove = __devexit_p(r82600_remove_one), + .remove = r82600_remove_one, .id_table = r82600_pci_tbl, }; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 5715b7c2c51..da7e2986e3d 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -1692,8 +1692,7 @@ fail0: * < 0 for error code */ -static int __devinit sbridge_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; u8 mc, num_mc = 0; @@ -1744,7 +1743,7 @@ fail0: * sbridge_remove destructor for one instance of device * */ -static void __devexit sbridge_remove(struct pci_dev *pdev) +static void sbridge_remove(struct pci_dev *pdev) { struct sbridge_dev *sbridge_dev; @@ -1785,7 +1784,7 @@ MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl); static struct pci_driver sbridge_driver = { .name = "sbridge_edac", .probe = sbridge_probe, - .remove = __devexit_p(sbridge_remove), + .remove = sbridge_remove, .id_table = sbridge_pci_tbl, }; diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 1e904b7b79a..a0820536b7d 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -82,7 +82,7 @@ static void tile_edac_check(struct mem_ctl_info *mci) * Initialize the 'csrows' table within the mci control structure with the * addressing of memory. */ -static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) +static int tile_edac_init_csrows(struct mem_ctl_info *mci) { struct csrow_info *csrow = mci->csrows[0]; struct tile_edac_priv *priv = mci->pvt_info; @@ -120,7 +120,7 @@ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) return 0; } -static int __devinit tile_edac_mc_probe(struct platform_device *pdev) +static int tile_edac_mc_probe(struct platform_device *pdev) { char hv_file[32]; int hv_devhdl; @@ -186,7 +186,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev) return 0; } -static int __devexit tile_edac_mc_remove(struct platform_device *pdev) +static int tile_edac_mc_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); @@ -202,7 +202,7 @@ static struct platform_driver tile_edac_mc_driver = { .owner = THIS_MODULE, }, .probe = tile_edac_mc_probe, - .remove = __devexit_p(tile_edac_mc_remove), + .remove = tile_edac_mc_remove, }; /* diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 08a992693e6..c9db24d95ca 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -418,8 +418,7 @@ fail: return rc; } -static int __devinit x38_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int x38_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; @@ -435,7 +434,7 @@ static int __devinit x38_init_one(struct pci_dev *pdev, return rc; } -static void __devexit x38_remove_one(struct pci_dev *pdev) +static void x38_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; @@ -464,7 +463,7 @@ MODULE_DEVICE_TABLE(pci, x38_pci_tbl); static struct pci_driver x38_driver = { .name = EDAC_MOD_STR, .probe = x38_init_one, - .remove = __devexit_p(x38_remove_one), + .remove = x38_remove_one, .id_table = x38_pci_tbl, }; |