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

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
...@@ -248,6 +248,8 @@ struct i7core_dev { ...@@ -248,6 +248,8 @@ struct i7core_dev {
}; };
struct i7core_pvt { struct i7core_pvt {
struct device addrmatch_dev, chancounts_dev;
struct pci_dev *pci_noncore; struct pci_dev *pci_noncore;
struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1];
struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_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) ...@@ -662,6 +664,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
Error insertion routines Error insertion routines
****************************************************************************/ ****************************************************************************/
#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
/* The i7core has independent error injection features per channel. /* The i7core has independent error injection features per channel.
However, to have a simpler code, we don't allow enabling error injection However, to have a simpler code, we don't allow enabling error injection
on more than one channel. on more than one channel.
...@@ -691,9 +695,11 @@ static int disable_inject(const struct mem_ctl_info *mci) ...@@ -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 0 - refers to the lower 32-byte half cacheline
* bit 1 - refers to the upper 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) 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; unsigned long value;
int rc; int rc;
...@@ -709,9 +715,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, ...@@ -709,9 +715,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
return count; return count;
} }
static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, static ssize_t i7core_inject_section_show(struct device *dev,
char *data) struct device_attribute *mattr,
char *data)
{ {
struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info; struct i7core_pvt *pvt = mci->pvt_info;
return sprintf(data, "0x%08x\n", pvt->inject.section); return sprintf(data, "0x%08x\n", pvt->inject.section);
} }
...@@ -724,10 +732,12 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, ...@@ -724,10 +732,12 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
* bit 1 - inject ECC error * bit 1 - inject ECC error
* bit 2 - inject parity 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) const char *data, size_t count)
{ {
struct i7core_pvt *pvt = mci->pvt_info; struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info;
unsigned long value; unsigned long value;
int rc; int rc;
...@@ -742,10 +752,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, ...@@ -742,10 +752,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
return count; return count;
} }
static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, static ssize_t i7core_inject_type_show(struct device *dev,
char *data) struct device_attribute *mattr,
char *data)
{ {
struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info; struct i7core_pvt *pvt = mci->pvt_info;
return sprintf(data, "0x%08x\n", pvt->inject.type); 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, ...@@ -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 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
* uncorrectable error to be injected. * 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,
const char *data, size_t count) 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; struct i7core_pvt *pvt = mci->pvt_info;
unsigned long value; unsigned long value;
int rc; int rc;
...@@ -777,10 +792,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, ...@@ -777,10 +792,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
return count; return count;
} }
static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, static ssize_t i7core_inject_eccmask_show(struct device *dev,
char *data) struct device_attribute *mattr,
char *data)
{ {
struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info; struct i7core_pvt *pvt = mci->pvt_info;
return sprintf(data, "0x%08x\n", pvt->inject.eccmask); 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, ...@@ -797,9 +815,11 @@ static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
#define DECLARE_ADDR_MATCH(param, limit) \ #define DECLARE_ADDR_MATCH(param, limit) \
static ssize_t i7core_inject_store_##param( \ static ssize_t i7core_inject_store_##param( \
struct mem_ctl_info *mci, \ struct device *dev, \
const char *data, size_t count) \ struct device_attribute *mattr, \
const char *data, size_t count) \
{ \ { \
struct mem_ctl_info *mci = to_mci(dev); \
struct i7core_pvt *pvt; \ struct i7core_pvt *pvt; \
long value; \ long value; \
int rc; \ int rc; \
...@@ -824,9 +844,11 @@ static ssize_t i7core_inject_store_##param( \ ...@@ -824,9 +844,11 @@ static ssize_t i7core_inject_store_##param( \
} \ } \
\ \
static ssize_t i7core_inject_show_##param( \ static ssize_t i7core_inject_show_##param( \
struct mem_ctl_info *mci, \ struct device *dev, \
char *data) \ struct device_attribute *mattr, \
char *data) \
{ \ { \
struct mem_ctl_info *mci = to_mci(dev); \
struct i7core_pvt *pvt; \ struct i7core_pvt *pvt; \
\ \
pvt = mci->pvt_info; \ pvt = mci->pvt_info; \
...@@ -838,14 +860,9 @@ static ssize_t i7core_inject_show_##param( \ ...@@ -838,14 +860,9 @@ static ssize_t i7core_inject_show_##param( \
} }
#define ATTR_ADDR_MATCH(param) \ #define ATTR_ADDR_MATCH(param) \
{ \ static DEVICE_ATTR(param, S_IRUGO | S_IWUSR, \
.attr = { \ i7core_inject_show_##param, \
.name = #param, \ i7core_inject_store_##param)
.mode = (S_IRUGO | S_IWUSR) \
}, \
.show = i7core_inject_show_##param, \
.store = i7core_inject_store_##param, \
}
DECLARE_ADDR_MATCH(channel, 3); DECLARE_ADDR_MATCH(channel, 3);
DECLARE_ADDR_MATCH(dimm, 3); DECLARE_ADDR_MATCH(dimm, 3);
...@@ -854,6 +871,13 @@ DECLARE_ADDR_MATCH(bank, 32); ...@@ -854,6 +871,13 @@ DECLARE_ADDR_MATCH(bank, 32);
DECLARE_ADDR_MATCH(page, 0x10000); DECLARE_ADDR_MATCH(page, 0x10000);
DECLARE_ADDR_MATCH(col, 0x4000); 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) static int write_and_test(struct pci_dev *dev, const int where, const u32 val)
{ {
u32 read; u32 read;
...@@ -899,9 +923,11 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val) ...@@ -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 * is reliable enough to check if the MC is using the
* three channels. However, this is not clear at the datasheet. * 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,
const char *data, size_t count) 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; struct i7core_pvt *pvt = mci->pvt_info;
u32 injectmask; u32 injectmask;
u64 mask = 0; u64 mask = 0;
...@@ -1002,9 +1028,11 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, ...@@ -1002,9 +1028,11 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
return count; return count;
} }
static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, static ssize_t i7core_inject_enable_show(struct device *dev,
char *data) struct device_attribute *mattr,
char *data)
{ {
struct mem_ctl_info *mci = to_mci(dev);
struct i7core_pvt *pvt = mci->pvt_info; struct i7core_pvt *pvt = mci->pvt_info;
u32 injectmask; u32 injectmask;
...@@ -1024,12 +1052,14 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, ...@@ -1024,12 +1052,14 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
#define DECLARE_COUNTER(param) \ #define DECLARE_COUNTER(param) \
static ssize_t i7core_show_counter_##param( \ static ssize_t i7core_show_counter_##param( \
struct mem_ctl_info *mci, \ struct device *dev, \
char *data) \ struct device_attribute *mattr, \
char *data) \
{ \ { \
struct mem_ctl_info *mci = to_mci(dev); \
struct i7core_pvt *pvt = mci->pvt_info; \ struct i7core_pvt *pvt = mci->pvt_info; \
\ \
debugf1("%s() \n", __func__); \ debugf1("%s()\n", __func__); \
if (!pvt->ce_count_available || (pvt->is_registered)) \ if (!pvt->ce_count_available || (pvt->is_registered)) \
return sprintf(data, "data unavailable\n"); \ return sprintf(data, "data unavailable\n"); \
return sprintf(data, "%lu\n", \ return sprintf(data, "%lu\n", \
...@@ -1037,121 +1067,167 @@ static ssize_t i7core_show_counter_##param( \ ...@@ -1037,121 +1067,167 @@ static ssize_t i7core_show_counter_##param( \
} }
#define ATTR_COUNTER(param) \ #define ATTR_COUNTER(param) \
{ \ static DEVICE_ATTR(udimm##param, S_IRUGO | S_IWUSR, \
.attr = { \ i7core_show_counter_##param, \
.name = __stringify(udimm##param), \ NULL)
.mode = (S_IRUGO | S_IWUSR) \
}, \
.show = i7core_show_counter_##param \
}
DECLARE_COUNTER(0); DECLARE_COUNTER(0);
DECLARE_COUNTER(1); DECLARE_COUNTER(1);
DECLARE_COUNTER(2); 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[] = { static struct attribute *i7core_addrmatch_attrs[] = {
ATTR_ADDR_MATCH(channel), &dev_attr_channel.attr,
ATTR_ADDR_MATCH(dimm), &dev_attr_dimm.attr,
ATTR_ADDR_MATCH(rank), &dev_attr_rank.attr,
ATTR_ADDR_MATCH(bank), &dev_attr_bank.attr,
ATTR_ADDR_MATCH(page), &dev_attr_page.attr,
ATTR_ADDR_MATCH(col), &dev_attr_col.attr,
{ } /* End of list */ NULL
}; };
static const struct mcidev_sysfs_group i7core_inject_addrmatch = { static struct attribute_group addrmatch_grp = {
.name = "inject_addrmatch", .attrs = i7core_addrmatch_attrs,
.mcidev_attr = i7core_addrmatch_attrs,
}; };
static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { static const struct attribute_group *addrmatch_groups[] = {
ATTR_COUNTER(0), &addrmatch_grp,
ATTR_COUNTER(1), NULL
ATTR_COUNTER(2),
{ .attr = { .name = NULL } }
}; };
static const struct mcidev_sysfs_group i7core_udimm_counters = { static void addrmatch_release(struct device *device)
.name = "all_channel_counts", {
.mcidev_attr = i7core_udimm_counters_attrs, 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[] = { /*
{ * all_channel_counts sysfs struct
.attr = { */
.name = "inject_section",
.mode = (S_IRUGO | S_IWUSR) static struct attribute *i7core_udimm_counters_attrs[] = {
}, &dev_attr_udimm0.attr,
.show = i7core_inject_section_show, &dev_attr_udimm1.attr,
.store = i7core_inject_section_store, &dev_attr_udimm2.attr,
}, { NULL
.attr = { };
.name = "inject_type",
.mode = (S_IRUGO | S_IWUSR) static struct attribute_group all_channel_counts_grp = {
}, .attrs = i7core_udimm_counters_attrs,
.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 */
}; };
static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = { static const struct attribute_group *all_channel_counts_groups[] = {
{ &all_channel_counts_grp,
.attr = { NULL
.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 */
}; };
static void all_channel_counts_release(struct device *device)
{
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 Device initialization routines: put/get, init/exit
****************************************************************************/ ****************************************************************************/
...@@ -2122,6 +2198,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) ...@@ -2122,6 +2198,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
i7core_pci_ctl_release(pvt); i7core_pci_ctl_release(pvt);
/* Remove MC sysfs nodes */ /* Remove MC sysfs nodes */
i7core_delete_sysfs_devices(mci);
edac_mc_del_mc(mci->pdev); edac_mc_del_mc(mci->pdev);
debugf1("%s: free mci struct\n", mci->ctl_name); debugf1("%s: free mci struct\n", mci->ctl_name);
...@@ -2180,10 +2257,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) ...@@ -2180,10 +2257,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; 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 basic config */
get_dimm_config(mci); get_dimm_config(mci);
...@@ -2207,6 +2280,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) ...@@ -2207,6 +2280,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
rc = -EINVAL; rc = -EINVAL;
goto fail0; 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 */ /* Default error mask is any memory */
pvt->inject.channel = 0; pvt->inject.channel = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment