Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c4cdb5a authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: convert it to use struct device



Instead of relying on a complex logic inside the edac core to create
a "device tree-like" sysfs struct, just use device_add.

Reviewed-by: default avatarAristeu Rozanski <arozansk@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c5608759
Loading
Loading
Loading
Loading
+209 −129
Original line number Diff line number Diff line
@@ -248,6 +248,8 @@ struct i7core_dev {
};

struct i7core_pvt {
	struct device addrmatch_dev, chancounts_dev;

	struct pci_dev	*pci_noncore;
	struct pci_dev	*pci_mcr[MAX_MCR_FUNC + 1];
	struct pci_dev	*pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
@@ -662,6 +664,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
			Error insertion routines
 ****************************************************************************/

#define to_mci(k) container_of(k, struct mem_ctl_info, dev)

/* The i7core has independent error injection features per channel.
   However, to have a simpler code, we don't allow enabling error injection
   on more than one channel.
@@ -691,9 +695,11 @@ static int disable_inject(const struct mem_ctl_info *mci)
 *	bit 0 - refers to the lower 32-byte half cacheline
 *	bit 1 - refers to the upper 32-byte half cacheline
 */
static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
static ssize_t i7core_inject_section_store(struct device *dev,
					   struct device_attribute *mattr,
					   const char *data, size_t count)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;
	unsigned long value;
	int rc;
@@ -709,9 +715,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
	return count;
}

static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
static ssize_t i7core_inject_section_show(struct device *dev,
					  struct device_attribute *mattr,
					  char *data)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;
	return sprintf(data, "0x%08x\n", pvt->inject.section);
}
@@ -724,9 +732,11 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
 *	bit 1 - inject ECC error
 *	bit 2 - inject parity error
 */
static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
static ssize_t i7core_inject_type_store(struct device *dev,
					struct device_attribute *mattr,
					const char *data, size_t count)
{
	struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info;
	unsigned long value;
	int rc;
@@ -742,10 +752,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
	return count;
}

static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
static ssize_t i7core_inject_type_show(struct device *dev,
				       struct device_attribute *mattr,
				       char *data)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;

	return sprintf(data, "0x%08x\n", pvt->inject.type);
}

@@ -759,9 +772,11 @@ static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
 *   23:16 and 31:24). Flipping bits in two symbol pairs will cause an
 *   uncorrectable error to be injected.
 */
static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
static ssize_t i7core_inject_eccmask_store(struct device *dev,
					   struct device_attribute *mattr,
					   const char *data, size_t count)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;
	unsigned long value;
	int rc;
@@ -777,10 +792,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
	return count;
}

static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
static ssize_t i7core_inject_eccmask_show(struct device *dev,
					  struct device_attribute *mattr,
					  char *data)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;

	return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
}

@@ -797,9 +815,11 @@ static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,

#define DECLARE_ADDR_MATCH(param, limit)			\
static ssize_t i7core_inject_store_##param(			\
		struct mem_ctl_info *mci,			\
	struct device *dev,					\
	struct device_attribute *mattr,				\
	const char *data, size_t count)				\
{								\
	struct mem_ctl_info *mci = to_mci(dev);			\
	struct i7core_pvt *pvt;					\
	long value;						\
	int rc;							\
@@ -824,9 +844,11 @@ static ssize_t i7core_inject_store_##param( \
}								\
								\
static ssize_t i7core_inject_show_##param(			\
		struct mem_ctl_info *mci,			\
	struct device *dev,					\
	struct device_attribute *mattr,				\
	char *data)						\
{								\
	struct mem_ctl_info *mci = to_mci(dev);			\
	struct i7core_pvt *pvt;					\
								\
	pvt = mci->pvt_info;					\
@@ -838,14 +860,9 @@ static ssize_t i7core_inject_show_##param( \
}

#define ATTR_ADDR_MATCH(param)					\
	{							\
		.attr = {					\
			.name = #param,				\
			.mode = (S_IRUGO | S_IWUSR)		\
		},						\
		.show  = i7core_inject_show_##param,		\
		.store = i7core_inject_store_##param,		\
	}
	static DEVICE_ATTR(param, S_IRUGO | S_IWUSR,		\
		    i7core_inject_show_##param,			\
		    i7core_inject_store_##param)

DECLARE_ADDR_MATCH(channel, 3);
DECLARE_ADDR_MATCH(dimm, 3);
@@ -854,6 +871,13 @@ DECLARE_ADDR_MATCH(bank, 32);
DECLARE_ADDR_MATCH(page, 0x10000);
DECLARE_ADDR_MATCH(col, 0x4000);

ATTR_ADDR_MATCH(channel);
ATTR_ADDR_MATCH(dimm);
ATTR_ADDR_MATCH(rank);
ATTR_ADDR_MATCH(bank);
ATTR_ADDR_MATCH(page);
ATTR_ADDR_MATCH(col);

static int write_and_test(struct pci_dev *dev, const int where, const u32 val)
{
	u32 read;
@@ -899,9 +923,11 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val)
 *    is reliable enough to check if the MC is using the
 *    three channels. However, this is not clear at the datasheet.
 */
static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
static ssize_t i7core_inject_enable_store(struct device *dev,
					  struct device_attribute *mattr,
					  const char *data, size_t count)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;
	u32 injectmask;
	u64 mask = 0;
@@ -1002,9 +1028,11 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
	return count;
}

