drivers/edac/zynqmp_edac.c

Source file repositories/reference/linux-study-clean/drivers/edac/zynqmp_edac.c

File Facts

System
Linux kernel
Corpus path
drivers/edac/zynqmp_edac.c
Extension
.c
Size
12188 bytes
Lines
466
Domain
Driver Families
Bucket
drivers/edac
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations inject_ce_fops = {
	.open = simple_open,
	.write = inject_ce_write,
	.llseek = generic_file_llseek,
};

/*
 * To get the Uncorrectable Error injected, the following steps are needed:
 * - Setup the optional Fault Injection Count:
 *      echo <fault_count val> > /sys/kernel/debug/edac/ocm/inject_fault_count
 * - Write the Uncorrectable Error bit position values:
 *      echo <bit_pos0 val>,<bit_pos1 val> > /sys/kernel/debug/edac/ocm/inject_ue_bitpos
 */
static ssize_t inject_ue_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 edac_priv *priv = edac_dev->pvt_info;
	char buf[6], *pbuf, *token[2];
	u64 ue_bitpos;
	int i, ret;
	u8 len;

	if (!data)
		return -EFAULT;

	len = min_t(size_t, count, sizeof(buf));
	if (copy_from_user(buf, data, len))
		return -EFAULT;

	buf[len] = '\0';
	pbuf = &buf[0];
	for (i = 0; i < OCM_NUM_UE_BITPOS; i++)
		token[i] = strsep(&pbuf, ",");

	ret = kstrtou8(token[0], 0, &priv->ue_bitpos[0]);
	if (ret)
		return ret;

	ret = kstrtou8(token[1], 0, &priv->ue_bitpos[1]);
	if (ret)
		return ret;

	if (priv->ue_bitpos[0] > UE_MAX_BITPOS_UPPER ||
	    priv->ue_bitpos[1] > UE_MAX_BITPOS_UPPER)
		return -EINVAL;

	if (priv->ue_bitpos[0] == priv->ue_bitpos[1]) {
		edac_printk(KERN_ERR, EDAC_DEVICE, "Bit positions should not be equal\n");
		return -EINVAL;
	}

	ue_bitpos = BIT(priv->ue_bitpos[0]) | BIT(priv->ue_bitpos[1]);

	writel((u32)ue_bitpos, priv->baseaddr + OCM_FID0_OFST);
	writel((u32)(ue_bitpos >> 32), priv->baseaddr + OCM_FID1_OFST);

	write_fault_count(priv);

	return count;
}

static const struct file_operations inject_ue_fops = {
	.open = simple_open,
	.write = inject_ue_write,
	.llseek = generic_file_llseek,
};

static void setup_debugfs(struct edac_device_ctl_info *edac_dev)
{
	struct edac_priv *priv = edac_dev->pvt_info;

	priv->debugfs_dir = edac_debugfs_create_dir("ocm");
	if (!priv->debugfs_dir)
		return;

	edac_debugfs_create_x32("inject_fault_count", 0644, priv->debugfs_dir,
				&priv->fault_injection_cnt);
	edac_debugfs_create_file("inject_ue_bitpos", 0644, priv->debugfs_dir,
				 edac_dev, &inject_ue_fops);
	edac_debugfs_create_file("inject_ce_bitpos", 0644, priv->debugfs_dir,
				 edac_dev, &inject_ce_fops);
}
#endif

static int edac_probe(struct platform_device *pdev)
{
	struct edac_device_ctl_info *dci;
	struct edac_priv *priv;
	void __iomem *baseaddr;

Annotation

Implementation Notes