EDAC, mce_amd_inj: Convert mce_amd_inj module to debugfs
[deliverable/linux.git] / drivers / edac / mce_amd_inj.c
CommitLineData
9cdeb404 1/*
fd19fcd6
BP
2 * A simple MCE injection facility for testing different aspects of the RAS
3 * code. This driver should be built as module so that it can be loaded
4 * on production kernels for testing purposes.
9cdeb404
BP
5 *
6 * This file may be distributed under the terms of the GNU General Public
7 * License version 2.
8 *
fd19fcd6 9 * Copyright (c) 2010-14: Borislav Petkov <bp@alien8.de>
9cdeb404
BP
10 * Advanced Micro Devices Inc.
11 */
12
13#include <linux/kobject.h>
fd19fcd6 14#include <linux/debugfs.h>
51990e82 15#include <linux/device.h>
80a2e2e3 16#include <linux/module.h>
9cdeb404
BP
17#include <asm/mce.h>
18
47ca08a4 19#include "mce_amd.h"
9cdeb404 20
9cdeb404
BP
21/*
22 * Collect all the MCi_XXX settings
23 */
24static struct mce i_mce;
fd19fcd6 25static struct dentry *dfs_inj;
9cdeb404 26
fd19fcd6
BP
27#define MCE_INJECT_SET(reg) \
28static int inj_##reg##_set(void *data, u64 val) \
9cdeb404 29{ \
fd19fcd6 30 struct mce *m = (struct mce *)data; \
9cdeb404 31 \
fd19fcd6
BP
32 m->reg = val; \
33 return 0; \
9cdeb404
BP
34}
35
fd19fcd6
BP
36MCE_INJECT_SET(status);
37MCE_INJECT_SET(misc);
38MCE_INJECT_SET(addr);
9cdeb404 39
fd19fcd6
BP
40#define MCE_INJECT_GET(reg) \
41static int inj_##reg##_get(void *data, u64 *val) \
9cdeb404 42{ \
fd19fcd6
BP
43 struct mce *m = (struct mce *)data; \
44 \
45 *val = m->reg; \
46 return 0; \
9cdeb404
BP
47}
48
fd19fcd6
BP
49MCE_INJECT_GET(status);
50MCE_INJECT_GET(misc);
51MCE_INJECT_GET(addr);
9cdeb404 52
fd19fcd6
BP
53DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
54DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
55DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
9cdeb404
BP
56
57/*
58 * This denotes into which bank we're injecting and triggers
59 * the injection, at the same time.
60 */
fd19fcd6 61static int inj_bank_set(void *data, u64 val)
9cdeb404 62{
fd19fcd6 63 struct mce *m = (struct mce *)data;
9cdeb404 64
fd19fcd6
BP
65 if (val > 5) {
66 if (boot_cpu_data.x86 != 0x15 || val > 6) {
67 pr_err("Non-existent MCE bank: %llu\n", val);
1b07ca47
BP
68 return -EINVAL;
69 }
fd19fcd6 70 }
9cdeb404 71
fd19fcd6 72 m->bank = val;
9cdeb404 73
fd19fcd6 74 amd_decode_mce(NULL, 0, m);
9cdeb404 75
fd19fcd6 76 return 0;
9cdeb404
BP
77}
78
fd19fcd6 79static int inj_bank_get(void *data, u64 *val)
9cdeb404 80{
fd19fcd6 81 struct mce *m = (struct mce *)data;
9cdeb404 82
fd19fcd6
BP
83 *val = m->bank;
84 return 0;
85}
9cdeb404 86
fd19fcd6
BP
87DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
88
89struct dfs_node {
90 char *name;
91 struct dentry *d;
92 const struct file_operations *fops;
93} dfs_fls[] = {
94 { .name = "status", .fops = &status_fops },
95 { .name = "misc", .fops = &misc_fops },
96 { .name = "addr", .fops = &addr_fops },
97 { .name = "bank", .fops = &bank_fops },
9cdeb404
BP
98};
99
fd19fcd6 100static int __init init_mce_inject(void)
9cdeb404 101{
fd19fcd6 102 int i;
9cdeb404 103
fd19fcd6
BP
104 dfs_inj = debugfs_create_dir("mce-inject", NULL);
105 if (!dfs_inj)
9cdeb404
BP
106 return -EINVAL;
107
fd19fcd6
BP
108 for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) {
109 dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name,
110 S_IRUSR | S_IWUSR,
111 dfs_inj,
112 &i_mce,
113 dfs_fls[i].fops);
9cdeb404 114
fd19fcd6
BP
115 if (!dfs_fls[i].d)
116 goto err_dfs_add;
9cdeb404 117 }
fd19fcd6 118
9cdeb404
BP
119 return 0;
120
fd19fcd6 121err_dfs_add:
df4b2a30 122 while (--i >= 0)
fd19fcd6 123 debugfs_remove(dfs_fls[i].d);
9cdeb404 124
fd19fcd6
BP
125 debugfs_remove(dfs_inj);
126 dfs_inj = NULL;
9cdeb404 127
fd19fcd6 128 return -ENOMEM;
9cdeb404
BP
129}
130
fd19fcd6 131static void __exit exit_mce_inject(void)
9cdeb404
BP
132{
133 int i;
134
fd19fcd6
BP
135 for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
136 debugfs_remove(dfs_fls[i].d);
9cdeb404 137
fd19fcd6 138 memset(&dfs_fls, 0, sizeof(dfs_fls));
9cdeb404 139
fd19fcd6
BP
140 debugfs_remove(dfs_inj);
141 dfs_inj = NULL;
9cdeb404 142}
fd19fcd6
BP
143module_init(init_mce_inject);
144module_exit(exit_mce_inject);
9cdeb404
BP
145
146MODULE_LICENSE("GPL");
43aff26c 147MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
9cdeb404 148MODULE_AUTHOR("AMD Inc.");
fd19fcd6 149MODULE_DESCRIPTION("MCE injection facility for RAS testing");
This page took 0.252475 seconds and 5 git commands to generate.