static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
static ssize_t i7core_inject_enable_show(struct device *dev,
					 struct device_attribute *mattr,
					 char *data)
{
	struct mem_ctl_info *mci = to_mci(dev);
	struct i7core_pvt *pvt = mci->pvt_info;
	u32 injectmask;

@@ -1024,9 +1052,11 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,

#define DECLARE_COUNTER(param)					\
static ssize_t i7core_show_counter_##param(			\
		struct mem_ctl_info *mci,			\
	struct device *dev,					\
	struct device_attribute *mattr,				\
	char *data)						\
{								\
	struct mem_ctl_info *mci = to_mci(dev);			\
	struct i7core_pvt *pvt = mci->pvt_info;			\
								\
	debugf1("%s()\n", __func__);				\
@@ -1037,121 +1067,167 @@ static ssize_t i7core_show_counter_##param( \
}

#define ATTR_COUNTER(param)					\
	{							\
		.attr = {					\
			.name = __stringify(udimm##param),	\
			.mode = (S_IRUGO | S_IWUSR)		\
		},						\
		.show  = i7core_show_counter_##param		\
	}
	static DEVICE_ATTR(udimm##param, S_IRUGO | S_IWUSR,	\
		    i7core_show_counter_##param,		\
		    NULL)

DECLARE_COUNTER(0);
DECLARE_COUNTER(1);
DECLARE_COUNTER(2);

ATTR_COUNTER(0);
ATTR_COUNTER(1);
ATTR_COUNTER(2);

/*
 * Sysfs struct
 * inject_addrmatch device sysfs struct
 */

static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
	ATTR_ADDR_MATCH(channel),
	ATTR_ADDR_MATCH(dimm),
	ATTR_ADDR_MATCH(rank),
	ATTR_ADDR_MATCH(bank),
	ATTR_ADDR_MATCH(page),
	ATTR_ADDR_MATCH(col),
	{ } /* End of list */
static struct attribute *i7core_addrmatch_attrs[] = {
	&dev_attr_channel.attr,
	&dev_attr_dimm.attr,
	&dev_attr_rank.attr,
	&dev_attr_bank.attr,
	&dev_attr_page.attr,
	&dev_attr_col.attr,
	NULL
};

static const struct mcidev_sysfs_group i7core_inject_addrmatch = {
	.name  = "inject_addrmatch",
	.mcidev_attr = i7core_addrmatch_attrs,
static struct attribute_group addrmatch_grp = {
	.attrs	= i7core_addrmatch_attrs,
};

static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
	ATTR_COUNTER(0),
	ATTR_COUNTER(1),
	ATTR_COUNTER(2),
	{ .attr = { .name = NULL } }
static const struct attribute_group *addrmatch_groups[] = {
	&addrmatch_grp,
	NULL
};

static const struct mcidev_sysfs_group i7core_udimm_counters = {
	.name  = "all_channel_counts",
	.mcidev_attr = i7core_udimm_counters_attrs,
static void addrmatch_release(struct device *device)
{
	debugf1("Releasing device %s\n", dev_name(device));
}

static struct device_type addrmatch_type = {
	.groups		= addrmatch_groups,
	.release	= addrmatch_release,
};

static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = {
	{
		.attr = {
			.name = "inject_section",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_section_show,
		.store = i7core_inject_section_store,
	}, {
		.attr = {
			.name = "inject_type",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_type_show,
		.store = i7core_inject_type_store,
	}, {
		.attr = {
			.name = "inject_eccmask",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_eccmask_show,
		.store = i7core_inject_eccmask_store,
	}, {
		.grp = &i7core_inject_addrmatch,
	}, {
		.attr = {
			.name = "inject_enable",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_enable_show,
		.store = i7core_inject_enable_store,
	},
	{ }	/* End of list */
/*
 * all_channel_counts sysfs struct
 */

static struct attribute *i7core_udimm_counters_attrs[] = {
	&dev_attr_udimm0.attr,
	&dev_attr_udimm1.attr,
	&dev_attr_udimm2.attr,
	NULL
};

static struct attribute_group all_channel_counts_grp = {
	.attrs	= i7core_udimm_counters_attrs,
};

static const struct attribute_group *all_channel_counts_groups[] = {
	&all_channel_counts_grp,
	NULL
};

static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = {
static void all_channel_counts_release(struct device *device)
{
		.attr = {
			.name = "inject_section",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_section_show,
		.store = i7core_inject_section_store,
	}, {
		.attr = {
			.name = "inject_type",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_type_show,
		.store = i7core_inject_type_store,
	}, {
		.attr = {
			.name = "inject_eccmask",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_eccmask_show,
		.store = i7core_inject_eccmask_store,
	}, {
		.grp = &i7core_inject_addrmatch,
	}, {
		.attr = {
			.name = "inject_enable",
			.mode = (S_IRUGO | S_IWUSR)
		},
		.show  = i7core_inject_enable_show,
		.store = i7core_inject_enable_store,
	}, {
		.grp = &i7core_udimm_counters,
	},
	{ }	/* End of list */
	debugf1("Releasing device %s\n", dev_name(device));
}

static struct device_type all_channel_counts_type = {
	.groups		= all_channel_counts_groups,
	.release	= all_channel_counts_release,
};

/*
 * inject sysfs attributes
 */

static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR,
		   i7core_inject_section_show, i7core_inject_section_store);

static DEVICE_ATTR(inject_type, S_IRUGO | S_IWUSR,
		   i7core_inject_type_show, i7core_inject_type_store);


static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR,
		   i7core_inject_eccmask_show, i7core_inject_eccmask_store);

static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR,
		   i7core_inject_enable_show, i7core_inject_enable_store);

static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
{
	struct i7core_pvt *pvt = mci->pvt_info;
	int rc;

	rc = device_create_file(&mci->dev, &dev_attr_inject_section);
	if (rc < 0)
		return rc;
	rc = device_create_file(&mci->dev, &dev_attr_inject_type);
	if (rc < 0)
		return rc;
	rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask);
	if (rc < 0)
		return rc;
	rc = device_create_file(&mci->dev, &dev_attr_inject_enable);
	if (rc < 0)
		return rc;

	pvt->addrmatch_dev.type = &addrmatch_type;
	pvt->addrmatch_dev.bus = mci->dev.bus;
	device_initialize(&pvt->addrmatch_dev);
	pvt->addrmatch_dev.parent = &mci->dev;
	dev_set_name(&pvt->addrmatch_dev, "inject_addrmatch");
	dev_set_drvdata(&pvt->addrmatch_dev, mci);

	debugf1("%s(): creating %s\n", __func__,
		dev_name(&pvt->addrmatch_dev));

	rc = device_add(&pvt->addrmatch_dev);
	if (rc < 0)
		return rc;

	if (!pvt->is_registered) {
		pvt->chancounts_dev.type = &all_channel_counts_type;
		pvt->chancounts_dev.bus = mci->dev.bus;
		device_initialize(&pvt->chancounts_dev);
		pvt->chancounts_dev.parent = &mci->dev;
		dev_set_name(&pvt->chancounts_dev, "all_channel_counts");
		dev_set_drvdata(&pvt->chancounts_dev, mci);

		debugf1("%s(): creating %s\n", __func__,
			dev_name(&pvt->chancounts_dev));

		rc = device_add(&pvt->chancounts_dev);
		if (rc < 0)
			return rc;
	}
	return 0;
}

static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci)
{
	struct i7core_pvt *pvt = mci->pvt_info;

	debugf1("\n");

	device_remove_file(&mci->dev, &dev_attr_inject_section);
	device_remove_file(&mci->dev, &dev_attr_inject_type);
	device_remove_file(&mci->dev, &dev_attr_inject_eccmask);
	device_remove_file(&mci->dev, &dev_attr_inject_enable);

	if (!pvt->is_registered) {
		put_device(&pvt->chancounts_dev);
		device_del(&pvt->chancounts_dev);
	}
	put_device(&pvt->addrmatch_dev);
	device_del(&pvt->addrmatch_dev);
}

/****************************************************************************
	Device initialization routines: put/get, init/exit
 ****************************************************************************/
@@ -2122,6 +2198,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
	i7core_pci_ctl_release(pvt);

	/* Remove MC sysfs nodes */
	i7core_delete_sysfs_devices(mci);
	edac_mc_del_mc(mci->pdev);

	debugf1("%s: free mci struct\n", mci->ctl_name);
@@ -2180,10 +2257,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
	if (unlikely(rc < 0))
		goto fail0;

	if (pvt->is_registered)
		mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs;
	else
		mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs;

	/* Get dimm basic config */
	get_dimm_config(mci);
@@ -2207,6 +2280,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
		rc = -EINVAL;
		goto fail0;
	}
	if (i7core_create_sysfs_devices(mci)) {
		debugf0("MC: " __FILE__
			": %s(): failed to create sysfs nodes\n", __func__);
		edac_mc_del_mc(mci->pdev);
		rc = -EINVAL;
		goto fail0;
	}

	/* Default error mask is any memory */
	pvt->inject.channel = 0;