aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorAravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>2015-06-02 16:35:56 -0400
committerBorislav Petkov <bp@suse.de>2015-06-03 10:47:51 -0400
commit0451d14d05618e5fcbdc5017a30e3d609ddc8229 (patch)
tree72ca627ed3267a8a945998c71f79082ed6c9e6a5 /drivers/edac
parent685d46d72ba456569d739cc3ff43577f4001d52f (diff)
EDAC, mce_amd_inj: Modify flags attribute to use string arguments
Use strings such as "hw" or "sw" to indicate the type of error injection to be performed. Current flags attribute derives the meanings of values that can be programmed into it from asm/mce.h. Moving to defined strings for the attribute allows this module to be self-sufficient and removes the dependency. Also, we can introduce new flags as and when needed without having to worry about conflicting with the flags already defined in asm/mce.h. Also, modify do_inject() to use the newly defined injection_type enum to figure out the injection mechanism we need to use Suggested-by: Borislav Petkov <bp@suse.de> Signed-off-by: Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com> Cc: linux-edac <linux-edac@vger.kernel.org> Cc: mchehab@osg.samsung.com Cc: x86-ml <x86@kernel.org> Link: http://lkml.kernel.org/r/1433277362-10911-4-git-send-email-Aravind.Gopalakrishnan@amd.com [ Use strstrip() return value. ] Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/mce_amd_inj.c81
1 files changed, 71 insertions, 10 deletions
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 15f6aa18b2f8..2a0c829fef3d 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -15,6 +15,8 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/cpu.h> 17#include <linux/cpu.h>
18#include <linux/string.h>
19#include <linux/uaccess.h>
18#include <asm/mce.h> 20#include <asm/mce.h>
19 21
20#include "mce_amd.h" 22#include "mce_amd.h"
@@ -27,6 +29,23 @@ static struct dentry *dfs_inj;
27 29
28static u8 n_banks; 30static u8 n_banks;
29 31
32#define MAX_FLAG_OPT_SIZE 3
33
34enum injection_type {
35 SW_INJ = 0, /* SW injection, simply decode the error */
36 HW_INJ, /* Trigger a #MC */
37 N_INJ_TYPES,
38};
39
40static const char * const flags_options[] = {
41 [SW_INJ] = "sw",
42 [HW_INJ] = "hw",
43 NULL
44};
45
46/* Set default injection to SW_INJ */
47enum injection_type inj_type = SW_INJ;
48
30#define MCE_INJECT_SET(reg) \ 49#define MCE_INJECT_SET(reg) \
31static int inj_##reg##_set(void *data, u64 val) \ 50static int inj_##reg##_set(void *data, u64 val) \
32{ \ 51{ \
@@ -81,24 +100,66 @@ static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
81 return err; 100 return err;
82} 101}
83 102
84static int flags_get(void *data, u64 *val) 103static int __set_inj(const char *buf)
85{ 104{
86 struct mce *m = (struct mce *)data; 105 int i;
87 106
88 *val = m->inject_flags; 107 for (i = 0; i < N_INJ_TYPES; i++) {
108 if (!strncmp(flags_options[i], buf, strlen(flags_options[i]))) {
109 inj_type = i;
110 return 0;
111 }
112 }
113 return -EINVAL;
114}
89 115
90 return 0; 116static ssize_t flags_read(struct file *filp, char __user *ubuf,
117 size_t cnt, loff_t *ppos)
118{
119 char buf[MAX_FLAG_OPT_SIZE];
120 int n;
121
122 n = sprintf(buf, "%s\n", flags_options[inj_type]);
123
124 return simple_read_from_buffer(ubuf, cnt, ppos, buf, n);
91} 125}
92 126
93static int flags_set(void *data, u64 val) 127static ssize_t flags_write(struct file *filp, const char __user *ubuf,
128 size_t cnt, loff_t *ppos)
94{ 129{
95 struct mce *m = (struct mce *)data; 130 char buf[MAX_FLAG_OPT_SIZE], *__buf;
131 int err;
132 size_t ret;
96 133
97 m->inject_flags = (u8)val; 134 if (cnt > MAX_FLAG_OPT_SIZE)
98 return 0; 135 cnt = MAX_FLAG_OPT_SIZE;
136
137 ret = cnt;
138
139 if (copy_from_user(&buf, ubuf, cnt))
140 return -EFAULT;
141
142 buf[cnt - 1] = 0;
143
144 /* strip whitespace */
145 __buf = strstrip(buf);
146
147 err = __set_inj(__buf);
148 if (err) {
149 pr_err("%s: Invalid flags value: %s\n", __func__, __buf);
150 return err;
151 }
152
153 *ppos += ret;
154
155 return ret;
99} 156}
100 157
101DEFINE_SIMPLE_ATTRIBUTE(flags_fops, flags_get, flags_set, "%llu\n"); 158static const struct file_operations flags_fops = {
159 .read = flags_read,
160 .write = flags_write,
161 .llseek = generic_file_llseek,
162};
102 163
103/* 164/*
104 * On which CPU to inject? 165 * On which CPU to inject?
@@ -130,7 +191,7 @@ static void do_inject(void)
130 unsigned int cpu = i_mce.extcpu; 191 unsigned int cpu = i_mce.extcpu;
131 u8 b = i_mce.bank; 192 u8 b = i_mce.bank;
132 193
133 if (!(i_mce.inject_flags & MCJ_EXCEPTION)) { 194 if (inj_type == SW_INJ) {
134 amd_decode_mce(NULL, 0, &i_mce); 195 amd_decode_mce(NULL, 0, &i_mce);
135 return; 196 return;
136 } 197 }