diff options
-rw-r--r-- | Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml | 67 | ||||
-rw-r--r-- | MAINTAINERS | 11 | ||||
-rw-r--r-- | drivers/edac/Kconfig | 7 | ||||
-rw-r--r-- | drivers/edac/Makefile | 1 | ||||
-rw-r--r-- | drivers/edac/al_mc_edac.c | 354 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 6 | ||||
-rw-r--r-- | drivers/edac/aspeed_edac.c | 22 | ||||
-rw-r--r-- | drivers/edac/e752x_edac.c | 2 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 22 | ||||
-rw-r--r-- | drivers/edac/ghes_edac.c | 2 | ||||
-rw-r--r-- | drivers/edac/i5100_edac.c | 11 | ||||
-rw-r--r-- | drivers/edac/i5400_edac.c | 4 | ||||
-rw-r--r-- | drivers/edac/i7300_edac.c | 4 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 4 | ||||
-rw-r--r-- | drivers/edac/ie31200_edac.c | 6 | ||||
-rw-r--r-- | drivers/edac/mce_amd.c | 11 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 7 | ||||
-rw-r--r-- | drivers/edac/thunderx_edac.c | 2 | ||||
-rw-r--r-- | drivers/edac/ti_edac.c | 5 |
19 files changed, 496 insertions, 52 deletions
diff --git a/Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml b/Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml new file mode 100644 index 000000000000..a25387df0865 --- /dev/null +++ b/Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/edac/amazon,al-mc-edac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amazon's Annapurna Labs Memory Controller EDAC + +maintainers: + - Talel Shenhar <talel@amazon.com> + - Talel Shenhar <talelshenhar@gmail.com> + +description: | + EDAC node is defined to describe on-chip error detection and correction for + Amazon's Annapurna Labs Memory Controller. + +properties: + + compatible: + const: amazon,al-mc-edac + + reg: + maxItems: 1 + + "#address-cells": + const: 2 + + "#size-cells": + const: 2 + + interrupts: + minItems: 1 + maxItems: 2 + items: + - description: uncorrectable error interrupt + - description: correctable error interrupt + + interrupt-names: + minItems: 1 + maxItems: 2 + items: + - const: ue + - const: ce + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + soc { + #address-cells = <2>; + #size-cells = <2>; + edac@f0080000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "amazon,al-mc-edac"; + reg = <0x0 0xf0080000 0x0 0x00010000>; + interrupt-parent = <&amazon_al_system_fabric>; + interrupt-names = "ue"; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index d61d45daa31b..5edaa33a0e98 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -802,6 +802,13 @@ S: Maintained F: Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt F: drivers/irqchip/irq-al-fic.c +AMAZON ANNAPURNA LABS MEMORY CONTROLLER EDAC +M: Talel Shenhar <talel@amazon.com> +M: Talel Shenhar <talelshenhar@gmail.com> +S: Maintained +F: Documentation/devicetree/bindings/edac/amazon,al-mc-edac.yaml +F: drivers/edac/al_mc_edac.c + AMAZON ANNAPURNA LABS THERMAL MMIO DRIVER M: Talel Shenhar <talel@amazon.com> S: Maintained @@ -2509,7 +2516,7 @@ S: Maintained F: drivers/clk/socfpga/ ARM/SOCFPGA EDAC SUPPORT -M: Thor Thayer <thor.thayer@linux.intel.com> +M: Dinh Nguyen <dinguyen@kernel.org> S: Maintained F: drivers/edac/altera_edac. @@ -6184,7 +6191,7 @@ S: Supported F: drivers/edac/bluefield_edac.c EDAC-CALXEDA -M: Robert Richter <rric@kernel.org> +M: Andre Przywara <andre.przywara@arm.com> L: linux-edac@vger.kernel.org S: Maintained F: drivers/edac/highbank* diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 7b6ec3014ba2..7a47680d6f07 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -100,6 +100,13 @@ config EDAC_AMD64_ERROR_INJECTION In addition, there are two control files, inject_read and inject_write, which trigger the DRAM ECC Read and Write respectively. +config EDAC_AL_MC + tristate "Amazon's Annapurna Lab Memory Controller" + depends on (ARCH_ALPINE || COMPILE_TEST) + help + Support for error detection and correction for Amazon's Annapurna + Labs Alpine chips which allow 1 bit correction and 2 bits detection. + config EDAC_AMD76X tristate "AMD 76x (760, 762, 768)" depends on PCI && X86_32 diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 269e15118cea..3a849168780d 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_EDAC_GHES) += ghes_edac.o edac_mce_amd-y := mce_amd.o obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o +obj-$(CONFIG_EDAC_AL_MC) += al_mc_edac.o obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o obj-$(CONFIG_EDAC_I5000) += i5000_edac.o diff --git a/drivers/edac/al_mc_edac.c b/drivers/edac/al_mc_edac.c new file mode 100644 index 000000000000..7d4f396c27b5 --- /dev/null +++ b/drivers/edac/al_mc_edac.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + */ +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/edac.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include "edac_module.h" + +/* Registers Offset */ +#define AL_MC_ECC_CFG 0x70 +#define AL_MC_ECC_CLEAR 0x7c +#define AL_MC_ECC_ERR_COUNT 0x80 +#define AL_MC_ECC_CE_ADDR0 0x84 +#define AL_MC_ECC_CE_ADDR1 0x88 +#define AL_MC_ECC_UE_ADDR0 0xa4 +#define AL_MC_ECC_UE_ADDR1 0xa8 +#define AL_MC_ECC_CE_SYND0 0x8c +#define AL_MC_ECC_CE_SYND1 0x90 +#define AL_MC_ECC_CE_SYND2 0x94 +#define AL_MC_ECC_UE_SYND0 0xac +#define AL_MC_ECC_UE_SYND1 0xb0 +#define AL_MC_ECC_UE_SYND2 0xb4 + +/* Registers Fields */ +#define AL_MC_ECC_CFG_SCRUB_DISABLED BIT(4) + +#define AL_MC_ECC_CLEAR_UE_COUNT BIT(3) +#define AL_MC_ECC_CLEAR_CE_COUNT BIT(2) +#define AL_MC_ECC_CLEAR_UE_ERR BIT(1) +#define AL_MC_ECC_CLEAR_CE_ERR BIT(0) + +#define AL_MC_ECC_ERR_COUNT_UE GENMASK(31, 16) +#define AL_MC_ECC_ERR_COUNT_CE GENMASK(15, 0) + +#define AL_MC_ECC_CE_ADDR0_RANK GENMASK(25, 24) +#define AL_MC_ECC_CE_ADDR0_ROW GENMASK(17, 0) + +#define AL_MC_ECC_CE_ADDR1_BG GENMASK(25, 24) +#define AL_MC_ECC_CE_ADDR1_BANK GENMASK(18, 16) +#define AL_MC_ECC_CE_ADDR1_COLUMN GENMASK(11, 0) + +#define AL_MC_ECC_UE_ADDR0_RANK GENMASK(25, 24) +#define AL_MC_ECC_UE_ADDR0_ROW GENMASK(17, 0) + +#define AL_MC_ECC_UE_ADDR1_BG GENMASK(25, 24) +#define AL_MC_ECC_UE_ADDR1_BANK GENMASK(18, 16) +#define AL_MC_ECC_UE_ADDR1_COLUMN GENMASK(11, 0) + +#define DRV_NAME "al_mc_edac" +#define AL_MC_EDAC_MSG_MAX 256 + +struct al_mc_edac { + void __iomem *mmio_base; + spinlock_t lock; + int irq_ce; + int irq_ue; +}; + +static void prepare_msg(char *message, size_t buffer_size, + enum hw_event_mc_err_type type, + u8 rank, u32 row, u8 bg, u8 bank, u16 column, + u32 syn0, u32 syn1, u32 syn2) +{ + snprintf(message, buffer_size, + "%s rank=0x%x row=0x%x bg=0x%x bank=0x%x col=0x%x syn0: 0x%x syn1: 0x%x syn2: 0x%x", + type == HW_EVENT_ERR_UNCORRECTED ? "UE" : "CE", + rank, row, bg, bank, column, syn0, syn1, syn2); +} + +static int handle_ce(struct mem_ctl_info *mci) +{ + u32 eccerrcnt, ecccaddr0, ecccaddr1, ecccsyn0, ecccsyn1, ecccsyn2, row; + struct al_mc_edac *al_mc = mci->pvt_info; + char msg[AL_MC_EDAC_MSG_MAX]; + u16 ce_count, column; + unsigned long flags; + u8 rank, bg, bank; + + eccerrcnt = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_ERR_COUNT); + ce_count = FIELD_GET(AL_MC_ECC_ERR_COUNT_CE, eccerrcnt); + if (!ce_count) + return 0; + + ecccaddr0 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_CE_ADDR0); + ecccaddr1 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_CE_ADDR1); + ecccsyn0 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_CE_SYND0); + ecccsyn1 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_CE_SYND1); + ecccsyn2 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_CE_SYND2); + + writel_relaxed(AL_MC_ECC_CLEAR_CE_COUNT | AL_MC_ECC_CLEAR_CE_ERR, + al_mc->mmio_base + AL_MC_ECC_CLEAR); + + dev_dbg(mci->pdev, "eccuaddr0=0x%08x eccuaddr1=0x%08x\n", + ecccaddr0, ecccaddr1); + + rank = FIELD_GET(AL_MC_ECC_CE_ADDR0_RANK, ecccaddr0); + row = FIELD_GET(AL_MC_ECC_CE_ADDR0_ROW, ecccaddr0); + + bg = FIELD_GET(AL_MC_ECC_CE_ADDR1_BG, ecccaddr1); + bank = FIELD_GET(AL_MC_ECC_CE_ADDR1_BANK, ecccaddr1); + column = FIELD_GET(AL_MC_ECC_CE_ADDR1_COLUMN, ecccaddr1); + + prepare_msg(msg, sizeof(msg), HW_EVENT_ERR_CORRECTED, + rank, row, bg, bank, column, + ecccsyn0, ecccsyn1, ecccsyn2); + + spin_lock_irqsave(&al_mc->lock, flags); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + ce_count, 0, 0, 0, 0, 0, -1, mci->ctl_name, msg); + spin_unlock_irqrestore(&al_mc->lock, flags); + + return ce_count; +} + +static int handle_ue(struct mem_ctl_info *mci) +{ + u32 eccerrcnt, eccuaddr0, eccuaddr1, eccusyn0, eccusyn1, eccusyn2, row; + struct al_mc_edac *al_mc = mci->pvt_info; + char msg[AL_MC_EDAC_MSG_MAX]; + u16 ue_count, column; + unsigned long flags; + u8 rank, bg, bank; + + eccerrcnt = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_ERR_COUNT); + ue_count = FIELD_GET(AL_MC_ECC_ERR_COUNT_UE, eccerrcnt); + if (!ue_count) + return 0; + + eccuaddr0 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_UE_ADDR0); + eccuaddr1 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_UE_ADDR1); + eccusyn0 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_UE_SYND0); + eccusyn1 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_UE_SYND1); + eccusyn2 = readl_relaxed(al_mc->mmio_base + AL_MC_ECC_UE_SYND2); + + writel_relaxed(AL_MC_ECC_CLEAR_UE_COUNT | AL_MC_ECC_CLEAR_UE_ERR, + al_mc->mmio_base + AL_MC_ECC_CLEAR); + + dev_dbg(mci->pdev, "eccuaddr0=0x%08x eccuaddr1=0x%08x\n", + eccuaddr0, eccuaddr1); + + rank = FIELD_GET(AL_MC_ECC_UE_ADDR0_RANK, eccuaddr0); + row = FIELD_GET(AL_MC_ECC_UE_ADDR0_ROW, eccuaddr0); + + bg = FIELD_GET(AL_MC_ECC_UE_ADDR1_BG, eccuaddr1); + bank = FIELD_GET(AL_MC_ECC_UE_ADDR1_BANK, eccuaddr1); + column = FIELD_GET(AL_MC_ECC_UE_ADDR1_COLUMN, eccuaddr1); + + prepare_msg(msg, sizeof(msg), HW_EVENT_ERR_UNCORRECTED, + rank, row, bg, bank, column, + eccusyn0, eccusyn1, eccusyn2); + + spin_lock_irqsave(&al_mc->lock, flags); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + ue_count, 0, 0, 0, 0, 0, -1, mci->ctl_name, msg); + spin_unlock_irqrestore(&al_mc->lock, flags); + + return ue_count; +} + +static void al_mc_edac_check(struct mem_ctl_info *mci) +{ + struct al_mc_edac *al_mc = mci->pvt_info; + + if (al_mc->irq_ue <= 0) + handle_ue(mci); + + if (al_mc->irq_ce <= 0) + handle_ce(mci); +} + +static irqreturn_t al_mc_edac_irq_handler_ue(int irq, void *info) +{ + struct platform_device *pdev = info; + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + if (handle_ue(mci)) + return IRQ_HANDLED; + return IRQ_NONE; +} + +static irqreturn_t al_mc_edac_irq_handler_ce(int irq, void *info) +{ + struct platform_device *pdev = info; + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + if (handle_ce(mci)) + return IRQ_HANDLED; + return IRQ_NONE; +} + +static enum scrub_type get_scrub_mode(void __iomem *mmio_base) +{ + u32 ecccfg0; + + ecccfg0 = readl(mmio_base + AL_MC_ECC_CFG); + + if (FIELD_GET(AL_MC_ECC_CFG_SCRUB_DISABLED, ecccfg0)) + return SCRUB_NONE; + else + return SCRUB_HW_SRC; +} + +static void devm_al_mc_edac_free(void *data) +{ + edac_mc_free(data); +} + +static void devm_al_mc_edac_del(void *data) +{ + edac_mc_del_mc(data); +} + +static int al_mc_edac_probe(struct platform_device *pdev) +{ + struct edac_mc_layer layers[1]; + struct mem_ctl_info *mci; + struct al_mc_edac *al_mc; + void __iomem *mmio_base; + struct dimm_info *dimm; + int ret; + + mmio_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mmio_base)) { + dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n", + PTR_ERR(mmio_base)); + return PTR_ERR(mmio_base); + } + + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = 1; + layers[0].is_virt_csrow = false; + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, + sizeof(struct al_mc_edac)); + if (!mci) + return -ENOMEM; + + ret = devm_add_action(&pdev->dev, devm_al_mc_edac_free, mci); + if (ret) { + edac_mc_free(mci); + return ret; + } + + platform_set_drvdata(pdev, mci); + al_mc = mci->pvt_info; + + al_mc->mmio_base = mmio_base; + + al_mc->irq_ue = of_irq_get_byname(pdev->dev.of_node, "ue"); + if (al_mc->irq_ue <= 0) + dev_dbg(&pdev->dev, + "no IRQ defined for UE - falling back to polling\n"); + + al_mc->irq_ce = of_irq_get_byname(pdev->dev.of_node, "ce"); + if (al_mc->irq_ce <= 0) + dev_dbg(&pdev->dev, + "no IRQ defined for CE - falling back to polling\n"); + + /* + * In case both interrupts (ue/ce) are to be found, use interrupt mode. + * In case none of the interrupt are foud, use polling mode. + * In case only one interrupt is found, use interrupt mode for it but + * keep polling mode enable for the other. + */ + if (al_mc->irq_ue <= 0 || al_mc->irq_ce <= 0) { + edac_op_state = EDAC_OPSTATE_POLL; + mci->edac_check = al_mc_edac_check; + } else { + edac_op_state = EDAC_OPSTATE_INT; + } + + spin_lock_init(&al_mc->lock); + + mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR4; + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = DRV_NAME; + mci->ctl_name = "al_mc"; + mci->pdev = &pdev->dev; + mci->scrub_mode = get_scrub_mode(mmio_base); + + dimm = *mci->dimms; + dimm->grain = 1; + + ret = edac_mc_add_mc(mci); + if (ret < 0) { + dev_err(&pdev->dev, + "fail to add memory controller device (%d)\n", + ret); + return ret; + } + + ret = devm_add_action(&pdev->dev, devm_al_mc_edac_del, &pdev->dev); + if (ret) { + edac_mc_del_mc(&pdev->dev); + return ret; + } + + if (al_mc->irq_ue > 0) { + ret = devm_request_irq(&pdev->dev, + al_mc->irq_ue, + al_mc_edac_irq_handler_ue, + IRQF_SHARED, + pdev->name, + pdev); + if (ret != 0) { + dev_err(&pdev->dev, + "failed to request UE IRQ %d (%d)\n", + al_mc->irq_ue, ret); + return ret; + } + } + + if (al_mc->irq_ce > 0) { + ret = devm_request_irq(&pdev->dev, + al_mc->irq_ce, + al_mc_edac_irq_handler_ce, + IRQF_SHARED, + pdev->name, + pdev); + if (ret != 0) { + dev_err(&pdev->dev, + "failed to request CE IRQ %d (%d)\n", + al_mc->irq_ce, ret); + return ret; + } + } + + return 0; +} + +static const struct of_device_id al_mc_edac_of_match[] = { + { .compatible = "amazon,al-mc-edac", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, al_mc_edac_of_match); + +static struct platform_driver al_mc_edac_driver = { + .probe = al_mc_edac_probe, + .driver = { + .name = DRV_NAME, + .of_match_table = al_mc_edac_of_match, + }, +}; + +module_platform_driver(al_mc_edac_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Talel Shenhar"); +MODULE_DESCRIPTION("Amazon's Annapurna Lab's Memory Controller EDAC Driver"); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index fcc08bbf6945..1362274d840b 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3385,6 +3385,12 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) break; case 0x19: + if (pvt->model >= 0x20 && pvt->model <= 0x2f) { + fam_type = &family_types[F17_M70H_CPUS]; + pvt->ops = &family_types[F17_M70H_CPUS].ops; + fam_type->ctl_name = "F19h_M20h"; + break; + } fam_type = &family_types[F19_CPUS]; pvt->ops = &family_types[F19_CPUS].ops; family_types[F19_CPUS].ctl_name = "F19h"; diff --git a/drivers/edac/aspeed_edac.c b/drivers/edac/aspeed_edac.c index b194658b8b5c..fde809efc520 100644 --- a/drivers/edac/aspeed_edac.c +++ b/drivers/edac/aspeed_edac.c @@ -209,8 +209,8 @@ static int config_irq(void *ctx, struct platform_device *pdev) /* register interrupt handler */ irq = platform_get_irq(pdev, 0); dev_dbg(&pdev->dev, "got irq %d\n", irq); - if (!irq) - return -ENODEV; + if (irq < 0) + return irq; rc = devm_request_irq(&pdev->dev, irq, mcr_isr, IRQF_TRIGGER_HIGH, DRV_NAME, ctx); @@ -388,23 +388,7 @@ static struct platform_driver aspeed_driver = { .probe = aspeed_probe, .remove = aspeed_remove }; - - -static int __init aspeed_init(void) -{ - return platform_driver_register(&aspeed_driver); -} - - -static void __exit aspeed_exit(void) -{ - platform_driver_unregister(&aspeed_driver); -} - - -module_init(aspeed_init); -module_exit(aspeed_exit); - +module_platform_driver(aspeed_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Stefan Schaeckeler <sschaeck@cisco.com>"); diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index de732dc2ef33..313d08018166 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -7,7 +7,7 @@ * Implement support for the e7520, E7525, e7320 and i3100 memory controllers. * * Datasheets: - * http://www.intel.in/content/www/in/en/chipsets/e7525-memory-controller-hub-datasheet.html + * https://www.intel.in/content/www/in/en/chipsets/e7525-memory-controller-hub-datasheet.html * ftp://download.intel.com/design/intarch/datashts/31345803.pdf * * Written by Tom Zimmerman diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 4e6aca595133..2f9f1e74bb35 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -474,8 +474,12 @@ static ssize_t dimmdev_location_show(struct device *dev, struct device_attribute *mattr, char *data) { struct dimm_info *dimm = to_dimm(dev); + ssize_t count; - return edac_dimm_info_location(dimm, data, PAGE_SIZE); + count = edac_dimm_info_location(dimm, data, PAGE_SIZE); + count += scnprintf(data + count, PAGE_SIZE - count, "\n"); + + return count; } static ssize_t dimmdev_label_show(struct device *dev, @@ -813,15 +817,23 @@ static ssize_t mci_max_location_show(struct device *dev, char *data) { struct mem_ctl_info *mci = to_mci(dev); - int i; + int len = PAGE_SIZE; char *p = data; + int i, n; for (i = 0; i < mci->n_layers; i++) { - p += sprintf(p, "%s %d ", - edac_layer_name[mci->layers[i].type], - mci->layers[i].size - 1); + n = scnprintf(p, len, "%s %d ", + edac_layer_name[mci->layers[i].type], + mci->layers[i].size - 1); + len -= n; + if (len <= 0) + goto out; + + p += n; } + p += scnprintf(p, len, "\n"); +out: return p - data; } diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 94d1e3165052..dbbefd2798c5 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -4,7 +4,7 @@ * * Copyright (c) 2013 by Mauro Carvalho Chehab * - * Red Hat Inc. http://www.redhat.com + * Red Hat Inc. https://www.redhat.com */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 191aa7c19ded..324a46b8479b 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -1061,16 +1061,15 @@ static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) PCI_DEVICE_ID_INTEL_5100_19, 0); if (!einj) { ret = -ENODEV; - goto bail_einj; + goto bail_mc_free; } rc = pci_enable_device(einj); if (rc < 0) { ret = rc; - goto bail_disable_einj; + goto bail_einj; } - mci->pdev = &pdev->dev; priv = mci->pvt_info; @@ -1136,14 +1135,14 @@ static int i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) bail_scrub: priv->scrub_enable = 0; cancel_delayed_work_sync(&(priv->i5100_scrubbing)); - edac_mc_free(mci); - -bail_disable_einj: pci_disable_device(einj); bail_einj: pci_dev_put(einj); +bail_mc_free: + edac_mc_free(mci); + bail_disable_ch1: pci_disable_device(ch1mm); diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index f131c05ade9f..92d63eb533ae 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -8,7 +8,7 @@ * Ben Woodard <woodard@redhat.com> * Mauro Carvalho Chehab * - * Red Hat Inc. http://www.redhat.com + * Red Hat Inc. https://www.redhat.com * * Forked and adapted from the i5000_edac driver which was * written by Douglas Thompson Linux Networx <norsk5@xmission.com> @@ -1460,7 +1460,7 @@ module_exit(i5400_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ben Woodard <woodard@redhat.com>"); MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)"); MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - " I5400_REVISION); diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 2e9bbe56cde9..4f28b8c8d378 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -5,7 +5,7 @@ * Copyright (c) 2010 by: * Mauro Carvalho Chehab * - * Red Hat Inc. http://www.redhat.com + * Red Hat Inc. https://www.redhat.com * * Intel 7300 Chipset Memory Controller Hub (MCH) - Datasheet * http://www.intel.com/Assets/PDF/datasheet/318082.pdf @@ -1206,7 +1206,7 @@ module_exit(i7300_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)"); MODULE_DESCRIPTION("MC Driver for Intel I7300 memory controllers - " I7300_REVISION); diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 2acd9f9284a2..23d25724bae4 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -9,7 +9,7 @@ * Copyright (c) 2009-2010 by: * Mauro Carvalho Chehab * - * Red Hat Inc. http://www.redhat.com + * Red Hat Inc. https://www.redhat.com * * Forked and adapted from the i5400_edac driver * @@ -2391,7 +2391,7 @@ module_exit(i7core_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)"); MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - " I7CORE_REVISION); diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index ebe50996cc42..c47963240b65 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -9,7 +9,7 @@ * Since the DRAM controller is on the cpu chip, we can use its PCI device * id to identify these processors. * - * PCI DRAM controller device ids (Taken from The PCI ID Repository - http://pci-ids.ucw.cz/) + * PCI DRAM controller device ids (Taken from The PCI ID Repository - https://pci-ids.ucw.cz/) * * 0108: Xeon E3-1200 Processor Family DRAM Controller * 010c: Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller @@ -23,9 +23,9 @@ * 3e..: 8th/9th Gen Core Processor Host Bridge/DRAM Registers * * Based on Intel specification: - * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf + * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf * http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html - * http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html + * https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html * https://www.intel.com/content/www/us/en/products/docs/processors/core/8th-gen-core-family-datasheet-vol-2.html * * According to the above datasheet (p.16): diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 325aedf46ff2..4fd06a3dc6fe 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -210,6 +210,11 @@ static const char * const smca_if_mce_desc[] = { "L2 BTB Multi-Match Error", "L2 Cache Response Poison Error", "System Read Data Error", + "Hardware Assertion Error", + "L1-TLB Multi-Hit", + "L2-TLB Multi-Hit", + "BSR Parity Error", + "CT MCE", }; static const char * const smca_l2_mce_desc[] = { @@ -228,7 +233,8 @@ static const char * const smca_de_mce_desc[] = { "Fetch address FIFO parity error", "Patch RAM data parity error", "Patch RAM sequencer parity error", - "Micro-op buffer parity error" + "Micro-op buffer parity error", + "Hardware Assertion MCA Error", }; static const char * const smca_ex_mce_desc[] = { @@ -244,6 +250,8 @@ static const char * const smca_ex_mce_desc[] = { "Scheduling queue parity error", "Branch buffer queue parity error", "Hardware Assertion error", + "Spec Map parity error", + "Retire Map parity error", }; static const char * const smca_fp_mce_desc[] = { @@ -360,6 +368,7 @@ static const char * const smca_smu2_mce_desc[] = { "Instruction Tag Cache Bank A ECC or parity error", "Instruction Tag Cache Bank B ECC or parity error", "System Hub Read Buffer ECC or parity error", + "PHY RAM ECC error", }; static const char * const smca_mp5_mce_desc[] = { diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index c5ab634cb6a4..93daa4297f2e 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -939,12 +939,9 @@ static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr) static enum dev_type __ibridge_get_width(u32 mtr) { - enum dev_type type; + enum dev_type type = DEV_UNKNOWN; switch (mtr) { - case 3: - type = DEV_UNKNOWN; - break; case 2: type = DEV_X16; break; @@ -3552,6 +3549,6 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mauro Carvalho Chehab"); -MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)"); MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - " SBRIDGE_REVISION); diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 4af9744cc6d0..0eb5eb97fd74 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -454,7 +454,7 @@ DEBUGFS_STRUCT(inject_int, 0200, thunderx_lmc_inject_int_write, NULL); DEBUGFS_STRUCT(inject_ecc, 0200, thunderx_lmc_inject_ecc_write, NULL); DEBUGFS_STRUCT(int_w1c, 0400, NULL, thunderx_lmc_int_read); -struct debugfs_entry *lmc_dfs_ents[] = { +static struct debugfs_entry *lmc_dfs_ents[] = { &debugfs_mask0, &debugfs_mask2, &debugfs_parity_test, diff --git a/drivers/edac/ti_edac.c b/drivers/edac/ti_edac.c index 8be3e89a510e..e7eae20f83d1 100644 --- a/drivers/edac/ti_edac.c +++ b/drivers/edac/ti_edac.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/ * * Texas Instruments DDR3 ECC error correction and detection driver * @@ -278,7 +278,8 @@ static int ti_edac_probe(struct platform_device *pdev) /* add EMIF ECC error handler */ error_irq = platform_get_irq(pdev, 0); - if (!error_irq) { + if (error_irq < 0) { + ret = error_irq; edac_printk(KERN_ERR, EDAC_MOD_NAME, "EMIF irq number not defined.\n"); goto err; |