Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/edac/debugfs.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
3
#include <linux/string_choices.h>
4
5
#include "edac_module.h"
6
7
static struct dentry *edac_debugfs;
8
9
static ssize_t edac_fake_inject_write(struct file *file,
10
const char __user *data,
11
size_t count, loff_t *ppos)
12
{
13
struct device *dev = file->private_data;
14
struct mem_ctl_info *mci = to_mci(dev);
15
static enum hw_event_mc_err_type type;
16
u16 errcount = mci->fake_inject_count;
17
18
if (!errcount)
19
errcount = 1;
20
21
type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED
22
: HW_EVENT_ERR_CORRECTED;
23
24
printk(KERN_DEBUG
25
"Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n",
26
errcount,
27
(type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE",
28
str_plural(errcount),
29
mci->fake_inject_layer[0],
30
mci->fake_inject_layer[1],
31
mci->fake_inject_layer[2]
32
);
33
edac_mc_handle_error(type, mci, errcount, 0, 0, 0,
34
mci->fake_inject_layer[0],
35
mci->fake_inject_layer[1],
36
mci->fake_inject_layer[2],
37
"FAKE ERROR", "for EDAC testing only");
38
39
return count;
40
}
41
42
static const struct file_operations debug_fake_inject_fops = {
43
.open = simple_open,
44
.write = edac_fake_inject_write,
45
.llseek = generic_file_llseek,
46
};
47
48
void __init edac_debugfs_init(void)
49
{
50
edac_debugfs = debugfs_create_dir("edac", NULL);
51
}
52
53
void edac_debugfs_exit(void)
54
{
55
debugfs_remove_recursive(edac_debugfs);
56
}
57
58
void edac_create_debugfs_nodes(struct mem_ctl_info *mci)
59
{
60
struct dentry *parent;
61
char name[80];
62
int i;
63
64
parent = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs);
65
66
for (i = 0; i < mci->n_layers; i++) {
67
sprintf(name, "fake_inject_%s",
68
edac_layer_name[mci->layers[i].type]);
69
debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent,
70
&mci->fake_inject_layer[i]);
71
}
72
73
debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent,
74
&mci->fake_inject_ue);
75
76
debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent,
77
&mci->fake_inject_count);
78
79
debugfs_create_file("fake_inject", S_IWUSR, parent, &mci->dev,
80
&debug_fake_inject_fops);
81
82
mci->debugfs = parent;
83
}
84
85
/* Create a toplevel dir under EDAC's debugfs hierarchy */
86
struct dentry *edac_debugfs_create_dir(const char *dirname)
87
{
88
if (!edac_debugfs)
89
return NULL;
90
91
return debugfs_create_dir(dirname, edac_debugfs);
92
}
93
EXPORT_SYMBOL_GPL(edac_debugfs_create_dir);
94
95
/* Create a toplevel dir under EDAC's debugfs hierarchy with parent @parent */
96
struct dentry *
97
edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent)
98
{
99
return debugfs_create_dir(dirname, parent);
100
}
101
EXPORT_SYMBOL_GPL(edac_debugfs_create_dir_at);
102
103
/*
104
* Create a file under EDAC's hierarchy or a sub-hierarchy:
105
*
106
* @name: file name
107
* @mode: file permissions
108
* @parent: parent dentry. If NULL, it becomes the toplevel EDAC dir
109
* @data: private data of caller
110
* @fops: file operations of this file
111
*/
112
struct dentry *
113
edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
114
void *data, const struct file_operations *fops)
115
{
116
if (!parent)
117
parent = edac_debugfs;
118
119
return debugfs_create_file(name, mode, parent, data, fops);
120
}
121
EXPORT_SYMBOL_GPL(edac_debugfs_create_file);
122
123
/* Wrapper for debugfs_create_x8() */
124
void edac_debugfs_create_x8(const char *name, umode_t mode,
125
struct dentry *parent, u8 *value)
126
{
127
if (!parent)
128
parent = edac_debugfs;
129
130
debugfs_create_x8(name, mode, parent, value);
131
}
132
EXPORT_SYMBOL_GPL(edac_debugfs_create_x8);
133
134
/* Wrapper for debugfs_create_x16() */
135
void edac_debugfs_create_x16(const char *name, umode_t mode,
136
struct dentry *parent, u16 *value)
137
{
138
if (!parent)
139
parent = edac_debugfs;
140
141
debugfs_create_x16(name, mode, parent, value);
142
}
143
EXPORT_SYMBOL_GPL(edac_debugfs_create_x16);
144
145
/* Wrapper for debugfs_create_x32() */
146
void edac_debugfs_create_x32(const char *name, umode_t mode,
147
struct dentry *parent, u32 *value)
148
{
149
if (!parent)
150
parent = edac_debugfs;
151
152
debugfs_create_x32(name, mode, parent, value);
153
}
154
EXPORT_SYMBOL_GPL(edac_debugfs_create_x32);
155
156