Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include "edac_module.h"
0003 
0004 static struct dentry *edac_debugfs;
0005 
0006 static ssize_t edac_fake_inject_write(struct file *file,
0007                       const char __user *data,
0008                       size_t count, loff_t *ppos)
0009 {
0010     struct device *dev = file->private_data;
0011     struct mem_ctl_info *mci = to_mci(dev);
0012     static enum hw_event_mc_err_type type;
0013     u16 errcount = mci->fake_inject_count;
0014 
0015     if (!errcount)
0016         errcount = 1;
0017 
0018     type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED
0019                    : HW_EVENT_ERR_CORRECTED;
0020 
0021     printk(KERN_DEBUG
0022            "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",
0023         errcount,
0024         (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE",
0025         errcount > 1 ? "s" : "",
0026         mci->fake_inject_layer[0],
0027         mci->fake_inject_layer[1],
0028         mci->fake_inject_layer[2]
0029            );
0030     edac_mc_handle_error(type, mci, errcount, 0, 0, 0,
0031                  mci->fake_inject_layer[0],
0032                  mci->fake_inject_layer[1],
0033                  mci->fake_inject_layer[2],
0034                  "FAKE ERROR", "for EDAC testing only");
0035 
0036     return count;
0037 }
0038 
0039 static const struct file_operations debug_fake_inject_fops = {
0040     .open = simple_open,
0041     .write = edac_fake_inject_write,
0042     .llseek = generic_file_llseek,
0043 };
0044 
0045 void __init edac_debugfs_init(void)
0046 {
0047     edac_debugfs = debugfs_create_dir("edac", NULL);
0048 }
0049 
0050 void edac_debugfs_exit(void)
0051 {
0052     debugfs_remove_recursive(edac_debugfs);
0053 }
0054 
0055 void edac_create_debugfs_nodes(struct mem_ctl_info *mci)
0056 {
0057     struct dentry *parent;
0058     char name[80];
0059     int i;
0060 
0061     parent = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs);
0062 
0063     for (i = 0; i < mci->n_layers; i++) {
0064         sprintf(name, "fake_inject_%s",
0065                  edac_layer_name[mci->layers[i].type]);
0066         debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent,
0067                   &mci->fake_inject_layer[i]);
0068     }
0069 
0070     debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent,
0071                 &mci->fake_inject_ue);
0072 
0073     debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent,
0074                &mci->fake_inject_count);
0075 
0076     debugfs_create_file("fake_inject", S_IWUSR, parent, &mci->dev,
0077                 &debug_fake_inject_fops);
0078 
0079     mci->debugfs = parent;
0080 }
0081 
0082 /* Create a toplevel dir under EDAC's debugfs hierarchy */
0083 struct dentry *edac_debugfs_create_dir(const char *dirname)
0084 {
0085     if (!edac_debugfs)
0086         return NULL;
0087 
0088     return debugfs_create_dir(dirname, edac_debugfs);
0089 }
0090 EXPORT_SYMBOL_GPL(edac_debugfs_create_dir);
0091 
0092 /* Create a toplevel dir under EDAC's debugfs hierarchy with parent @parent */
0093 struct dentry *
0094 edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent)
0095 {
0096     return debugfs_create_dir(dirname, parent);
0097 }
0098 EXPORT_SYMBOL_GPL(edac_debugfs_create_dir_at);
0099 
0100 /*
0101  * Create a file under EDAC's hierarchy or a sub-hierarchy:
0102  *
0103  * @name: file name
0104  * @mode: file permissions
0105  * @parent: parent dentry. If NULL, it becomes the toplevel EDAC dir
0106  * @data: private data of caller
0107  * @fops: file operations of this file
0108  */
0109 struct dentry *
0110 edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
0111              void *data, const struct file_operations *fops)
0112 {
0113     if (!parent)
0114         parent = edac_debugfs;
0115 
0116     return debugfs_create_file(name, mode, parent, data, fops);
0117 }
0118 EXPORT_SYMBOL_GPL(edac_debugfs_create_file);
0119 
0120 /* Wrapper for debugfs_create_x8() */
0121 void edac_debugfs_create_x8(const char *name, umode_t mode,
0122                 struct dentry *parent, u8 *value)
0123 {
0124     if (!parent)
0125         parent = edac_debugfs;
0126 
0127     debugfs_create_x8(name, mode, parent, value);
0128 }
0129 EXPORT_SYMBOL_GPL(edac_debugfs_create_x8);
0130 
0131 /* Wrapper for debugfs_create_x16() */
0132 void edac_debugfs_create_x16(const char *name, umode_t mode,
0133                  struct dentry *parent, u16 *value)
0134 {
0135     if (!parent)
0136         parent = edac_debugfs;
0137 
0138     debugfs_create_x16(name, mode, parent, value);
0139 }
0140 EXPORT_SYMBOL_GPL(edac_debugfs_create_x16);
0141 
0142 /* Wrapper for debugfs_create_x32() */
0143 void edac_debugfs_create_x32(const char *name, umode_t mode,
0144                  struct dentry *parent, u32 *value)
0145 {
0146     if (!parent)
0147         parent = edac_debugfs;
0148 
0149     debugfs_create_x32(name, mode, parent, value);
0150 }
0151 EXPORT_SYMBOL_GPL(edac_debugfs_create_x32);