aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-09-23 18:56:47 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 11:45:01 -0300
commita5538e531fc1e00ac7185dcfcebf33c37b5d742e (patch)
tree5fbc7a51f9282c401dd6c98ad755dab51c9113e3 /drivers/edac
parentedac_core: Allow the creation of sysfs groups (diff)
downloadlinux-dev-a5538e531fc1e00ac7185dcfcebf33c37b5d742e.tar.xz
linux-dev-a5538e531fc1e00ac7185dcfcebf33c37b5d742e.zip
i7core_edac: Add support for sysfs addrmatch group
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c173
1 files changed, 70 insertions, 103 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 0478cc85e920..afa5281e8df9 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -778,105 +778,59 @@ static ssize_t i7core_inject_eccmask_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_addrmatch_store(struct mem_ctl_info *mci,
- const char *data, size_t count)
-{
- struct i7core_pvt *pvt = mci->pvt_info;
- char *cmd, *val;
- long value;
- int rc;
-
- if (pvt->inject.enable)
- disable_inject(mci);
-
- do {
- cmd = strsep((char **) &data, ":");
- if (!cmd)
- break;
- val = strsep((char **) &data, " \n\t");
- if (!val)
- return cmd - data;
-
- if (!strcasecmp(val, "any"))
- value = -1;
- else {
- rc = strict_strtol(val, 10, &value);
- if ((rc < 0) || (value < 0))
- return cmd - data;
- }
-
- if (!strcasecmp(cmd, "channel")) {
- if (value < 3)
- pvt->inject.channel = value;
- else
- return cmd - data;
- } else if (!strcasecmp(cmd, "dimm")) {
- if (value < 3)
- pvt->inject.dimm = value;
- else
- return cmd - data;
- } else if (!strcasecmp(cmd, "rank")) {
- if (value < 4)
- pvt->inject.rank = value;
- else
- return cmd - data;
- } else if (!strcasecmp(cmd, "bank")) {
- if (value < 32)
- pvt->inject.bank = value;
- else
- return cmd - data;
- } else if (!strcasecmp(cmd, "page")) {
- if (value <= 0xffff)
- pvt->inject.page = value;
- else
- return cmd - data;
- } else if (!strcasecmp(cmd, "col") ||
- !strcasecmp(cmd, "column")) {
- if (value <= 0x3fff)
- pvt->inject.col = value;
- else
- return cmd - data;
- }
- } while (1);
- return count;
+#define DECLARE_ADDR_MATCH(param, limit) \
+static ssize_t i7core_inject_store_##param( \
+ struct mem_ctl_info *mci, \
+ const char *data, size_t count) \
+{ \
+ struct i7core_pvt *pvt = mci->pvt_info; \
+ long value; \
+ int rc; \
+ \
+ if (pvt->inject.enable) \
+ disable_inject(mci); \
+ \
+ if (!strcasecmp(data, "any")) \
+ value = -1; \
+ else { \
+ rc = strict_strtoul(data, 10, &value); \
+ if ((rc < 0) || (value >= limit)) \
+ return -EIO; \
+ } \
+ \
+ pvt->inject.param = value; \
+ \
+ return count; \
+} \
+ \
+static ssize_t i7core_inject_show_##param( \
+ struct mem_ctl_info *mci, \
+ char *data) \
+{ \
+ struct i7core_pvt *pvt = mci->pvt_info; \
+ if (pvt->inject.param < 0) \
+ return sprintf(data, "any\n"); \
+ else \
+ return sprintf(data, "%d\n", pvt->inject.param);\
}
-static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
- char *data)
-{
- struct i7core_pvt *pvt = mci->pvt_info;
- char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
-
- if (pvt->inject.channel < 0)
- sprintf(channel, "any");
- else
- sprintf(channel, "%d", pvt->inject.channel);
- if (pvt->inject.dimm < 0)
- sprintf(dimm, "any");
- else
- sprintf(dimm, "%d", pvt->inject.dimm);
- if (pvt->inject.bank < 0)
- sprintf(bank, "any");
- else
- sprintf(bank, "%d", pvt->inject.bank);
- if (pvt->inject.rank < 0)
- sprintf(rank, "any");
- else
- sprintf(rank, "%d", pvt->inject.rank);
- if (pvt->inject.page < 0)
- sprintf(page, "any");
- else
- sprintf(page, "0x%04x", pvt->inject.page);
- if (pvt->inject.col < 0)
- sprintf(col, "any");
- else
- sprintf(col, "0x%04x", pvt->inject.col);
+#define ATTR_ADDR_MATCH(param) \
+ { \
+ .attr = { \
+ .name = #param, \
+ .mode = (S_IRUGO | S_IWUSR) \
+ }, \
+ .show = i7core_inject_show_##param, \
+ .store = i7core_inject_store_##param, \
+ }
- return sprintf(data, "channel: %s\ndimm: %s\nbank: %s\n"
- "rank: %s\npage: %s\ncolumn: %s\n",
- channel, dimm, bank, rank, page, col);
-}
+DECLARE_ADDR_MATCH(channel, 3);
+DECLARE_ADDR_MATCH(dimm, 3);
+DECLARE_ADDR_MATCH(rank, 4);
+DECLARE_ADDR_MATCH(bank, 32);
+DECLARE_ADDR_MATCH(page, 0x10000);
+DECLARE_ADDR_MATCH(col, 0x4000);
static int write_and_test(struct pci_dev *dev, int where, u32 val)
{
@@ -1079,7 +1033,25 @@ static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
/*
* Sysfs struct
*/
-static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
+
+
+static 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),
+ { .attr = { .name = NULL } }
+};
+
+
+static struct mcidev_sysfs_group i7core_inject_addrmatch = {
+ .name = "inject_addrmatch",
+ .mcidev_attr = i7core_addrmatch_attrs,
+};
+
+static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
{
.attr = {
.name = "inject_section",
@@ -1102,12 +1074,7 @@ static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
.show = i7core_inject_eccmask_show,
.store = i7core_inject_eccmask_store,
}, {
- .attr = {
- .name = "inject_addrmatch",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = i7core_inject_addrmatch_show,
- .store = i7core_inject_addrmatch_store,
+ .grp = &i7core_inject_addrmatch,
}, {
.attr = {
.name = "inject_enable",
@@ -1750,7 +1717,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
i7core_dev->socket);
mci->dev_name = pci_name(i7core_dev->pdev[0]);
mci->ctl_page_to_phys = NULL;
- mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
+ mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
/* Set the function pointer to an actual operation function */
mci->edac_check = i7core_check_error;