[PATCH v4 3/4] edac: Add L3/SoC EDAC support to the APM X-Gene SoC EDAC driver

Borislav Petkov bp at alien8.de
Tue Sep 22 09:40:47 PDT 2015


On Fri, Aug 14, 2015 at 12:46:08AM -0600, Loc Ho wrote:
> This patch adds EDAC support for the L3 and SoC components.
> 
> Signed-off-by: Loc Ho <lho at apm.com>
> ---
>  drivers/edac/xgene_edac.c | 1169 +++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 975 insertions(+), 194 deletions(-)

...

> +/* L3 Error device */
> +#define L3C_ESR				(0x0A * 4)
> +#define  L3C_ESR_DATATAG_MASK		BIT(9)
> +#define  L3C_ESR_MULTIHIT_MASK		BIT(8)
> +#define  L3C_ESR_UCEVICT_MASK		BIT(6)
> +#define  L3C_ESR_MULTIUCERR_MASK	BIT(5)
> +#define  L3C_ESR_MULTICERR_MASK		BIT(4)
> +#define  L3C_ESR_UCERR_MASK		BIT(3)
> +#define  L3C_ESR_CERR_MASK		BIT(2)
> +#define  L3C_ESR_UCERRINTR_MASK		BIT(1)
> +#define  L3C_ESR_CERRINTR_MASK		BIT(0)
> +#define L3C_ECR				(0x0B * 4)
> +#define  L3C_ECR_UCINTREN		BIT(3)
> +#define  L3C_ECR_CINTREN		BIT(2)
> +#define  L3C_UCERREN			BIT(1)
> +#define  L3C_CERREN			BIT(0)
> +#define L3C_ELR				(0x0C * 4)
> +#define  L3C_ELR_ERRSYN(src)		((src & 0xFF800000) >> 23)
> +#define  L3C_ELR_ERRWAY(src)		((src & 0x007E0000) >> 17)
> +#define  L3C_ELR_AGENTID(src)		((src & 0x0001E000) >> 13)
> +#define  L3C_ELR_ERRGRP(src)		((src & 0x00000F00) >> 8)
> +#define  L3C_ELR_OPTYPE(src)		((src & 0x000000F0) >> 4)
> +#define  L3C_ELR_PADDRHIGH(src)		(src & 0x0000000F)
> +#define L3C_AELR			(0x0D * 4)
> +#define L3C_BELR			(0x0E * 4)
> +#define  L3C_BELR_BANK(src)		(src & 0x0000000F)
> +
> +struct xgene_edac_dev_ctx {
> +	struct list_head	next;
> +	struct device		ddev;
> +	char			*name;
> +	struct xgene_edac	*edac;
> +	struct edac_device_ctl_info *edac_dev;
> +	int			edac_idx;
> +	void __iomem		*dev_csr;
> +	int			version;
> +};
> +

Put the comment ontop of the function. Also, I'd fixup the comment like this:

/*
 * Version 1 of the L3 controller has broken single bit correctable logic for
 * certain error syndromes. Log them as uncorrectable in that case.
 */

and then you can drop the comment in the function itself and at the call site.

> +static bool xgene_edac_l3_v1_errata_chk(u32 l3cesr, u32 l3celr)

This function name should be something like:

should_promote_error_to_uc()

or so because it is what it does.

