On Thu, Oct 11, 2018 at 02:12:35PM -0700, Tony Luck wrote: > From: Qiuxu Zhuo <qiuxu.zhuo@xxxxxxxxx> > > 1) The skx_edac debugfs node is '/sys/kernel/debug/skx_edac_test, > move it under EDAC debugfs root node '/sys/kernel/debug/edac/' > > 2) Use skx_mce_check_error() instead of skx_decode() for debugfs, > then the decoded result is showed via EDAC core. Because EDAC > core show the decoded result in a more readable format as like: > CPU_SrcID#[0-9]_MC#[0-9]_Chan#[0-9]_DIMM#[0-9]. > > Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@xxxxxxxxx> > Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx> > --- > drivers/edac/skx_edac.c | 91 ++++++++++++++++++++--------------------- > 1 file changed, 44 insertions(+), 47 deletions(-) > > diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c > index fae095162c01..a710169abdbc 100644 > --- a/drivers/edac/skx_edac.c > +++ b/drivers/edac/skx_edac.c > @@ -894,53 +894,6 @@ static bool skx_decode(struct decoded_addr *res) > skx_rir_decode(res) && skx_mad_decode(res); > } > > -#ifdef CONFIG_EDAC_DEBUG > -/* > - * Debug feature. Make /sys/kernel/debug/skx_edac_test/addr. > - * Write an address to this file to exercise the address decode > - * logic in this driver. > - */ > -static struct dentry *skx_test; > -static u64 skx_fake_addr; > - > -static int debugfs_u64_set(void *data, u64 val) > -{ > - struct decoded_addr res; > - > - res.addr = val; > - skx_decode(&res); > - > - return 0; > -} > - > -DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); > - > -static struct dentry *mydebugfs_create(const char *name, umode_t mode, > - struct dentry *parent, u64 *value) > -{ > - return debugfs_create_file(name, mode, parent, value, &fops_u64_wo); > -} > - > -static void setup_skx_debug(void) > -{ > - skx_test = debugfs_create_dir("skx_edac_test", NULL); > - mydebugfs_create("addr", S_IWUSR, skx_test, &skx_fake_addr); > -} > - > -static void teardown_skx_debug(void) > -{ > - debugfs_remove_recursive(skx_test); > -} > -#else > -static void setup_skx_debug(void) > -{ > -} > - > -static void teardown_skx_debug(void) > -{ > -} > -#endif /*CONFIG_EDAC_DEBUG*/ > - > static void skx_mce_output_error(struct mem_ctl_info *mci, > const struct mce *m, > struct decoded_addr *res) > @@ -1072,6 +1025,50 @@ static struct notifier_block skx_mce_dec = { > .priority = MCE_PRIO_EDAC, > }; > > +#ifdef CONFIG_EDAC_DEBUG > +/* > + * Debug feature. > + * Exercise the address decode logic by writing an address to > + * /sys/kernel/debug/edac/skx_edac_test/addr. > + */ > +static struct dentry *skx_test; > +static u64 skx_fake_addr; What is that unused variable for? > + > +static int debugfs_u64_set(void *data, u64 val) > +{ > + struct mce m; memset(&m, ... otherwise, funky headscratchers will happen as to where the h*ll is this value set?!? I'm talking from experience here. > + > + m.mcgstatus = 0; > + /* ADDRV + MemRd + Unknown channel */ > + m.status = MCI_STATUS_ADDRV + 0x90; > + /* One corrected error */ > + m.status |= 1ULL << MCI_STATUS_CEC_SHIFT; BIT_ULL() > + m.addr = val; > + m.socketid = 0; And if you memset above, you don't need those silly zeroing lines to clutter the code. > + skx_mce_check_error(NULL, 0, &m); > + > + return 0; > +} > +DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); > + > +static void setup_skx_debug(void) > +{ > + skx_test = edac_debugfs_create_dir("skx_edac_test"); > + if (!skx_test) > + return; > + edac_debugfs_create_file("addr", 0200, skx_test, > + &skx_fake_addr, &fops_u64_wo); Error handling needs to remove skx_test on error. > +} > + > +static void teardown_skx_debug(void) > +{ > + debugfs_remove_recursive(skx_test); > +} > +#else > +static void setup_skx_debug(void) {} > +static void teardown_skx_debug(void) {} > +#endif /*CONFIG_EDAC_DEBUG*/ > + > static void skx_remove(void) > { > int i, j; > -- > 2.17.1 > -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.