From 1b51adc6b7ac31fa446ef066107827fffd5dd1f2 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 4 Oct 2018 21:05:19 +0530 Subject: EDAC, synopsys: Improve code readability Clean up the driver code. Update the debug messages for EDAC errors reported. Increase the indentation of the macros for better readability. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: manish.narani@xilinx.com CC: mark.rutland@arm.com CC: mchehab@kernel.org CC: michal.simek@xilinx.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1538667328-9465-2-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 104 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 0c9c59e2b5a3..1936c73f1d15 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -26,74 +26,74 @@ #include "edac_module.h" /* Number of cs_rows needed per memory controller */ -#define SYNPS_EDAC_NR_CSROWS 1 +#define SYNPS_EDAC_NR_CSROWS 1 /* Number of channels per memory controller */ -#define SYNPS_EDAC_NR_CHANS 1 +#define SYNPS_EDAC_NR_CHANS 1 /* Granularity of reported error in bytes */ -#define SYNPS_EDAC_ERR_GRAIN 1 +#define SYNPS_EDAC_ERR_GRAIN 1 -#define SYNPS_EDAC_MSG_SIZE 256 +#define SYNPS_EDAC_MSG_SIZE 256 -#define SYNPS_EDAC_MOD_STRING "synps_edac" -#define SYNPS_EDAC_MOD_VER "1" +#define SYNPS_EDAC_MOD_STRING "synps_edac" +#define SYNPS_EDAC_MOD_VER "1" /* Synopsys DDR memory controller registers that are relevant to ECC */ -#define CTRL_OFST 0x0 -#define T_ZQ_OFST 0xA4 +#define CTRL_OFST 0x0 +#define T_ZQ_OFST 0xA4 /* ECC control register */ -#define ECC_CTRL_OFST 0xC4 +#define ECC_CTRL_OFST 0xC4 /* ECC log register */ -#define CE_LOG_OFST 0xC8 +#define CE_LOG_OFST 0xC8 /* ECC address register */ -#define CE_ADDR_OFST 0xCC +#define CE_ADDR_OFST 0xCC /* ECC data[31:0] register */ -#define CE_DATA_31_0_OFST 0xD0 +#define CE_DATA_31_0_OFST 0xD0 /* Uncorrectable error info registers */ -#define UE_LOG_OFST 0xDC -#define UE_ADDR_OFST 0xE0 -#define UE_DATA_31_0_OFST 0xE4 +#define UE_LOG_OFST 0xDC +#define UE_ADDR_OFST 0xE0 +#define UE_DATA_31_0_OFST 0xE4 -#define STAT_OFST 0xF0 -#define SCRUB_OFST 0xF4 +#define STAT_OFST 0xF0 +#define SCRUB_OFST 0xF4 /* Control register bit field definitions */ -#define CTRL_BW_MASK 0xC -#define CTRL_BW_SHIFT 2 +#define CTRL_BW_MASK 0xC +#define CTRL_BW_SHIFT 2 -#define DDRCTL_WDTH_16 1 -#define DDRCTL_WDTH_32 0 +#define DDRCTL_WDTH_16 1 +#define DDRCTL_WDTH_32 0 /* ZQ register bit field definitions */ -#define T_ZQ_DDRMODE_MASK 0x2 +#define T_ZQ_DDRMODE_MASK 0x2 /* ECC control register bit field definitions */ -#define ECC_CTRL_CLR_CE_ERR 0x2 -#define ECC_CTRL_CLR_UE_ERR 0x1 +#define ECC_CTRL_CLR_CE_ERR 0x2 +#define ECC_CTRL_CLR_UE_ERR 0x1 /* ECC correctable/uncorrectable error log register definitions */ -#define LOG_VALID 0x1 -#define CE_LOG_BITPOS_MASK 0xFE -#define CE_LOG_BITPOS_SHIFT 1 +#define LOG_VALID 0x1 +#define CE_LOG_BITPOS_MASK 0xFE +#define CE_LOG_BITPOS_SHIFT 1 /* ECC correctable/uncorrectable error address register definitions */ -#define ADDR_COL_MASK 0xFFF -#define ADDR_ROW_MASK 0xFFFF000 -#define ADDR_ROW_SHIFT 12 -#define ADDR_BANK_MASK 0x70000000 -#define ADDR_BANK_SHIFT 28 +#define ADDR_COL_MASK 0xFFF +#define ADDR_ROW_MASK 0xFFFF000 +#define ADDR_ROW_SHIFT 12 +#define ADDR_BANK_MASK 0x70000000 +#define ADDR_BANK_SHIFT 28 /* ECC statistic register definitions */ -#define STAT_UECNT_MASK 0xFF -#define STAT_CECNT_MASK 0xFF00 -#define STAT_CECNT_SHIFT 8 +#define STAT_UECNT_MASK 0xFF +#define STAT_CECNT_MASK 0xFF00 +#define STAT_CECNT_SHIFT 8 /* ECC scrub register definitions */ -#define SCRUB_MODE_MASK 0x7 -#define SCRUB_MODE_SECDED 0x4 +#define SCRUB_MODE_MASK 0x7 +#define SCRUB_MODE_SECDED 0x4 /** * struct ecc_error_info - ECC error log information @@ -172,7 +172,7 @@ static int synps_edac_geterror_info(void __iomem *base, p->ceinfo.col = regval & ADDR_COL_MASK; p->ceinfo.bank = (regval & ADDR_BANK_MASK) >> ADDR_BANK_SHIFT; p->ceinfo.data = readl(base + CE_DATA_31_0_OFST); - edac_dbg(3, "ce bit position: %d data: %d\n", p->ceinfo.bitpos, + edac_dbg(3, "CE bit position: %d data: %d\n", p->ceinfo.bitpos, p->ceinfo.data); clearval = ECC_CTRL_CLR_CE_ERR; @@ -250,7 +250,7 @@ static void synps_edac_check(struct mem_ctl_info *mci) priv->ue_cnt += priv->stat.ue_cnt; synps_edac_handle_error(mci, &priv->stat); - edac_dbg(3, "Total error count ce %d ue %d\n", + edac_dbg(3, "Total error count CE %d UE %d\n", priv->ce_cnt, priv->ue_cnt); } @@ -295,9 +295,9 @@ static enum dev_type synps_edac_get_dtype(const void __iomem *base) */ static bool synps_edac_get_eccstate(void __iomem *base) { + bool state = false; enum dev_type dt; u32 ecctype; - bool state = false; dt = synps_edac_get_dtype(base); if (dt == DEV_UNKNOWN) @@ -359,23 +359,23 @@ static enum mem_type synps_edac_get_mtype(const void __iomem *base) */ static int synps_edac_init_csrows(struct mem_ctl_info *mci) { + struct synps_edac_priv *priv = mci->pvt_info; struct csrow_info *csi; struct dimm_info *dimm; - struct synps_edac_priv *priv = mci->pvt_info; - u32 size; - int row, j; + u32 size, row; + int j; for (row = 0; row < mci->nr_csrows; row++) { csi = mci->csrows[row]; size = synps_edac_get_memsize(); for (j = 0; j < csi->nr_channels; j++) { - dimm = csi->channels[j]->dimm; - dimm->edac_mode = EDAC_FLAG_SECDED; - dimm->mtype = synps_edac_get_mtype(priv->baseaddr); - dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels; - dimm->grain = SYNPS_EDAC_ERR_GRAIN; - dimm->dtype = synps_edac_get_dtype(priv->baseaddr); + dimm = csi->channels[j]->dimm; + dimm->edac_mode = EDAC_FLAG_SECDED; + dimm->mtype = synps_edac_get_mtype(priv->baseaddr); + dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels; + dimm->grain = SYNPS_EDAC_ERR_GRAIN; + dimm->dtype = synps_edac_get_dtype(priv->baseaddr); } } @@ -434,12 +434,12 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci, */ static int synps_edac_mc_probe(struct platform_device *pdev) { - struct mem_ctl_info *mci; struct edac_mc_layer layers[2]; struct synps_edac_priv *priv; - int rc; - struct resource *res; + struct mem_ctl_info *mci; void __iomem *baseaddr; + struct resource *res; + int rc; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); baseaddr = devm_ioremap_resource(&pdev->dev, res); -- cgit v1.2.3-59-g8ed1b From bb894bc46ed03baad5d53ea8e0b0eab4eba3002e Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 4 Oct 2018 21:05:20 +0530 Subject: EDAC, synopsys: Shorten static function names Shorten static function names, remove the unnecessary 'synps_' prefix in function names. [ bp: Drop the "edac_" prefix too as that prefix is reserved for EDAC core functions. ] Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1538667328-9465-3-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 79 +++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 1936c73f1d15..fbaf33540ce3 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -142,7 +142,7 @@ struct synps_edac_priv { }; /** - * synps_edac_geterror_info - Get the current ecc error info + * get_error_info - Get the current ecc error info * @base: Pointer to the base address of the ddr memory controller * @p: Pointer to the synopsys ecc status structure * @@ -150,8 +150,7 @@ struct synps_edac_priv { * * Return: one if there is no error otherwise returns zero */ -static int synps_edac_geterror_info(void __iomem *base, - struct synps_ecc_status *p) +static int get_error_info(void __iomem *base, struct synps_ecc_status *p) { u32 regval, clearval = 0; @@ -196,14 +195,13 @@ out: } /** - * synps_edac_handle_error - Handle controller error types CE and UE + * handle_error - Handle controller error types CE and UE * @mci: Pointer to the edac memory controller instance * @p: Pointer to the synopsys ecc status structure * - * Handles the controller ECC correctable and un correctable error. + * Handles the controller ECC correctable and uncorrectable error. */ -static void synps_edac_handle_error(struct mem_ctl_info *mci, - struct synps_ecc_status *p) +static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) { struct synps_edac_priv *priv = mci->pvt_info; struct ecc_error_info *pinf; @@ -232,30 +230,30 @@ static void synps_edac_handle_error(struct mem_ctl_info *mci, } /** - * synps_edac_check - Check controller for ECC errors + * check_errors - Check controller for ECC errors * @mci: Pointer to the edac memory controller instance * * Used to check and post ECC errors. Called by the polling thread */ -static void synps_edac_check(struct mem_ctl_info *mci) +static void check_errors(struct mem_ctl_info *mci) { struct synps_edac_priv *priv = mci->pvt_info; int status; - status = synps_edac_geterror_info(priv->baseaddr, &priv->stat); + status = get_error_info(priv->baseaddr, &priv->stat); if (status) return; priv->ce_cnt += priv->stat.ce_cnt; priv->ue_cnt += priv->stat.ue_cnt; - synps_edac_handle_error(mci, &priv->stat); + handle_error(mci, &priv->stat); edac_dbg(3, "Total error count CE %d UE %d\n", priv->ce_cnt, priv->ue_cnt); } /** - * synps_edac_get_dtype - Return the controller memory width + * get_dtype - Return the controller memory width * @base: Pointer to the ddr memory controller base address * * Get the EDAC device type width appropriate for the current controller @@ -263,7 +261,7 @@ static void synps_edac_check(struct mem_ctl_info *mci) * * Return: a device type width enumeration. */ -static enum dev_type synps_edac_get_dtype(const void __iomem *base) +static enum dev_type get_dtype(const void __iomem *base) { enum dev_type dt; u32 width; @@ -286,20 +284,20 @@ static enum dev_type synps_edac_get_dtype(const void __iomem *base) } /** - * synps_edac_get_eccstate - Return the controller ecc enable/disable status - * @base: Pointer to the ddr memory controller base address + * get_ecc_state - Return the controller ECC enable/disable status + * @base: Pointer to the DDR memory controller base address * - * Get the ECC enable/disable status for the controller + * Get the ECC enable/disable status for the controller. * - * Return: a ecc status boolean i.e true/false - enabled/disabled. + * Return: a ECC status boolean i.e true/false - enabled/disabled. */ -static bool synps_edac_get_eccstate(void __iomem *base) +static bool get_ecc_state(void __iomem *base) { bool state = false; enum dev_type dt; u32 ecctype; - dt = synps_edac_get_dtype(base); + dt = get_dtype(base); if (dt == DEV_UNKNOWN) return state; @@ -311,11 +309,11 @@ static bool synps_edac_get_eccstate(void __iomem *base) } /** - * synps_edac_get_memsize - reads the size of the attached memory device + * get_memsize - reads the size of the attached memory device * * Return: the memory size in bytes */ -static u32 synps_edac_get_memsize(void) +static u32 get_memsize(void) { struct sysinfo inf; @@ -325,7 +323,7 @@ static u32 synps_edac_get_memsize(void) } /** - * synps_edac_get_mtype - Returns controller memory type + * get_mtype - Returns controller memory type * @base: pointer to the synopsys ecc status structure * * Get the EDAC memory type appropriate for the current controller @@ -333,7 +331,7 @@ static u32 synps_edac_get_memsize(void) * * Return: a memory type enumeration. */ -static enum mem_type synps_edac_get_mtype(const void __iomem *base) +static enum mem_type get_mtype(const void __iomem *base) { enum mem_type mt; u32 memtype; @@ -349,7 +347,7 @@ static enum mem_type synps_edac_get_mtype(const void __iomem *base) } /** - * synps_edac_init_csrows - Initialize the cs row data + * init_csrows - Initialize the cs row data * @mci: Pointer to the edac memory controller instance * * Initializes the chip select rows associated with the EDAC memory @@ -357,7 +355,7 @@ static enum mem_type synps_edac_get_mtype(const void __iomem *base) * * Return: Unconditionally 0. */ -static int synps_edac_init_csrows(struct mem_ctl_info *mci) +static int init_csrows(struct mem_ctl_info *mci) { struct synps_edac_priv *priv = mci->pvt_info; struct csrow_info *csi; @@ -367,15 +365,15 @@ static int synps_edac_init_csrows(struct mem_ctl_info *mci) for (row = 0; row < mci->nr_csrows; row++) { csi = mci->csrows[row]; - size = synps_edac_get_memsize(); + size = get_memsize(); for (j = 0; j < csi->nr_channels; j++) { dimm = csi->channels[j]->dimm; dimm->edac_mode = EDAC_FLAG_SECDED; - dimm->mtype = synps_edac_get_mtype(priv->baseaddr); + dimm->mtype = get_mtype(priv->baseaddr); dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels; dimm->grain = SYNPS_EDAC_ERR_GRAIN; - dimm->dtype = synps_edac_get_dtype(priv->baseaddr); + dimm->dtype = get_dtype(priv->baseaddr); } } @@ -383,7 +381,7 @@ static int synps_edac_init_csrows(struct mem_ctl_info *mci) } /** - * synps_edac_mc_init - Initialize driver instance + * mc_init - Initialize driver instance * @mci: Pointer to the edac memory controller instance * @pdev: Pointer to the platform_device struct * @@ -393,8 +391,7 @@ static int synps_edac_init_csrows(struct mem_ctl_info *mci) * * Return: Always zero. */ -static int synps_edac_mc_init(struct mem_ctl_info *mci, - struct platform_device *pdev) +static int mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) { int status; struct synps_edac_priv *priv; @@ -415,16 +412,16 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci, mci->mod_name = SYNPS_EDAC_MOD_VER; edac_op_state = EDAC_OPSTATE_POLL; - mci->edac_check = synps_edac_check; + mci->edac_check = check_errors; mci->ctl_page_to_phys = NULL; - status = synps_edac_init_csrows(mci); + status = init_csrows(mci); return status; } /** - * synps_edac_mc_probe - Check controller and bind driver + * mc_probe - Check controller and bind driver * @pdev: Pointer to the platform_device struct * * Probes a specific controller instance for binding with the driver. @@ -432,7 +429,7 @@ static int synps_edac_mc_init(struct mem_ctl_info *mci, * Return: 0 if the controller instance was successfully bound to the * driver; otherwise, < 0 on error. */ -static int synps_edac_mc_probe(struct platform_device *pdev) +static int mc_probe(struct platform_device *pdev) { struct edac_mc_layer layers[2]; struct synps_edac_priv *priv; @@ -446,7 +443,7 @@ static int synps_edac_mc_probe(struct platform_device *pdev) if (IS_ERR(baseaddr)) return PTR_ERR(baseaddr); - if (!synps_edac_get_eccstate(baseaddr)) { + if (!get_ecc_state(baseaddr)) { edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); return -ENXIO; } @@ -468,7 +465,7 @@ static int synps_edac_mc_probe(struct platform_device *pdev) priv = mci->pvt_info; priv->baseaddr = baseaddr; - rc = synps_edac_mc_init(mci, pdev); + rc = mc_init(mci, pdev); if (rc) { edac_printk(KERN_ERR, EDAC_MC, "Failed to initialize instance\n"); @@ -496,12 +493,12 @@ free_edac_mc: } /** - * synps_edac_mc_remove - Unbind driver from controller + * mc_remove - Unbind driver from controller * @pdev: Pointer to the platform_device struct * * Return: Unconditionally 0 */ -static int synps_edac_mc_remove(struct platform_device *pdev) +static int mc_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); @@ -523,8 +520,8 @@ static struct platform_driver synps_edac_mc_driver = { .name = "synopsys-edac", .of_match_table = synps_edac_match, }, - .probe = synps_edac_mc_probe, - .remove = synps_edac_mc_remove, + .probe = mc_probe, + .remove = mc_remove, }; module_platform_driver(synps_edac_mc_driver); -- cgit v1.2.3-59-g8ed1b From 225af74d6312b2ab195426dbbe3fd2b8f40786fd Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 4 Oct 2018 21:05:21 +0530 Subject: EDAC, synopsys: Correct comments Spellcheck and improve/correct comments. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: michal.simek@xilinx.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1538667328-9465-4-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 104 +++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index fbaf33540ce3..b4666310a5f6 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -96,12 +96,12 @@ #define SCRUB_MODE_SECDED 0x4 /** - * struct ecc_error_info - ECC error log information - * @row: Row number - * @col: Column number - * @bank: Bank number - * @bitpos: Bit position - * @data: Data causing the error + * struct ecc_error_info - ECC error log information. + * @row: Row number. + * @col: Column number. + * @bank: Bank number. + * @bitpos: Bit position. + * @data: Data causing the error. */ struct ecc_error_info { u32 row; @@ -112,11 +112,11 @@ struct ecc_error_info { }; /** - * struct synps_ecc_status - ECC status information to report - * @ce_cnt: Correctable error count - * @ue_cnt: Uncorrectable error count - * @ceinfo: Correctable error log information - * @ueinfo: Uncorrectable error log information + * struct synps_ecc_status - ECC status information to report. + * @ce_cnt: Correctable error count. + * @ue_cnt: Uncorrectable error count. + * @ceinfo: Correctable error log information. + * @ueinfo: Uncorrectable error log information. */ struct synps_ecc_status { u32 ce_cnt; @@ -126,12 +126,12 @@ struct synps_ecc_status { }; /** - * struct synps_edac_priv - DDR memory controller private instance data - * @baseaddr: Base address of the DDR controller - * @message: Buffer for framing the event specific info - * @stat: ECC status information - * @ce_cnt: Correctable Error count - * @ue_cnt: Uncorrectable Error count + * struct synps_edac_priv - DDR memory controller private instance data. + * @baseaddr: Base address of the DDR controller. + * @message: Buffer for framing the event specific info. + * @stat: ECC status information. + * @ce_cnt: Correctable Error count. + * @ue_cnt: Uncorrectable Error count. */ struct synps_edac_priv { void __iomem *baseaddr; @@ -142,13 +142,11 @@ struct synps_edac_priv { }; /** - * get_error_info - Get the current ecc error info - * @base: Pointer to the base address of the ddr memory controller - * @p: Pointer to the synopsys ecc status structure + * get_error_info - Get the current ECC error info. + * @base: Base address of the DDR memory controller. + * @p: Synopsys ECC status structure. * - * Determines there is any ecc error or not - * - * Return: one if there is no error otherwise returns zero + * Return: one if there is no error otherwise zero. */ static int get_error_info(void __iomem *base, struct synps_ecc_status *p) { @@ -195,11 +193,11 @@ out: } /** - * handle_error - Handle controller error types CE and UE - * @mci: Pointer to the edac memory controller instance - * @p: Pointer to the synopsys ecc status structure + * handle_error - Handle Correctable and Uncorrectable errors. + * @mci: EDAC memory controller instance. + * @p: Synopsys ECC status structure. * - * Handles the controller ECC correctable and uncorrectable error. + * Handles ECC correctable and uncorrectable errors. */ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) { @@ -230,10 +228,10 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) } /** - * check_errors - Check controller for ECC errors - * @mci: Pointer to the edac memory controller instance + * check_errors - Check controller for ECC errors. + * @mci: EDAC memory controller instance. * - * Used to check and post ECC errors. Called by the polling thread + * Check and post ECC errors. Called by the polling thread. */ static void check_errors(struct mem_ctl_info *mci) { @@ -253,8 +251,8 @@ static void check_errors(struct mem_ctl_info *mci) } /** - * get_dtype - Return the controller memory width - * @base: Pointer to the ddr memory controller base address + * get_dtype - Return the controller memory width. + * @base: DDR memory controller base address. * * Get the EDAC device type width appropriate for the current controller * configuration. @@ -284,12 +282,12 @@ static enum dev_type get_dtype(const void __iomem *base) } /** - * get_ecc_state - Return the controller ECC enable/disable status - * @base: Pointer to the DDR memory controller base address + * get_ecc_state - Return the controller ECC enable/disable status. + * @base: DDR memory controller base address. * - * Get the ECC enable/disable status for the controller. + * Get the ECC enable/disable status of the controller. * - * Return: a ECC status boolean i.e true/false - enabled/disabled. + * Return: true if enabled, otherwise false. */ static bool get_ecc_state(void __iomem *base) { @@ -309,9 +307,9 @@ static bool get_ecc_state(void __iomem *base) } /** - * get_memsize - reads the size of the attached memory device + * get_memsize - Read the size of the attached memory device. * - * Return: the memory size in bytes + * Return: the memory size in bytes. */ static u32 get_memsize(void) { @@ -323,8 +321,8 @@ static u32 get_memsize(void) } /** - * get_mtype - Returns controller memory type - * @base: pointer to the synopsys ecc status structure + * get_mtype - Return the controller memory type. + * @base: Synopsys ECC status structure. * * Get the EDAC memory type appropriate for the current controller * configuration. @@ -347,11 +345,11 @@ static enum mem_type get_mtype(const void __iomem *base) } /** - * init_csrows - Initialize the cs row data - * @mci: Pointer to the edac memory controller instance + * init_csrows - Initialize the csrow data. + * @mci: EDAC memory controller instance. * - * Initializes the chip select rows associated with the EDAC memory - * controller instance + * Initialize the chip select rows associated with the EDAC memory + * controller instance. * * Return: Unconditionally 0. */ @@ -381,11 +379,11 @@ static int init_csrows(struct mem_ctl_info *mci) } /** - * mc_init - Initialize driver instance - * @mci: Pointer to the edac memory controller instance - * @pdev: Pointer to the platform_device struct + * mc_init - Initialize one driver instance. + * @mci: EDAC memory controller instance. + * @pdev: platform device. * - * Performs initialization of the EDAC memory controller instance and + * Perform initialization of the EDAC memory controller instance and * related driver-private data associated with the memory controller the * instance is bound to. * @@ -421,10 +419,10 @@ static int mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) } /** - * mc_probe - Check controller and bind driver - * @pdev: Pointer to the platform_device struct + * mc_probe - Check controller and bind driver. + * @pdev: platform device. * - * Probes a specific controller instance for binding with the driver. + * Probe a specific controller instance for binding with the driver. * * Return: 0 if the controller instance was successfully bound to the * driver; otherwise, < 0 on error. @@ -493,8 +491,8 @@ free_edac_mc: } /** - * mc_remove - Unbind driver from controller - * @pdev: Pointer to the platform_device struct + * mc_remove - Unbind driver from controller. + * @pdev: Platform device. * * Return: Unconditionally 0 */ -- cgit v1.2.3-59-g8ed1b From fa9f6b9e1cf9620def93c985d424289eedf61b34 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 4 Oct 2018 21:05:22 +0530 Subject: EDAC, synopsys: Return void for functions always returning 0 The current driver has functions which are always returning 0 - make them return void instead. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1538667328-9465-5-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index b4666310a5f6..a625a68345a3 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -350,10 +350,8 @@ static enum mem_type get_mtype(const void __iomem *base) * * Initialize the chip select rows associated with the EDAC memory * controller instance. - * - * Return: Unconditionally 0. */ -static int init_csrows(struct mem_ctl_info *mci) +static void init_csrows(struct mem_ctl_info *mci) { struct synps_edac_priv *priv = mci->pvt_info; struct csrow_info *csi; @@ -374,8 +372,6 @@ static int init_csrows(struct mem_ctl_info *mci) dimm->dtype = get_dtype(priv->baseaddr); } } - - return 0; } /** @@ -386,12 +382,9 @@ static int init_csrows(struct mem_ctl_info *mci) * Perform initialization of the EDAC memory controller instance and * related driver-private data associated with the memory controller the * instance is bound to. - * - * Return: Always zero. */ -static int mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) +static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) { - int status; struct synps_edac_priv *priv; mci->pdev = &pdev->dev; @@ -413,9 +406,7 @@ static int mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) mci->edac_check = check_errors; mci->ctl_page_to_phys = NULL; - status = init_csrows(mci); - - return status; + init_csrows(mci); } /** @@ -463,12 +454,7 @@ static int mc_probe(struct platform_device *pdev) priv = mci->pvt_info; priv->baseaddr = baseaddr; - rc = mc_init(mci, pdev); - if (rc) { - edac_printk(KERN_ERR, EDAC_MC, - "Failed to initialize instance\n"); - goto free_edac_mc; - } + mc_init(mci, pdev); rc = edac_mc_add_mc(mci); if (rc) { -- cgit v1.2.3-59-g8ed1b From 3d02a8975e321ef6219ec911742d741d2d73c89c Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 4 Oct 2018 21:05:23 +0530 Subject: EDAC, synopsys: Add platform specific structures for the DDR Controller Add platform specific structures so that different IP support can be added later using quirks. [ bp: fix function names. ] Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1538667328-9465-6-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 86 ++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index a625a68345a3..1c3795dd7b82 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "edac_module.h" @@ -130,6 +132,7 @@ struct synps_ecc_status { * @baseaddr: Base address of the DDR controller. * @message: Buffer for framing the event specific info. * @stat: ECC status information. + * @p_data: Platform data. * @ce_cnt: Correctable Error count. * @ue_cnt: Uncorrectable Error count. */ @@ -137,20 +140,41 @@ struct synps_edac_priv { void __iomem *baseaddr; char message[SYNPS_EDAC_MSG_SIZE]; struct synps_ecc_status stat; + const struct synps_platform_data *p_data; u32 ce_cnt; u32 ue_cnt; }; /** - * get_error_info - Get the current ECC error info. - * @base: Base address of the DDR memory controller. - * @p: Synopsys ECC status structure. + * struct synps_platform_data - synps platform data structure. + * @get_error_info: Get EDAC error info. + * @get_mtype: Get mtype. + * @get_dtype: Get dtype. + * @get_ecc_state: Get ECC state. + * @quirks: To differentiate IPs. + */ +struct synps_platform_data { + int (*get_error_info)(struct synps_edac_priv *priv); + enum mem_type (*get_mtype)(const void __iomem *base); + enum dev_type (*get_dtype)(const void __iomem *base); + bool (*get_ecc_state)(void __iomem *base); + int quirks; +}; + +/** + * zynq_get_error_info - Get the current ECC error info. + * @priv: DDR memory controller private instance data. * - * Return: one if there is no error otherwise zero. + * Return: one if there is no error, otherwise zero. */ -static int get_error_info(void __iomem *base, struct synps_ecc_status *p) +static int zynq_get_error_info(struct synps_edac_priv *priv) { + struct synps_ecc_status *p; u32 regval, clearval = 0; + void __iomem *base; + + base = priv->baseaddr; + p = &priv->stat; regval = readl(base + STAT_OFST); if (!regval) @@ -236,9 +260,10 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) static void check_errors(struct mem_ctl_info *mci) { struct synps_edac_priv *priv = mci->pvt_info; + const struct synps_platform_data *p_data = priv->p_data; int status; - status = get_error_info(priv->baseaddr, &priv->stat); + status = p_data->get_error_info(priv); if (status) return; @@ -251,7 +276,7 @@ static void check_errors(struct mem_ctl_info *mci) } /** - * get_dtype - Return the controller memory width. + * zynq_get_dtype - Return the controller memory width. * @base: DDR memory controller base address. * * Get the EDAC device type width appropriate for the current controller @@ -259,7 +284,7 @@ static void check_errors(struct mem_ctl_info *mci) * * Return: a device type width enumeration. */ -static enum dev_type get_dtype(const void __iomem *base) +static enum dev_type zynq_get_dtype(const void __iomem *base) { enum dev_type dt; u32 width; @@ -282,20 +307,20 @@ static enum dev_type get_dtype(const void __iomem *base) } /** - * get_ecc_state - Return the controller ECC enable/disable status. + * zynq_get_ecc_state - Return the controller ECC enable/disable status. * @base: DDR memory controller base address. * * Get the ECC enable/disable status of the controller. * * Return: true if enabled, otherwise false. */ -static bool get_ecc_state(void __iomem *base) +static bool zynq_get_ecc_state(void __iomem *base) { bool state = false; enum dev_type dt; u32 ecctype; - dt = get_dtype(base); + dt = zynq_get_dtype(base); if (dt == DEV_UNKNOWN) return state; @@ -321,7 +346,7 @@ static u32 get_memsize(void) } /** - * get_mtype - Return the controller memory type. + * zynq_get_mtype - Return the controller memory type. * @base: Synopsys ECC status structure. * * Get the EDAC memory type appropriate for the current controller @@ -329,7 +354,7 @@ static u32 get_memsize(void) * * Return: a memory type enumeration. */ -static enum mem_type get_mtype(const void __iomem *base) +static enum mem_type zynq_get_mtype(const void __iomem *base) { enum mem_type mt; u32 memtype; @@ -354,11 +379,14 @@ static enum mem_type get_mtype(const void __iomem *base) static void init_csrows(struct mem_ctl_info *mci) { struct synps_edac_priv *priv = mci->pvt_info; + const struct synps_platform_data *p_data; struct csrow_info *csi; struct dimm_info *dimm; u32 size, row; int j; + p_data = priv->p_data; + for (row = 0; row < mci->nr_csrows; row++) { csi = mci->csrows[row]; size = get_memsize(); @@ -366,10 +394,10 @@ static void init_csrows(struct mem_ctl_info *mci) for (j = 0; j < csi->nr_channels; j++) { dimm = csi->channels[j]->dimm; dimm->edac_mode = EDAC_FLAG_SECDED; - dimm->mtype = get_mtype(priv->baseaddr); + dimm->mtype = p_data->get_mtype(priv->baseaddr); dimm->nr_pages = (size >> PAGE_SHIFT) / csi->nr_channels; dimm->grain = SYNPS_EDAC_ERR_GRAIN; - dimm->dtype = get_dtype(priv->baseaddr); + dimm->dtype = p_data->get_dtype(priv->baseaddr); } } } @@ -409,6 +437,21 @@ static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) init_csrows(mci); } +static const struct synps_platform_data zynq_edac_def = { + .get_error_info = zynq_get_error_info, + .get_mtype = zynq_get_mtype, + .get_dtype = zynq_get_dtype, + .get_ecc_state = zynq_get_ecc_state, + .quirks = 0, +}; + +static const struct of_device_id synps_edac_match[] = { + { .compatible = "xlnx,zynq-ddrc-a05", .data = (void *)&zynq_edac_def }, + { /* end of table */ } +}; + +MODULE_DEVICE_TABLE(of, synps_edac_match); + /** * mc_probe - Check controller and bind driver. * @pdev: platform device. @@ -420,6 +463,7 @@ static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) */ static int mc_probe(struct platform_device *pdev) { + const struct synps_platform_data *p_data; struct edac_mc_layer layers[2]; struct synps_edac_priv *priv; struct mem_ctl_info *mci; @@ -432,7 +476,8 @@ static int mc_probe(struct platform_device *pdev) if (IS_ERR(baseaddr)) return PTR_ERR(baseaddr); - if (!get_ecc_state(baseaddr)) { + p_data = of_device_get_match_data(&pdev->dev); + if (!p_data->get_ecc_state(baseaddr)) { edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); return -ENXIO; } @@ -454,6 +499,8 @@ static int mc_probe(struct platform_device *pdev) priv = mci->pvt_info; priv->baseaddr = baseaddr; + priv->p_data = p_data; + mc_init(mci, pdev); rc = edac_mc_add_mc(mci); @@ -492,13 +539,6 @@ static int mc_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id synps_edac_match[] = { - { .compatible = "xlnx,zynq-ddrc-a05", }, - { /* end of table */ } -}; - -MODULE_DEVICE_TABLE(of, synps_edac_match); - static struct platform_driver synps_edac_mc_driver = { .driver = { .name = "synopsys-edac", -- cgit v1.2.3-59-g8ed1b From 84de0b493ff62993c4047dd15318cc23f83923d3 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 25 Oct 2018 11:36:56 +0530 Subject: EDAC, synopsys: Add error handling for the of_device_get_match_data() result The function of_device_get_match_data() can return NULL in case of error. Add error handling for the same in the mc_probe() function. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1540447621-22870-2-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 1c3795dd7b82..0005ef387af6 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -477,6 +477,9 @@ static int mc_probe(struct platform_device *pdev) return PTR_ERR(baseaddr); p_data = of_device_get_match_data(&pdev->dev); + if (!p_data) + return -ENODEV; + if (!p_data->get_ecc_state(baseaddr)) { edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); return -ENXIO; -- cgit v1.2.3-59-g8ed1b From e926ae573b0f550de2b23883a1571cfa7ad7dff0 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 25 Oct 2018 11:36:58 +0530 Subject: EDAC, synopsys: Add macro defines for ZynqMP DDRC Add macro defines for ZynqMP DDR controller. These macros will be used for ZynqMP ECC operations. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1540447621-22870-4-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 168 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 0005ef387af6..d1999e03f118 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -97,6 +97,174 @@ #define SCRUB_MODE_MASK 0x7 #define SCRUB_MODE_SECDED 0x4 +/* DDR ECC Quirks */ +#define DDR_ECC_INTR_SUPPORT BIT(0) +#define DDR_ECC_DATA_POISON_SUPPORT BIT(1) + +/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */ +/* ECC Configuration Registers */ +#define ECC_CFG0_OFST 0x70 +#define ECC_CFG1_OFST 0x74 + +/* ECC Status Register */ +#define ECC_STAT_OFST 0x78 + +/* ECC Clear Register */ +#define ECC_CLR_OFST 0x7C + +/* ECC Error count Register */ +#define ECC_ERRCNT_OFST 0x80 + +/* ECC Corrected Error Address Register */ +#define ECC_CEADDR0_OFST 0x84 +#define ECC_CEADDR1_OFST 0x88 + +/* ECC Syndrome Registers */ +#define ECC_CSYND0_OFST 0x8C +#define ECC_CSYND1_OFST 0x90 +#define ECC_CSYND2_OFST 0x94 + +/* ECC Bit Mask0 Address Register */ +#define ECC_BITMASK0_OFST 0x98 +#define ECC_BITMASK1_OFST 0x9C +#define ECC_BITMASK2_OFST 0xA0 + +/* ECC UnCorrected Error Address Register */ +#define ECC_UEADDR0_OFST 0xA4 +#define ECC_UEADDR1_OFST 0xA8 + +/* ECC Syndrome Registers */ +#define ECC_UESYND0_OFST 0xAC +#define ECC_UESYND1_OFST 0xB0 +#define ECC_UESYND2_OFST 0xB4 + +/* ECC Poison Address Reg */ +#define ECC_POISON0_OFST 0xB8 +#define ECC_POISON1_OFST 0xBC + +#define ECC_ADDRMAP0_OFFSET 0x200 + +/* Control register bitfield definitions */ +#define ECC_CTRL_BUSWIDTH_MASK 0x3000 +#define ECC_CTRL_BUSWIDTH_SHIFT 12 +#define ECC_CTRL_CLR_CE_ERRCNT BIT(2) +#define ECC_CTRL_CLR_UE_ERRCNT BIT(3) + +/* DDR Control Register width definitions */ +#define DDRCTL_EWDTH_16 2 +#define DDRCTL_EWDTH_32 1 +#define DDRCTL_EWDTH_64 0 + +/* ECC status register definitions */ +#define ECC_STAT_UECNT_MASK 0xF0000 +#define ECC_STAT_UECNT_SHIFT 16 +#define ECC_STAT_CECNT_MASK 0xF00 +#define ECC_STAT_CECNT_SHIFT 8 +#define ECC_STAT_BITNUM_MASK 0x7F + +/* DDR QOS Interrupt register definitions */ +#define DDR_QOS_IRQ_STAT_OFST 0x20200 +#define DDR_QOSUE_MASK 0x4 +#define DDR_QOSCE_MASK 0x2 +#define ECC_CE_UE_INTR_MASK 0x6 +#define DDR_QOS_IRQ_EN_OFST 0x20208 +#define DDR_QOS_IRQ_DB_OFST 0x2020C + +/* ECC Corrected Error Register Mask and Shifts*/ +#define ECC_CEADDR0_RW_MASK 0x3FFFF +#define ECC_CEADDR0_RNK_MASK BIT(24) +#define ECC_CEADDR1_BNKGRP_MASK 0x3000000 +#define ECC_CEADDR1_BNKNR_MASK 0x70000 +#define ECC_CEADDR1_BLKNR_MASK 0xFFF +#define ECC_CEADDR1_BNKGRP_SHIFT 24 +#define ECC_CEADDR1_BNKNR_SHIFT 16 + +/* ECC Poison register shifts */ +#define ECC_POISON0_RANK_SHIFT 24 +#define ECC_POISON0_RANK_MASK BIT(24) +#define ECC_POISON0_COLUMN_SHIFT 0 +#define ECC_POISON0_COLUMN_MASK 0xFFF +#define ECC_POISON1_BG_SHIFT 28 +#define ECC_POISON1_BG_MASK 0x30000000 +#define ECC_POISON1_BANKNR_SHIFT 24 +#define ECC_POISON1_BANKNR_MASK 0x7000000 +#define ECC_POISON1_ROW_SHIFT 0 +#define ECC_POISON1_ROW_MASK 0x3FFFF + +/* DDR Memory type defines */ +#define MEM_TYPE_DDR3 0x1 +#define MEM_TYPE_LPDDR3 0x8 +#define MEM_TYPE_DDR2 0x4 +#define MEM_TYPE_DDR4 0x10 +#define MEM_TYPE_LPDDR4 0x20 + +/* DDRC Software control register */ +#define DDRC_SWCTL 0x320 + +/* DDRC ECC CE & UE poison mask */ +#define ECC_CEPOISON_MASK 0x3 +#define ECC_UEPOISON_MASK 0x1 + +/* DDRC Device config masks */ +#define DDRC_MSTR_CFG_MASK 0xC0000000 +#define DDRC_MSTR_CFG_SHIFT 30 +#define DDRC_MSTR_CFG_X4_MASK 0x0 +#define DDRC_MSTR_CFG_X8_MASK 0x1 +#define DDRC_MSTR_CFG_X16_MASK 0x2 +#define DDRC_MSTR_CFG_X32_MASK 0x3 + +#define DDR_MAX_ROW_SHIFT 18 +#define DDR_MAX_COL_SHIFT 14 +#define DDR_MAX_BANK_SHIFT 3 +#define DDR_MAX_BANKGRP_SHIFT 2 + +#define ROW_MAX_VAL_MASK 0xF +#define COL_MAX_VAL_MASK 0xF +#define BANK_MAX_VAL_MASK 0x1F +#define BANKGRP_MAX_VAL_MASK 0x1F +#define RANK_MAX_VAL_MASK 0x1F + +#define ROW_B0_BASE 6 +#define ROW_B1_BASE 7 +#define ROW_B2_BASE 8 +#define ROW_B3_BASE 9 +#define ROW_B4_BASE 10 +#define ROW_B5_BASE 11 +#define ROW_B6_BASE 12 +#define ROW_B7_BASE 13 +#define ROW_B8_BASE 14 +#define ROW_B9_BASE 15 +#define ROW_B10_BASE 16 +#define ROW_B11_BASE 17 +#define ROW_B12_BASE 18 +#define ROW_B13_BASE 19 +#define ROW_B14_BASE 20 +#define ROW_B15_BASE 21 +#define ROW_B16_BASE 22 +#define ROW_B17_BASE 23 + +#define COL_B2_BASE 2 +#define COL_B3_BASE 3 +#define COL_B4_BASE 4 +#define COL_B5_BASE 5 +#define COL_B6_BASE 6 +#define COL_B7_BASE 7 +#define COL_B8_BASE 8 +#define COL_B9_BASE 9 +#define COL_B10_BASE 10 +#define COL_B11_BASE 11 +#define COL_B12_BASE 12 +#define COL_B13_BASE 13 + +#define BANK_B0_BASE 2 +#define BANK_B1_BASE 3 +#define BANK_B2_BASE 4 + +#define BANKGRP_B0_BASE 2 +#define BANKGRP_B1_BASE 3 + +#define RANK_B0_BASE 6 + /** * struct ecc_error_info - ECC error log information. * @row: Row number. -- cgit v1.2.3-59-g8ed1b From b500b4a029d577c6b5f3d7480ef2635dd1f30a55 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 25 Oct 2018 11:36:59 +0530 Subject: EDAC, synopsys: Add ECC support for ZynqMP DDR controller Add ECC support for ZynqMP DDR controller IP. The IP supports interrupts for corrected and uncorrected errors. Add interrupt handlers for the same. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1540447621-22870-5-git-send-email-manish.narani@xilinx.com --- drivers/edac/Kconfig | 2 +- drivers/edac/synopsys_edac.c | 322 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 306 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 41c9ccdd20d6..ec2727b27556 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -442,7 +442,7 @@ config EDAC_ALTERA_SDMMC config EDAC_SYNOPSYS tristate "Synopsys DDR Memory Controller" - depends on ARCH_ZYNQ + depends on ARCH_ZYNQ || ARCH_ZYNQMP help Support for error detection and correction on the Synopsys DDR memory controller. diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index d1999e03f118..e81f18aa9576 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -272,6 +273,8 @@ * @bank: Bank number. * @bitpos: Bit position. * @data: Data causing the error. + * @bankgrpnr: Bank group number. + * @blknr: Block number. */ struct ecc_error_info { u32 row; @@ -279,6 +282,8 @@ struct ecc_error_info { u32 bank; u32 bitpos; u32 data; + u32 bankgrpnr; + u32 blknr; }; /** @@ -384,6 +389,66 @@ out: return 0; } +/** + * zynqmp_get_error_info - Get the current ECC error info. + * @priv: DDR memory controller private instance data. + * + * Return: one if there is no error otherwise returns zero. + */ +static int zynqmp_get_error_info(struct synps_edac_priv *priv) +{ + struct synps_ecc_status *p; + u32 regval, clearval = 0; + void __iomem *base; + + base = priv->baseaddr; + p = &priv->stat; + + regval = readl(base + ECC_STAT_OFST); + if (!regval) + return 1; + + p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT; + p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT; + if (!p->ce_cnt) + goto ue_err; + + p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK); + + regval = readl(base + ECC_CEADDR0_OFST); + p->ceinfo.row = (regval & ECC_CEADDR0_RW_MASK); + regval = readl(base + ECC_CEADDR1_OFST); + p->ceinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >> + ECC_CEADDR1_BNKNR_SHIFT; + p->ceinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >> + ECC_CEADDR1_BNKGRP_SHIFT; + p->ceinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK); + p->ceinfo.data = readl(base + ECC_CSYND0_OFST); + edac_dbg(2, "ECCCSYN0: 0x%08X ECCCSYN1: 0x%08X ECCCSYN2: 0x%08X\n", + readl(base + ECC_CSYND0_OFST), readl(base + ECC_CSYND1_OFST), + readl(base + ECC_CSYND2_OFST)); +ue_err: + if (!p->ue_cnt) + goto out; + + regval = readl(base + ECC_UEADDR0_OFST); + p->ueinfo.row = (regval & ECC_CEADDR0_RW_MASK); + regval = readl(base + ECC_UEADDR1_OFST); + p->ueinfo.bankgrpnr = (regval & ECC_CEADDR1_BNKGRP_MASK) >> + ECC_CEADDR1_BNKGRP_SHIFT; + p->ueinfo.bank = (regval & ECC_CEADDR1_BNKNR_MASK) >> + ECC_CEADDR1_BNKNR_SHIFT; + p->ueinfo.blknr = (regval & ECC_CEADDR1_BLKNR_MASK); + p->ueinfo.data = readl(base + ECC_UESYND0_OFST); +out: + clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT; + clearval |= ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT; + writel(clearval, base + ECC_CLR_OFST); + writel(0x0, base + ECC_CLR_OFST); + + return 0; +} + /** * handle_error - Handle Correctable and Uncorrectable errors. * @mci: EDAC memory controller instance. @@ -398,9 +463,25 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) if (p->ce_cnt) { pinf = &p->ceinfo; - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "DDR ECC error type :%s Row %d Bank %d Col %d ", - "CE", pinf->row, pinf->bank, pinf->col); + if (!priv->p_data->quirks) { + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "DDR ECC error type:%s Row %d Bank %d Col %d ", + "CE", pinf->row, pinf->bank, pinf->col); + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "Bit Position: %d Data: 0x%08x\n", + pinf->bitpos, pinf->data); + } else { + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "DDR ECC error type:%s Row %d Bank %d Col %d ", + "CE", pinf->row, pinf->bank, pinf->col); + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "BankGroup Number %d Block Number %d ", + pinf->bankgrpnr, pinf->blknr); + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "Bit Position: %d Data: 0x%08x\n", + pinf->bitpos, pinf->data); + } + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, p->ce_cnt, 0, 0, 0, 0, 0, -1, priv->message, ""); @@ -408,9 +489,19 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) if (p->ue_cnt) { pinf = &p->ueinfo; - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "DDR ECC error type :%s Row %d Bank %d Col %d ", - "UE", pinf->row, pinf->bank, pinf->col); + if (!priv->p_data->quirks) { + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "DDR ECC error type :%s Row %d Bank %d Col %d ", + "UE", pinf->row, pinf->bank, pinf->col); + } else { + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "DDR ECC error type :%s Row %d Bank %d Col %d ", + "UE", pinf->row, pinf->bank, pinf->col); + snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, + "BankGroup Number %d Block Number %d", + pinf->bankgrpnr, pinf->blknr); + } + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, p->ue_cnt, 0, 0, 0, 0, 0, -1, priv->message, ""); @@ -419,6 +510,42 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) memset(p, 0, sizeof(*p)); } +/** + * intr_handler - Interrupt Handler for ECC interrupts. + * @irq: IRQ number. + * @dev_id: Device ID. + * + * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise. + */ +static irqreturn_t intr_handler(int irq, void *dev_id) +{ + const struct synps_platform_data *p_data; + struct mem_ctl_info *mci = dev_id; + struct synps_edac_priv *priv; + int status, regval; + + priv = mci->pvt_info; + p_data = priv->p_data; + + regval = readl(priv->baseaddr + DDR_QOS_IRQ_STAT_OFST); + regval &= (DDR_QOSCE_MASK | DDR_QOSUE_MASK); + if (!(regval & ECC_CE_UE_INTR_MASK)) + return IRQ_NONE; + + status = p_data->get_error_info(priv); + if (status) + return IRQ_NONE; + + priv->ce_cnt += priv->stat.ce_cnt; + priv->ue_cnt += priv->stat.ue_cnt; + handle_error(mci, &priv->stat); + + edac_dbg(3, "Total error count CE %d UE %d\n", + priv->ce_cnt, priv->ue_cnt); + writel(regval, priv->baseaddr + DDR_QOS_IRQ_STAT_OFST); + return IRQ_HANDLED; +} + /** * check_errors - Check controller for ECC errors. * @mci: EDAC memory controller instance. @@ -427,10 +554,13 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) */ static void check_errors(struct mem_ctl_info *mci) { - struct synps_edac_priv *priv = mci->pvt_info; - const struct synps_platform_data *p_data = priv->p_data; + const struct synps_platform_data *p_data; + struct synps_edac_priv *priv; int status; + priv = mci->pvt_info; + p_data = priv->p_data; + status = p_data->get_error_info(priv); if (status) return; @@ -474,6 +604,39 @@ static enum dev_type zynq_get_dtype(const void __iomem *base) return dt; } +/** + * zynqmp_get_dtype - Return the controller memory width. + * @base: DDR memory controller base address. + * + * Get the EDAC device type width appropriate for the current controller + * configuration. + * + * Return: a device type width enumeration. + */ +static enum dev_type zynqmp_get_dtype(const void __iomem *base) +{ + enum dev_type dt; + u32 width; + + width = readl(base + CTRL_OFST); + width = (width & ECC_CTRL_BUSWIDTH_MASK) >> ECC_CTRL_BUSWIDTH_SHIFT; + switch (width) { + case DDRCTL_EWDTH_16: + dt = DEV_X2; + break; + case DDRCTL_EWDTH_32: + dt = DEV_X4; + break; + case DDRCTL_EWDTH_64: + dt = DEV_X8; + break; + default: + dt = DEV_UNKNOWN; + } + + return dt; +} + /** * zynq_get_ecc_state - Return the controller ECC enable/disable status. * @base: DDR memory controller base address. @@ -484,19 +647,43 @@ static enum dev_type zynq_get_dtype(const void __iomem *base) */ static bool zynq_get_ecc_state(void __iomem *base) { - bool state = false; enum dev_type dt; u32 ecctype; dt = zynq_get_dtype(base); if (dt == DEV_UNKNOWN) - return state; + return false; ecctype = readl(base + SCRUB_OFST) & SCRUB_MODE_MASK; if ((ecctype == SCRUB_MODE_SECDED) && (dt == DEV_X2)) - state = true; + return true; + + return false; +} + +/** + * zynqmp_get_ecc_state - Return the controller ECC enable/disable status. + * @base: DDR memory controller base address. + * + * Get the ECC enable/disable status for the controller. + * + * Return: a ECC status boolean i.e true/false - enabled/disabled. + */ +static bool zynqmp_get_ecc_state(void __iomem *base) +{ + enum dev_type dt; + u32 ecctype; - return state; + dt = zynqmp_get_dtype(base); + if (dt == DEV_UNKNOWN) + return false; + + ecctype = readl(base + ECC_CFG0_OFST) & SCRUB_MODE_MASK; + if ((ecctype == SCRUB_MODE_SECDED) && + ((dt == DEV_X2) || (dt == DEV_X4) || (dt == DEV_X8))) + return true; + + return false; } /** @@ -537,6 +724,34 @@ static enum mem_type zynq_get_mtype(const void __iomem *base) return mt; } +/** + * zynqmp_get_mtype - Returns controller memory type. + * @base: Synopsys ECC status structure. + * + * Get the EDAC memory type appropriate for the current controller + * configuration. + * + * Return: a memory type enumeration. + */ +static enum mem_type zynqmp_get_mtype(const void __iomem *base) +{ + enum mem_type mt; + u32 memtype; + + memtype = readl(base + CTRL_OFST); + + if ((memtype & MEM_TYPE_DDR3) || (memtype & MEM_TYPE_LPDDR3)) + mt = MEM_DDR3; + else if (memtype & MEM_TYPE_DDR2) + mt = MEM_RDDR2; + else if ((memtype & MEM_TYPE_LPDDR4) || (memtype & MEM_TYPE_DDR4)) + mt = MEM_DDR4; + else + mt = MEM_EMPTY; + + return mt; +} + /** * init_csrows - Initialize the csrow data. * @mci: EDAC memory controller instance. @@ -598,13 +813,57 @@ static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev) mci->dev_name = SYNPS_EDAC_MOD_STRING; mci->mod_name = SYNPS_EDAC_MOD_VER; - edac_op_state = EDAC_OPSTATE_POLL; - mci->edac_check = check_errors; + if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) { + edac_op_state = EDAC_OPSTATE_INT; + } else { + edac_op_state = EDAC_OPSTATE_POLL; + mci->edac_check = check_errors; + } + mci->ctl_page_to_phys = NULL; init_csrows(mci); } +static void enable_intr(struct synps_edac_priv *priv) +{ + /* Enable UE/CE Interrupts */ + writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK, + priv->baseaddr + DDR_QOS_IRQ_EN_OFST); +} + +static void disable_intr(struct synps_edac_priv *priv) +{ + /* Disable UE/CE Interrupts */ + writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK, + priv->baseaddr + DDR_QOS_IRQ_DB_OFST); +} + +static int setup_irq(struct mem_ctl_info *mci, + struct platform_device *pdev) +{ + struct synps_edac_priv *priv = mci->pvt_info; + int ret, irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + edac_printk(KERN_ERR, EDAC_MC, + "No IRQ %d in DT\n", irq); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, intr_handler, + 0, dev_name(&pdev->dev), mci); + if (ret < 0) { + edac_printk(KERN_ERR, EDAC_MC, "Failed to request IRQ\n"); + return ret; + } + + enable_intr(priv); + + return 0; +} + static const struct synps_platform_data zynq_edac_def = { .get_error_info = zynq_get_error_info, .get_mtype = zynq_get_mtype, @@ -613,9 +872,26 @@ static const struct synps_platform_data zynq_edac_def = { .quirks = 0, }; +static const struct synps_platform_data zynqmp_edac_def = { + .get_error_info = zynqmp_get_error_info, + .get_mtype = zynqmp_get_mtype, + .get_dtype = zynqmp_get_dtype, + .get_ecc_state = zynqmp_get_ecc_state, + .quirks = DDR_ECC_INTR_SUPPORT, +}; + static const struct of_device_id synps_edac_match[] = { - { .compatible = "xlnx,zynq-ddrc-a05", .data = (void *)&zynq_edac_def }, - { /* end of table */ } + { + .compatible = "xlnx,zynq-ddrc-a05", + .data = (void *)&zynq_edac_def + }, + { + .compatible = "xlnx,zynqmp-ddrc-2.40a", + .data = (void *)&zynqmp_edac_def + }, + { + /* end of table */ + } }; MODULE_DEVICE_TABLE(of, synps_edac_match); @@ -674,6 +950,12 @@ static int mc_probe(struct platform_device *pdev) mc_init(mci, pdev); + if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) { + rc = setup_irq(mci, pdev); + if (rc) + goto free_edac_mc; + } + rc = edac_mc_add_mc(mci); if (rc) { edac_printk(KERN_ERR, EDAC_MC, @@ -685,7 +967,9 @@ static int mc_probe(struct platform_device *pdev) * Start capturing the correctable and uncorrectable errors. A write of * 0 starts the counters. */ - writel(0x0, baseaddr + ECC_CTRL_OFST); + if (!(priv->p_data->quirks & DDR_ECC_INTR_SUPPORT)) + writel(0x0, baseaddr + ECC_CTRL_OFST); + return rc; free_edac_mc: @@ -703,6 +987,10 @@ free_edac_mc: static int mc_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); + struct synps_edac_priv *priv = mci->pvt_info; + + if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) + disable_intr(priv); edac_mc_del_mc(&pdev->dev); edac_mc_free(mci); -- cgit v1.2.3-59-g8ed1b From 1a81361f75d8a5cbe9d77c30fe0f42b7cda621c8 Mon Sep 17 00:00:00 2001 From: Manish Narani Date: Thu, 25 Oct 2018 11:37:01 +0530 Subject: EDAC, synopsys: Add Error Injection support for ZynqMP DDR controller Add support for Error Injection for ZynqMP DDR controller IP. For injecting errors, the Row, Column, Bank, Bank Group and Rank bits positions are determined via Address Map registers of the Synopsys DDR controller. Signed-off-by: Manish Narani Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Michal Simek CC: amit.kucheria@linaro.org CC: devicetree@vger.kernel.org CC: leoyang.li@nxp.com CC: linux-arm-kernel@lists.infradead.org CC: linux-edac CC: mark.rutland@arm.com CC: robh+dt@kernel.org CC: sudeep.holla@arm.com Link: http://lkml.kernel.org/r/1540447621-22870-7-git-send-email-manish.narani@xilinx.com --- drivers/edac/synopsys_edac.c | 420 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 413 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index e81f18aa9576..2d263382d797 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -302,12 +302,18 @@ struct synps_ecc_status { /** * struct synps_edac_priv - DDR memory controller private instance data. - * @baseaddr: Base address of the DDR controller. - * @message: Buffer for framing the event specific info. - * @stat: ECC status information. - * @p_data: Platform data. - * @ce_cnt: Correctable Error count. - * @ue_cnt: Uncorrectable Error count. + * @baseaddr: Base address of the DDR controller. + * @message: Buffer for framing the event specific info. + * @stat: ECC status information. + * @p_data: Platform data. + * @ce_cnt: Correctable Error count. + * @ue_cnt: Uncorrectable Error count. + * @poison_addr: Data poison address. + * @row_shift: Bit shifts for row bit. + * @col_shift: Bit shifts for column bit. + * @bank_shift: Bit shifts for bank bit. + * @bankgrp_shift: Bit shifts for bank group bit. + * @rank_shift: Bit shifts for rank bit. */ struct synps_edac_priv { void __iomem *baseaddr; @@ -316,6 +322,14 @@ struct synps_edac_priv { const struct synps_platform_data *p_data; u32 ce_cnt; u32 ue_cnt; +#ifdef CONFIG_EDAC_DEBUG + ulong poison_addr; + u32 row_shift[18]; + u32 col_shift[14]; + u32 bank_shift[3]; + u32 bankgrp_shift[2]; + u32 rank_shift[1]; +#endif }; /** @@ -877,7 +891,11 @@ static const struct synps_platform_data zynqmp_edac_def = { .get_mtype = zynqmp_get_mtype, .get_dtype = zynqmp_get_dtype, .get_ecc_state = zynqmp_get_ecc_state, - .quirks = DDR_ECC_INTR_SUPPORT, + .quirks = (DDR_ECC_INTR_SUPPORT +#ifdef CONFIG_EDAC_DEBUG + | DDR_ECC_DATA_POISON_SUPPORT +#endif + ), }; static const struct of_device_id synps_edac_match[] = { @@ -896,6 +914,375 @@ static const struct of_device_id synps_edac_match[] = { MODULE_DEVICE_TABLE(of, synps_edac_match); +#ifdef CONFIG_EDAC_DEBUG +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + +/** + * ddr_poison_setup - Update poison registers. + * @priv: DDR memory controller private instance data. + * + * Update poison registers as per DDR mapping. + * Return: none. + */ +static void ddr_poison_setup(struct synps_edac_priv *priv) +{ + int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval; + int index; + ulong hif_addr = 0; + + hif_addr = priv->poison_addr >> 3; + + for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) { + if (priv->row_shift[index]) + row |= (((hif_addr >> priv->row_shift[index]) & + BIT(0)) << index); + else + break; + } + + for (index = 0; index < DDR_MAX_COL_SHIFT; index++) { + if (priv->col_shift[index] || index < 3) + col |= (((hif_addr >> priv->col_shift[index]) & + BIT(0)) << index); + else + break; + } + + for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) { + if (priv->bank_shift[index]) + bank |= (((hif_addr >> priv->bank_shift[index]) & + BIT(0)) << index); + else + break; + } + + for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) { + if (priv->bankgrp_shift[index]) + bankgrp |= (((hif_addr >> priv->bankgrp_shift[index]) + & BIT(0)) << index); + else + break; + } + + if (priv->rank_shift[0]) + rank = (hif_addr >> priv->rank_shift[0]) & BIT(0); + + regval = (rank << ECC_POISON0_RANK_SHIFT) & ECC_POISON0_RANK_MASK; + regval |= (col << ECC_POISON0_COLUMN_SHIFT) & ECC_POISON0_COLUMN_MASK; + writel(regval, priv->baseaddr + ECC_POISON0_OFST); + + regval = (bankgrp << ECC_POISON1_BG_SHIFT) & ECC_POISON1_BG_MASK; + regval |= (bank << ECC_POISON1_BANKNR_SHIFT) & ECC_POISON1_BANKNR_MASK; + regval |= (row << ECC_POISON1_ROW_SHIFT) & ECC_POISON1_ROW_MASK; + writel(regval, priv->baseaddr + ECC_POISON1_OFST); +} + +static ssize_t inject_data_error_show(struct device *dev, + struct device_attribute *mattr, + char *data) +{ + struct mem_ctl_info *mci = to_mci(dev); + struct synps_edac_priv *priv = mci->pvt_info; + + return sprintf(data, "Poison0 Addr: 0x%08x\n\rPoison1 Addr: 0x%08x\n\r" + "Error injection Address: 0x%lx\n\r", + readl(priv->baseaddr + ECC_POISON0_OFST), + readl(priv->baseaddr + ECC_POISON1_OFST), + priv->poison_addr); +} + +static ssize_t inject_data_error_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) +{ + struct mem_ctl_info *mci = to_mci(dev); + struct synps_edac_priv *priv = mci->pvt_info; + + if (kstrtoul(data, 0, &priv->poison_addr)) + return -EINVAL; + + ddr_poison_setup(priv); + + return count; +} + +static ssize_t inject_data_poison_show(struct device *dev, + struct device_attribute *mattr, + char *data) +{ + struct mem_ctl_info *mci = to_mci(dev); + struct synps_edac_priv *priv = mci->pvt_info; + + return sprintf(data, "Data Poisoning: %s\n\r", + (((readl(priv->baseaddr + ECC_CFG1_OFST)) & 0x3) == 0x3) + ? ("Correctable Error") : ("UnCorrectable Error")); +} + +static ssize_t inject_data_poison_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) +{ + struct mem_ctl_info *mci = to_mci(dev); + struct synps_edac_priv *priv = mci->pvt_info; + + writel(0, priv->baseaddr + DDRC_SWCTL); + if (strncmp(data, "CE", 2) == 0) + writel(ECC_CEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); + else + writel(ECC_UEPOISON_MASK, priv->baseaddr + ECC_CFG1_OFST); + writel(1, priv->baseaddr + DDRC_SWCTL); + + return count; +} + +static DEVICE_ATTR_RW(inject_data_error); +static DEVICE_ATTR_RW(inject_data_poison); + +static int edac_create_sysfs_attributes(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_data_error); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison); + if (rc < 0) + return rc; + return 0; +} + +static void edac_remove_sysfs_attributes(struct mem_ctl_info *mci) +{ + device_remove_file(&mci->dev, &dev_attr_inject_data_error); + device_remove_file(&mci->dev, &dev_attr_inject_data_poison); +} + +static void setup_row_address_map(struct synps_edac_priv *priv, u32 *addrmap) +{ + u32 addrmap_row_b2_10; + int index; + + priv->row_shift[0] = (addrmap[5] & ROW_MAX_VAL_MASK) + ROW_B0_BASE; + priv->row_shift[1] = ((addrmap[5] >> 8) & + ROW_MAX_VAL_MASK) + ROW_B1_BASE; + + addrmap_row_b2_10 = (addrmap[5] >> 16) & ROW_MAX_VAL_MASK; + if (addrmap_row_b2_10 != ROW_MAX_VAL_MASK) { + for (index = 2; index < 11; index++) + priv->row_shift[index] = addrmap_row_b2_10 + + index + ROW_B0_BASE; + + } else { + priv->row_shift[2] = (addrmap[9] & + ROW_MAX_VAL_MASK) + ROW_B2_BASE; + priv->row_shift[3] = ((addrmap[9] >> 8) & + ROW_MAX_VAL_MASK) + ROW_B3_BASE; + priv->row_shift[4] = ((addrmap[9] >> 16) & + ROW_MAX_VAL_MASK) + ROW_B4_BASE; + priv->row_shift[5] = ((addrmap[9] >> 24) & + ROW_MAX_VAL_MASK) + ROW_B5_BASE; + priv->row_shift[6] = (addrmap[10] & + ROW_MAX_VAL_MASK) + ROW_B6_BASE; + priv->row_shift[7] = ((addrmap[10] >> 8) & + ROW_MAX_VAL_MASK) + ROW_B7_BASE; + priv->row_shift[8] = ((addrmap[10] >> 16) & + ROW_MAX_VAL_MASK) + ROW_B8_BASE; + priv->row_shift[9] = ((addrmap[10] >> 24) & + ROW_MAX_VAL_MASK) + ROW_B9_BASE; + priv->row_shift[10] = (addrmap[11] & + ROW_MAX_VAL_MASK) + ROW_B10_BASE; + } + + priv->row_shift[11] = (((addrmap[5] >> 24) & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : (((addrmap[5] >> 24) & + ROW_MAX_VAL_MASK) + ROW_B11_BASE); + priv->row_shift[12] = ((addrmap[6] & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : ((addrmap[6] & + ROW_MAX_VAL_MASK) + ROW_B12_BASE); + priv->row_shift[13] = (((addrmap[6] >> 8) & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 8) & + ROW_MAX_VAL_MASK) + ROW_B13_BASE); + priv->row_shift[14] = (((addrmap[6] >> 16) & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 16) & + ROW_MAX_VAL_MASK) + ROW_B14_BASE); + priv->row_shift[15] = (((addrmap[6] >> 24) & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 24) & + ROW_MAX_VAL_MASK) + ROW_B15_BASE); + priv->row_shift[16] = ((addrmap[7] & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : ((addrmap[7] & + ROW_MAX_VAL_MASK) + ROW_B16_BASE); + priv->row_shift[17] = (((addrmap[7] >> 8) & ROW_MAX_VAL_MASK) == + ROW_MAX_VAL_MASK) ? 0 : (((addrmap[7] >> 8) & + ROW_MAX_VAL_MASK) + ROW_B17_BASE); +} + +static void setup_column_address_map(struct synps_edac_priv *priv, u32 *addrmap) +{ + u32 width, memtype; + int index; + + memtype = readl(priv->baseaddr + CTRL_OFST); + width = (memtype & ECC_CTRL_BUSWIDTH_MASK) >> ECC_CTRL_BUSWIDTH_SHIFT; + + priv->col_shift[0] = 0; + priv->col_shift[1] = 1; + priv->col_shift[2] = (addrmap[2] & COL_MAX_VAL_MASK) + COL_B2_BASE; + priv->col_shift[3] = ((addrmap[2] >> 8) & + COL_MAX_VAL_MASK) + COL_B3_BASE; + priv->col_shift[4] = (((addrmap[2] >> 16) & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 16) & + COL_MAX_VAL_MASK) + COL_B4_BASE); + priv->col_shift[5] = (((addrmap[2] >> 24) & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 24) & + COL_MAX_VAL_MASK) + COL_B5_BASE); + priv->col_shift[6] = ((addrmap[3] & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : ((addrmap[3] & + COL_MAX_VAL_MASK) + COL_B6_BASE); + priv->col_shift[7] = (((addrmap[3] >> 8) & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 8) & + COL_MAX_VAL_MASK) + COL_B7_BASE); + priv->col_shift[8] = (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 16) & + COL_MAX_VAL_MASK) + COL_B8_BASE); + priv->col_shift[9] = (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) == + COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 24) & + COL_MAX_VAL_MASK) + COL_B9_BASE); + if (width == DDRCTL_EWDTH_64) { + if (memtype & MEM_TYPE_LPDDR3) { + priv->col_shift[10] = ((addrmap[4] & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + ((addrmap[4] & COL_MAX_VAL_MASK) + + COL_B10_BASE); + priv->col_shift[11] = (((addrmap[4] >> 8) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[4] >> 8) & COL_MAX_VAL_MASK) + + COL_B11_BASE); + } else { + priv->col_shift[11] = ((addrmap[4] & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + ((addrmap[4] & COL_MAX_VAL_MASK) + + COL_B10_BASE); + priv->col_shift[13] = (((addrmap[4] >> 8) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[4] >> 8) & COL_MAX_VAL_MASK) + + COL_B11_BASE); + } + } else if (width == DDRCTL_EWDTH_32) { + if (memtype & MEM_TYPE_LPDDR3) { + priv->col_shift[10] = (((addrmap[3] >> 24) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) + + COL_B9_BASE); + priv->col_shift[11] = ((addrmap[4] & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + ((addrmap[4] & COL_MAX_VAL_MASK) + + COL_B10_BASE); + } else { + priv->col_shift[11] = (((addrmap[3] >> 24) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) + + COL_B9_BASE); + priv->col_shift[13] = ((addrmap[4] & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + ((addrmap[4] & COL_MAX_VAL_MASK) + + COL_B10_BASE); + } + } else { + if (memtype & MEM_TYPE_LPDDR3) { + priv->col_shift[10] = (((addrmap[3] >> 16) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) + + COL_B8_BASE); + priv->col_shift[11] = (((addrmap[3] >> 24) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) + + COL_B9_BASE); + priv->col_shift[13] = ((addrmap[4] & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + ((addrmap[4] & COL_MAX_VAL_MASK) + + COL_B10_BASE); + } else { + priv->col_shift[11] = (((addrmap[3] >> 16) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) + + COL_B8_BASE); + priv->col_shift[13] = (((addrmap[3] >> 24) & + COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 : + (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) + + COL_B9_BASE); + } + } + + if (width) { + for (index = 9; index > width; index--) { + priv->col_shift[index] = priv->col_shift[index - width]; + priv->col_shift[index - width] = 0; + } + } + +} + +static void setup_bank_address_map(struct synps_edac_priv *priv, u32 *addrmap) +{ + priv->bank_shift[0] = (addrmap[1] & BANK_MAX_VAL_MASK) + BANK_B0_BASE; + priv->bank_shift[1] = ((addrmap[1] >> 8) & + BANK_MAX_VAL_MASK) + BANK_B1_BASE; + priv->bank_shift[2] = (((addrmap[1] >> 16) & + BANK_MAX_VAL_MASK) == BANK_MAX_VAL_MASK) ? 0 : + (((addrmap[1] >> 16) & BANK_MAX_VAL_MASK) + + BANK_B2_BASE); + +} + +static void setup_bg_address_map(struct synps_edac_priv *priv, u32 *addrmap) +{ + priv->bankgrp_shift[0] = (addrmap[8] & + BANKGRP_MAX_VAL_MASK) + BANKGRP_B0_BASE; + priv->bankgrp_shift[1] = (((addrmap[8] >> 8) & BANKGRP_MAX_VAL_MASK) == + BANKGRP_MAX_VAL_MASK) ? 0 : (((addrmap[8] >> 8) + & BANKGRP_MAX_VAL_MASK) + BANKGRP_B1_BASE); + +} + +static void setup_rank_address_map(struct synps_edac_priv *priv, u32 *addrmap) +{ + priv->rank_shift[0] = ((addrmap[0] & RANK_MAX_VAL_MASK) == + RANK_MAX_VAL_MASK) ? 0 : ((addrmap[0] & + RANK_MAX_VAL_MASK) + RANK_B0_BASE); +} + +/** + * setup_address_map - Set Address Map by querying ADDRMAP registers. + * @priv: DDR memory controller private instance data. + * + * Set Address Map by querying ADDRMAP registers. + * + * Return: none. + */ +static void setup_address_map(struct synps_edac_priv *priv) +{ + u32 addrmap[12]; + int index; + + for (index = 0; index < 12; index++) { + u32 addrmap_offset; + + addrmap_offset = ECC_ADDRMAP0_OFFSET + (index * 4); + addrmap[index] = readl(priv->baseaddr + addrmap_offset); + } + + setup_row_address_map(priv, addrmap); + + setup_column_address_map(priv, addrmap); + + setup_bank_address_map(priv, addrmap); + + setup_bg_address_map(priv, addrmap); + + setup_rank_address_map(priv, addrmap); +} +#endif /* CONFIG_EDAC_DEBUG */ + /** * mc_probe - Check controller and bind driver. * @pdev: platform device. @@ -963,6 +1350,20 @@ static int mc_probe(struct platform_device *pdev) goto free_edac_mc; } +#ifdef CONFIG_EDAC_DEBUG + if (priv->p_data->quirks & DDR_ECC_DATA_POISON_SUPPORT) { + if (edac_create_sysfs_attributes(mci)) { + edac_printk(KERN_ERR, EDAC_MC, + "Failed to create sysfs entries\n"); + goto free_edac_mc; + } + } + + if (of_device_is_compatible(pdev->dev.of_node, + "xlnx,zynqmp-ddrc-2.40a")) + setup_address_map(priv); +#endif + /* * Start capturing the correctable and uncorrectable errors. A write of * 0 starts the counters. @@ -992,6 +1393,11 @@ static int mc_remove(struct platform_device *pdev) if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT) disable_intr(priv); +#ifdef CONFIG_EDAC_DEBUG + if (priv->p_data->quirks & DDR_ECC_DATA_POISON_SUPPORT) + edac_remove_sysfs_attributes(mci); +#endif + edac_mc_del_mc(&pdev->dev); edac_mc_free(mci); -- cgit v1.2.3-59-g8ed1b From 8fd8cbfeada59d381c49ad700607376416e2fdd8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 18 Oct 2018 17:15:22 +0300 Subject: EDAC, qcom_edac: Remove irq_handled local variable irq_handled isn't initialized to false on function entry. However, it is not really needed and the IRQ handler return value can be set directly instead. [ bp: rewrite commit message. ] Fixes: 27450653f1db ("drivers: edac: Add EDAC driver support for QCOM SoCs") Signed-off-by: Dan Carpenter Signed-off-by: Borislav Petkov CC: Channagoud Kadabi CC: Mauro Carvalho Chehab CC: Venkata Narendra Kumar Gutta CC: kernel-janitors@vger.kernel.org CC: linux-arm-msm@vger.kernel.org CC: linux-edac Link: http://lkml.kernel.org/r/20181018141522.rywdvjmlpk4ticiw@kili.mountain --- drivers/edac/qcom_edac.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c index 82bd775124f2..97a27e42dd61 100644 --- a/drivers/edac/qcom_edac.c +++ b/drivers/edac/qcom_edac.c @@ -292,7 +292,6 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl) struct llcc_drv_data *drv = edac_dev_ctl->pvt_info; irqreturn_t irq_rc = IRQ_NONE; u32 drp_error, trp_error, i; - bool irq_handled; int ret; /* Iterate over the banks and look for Tag RAM or Data RAM errors */ @@ -311,7 +310,7 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl) ret = dump_syn_reg(edev_ctl, LLCC_DRAM_UE, i); } if (!ret) - irq_handled = true; + irq_rc = IRQ_HANDLED; ret = regmap_read(drv->regmap, drv->offsets[i] + TRP_INTERRUPT_0_STATUS, @@ -327,12 +326,9 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl) ret = dump_syn_reg(edev_ctl, LLCC_TRAM_UE, i); } if (!ret) - irq_handled = true; + irq_rc = IRQ_HANDLED; } - if (irq_handled) - irq_rc = IRQ_HANDLED; - return irq_rc; } -- cgit v1.2.3-59-g8ed1b From 96c1c58eb0d715d3f66f374bb07aa96cb7cdd1fa Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 7 Nov 2018 10:22:37 +0800 Subject: EDAC, i82975x: Remove set but not used variable dtype Fix this gcc -Wunused-but-set-variable warning: drivers/edac/i82975x_edac.c:378:16: warning: variable 'dtype' set but not used [-Wunused-but-set-variable] It was introduced in 084a4fccef39 ("edac: move dimm properties to struct dimm_info") but never used. Also, remove the function i82975x_dram_type() and move the comment and the assignment to the place where it is used. [ bp: massage commit message and shorten comment. ] Signed-off-by: YueHaibing Signed-off-by: Borislav Petkov CC: "Arvind R." CC: Mauro Carvalho Chehab CC: ravi@jetztechnologies.com CC: arvino55@gmail.com CC: linux-edac Link: http://lkml.kernel.org/r/20181107022237.14048-1-yuehaibing@huawei.com --- drivers/edac/i82975x_edac.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 892815eaa97b..d514e7a8fa4d 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -358,14 +358,6 @@ static int dual_channel_active(void __iomem *mch_window) return dualch; } -static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) -{ - /* - * ECC is possible on i92975x ONLY with DEV_X8 - */ - return DEV_X8; -} - static void i82975x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, void __iomem *mch_window) { @@ -375,7 +367,6 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, u32 cumul_size, nr_pages; int index, chan; struct dimm_info *dimm; - enum dev_type dtype; last_cumul_size = 0; @@ -413,7 +404,6 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, * [0-7] for single-channel; i.e. csrow->nr_channels = 1 * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 */ - dtype = i82975x_dram_type(mch_window, index); for (chan = 0; chan < csrow->nr_channels; chan++) { dimm = mci->csrows[index]->channels[chan]->dimm; @@ -423,7 +413,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, (chan == 0) ? 'A' : 'B', index); dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ - dimm->dtype = i82975x_dram_type(mch_window, index); + + /* ECC is possible on i92975x ONLY with DEV_X8. */ + dimm->dtype = DEV_X8; + dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ dimm->edac_mode = EDAC_SECDED; /* only supported */ } -- cgit v1.2.3-59-g8ed1b From 24c9d423e86b17b25b4b510e81f10aa232fdaa60 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Tue, 6 Nov 2018 10:39:15 -0800 Subject: EDAC, skx: Fix randconfig builds in a better way It was previously noted that Kconfig complained about unmet dependencies when trying to configure skx_edac together with CONFIG_ACPI=n. First fix for this checked for ACPI when doing select ACPI_ADXL but this required stub functions for the case where ACPI wasn't selected. It also allowed building a driver that didn't actually work for a system that has non-volatile DIMMs. Arnd Bergmann pointed out that the right fix is to make EDAC_SKX "depend on ACPI". Fixes: a324e9396ca3 ("EDAC, skx: Fix randconfig builds") Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov CC: "Rafael J. Wysocki" CC: Arnd Bergmann CC: Mauro Carvalho Chehab CC: linux-edac CC: qiuxu.zhuo@intel.com Link: http://lkml.kernel.org/r/20181106183914.GA26731@agluck-desk --- drivers/edac/Kconfig | 4 ++-- include/linux/adxl.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index ec2727b27556..e286b5b99003 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -231,10 +231,10 @@ config EDAC_SBRIDGE config EDAC_SKX tristate "Intel Skylake server Integrated MC" - depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG + depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG && ACPI depends on ACPI_NFIT || !ACPI_NFIT # if ACPI_NFIT=m, EDAC_SKX can't be y select DMI - select ACPI_ADXL if ACPI + select ACPI_ADXL help Support for error detection and correction the Intel Skylake server Integrated Memory Controllers. If your diff --git a/include/linux/adxl.h b/include/linux/adxl.h index 2d29f55923e3..2a629acb4c3f 100644 --- a/include/linux/adxl.h +++ b/include/linux/adxl.h @@ -7,12 +7,7 @@ #ifndef _LINUX_ADXL_H #define _LINUX_ADXL_H -#ifdef CONFIG_ACPI_ADXL const char * const *adxl_get_component_names(void); int adxl_decode(u64 addr, u64 component_values[]); -#else -static inline const char * const *adxl_get_component_names(void) { return NULL; } -static inline int adxl_decode(u64 addr, u64 component_values[]) { return -EOPNOTSUPP; } -#endif #endif /* _LINUX_ADXL_H */ -- cgit v1.2.3-59-g8ed1b From 1722bc0e8c2f6f798948ade79c6678e15656a3e5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 9 Nov 2018 13:37:57 +0000 Subject: EDAC: Fix indentation issues in several EDAC drivers Replace spaces with tabs and insert missing indentation. [ bp: Rewrite commit message. ] Signed-off-by: Colin Ian King Signed-off-by: Borislav Petkov CC: "Arvind R." CC: Mark Gross CC: Mauro Carvalho Chehab CC: Ranganathan Desikan CC: kernel-janitors@vger.kernel.org CC: linux-edac Link: http://lkml.kernel.org/r/20181109133757.21471-1-colin.king@canonical.com --- drivers/edac/e752x_edac.c | 4 ++-- drivers/edac/i3000_edac.c | 4 ++-- drivers/edac/i5000_edac.c | 4 ++-- drivers/edac/i7core_edac.c | 2 +- drivers/edac/i82975x_edac.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index b5de9a13ea3f..de732dc2ef33 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -1446,8 +1446,8 @@ static int __init e752x_init(void) edac_dbg(3, "\n"); - /* Ensure that the OPSTATE is set correctly for POLL or NMI */ - opstate_init(); + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); pci_rc = pci_register_driver(&e752x_driver); return (pci_rc < 0) ? pci_rc : 0; diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 8085a32ec3bd..f564a4a8a4ae 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -508,8 +508,8 @@ static int __init i3000_init(void) edac_dbg(3, "MC:\n"); - /* Ensure that the OPSTATE is set correctly for POLL or NMI */ - opstate_init(); + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); pci_rc = pci_register_driver(&i3000_driver); if (pci_rc < 0) diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 53f24b18cd61..98bef13e3134 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1559,8 +1559,8 @@ static int __init i5000_init(void) edac_dbg(2, "MC:\n"); - /* Ensure that the OPSTATE is set correctly for POLL or NMI */ - opstate_init(); + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); pci_rc = pci_register_driver(&i5000_driver); diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 9ef448fef12f..40297550313a 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -724,7 +724,7 @@ static ssize_t i7core_inject_type_store(struct device *dev, const char *data, size_t count) { struct mem_ctl_info *mci = to_mci(dev); -struct i7core_pvt *pvt = mci->pvt_info; + struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index d514e7a8fa4d..ce1d6abfc6af 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -648,8 +648,8 @@ static int __init i82975x_init(void) edac_dbg(3, "\n"); - /* Ensure that the OPSTATE is set correctly for POLL or NMI */ - opstate_init(); + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); pci_rc = pci_register_driver(&i82975x_driver); if (pci_rc < 0) -- cgit v1.2.3-59-g8ed1b From 88a10b15173d76338e0808e4915edbd1aae5f264 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 1 Oct 2018 15:43:13 -0700 Subject: EDAC: Don't add devices under /sys/bus/edac Nobody(*) uses them. Dropping this will allow us to make the total number of memory controllers configurable (as we won't have to worry about duplicated device names under this directory). (*) https://lkml.kernel.org/r/20180927221054.580220e5@coco.lan Signed-off-by: Tony Luck Signed-off-by: Borislav Petkov Acked-by: Mauro Carvalho Chehab CC: Aristeu Rozanski Filho CC: Greg KH CC: Justin Ernst CC: Mauro Carvalho Chehab CC: Russ Anderson CC: linux-edac Link: http://lkml.kernel.org/r/20181001224313.GA9487@agluck-desk --- drivers/edac/edac_mc_sysfs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 20374b8248f0..4c1bee59c2e6 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -405,7 +405,6 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, struct csrow_info *csrow, int index) { csrow->dev.type = &csrow_attr_type; - csrow->dev.bus = mci->bus; csrow->dev.groups = csrow_dev_groups; device_initialize(&csrow->dev); csrow->dev.parent = &mci->dev; @@ -636,7 +635,6 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, dimm->mci = mci; dimm->dev.type = &dimm_attr_type; - dimm->dev.bus = mci->bus; device_initialize(&dimm->dev); dimm->dev.parent = &mci->dev; @@ -940,7 +938,6 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, device_initialize(&mci->dev); mci->dev.parent = mci_pdev; - mci->dev.bus = mci->bus; mci->dev.groups = groups; dev_set_name(&mci->dev, "mc%d", mci->mc_idx); dev_set_drvdata(&mci->dev, mci); -- cgit v1.2.3-59-g8ed1b From 861e6ed667c83d64a42b0db41a22d6b4de4e913f Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 6 Nov 2018 12:35:21 +0100 Subject: EDAC: Drop per-memory controller buses ... and use the single edac_subsys object returned from subsys_system_register(). The idea is to have a single bus and multiple devices on it. Signed-off-by: Borislav Petkov Acked-by: Mauro Carvalho Chehab CC: Aristeu Rozanski Filho CC: Greg KH CC: Justin Ernst CC: linux-edac CC: Mauro Carvalho Chehab CC: Russ Anderson Cc: Tony Luck Link: https://lkml.kernel.org/r/20180926152752.GG5584@zn.tnic --- drivers/edac/edac_mc.c | 9 +-------- drivers/edac/edac_mc_sysfs.c | 30 ++---------------------------- include/linux/edac.h | 6 ------ 3 files changed, 3 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 7d3edd713932..13594ffadcb3 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -55,8 +55,6 @@ static LIST_HEAD(mc_devices); */ static const char *edac_mc_owner; -static struct bus_type mc_bus[EDAC_MAX_MCS]; - int edac_get_report_status(void) { return edac_report; @@ -716,11 +714,6 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, int ret = -EINVAL; edac_dbg(0, "\n"); - if (mci->mc_idx >= EDAC_MAX_MCS) { - pr_warn_once("Too many memory controllers: %d\n", mci->mc_idx); - return -ENODEV; - } - #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) edac_mc_dump_mci(mci); @@ -760,7 +753,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, /* set load time so that error rate can be tracked */ mci->start_time = jiffies; - mci->bus = &mc_bus[mci->mc_idx]; + mci->bus = edac_get_sysfs_subsys(); if (edac_create_sysfs_mci_device(mci, groups)) { edac_mc_printk(mci, KERN_WARNING, diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 4c1bee59c2e6..464174685589 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -912,27 +912,8 @@ static const struct device_type mci_attr_type = { int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, const struct attribute_group **groups) { - char *name; int i, err; - /* - * The memory controller needs its own bus, in order to avoid - * namespace conflicts at /sys/bus/edac. - */ - name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); - if (!name) - return -ENOMEM; - - mci->bus->name = name; - - edac_dbg(0, "creating bus %s\n", mci->bus->name); - - err = bus_register(mci->bus); - if (err < 0) { - kfree(name); - return err; - } - /* get the /sys/devices/system/edac subsys reference */ mci->dev.type = &mci_attr_type; device_initialize(&mci->dev); @@ -947,7 +928,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, err = device_add(&mci->dev); if (err < 0) { edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev)); - goto fail_unregister_bus; + goto out; } /* @@ -995,10 +976,8 @@ fail_unregister_dimm: device_unregister(&dimm->dev); } device_unregister(&mci->dev); -fail_unregister_bus: - bus_unregister(mci->bus); - kfree(name); +out: return err; } @@ -1029,13 +1008,8 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) void edac_unregister_sysfs(struct mem_ctl_info *mci) { - struct bus_type *bus = mci->bus; - const char *name = mci->bus->name; - edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); device_unregister(&mci->dev); - bus_unregister(bus); - kfree(name); } static void mc_attr_release(struct device *dev) diff --git a/include/linux/edac.h b/include/linux/edac.h index 1d0c9ea8825d..342dabda9c7e 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -669,10 +669,4 @@ struct mem_ctl_info { bool fake_inject_ue; u16 fake_inject_count; }; - -/* - * Maximum number of memory controllers in the coherent fabric. - */ -#define EDAC_MAX_MCS 2 * MAX_NUMNODES - #endif -- cgit v1.2.3-59-g8ed1b From a6a386152a89f650ad93ebdf4ab160914e75ca20 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Fri, 16 Nov 2018 15:33:36 +0800 Subject: EDAC, skx: Fix function calling order in skx_exit() The order of function calling in skx_exit() is not the reversed order in skx_init(). Fix it. Signed-off-by: Qiuxu Zhuo Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Tony Luck CC: arozansk@redhat.com CC: linux-edac Link: http://lkml.kernel.org/r/1542353616-13421-1-git-send-email-qiuxu.zhuo@intel.com --- drivers/edac/skx_edac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index a99ea61dad32..b23c8aaa5f2b 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -1339,11 +1339,11 @@ static void __exit skx_exit(void) { edac_dbg(2, "\n"); mce_unregister_decode_chain(&skx_mce_dec); - skx_remove(); + teardown_skx_debug(); if (nvdimm_count) skx_adxl_put(); kfree(skx_msg); - teardown_skx_debug(); + skx_remove(); } module_init(skx_init); -- cgit v1.2.3-59-g8ed1b From e235dd43d8b0f0e036fc528504d7a129685fb572 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Fri, 16 Nov 2018 15:34:20 +0800 Subject: EDAC, skx: Prepend hex formatting with '0x' Some debug/error strings in hex formatting do not have the '0x' prefix. Prepend hex formatting with '0x' for them, but with one exception: "Couldn't enable %04x:%04x", instead of putting '0x' in this line, add the word 'device'. We commonly use 8086:1234 without the leading '0x' (e.g. as '-d' argument to lspci(8) and setpci(8) commands). Suggested-by: Borislav Petkov Signed-off-by: Qiuxu Zhuo Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: Tony Luck CC: arozansk@redhat.com CC: linux-edac Link: http://lkml.kernel.org/r/1542353660-13458-1-git-send-email-qiuxu.zhuo@intel.com --- drivers/edac/skx_edac.c | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index b23c8aaa5f2b..d8869f05c596 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -209,7 +209,7 @@ static int get_all_bus_mappings(void) d->bus[1] = GET_BITFIELD(reg, 8, 15); d->bus[2] = GET_BITFIELD(reg, 16, 23); d->bus[3] = GET_BITFIELD(reg, 24, 31); - edac_dbg(2, "busses: %x, %x, %x, %x\n", + edac_dbg(2, "busses: 0x%x, 0x%x, 0x%x, 0x%x\n", d->bus[0], d->bus[1], d->bus[2], d->bus[3]); list_add_tail(&d->list, &skx_edac_list); skx_num_sockets++; @@ -245,8 +245,8 @@ static int get_all_munits(const struct munit *m) /* Be sure that the device is enabled */ if (unlikely(pci_enable_device(pdev) < 0)) { - skx_printk(KERN_ERR, - "Couldn't enable %04x:%04x\n", PCI_VENDOR_ID_INTEL, m->did); + skx_printk(KERN_ERR, "Couldn't enable device %04x:%04x\n", + PCI_VENDOR_ID_INTEL, m->did); goto fail; } @@ -323,7 +323,7 @@ static int get_dimm_attr(u32 reg, int lobit, int hibit, int add, int minval, u32 val = GET_BITFIELD(reg, lobit, hibit); if (val < minval || val > maxval) { - edac_dbg(2, "bad %s = %d (raw=%x)\n", name, val, reg); + edac_dbg(2, "bad %s = %d (raw=0x%x)\n", name, val, reg); return -EINVAL; } return val + add; @@ -368,7 +368,7 @@ static int skx_get_hi_lo(void) skx_tohm |= (u64)reg << 32; pci_dev_put(pdev); - edac_dbg(2, "tolm=%llx tohm=%llx\n", skx_tolm, skx_tohm); + edac_dbg(2, "tolm=0x%llx tohm=0x%llx\n", skx_tolm, skx_tohm); return 0; } @@ -389,7 +389,7 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, size = ((1ull << (rows + cols + ranks)) * banks) >> (20 - 3); npages = MiB_TO_PAGES(size); - edac_dbg(0, "mc#%d: channel %d, dimm %d, %lld MiB (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", + edac_dbg(0, "mc#%d: channel %d, dimm %d, %lld MiB (%d pages) bank: %d, rank: %d, row: 0x%#x, col: 0x%#x\n", imc->mc, chan, dimmno, size, npages, banks, 1 << ranks, rows, cols); @@ -430,18 +430,18 @@ static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc, } if (smbios_handle < 0) { - skx_printk(KERN_ERR, "Can't find handle for NVDIMM ADR=%x\n", dev_handle); + skx_printk(KERN_ERR, "Can't find handle for NVDIMM ADR=0x%x\n", dev_handle); goto unknown_size; } if (flags & ACPI_NFIT_MEM_MAP_FAILED) { - skx_printk(KERN_ERR, "NVDIMM ADR=%x is not mapped\n", dev_handle); + skx_printk(KERN_ERR, "NVDIMM ADR=0x%x is not mapped\n", dev_handle); goto unknown_size; } size = dmi_memdev_size(smbios_handle); if (size == ~0ull) - skx_printk(KERN_ERR, "Can't find size for NVDIMM ADR=%x/SMBIOS=%x\n", + skx_printk(KERN_ERR, "Can't find size for NVDIMM ADR=0x%x/SMBIOS=0x%x\n", dev_handle, smbios_handle); unknown_size: @@ -616,7 +616,7 @@ static bool skx_sad_decode(struct decoded_addr *res) /* Simple sanity check for I/O space or out of range */ if (addr >= skx_tohm || (addr >= skx_tolm && addr < BIT_ULL(32))) { - edac_dbg(0, "Address %llx out of range\n", addr); + edac_dbg(0, "Address 0x%llx out of range\n", addr); return false; } @@ -631,7 +631,7 @@ restart: } prev_limit = limit + 1; } - edac_dbg(0, "No SAD entry for %llx\n", addr); + edac_dbg(0, "No SAD entry for 0x%llx\n", addr); return false; sad_found: @@ -709,7 +709,7 @@ sad_found: res->imc = GET_BITFIELD(d->mcroute, lchan * 3, lchan * 3 + 2); res->channel = GET_BITFIELD(d->mcroute, lchan * 2 + 18, lchan * 2 + 19); - edac_dbg(2, "%llx: socket=%d imc=%d channel=%d\n", + edac_dbg(2, "0x%llx: socket=%d imc=%d channel=%d\n", res->addr, res->socket, res->imc, res->channel); return true; } @@ -756,7 +756,7 @@ static bool skx_tad_decode(struct decoded_addr *res) if (SKX_TAD_BASE(base) <= res->addr && res->addr <= SKX_TAD_LIMIT(wayness)) goto tad_found; } - edac_dbg(0, "No TAD entry for %llx\n", res->addr); + edac_dbg(0, "No TAD entry for 0x%llx\n", res->addr); return false; tad_found: @@ -784,7 +784,7 @@ tad_found: res->chan_addr = channel_addr; - edac_dbg(2, "%llx: chan_addr=%llx sktways=%d chanways=%d\n", + edac_dbg(2, "0x%llx: chan_addr=0x%llx sktways=%d chanways=%d\n", res->addr, res->chan_addr, res->sktways, res->chanways); return true; } @@ -826,7 +826,7 @@ static bool skx_rir_decode(struct decoded_addr *res) } prev_limit = limit; } - edac_dbg(0, "No RIR entry for %llx\n", res->addr); + edac_dbg(0, "No RIR entry for 0x%llx\n", res->addr); return false; rir_found: @@ -845,7 +845,7 @@ rir_found: res->dimm = chan_rank / 4; res->rank = chan_rank % 4; - edac_dbg(2, "%llx: dimm=%d rank=%d chan_rank=%d rank_addr=%llx\n", + edac_dbg(2, "0x%llx: dimm=%d rank=%d chan_rank=%d rank_addr=0x%llx\n", res->addr, res->dimm, res->rank, res->channel_rank, res->rank_address); return true; @@ -908,7 +908,7 @@ static bool skx_mad_decode(struct decoded_addr *r) } r->row &= (1u << dimm->rowbits) - 1; - edac_dbg(2, "%llx: row=%x col=%x bank_addr=%d bank_group=%d\n", + edac_dbg(2, "0x%llx: row=0x%x col=0x%x bank_addr=%d bank_group=%d\n", r->addr, r->row, r->column, r->bank_address, r->bank_group); return true; @@ -1069,13 +1069,13 @@ static void skx_mce_output_error(struct mem_ctl_info *mci, } } if (adxl_component_count) { - snprintf(skx_msg, MSG_SIZE, "%s%s err_code:%04x:%04x %s", + snprintf(skx_msg, MSG_SIZE, "%s%s err_code:0x%04x:0x%04x %s", overflow ? " OVERFLOW" : "", (uncorrected_error && recoverable) ? " recoverable" : "", mscod, errcode, adxl_msg); } else { snprintf(skx_msg, MSG_SIZE, - "%s%s err_code:%04x:%04x socket:%d imc:%d rank:%d bg:%d ba:%d row:%x col:%x", + "%s%s err_code:0x%04x:0x%04x socket:%d imc:%d rank:%d bg:%d ba:%d row:0x%x col:0x%x", overflow ? " OVERFLOW" : "", (uncorrected_error && recoverable) ? " recoverable" : "", mscod, errcode, @@ -1151,15 +1151,15 @@ static int skx_mce_check_error(struct notifier_block *nb, unsigned long val, skx_mc_printk(mci, KERN_DEBUG, "HANDLING MCE MEMORY ERROR\n"); - skx_mc_printk(mci, KERN_DEBUG, "CPU %d: Machine Check %s: %Lx " + skx_mc_printk(mci, KERN_DEBUG, "CPU %d: Machine Check %s: 0x%llx " "Bank %d: %016Lx\n", mce->extcpu, type, mce->mcgstatus, mce->bank, mce->status); - skx_mc_printk(mci, KERN_DEBUG, "TSC %llx ", mce->tsc); - skx_mc_printk(mci, KERN_DEBUG, "ADDR %llx ", mce->addr); - skx_mc_printk(mci, KERN_DEBUG, "MISC %llx ", mce->misc); + skx_mc_printk(mci, KERN_DEBUG, "TSC 0x%llx ", mce->tsc); + skx_mc_printk(mci, KERN_DEBUG, "ADDR 0x%llx ", mce->addr); + skx_mc_printk(mci, KERN_DEBUG, "MISC 0x%llx ", mce->misc); - skx_mc_printk(mci, KERN_DEBUG, "PROCESSOR %u:%x TIME %llu SOCKET " - "%u APIC %x\n", mce->cpuvendor, mce->cpuid, + skx_mc_printk(mci, KERN_DEBUG, "PROCESSOR %u:0x%x TIME %llu SOCKET " + "%u APIC 0x%x\n", mce->cpuvendor, mce->cpuid, mce->time, mce->socketid, mce->apicid); skx_mce_output_error(mci, mce, &res); @@ -1291,7 +1291,7 @@ static int __init skx_init(void) if (rc < 0) goto fail; if (rc != m->per_socket * skx_num_sockets) { - edac_dbg(2, "Expected %d, got %d of %x\n", + edac_dbg(2, "Expected %d, got %d of 0x%x\n", m->per_socket * skx_num_sockets, rc, m->did); rc = -ENODEV; goto fail; -- cgit v1.2.3-59-g8ed1b From 85b9c8bfee67ed151c44861c71adc816fc1b46a9 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Fri, 16 Nov 2018 15:34:44 +0800 Subject: EDAC, skx: Move debugfs node under EDAC's hierarchy The debugfs node is /sys/kernel/debug/skx_edac_test. Rename it and move under EDAC debugfs root directory. Remove the unused 'skx_fake_addr' and remove the 'skx_test' on error. Co-developed-by: Tony Luck Signed-off-by: Qiuxu Zhuo Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: arozansk@redhat.com CC: linux-edac Link: http://lkml.kernel.org/r/1542353684-13496-1-git-send-email-qiuxu.zhuo@intel.com --- drivers/edac/skx_edac.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index d8869f05c596..6d38701c1b2e 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -923,12 +923,11 @@ static bool skx_decode(struct decoded_addr *res) #ifdef CONFIG_EDAC_DEBUG /* - * Debug feature. Make /sys/kernel/debug/skx_edac_test/addr. - * Write an address to this file to exercise the address decode - * logic in this driver. + * Debug feature. + * Exercise the address decode logic by writing an address to + * /sys/kernel/debug/edac/skx_test/addr. */ static struct dentry *skx_test; -static u64 skx_fake_addr; static int debugfs_u64_set(void *data, u64 val) { @@ -939,19 +938,19 @@ static int debugfs_u64_set(void *data, u64 val) return 0; } - DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); -static struct dentry *mydebugfs_create(const char *name, umode_t mode, - struct dentry *parent, u64 *value) -{ - return debugfs_create_file(name, mode, parent, value, &fops_u64_wo); -} - static void setup_skx_debug(void) { - skx_test = debugfs_create_dir("skx_edac_test", NULL); - mydebugfs_create("addr", S_IWUSR, skx_test, &skx_fake_addr); + skx_test = edac_debugfs_create_dir("skx_test"); + if (!skx_test) + return; + + if (!edac_debugfs_create_file("addr", 0200, skx_test, + NULL, &fops_u64_wo)) { + debugfs_remove(skx_test); + skx_test = NULL; + } } static void teardown_skx_debug(void) -- cgit v1.2.3-59-g8ed1b From fa1c071c1efb28baef2409e28c186d40c76d7839 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Fri, 16 Nov 2018 15:35:05 +0800 Subject: EDAC, skx: Let EDAC core show the decoded result for debugfs Current debugfs shows the decoded result in its own print format which is inconvenient for analysis/statistics. Use skx_mce_check_error() instead of skx_decode() for debugfs, then the decoded result is showed via EDAC core in a more readable format like "CPU_SrcID#[0-9]_MC#[0-9]_Chan#[0-9]_DIMM#[0-9]". Print a warning the first time this interface is used so the administrator can see the console log that error(s) have been faked. Co-developed-by: Tony Luck Signed-off-by: Qiuxu Zhuo Signed-off-by: Borislav Petkov CC: Mauro Carvalho Chehab CC: arozansk@redhat.com CC: linux-edac Link: http://lkml.kernel.org/r/1542353705-13531-1-git-send-email-qiuxu.zhuo@intel.com --- drivers/edac/skx_edac.c | 94 +++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index 6d38701c1b2e..93ef161bb5e1 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c @@ -921,52 +921,6 @@ static bool skx_decode(struct decoded_addr *res) skx_rir_decode(res) && skx_mad_decode(res); } -#ifdef CONFIG_EDAC_DEBUG -/* - * Debug feature. - * Exercise the address decode logic by writing an address to - * /sys/kernel/debug/edac/skx_test/addr. - */ -static struct dentry *skx_test; - -static int debugfs_u64_set(void *data, u64 val) -{ - struct decoded_addr res; - - res.addr = val; - skx_decode(&res); - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); - -static void setup_skx_debug(void) -{ - skx_test = edac_debugfs_create_dir("skx_test"); - if (!skx_test) - return; - - if (!edac_debugfs_create_file("addr", 0200, skx_test, - NULL, &fops_u64_wo)) { - debugfs_remove(skx_test); - skx_test = NULL; - } -} - -static void teardown_skx_debug(void) -{ - debugfs_remove_recursive(skx_test); -} -#else -static void setup_skx_debug(void) -{ -} - -static void teardown_skx_debug(void) -{ -} -#endif /*CONFIG_EDAC_DEBUG*/ - static bool skx_adxl_decode(struct decoded_addr *res) { @@ -1171,6 +1125,54 @@ static struct notifier_block skx_mce_dec = { .priority = MCE_PRIO_EDAC, }; +#ifdef CONFIG_EDAC_DEBUG +/* + * Debug feature. + * Exercise the address decode logic by writing an address to + * /sys/kernel/debug/edac/skx_test/addr. + */ +static struct dentry *skx_test; + +static int debugfs_u64_set(void *data, u64 val) +{ + struct mce m; + + pr_warn_once("Fake error to 0x%llx injected via debugfs\n", val); + + memset(&m, 0, sizeof(m)); + /* ADDRV + MemRd + Unknown channel */ + m.status = MCI_STATUS_ADDRV + 0x90; + /* One corrected error */ + m.status |= BIT_ULL(MCI_STATUS_CEC_SHIFT); + m.addr = val; + skx_mce_check_error(NULL, 0, &m); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); + +static void setup_skx_debug(void) +{ + skx_test = edac_debugfs_create_dir("skx_test"); + if (!skx_test) + return; + + if (!edac_debugfs_create_file("addr", 0200, skx_test, + NULL, &fops_u64_wo)) { + debugfs_remove(skx_test); + skx_test = NULL; + } +} + +static void teardown_skx_debug(void) +{ + debugfs_remove_recursive(skx_test); +} +#else +static void setup_skx_debug(void) {} +static void teardown_skx_debug(void) {} +#endif /*CONFIG_EDAC_DEBUG*/ + static void skx_remove(void) { int i, j; -- cgit v1.2.3-59-g8ed1b From a59817fa8f4d299c46c94842bd2acb2aeff67d88 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 19 Nov 2018 22:53:40 +0000 Subject: EDAC, fsl: Move error injection under CONFIG_EDAC_DEBUG Gate error injection feature with CONFIG_EDAC_DEBUG so that it is not visible in production setups. Suggested-by: Borislav Petkov Signed-off-by: York Sun Signed-off-by: Borislav Petkov Cc: linux-edac Link: https://lkml.kernel.org/r/20181119225303.13265-1-york.sun@nxp.com --- drivers/edac/fsl_ddr_edac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c index efc8276d1d9c..27826d38b4b7 100644 --- a/drivers/edac/fsl_ddr_edac.c +++ b/drivers/edac/fsl_ddr_edac.c @@ -51,6 +51,7 @@ static inline void ddr_out32(void __iomem *addr, u32 value) iowrite32be(value, addr); } +#ifdef CONFIG_EDAC_DEBUG /************************ MC SYSFS parts ***********************************/ #define to_mci(k) container_of(k, struct mem_ctl_info, dev) @@ -151,11 +152,14 @@ static DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR, fsl_mc_inject_data_lo_show, fsl_mc_inject_data_lo_store); static DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR, fsl_mc_inject_ctrl_show, fsl_mc_inject_ctrl_store); +#endif /* CONFIG_EDAC_DEBUG */ static struct attribute *fsl_ddr_dev_attrs[] = { +#ifdef CONFIG_EDAC_DEBUG &dev_attr_inject_data_hi.attr, &dev_attr_inject_data_lo.attr, &dev_attr_inject_ctrl.attr, +#endif NULL }; -- cgit v1.2.3-59-g8ed1b From 37d964f9147ac629f416fd813ed7dc093a2d8969 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 20 Nov 2018 16:33:04 +0100 Subject: EDAC, i82975x: Fix spelling mistake "reserverd" -> "reserved" Fix a spelling mistake in a register layout description. Signed-off-by: Alexandre Belloni Signed-off-by: Borislav Petkov Cc: "Arvind R." Cc: linux-edac Link: https://lkml.kernel.org/r/20181120153304.1218-1-alexandre.belloni@bootlin.com --- drivers/edac/i82975x_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index ce1d6abfc6af..7c6a2d4d2360 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -104,7 +104,7 @@ NOTE: Only ONE of the three must be enabled * * 31:14 Base Addr of 16K memory-mapped * configuration space - * 13:1 reserverd + * 13:1 reserved * 0 mem-mapped config space enable */ -- cgit v1.2.3-59-g8ed1b From bd44735418221e15b45102c31f0bc00046194f35 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 11 Dec 2018 17:52:07 +0800 Subject: EDAC, i5000: Remove set but not used local variables Remove unused local variables as reported by gcc's -Wunused-but-set-variable option. [ bp: simplify commit message. ] Signed-off-by: YueHaibing Signed-off-by: Borislav Petkov Cc: Mauro Carvalho Chehab Cc: linux-edac Link: https://lkml.kernel.org/r/20181211095207.25936-1-yuehaibing@huawei.com --- drivers/edac/i5000_edac.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 98bef13e3134..078a7351bf05 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1134,8 +1134,6 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) u32 actual_tolm; u16 limit; int slot_row; - int maxch; - int maxdimmperch; int way0, way1; pvt = mci->pvt_info; @@ -1145,9 +1143,6 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32), &pvt->u.ambase_top); - maxdimmperch = pvt->maxdimmperch; - maxch = pvt->maxch; - edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); @@ -1253,7 +1248,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) { struct i5000_pvt *pvt; struct dimm_info *dimm; - int empty, channel_count; + int empty; int max_csrows; int mtr; int csrow_megs; @@ -1261,8 +1256,6 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) int slot; pvt = mci->pvt_info; - - channel_count = pvt->maxch; max_csrows = pvt->maxdimmperch * 2; empty = 1; /* Assume NO memory */ -- cgit v1.2.3-59-g8ed1b From 75dfa87035f9a2659dd0c48af6b4d9899e79cdc9 Mon Sep 17 00:00:00 2001 From: Patrick Havelange Date: Wed, 19 Dec 2018 11:43:23 +0100 Subject: EDAC, fsl_ddr: Add LS1021A to the list of supported hardware The Freescale ddr driver also works on the LS1021A board. Signed-off-by: Patrick Havelange Signed-off-by: Borislav Petkov Cc: Mauro Carvalho Chehab Cc: York Sun Cc: arnout.vandecappelle@essensium.com Cc: linux-edac Cc: matthew.weber@rockwellcollins.com Cc: patrick.havelange@essensium.com Link: https://lkml.kernel.org/r/20181219104323.10324-1-patrick.havelange@essensium.com --- drivers/edac/fsl_ddr_edac.c | 4 ++-- drivers/edac/fsl_ddr_edac.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c index 27826d38b4b7..6d8ea226010d 100644 --- a/drivers/edac/fsl_ddr_edac.c +++ b/drivers/edac/fsl_ddr_edac.c @@ -2,8 +2,8 @@ * Freescale Memory Controller kernel module * * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and - * ARM-based Layerscape SoCs including LS2xxx. Originally split - * out from mpc85xx_edac EDAC driver. + * ARM-based Layerscape SoCs including LS2xxx and LS1021A. Originally + * split out from mpc85xx_edac EDAC driver. * * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc. * diff --git a/drivers/edac/fsl_ddr_edac.h b/drivers/edac/fsl_ddr_edac.h index 4ccee292eff1..589b9b4a5e8a 100644 --- a/drivers/edac/fsl_ddr_edac.h +++ b/drivers/edac/fsl_ddr_edac.h @@ -2,8 +2,8 @@ * Freescale Memory Controller kernel module * * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and - * ARM-based Layerscape SoCs including LS2xxx. Originally split - * out from mpc85xx_edac EDAC driver. + * ARM-based Layerscape SoCs including LS2xxx and LS1021A. Originally + * split out from mpc85xx_edac EDAC driver. * * Author: Dave Jiang * -- cgit v1.2.3-59-g8ed1b