> +{
> +	/*
> +	 * L3 version 1 has certain conditions in which correctable error
> +	 * needs to be flagged as un-correctable error. This function
> +	 * check for such conditions.
> +	 */
> +	if (l3cesr & L3C_ESR_DATATAG_MASK) {
> +		switch (L3C_ELR_ERRSYN(l3celr)) {
> +		case 0x13C:
> +		case 0x0B4:
> +		case 0x007:
> +		case 0x00D:
> +		case 0x00E:
> +		case 0x019:
> +		case 0x01A:
> +		case 0x01C:
> +		case 0x04E:
> +		case 0x041:
> +			return true;
> +		}
> +	} else if (L3C_ELR_ERRSYN(l3celr) == 9) {
> +		return true;
> +	}

No need for {} around a single statement.

...

> +static ssize_t xgene_edac_l3_inject_ctrl_write(struct file *file,
> +					       const char __user *data,
> +					       size_t count, loff_t *ppos)
> +{
> +	struct edac_device_ctl_info *edac_dev = file->private_data;
> +	struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
> +
> +	/* Generate all errors */
> +	writel(0xFFFFFFFF, ctx->dev_csr + L3C_ESR);
> +	return count;
> +}
> +
> +static const struct file_operations xgene_edac_l3_debug_inject_fops = {
> +	.open = simple_open,
> +	.write = xgene_edac_l3_inject_ctrl_write,
> +	.llseek = generic_file_llseek
> +};
> +
> +static void xgene_edac_l3_create_debugfs_nodes(
> +	struct edac_device_ctl_info *edac_dev)
> +{

This way of formatting the function name should be more readable:

static void
xgene_edac_l3_create_debugfs_nodes(struct edac_device_ctl_info *edac_dev)
{

> +	struct xgene_edac_dev_ctx *ctx = edac_dev->pvt_info;
> +	struct dentry *edac_debugfs;
> +	char name[30];

That's a 30-chars array on the stack ...

> +
> +	if (!ctx->edac->dfs)
> +		return;
> +	sprintf(name, "l3c%d", ctx->edac_idx);

... but you're not clearing or NULL-terminating the rest of it here,
should the string be smaller.

> +	edac_debugfs = debugfs_create_dir(name, ctx->edac->dfs);
> +	if (!edac_debugfs)
> +		return;
> +
> +	debugfs_create_file("l3_inject_ctrl", S_IWUSR, edac_debugfs, edac_dev,
> +			    &xgene_edac_l3_debug_inject_fops);
> +}
> +
> +static int xgene_edac_l3_add(struct xgene_edac *edac, struct device_node *np,
> +			     int version)
> +{
> +	struct edac_device_ctl_info *edac_dev;
> +	struct xgene_edac_dev_ctx *ctx;
> +	struct resource res;
> +	void __iomem *dev_csr;
> +	int edac_idx;
> +	int rc = 0;
> +
> +	if (!devres_open_group(edac->dev, xgene_edac_l3_add, GFP_KERNEL))
> +		return -ENOMEM;
> +
> +	rc = of_address_to_resource(np, 0, &res);
> +	if (rc < 0) {
> +		dev_err(edac->dev, "no L3 resource address\n");
> +		goto err_release_group;
> +	}
> +	dev_csr = devm_ioremap_resource(edac->dev, &res);
> +	if (IS_ERR(dev_csr)) {
> +		dev_err(edac->dev,
> +			"devm_ioremap_resource failed for L3 resource address\n");
> +		rc = PTR_ERR(dev_csr);
> +		goto err_release_group;
> +	}
> +
> +	edac_idx = edac_device_alloc_index();
> +	edac_dev = edac_device_alloc_ctl_info(sizeof(*ctx),
> +					      "l3c", 1, "l3c", 1, 0, NULL, 0,
> +					      edac_idx);
> +	if (!edac_dev) {
> +		rc = -ENOMEM;
> +		goto err_release_group;
> +	}
> +
> +	ctx = edac_dev->pvt_info;
> +	ctx->dev_csr = dev_csr;
> +	ctx->name = "xgene_l3_err";
> +	ctx->edac_idx = edac_idx;
> +	ctx->edac = edac;
> +	ctx->edac_dev = edac_dev;
> +	ctx->ddev = *edac->dev;
> +	ctx->version = version;
> +	edac_dev->dev = &ctx->ddev;
> +	edac_dev->ctl_name = ctx->name;
> +	edac_dev->dev_name = ctx->name;
> +	edac_dev->mod_name = EDAC_MOD_STR;
> +
> +	if (edac_op_state == EDAC_OPSTATE_POLL)
> +		edac_dev->edac_check = xgene_edac_l3_check;
> +
> +	xgene_edac_l3_create_debugfs_nodes(edac_dev);
> +
> +	rc = edac_device_add_device(edac_dev);
> +	if (rc > 0) {
> +		dev_err(edac->dev, "failed edac_device_add_device()\n");
> +		rc = -ENOMEM;
> +		goto err_ctl_free;
> +	}
> +
> +	if (edac_op_state == EDAC_OPSTATE_INT)
> +		edac_dev->op_state = OP_RUNNING_INTERRUPT;
> +
> +	list_add(&ctx->next, &edac->l3s);
> +
> +	xgene_edac_l3_hw_init(edac_dev, 1);
> +
> +	devres_remove_group(edac->dev, xgene_edac_l3_add);
> +
> +	dev_info(edac->dev, "X-Gene EDAC L3 registered\n");
> +	return 0;
> +
> +err_ctl_free:
> +	edac_device_free_ctl_info(edac_dev);
> +err_release_group:
> +	devres_release_group(edac->dev, xgene_edac_l3_add);
> +	return rc;
> +}
> +
> +static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3)
> +{
> +	struct edac_device_ctl_info *edac_dev = l3->edac_dev;
> +
> +	xgene_edac_l3_hw_init(edac_dev, 0);
> +	edac_device_del_device(l3->edac->dev);
> +	edac_device_free_ctl_info(edac_dev);
> +	return 0;
> +}

This is a natural point to stop. The rest should be in a separate patch
called something like "EDAC, xgene: Add SoC support...".

> +
> +/* SoC Error device */
> +#define IOBAXIS0TRANSERRINTSTS		0x0000
> +#define  IOBAXIS0_M_ILLEGAL_ACCESS_MASK	BIT(1)
> +#define  IOBAXIS0_ILLEGAL_ACCESS_MASK	BIT(0)
> +#define IOBAXIS0TRANSERRINTMSK		0x0004
> +#define IOBAXIS0TRANSERRREQINFOL	0x0008
> +#define IOBAXIS0TRANSERRREQINFOH	0x000c
> +#define  REQTYPE_RD(src)		(((src) & BIT(0)))
> +#define  ERRADDRH_RD(src)		(((src) & 0xffc00000) >> 22)
> +#define IOBAXIS1TRANSERRINTSTS		0x0010
> +#define IOBAXIS1TRANSERRINTMSK		0x0014
> +#define IOBAXIS1TRANSERRREQINFOL	0x0018
> +#define IOBAXIS1TRANSERRREQINFOH	0x001c
> +#define IOBPATRANSERRINTSTS		0x0020

...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.



More information about the linux-arm-kernel mailing list