diff options
author | Robert Richter <robert.richter@linaro.org> | 2013-10-29 17:56:13 -0400 |
---|---|---|
committer | Robert Richter <rric@kernel.org> | 2013-11-04 18:01:11 -0500 |
commit | 78cfbf0bbf6e085fd71e156c6147d205fba29f2b (patch) | |
tree | eca74fce12cccc53998a1dbfe0d2d735c46f52cd /drivers/edac/highbank_mc_edac.c | |
parent | 836dae5d0098ddb097468d5214919b122a301fc1 (diff) |
edac, highbank: Moving error injection to sysfs for edac
Always have the error injection i/f available, even if there is no
debugfs or EDAC_DEBUG enabled. We need this for testing production
kernels and environments.
Thus, the entry moves from:
/sys/kernel/debug/edac/mc0/inject_ctrl
to:
/sys/devices/system/edac/mc/mc0/inject_ctrl
No other changes of the interface.
Signed-off-by: Robert Richter <robert.richter@linaro.org>
Signed-off-by: Robert Richter <rric@kernel.org>
Diffstat (limited to 'drivers/edac/highbank_mc_edac.c')
-rw-r--r-- | drivers/edac/highbank_mc_edac.c | 55 |
1 files changed, 20 insertions, 35 deletions
diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 82211915e3b0..f784de1dc793 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c | |||
@@ -95,50 +95,34 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) | |||
95 | return IRQ_HANDLED; | 95 | return IRQ_HANDLED; |
96 | } | 96 | } |
97 | 97 | ||
98 | #ifdef CONFIG_EDAC_DEBUG | 98 | static void highbank_mc_err_inject(struct mem_ctl_info *mci, u8 synd) |
99 | static ssize_t highbank_mc_err_inject_write(struct file *file, | ||
100 | const char __user *data, | ||
101 | size_t count, loff_t *ppos) | ||
102 | { | 99 | { |
103 | struct mem_ctl_info *mci = file->private_data; | ||
104 | struct hb_mc_drvdata *pdata = mci->pvt_info; | 100 | struct hb_mc_drvdata *pdata = mci->pvt_info; |
105 | char buf[32]; | ||
106 | size_t buf_size; | ||
107 | u32 reg; | 101 | u32 reg; |
102 | |||
103 | reg = readl(pdata->mc_err_base + HB_DDR_ECC_OPT); | ||
104 | reg &= HB_DDR_ECC_OPT_MODE_MASK; | ||
105 | reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC; | ||
106 | writel(reg, pdata->mc_err_base + HB_DDR_ECC_OPT); | ||
107 | } | ||
108 | |||
109 | #define to_mci(k) container_of(k, struct mem_ctl_info, dev) | ||
110 | |||
111 | static ssize_t highbank_mc_inject_ctrl(struct device *dev, | ||
112 | struct device_attribute *attr, const char *buf, size_t count) | ||
113 | { | ||
114 | struct mem_ctl_info *mci = to_mci(dev); | ||
108 | u8 synd; | 115 | u8 synd; |
109 | 116 | ||
110 | buf_size = min(count, (sizeof(buf)-1)); | 117 | if (kstrtou8(buf, 16, &synd)) |
111 | if (copy_from_user(buf, data, buf_size)) | 118 | return -EINVAL; |
112 | return -EFAULT; | ||
113 | buf[buf_size] = 0; | ||
114 | 119 | ||
115 | if (!kstrtou8(buf, 16, &synd)) { | 120 | highbank_mc_err_inject(mci, synd); |
116 | reg = readl(pdata->mc_err_base + HB_DDR_ECC_OPT); | ||
117 | reg &= HB_DDR_ECC_OPT_MODE_MASK; | ||
118 | reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC; | ||
119 | writel(reg, pdata->mc_err_base + HB_DDR_ECC_OPT); | ||
120 | } | ||
121 | 121 | ||
122 | return count; | 122 | return count; |
123 | } | 123 | } |
124 | 124 | ||
125 | static const struct file_operations highbank_mc_debug_inject_fops = { | 125 | static DEVICE_ATTR(inject_ctrl, S_IWUSR, NULL, highbank_mc_inject_ctrl); |
126 | .open = simple_open, | ||
127 | .write = highbank_mc_err_inject_write, | ||
128 | .llseek = generic_file_llseek, | ||
129 | }; | ||
130 | |||
131 | static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) | ||
132 | { | ||
133 | if (mci->debugfs) | ||
134 | debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci, | ||
135 | &highbank_mc_debug_inject_fops); | ||
136 | ; | ||
137 | } | ||
138 | #else | ||
139 | static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) | ||
140 | {} | ||
141 | #endif | ||
142 | 126 | ||
143 | struct hb_mc_settings { | 127 | struct hb_mc_settings { |
144 | int err_offset; | 128 | int err_offset; |
@@ -259,7 +243,7 @@ static int highbank_mc_probe(struct platform_device *pdev) | |||
259 | goto err2; | 243 | goto err2; |
260 | } | 244 | } |
261 | 245 | ||
262 | highbank_mc_create_debugfs_nodes(mci); | 246 | device_create_file(&mci->dev, &dev_attr_inject_ctrl); |
263 | 247 | ||
264 | devres_close_group(&pdev->dev, NULL); | 248 | devres_close_group(&pdev->dev, NULL); |
265 | return 0; | 249 | return 0; |
@@ -275,6 +259,7 @@ static int highbank_mc_remove(struct platform_device *pdev) | |||
275 | { | 259 | { |
276 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); | 260 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); |
277 | 261 | ||
262 | device_remove_file(&mci->dev, &dev_attr_inject_ctrl); | ||
278 | edac_mc_del_mc(&pdev->dev); | 263 | edac_mc_del_mc(&pdev->dev); |
279 | edac_mc_free(mci); | 264 | edac_mc_free(mci); |
280 | return 0; | 265 | return 0; |