EDAC, skx: Let EDAC core show the decoded result for debugfs
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>
Fri, 16 Nov 2018 07:35:05 +0000 (15:35 +0800)
committerBorislav Petkov <bp@suse.de>
Fri, 16 Nov 2018 10:19:53 +0000 (11:19 +0100)
Current debugfs shows the decoded result in its own print format which
is inconvenient for analysis/statistics.

Use skx_mce_check_error() instead of skx_decode() for debugfs,
then the decoded result is showed via EDAC core in a more readable
format like "CPU_SrcID#[0-9]_MC#[0-9]_Chan#[0-9]_DIMM#[0-9]".

Print a warning the first time this interface is used so the
administrator can see the console log that error(s) have been faked.

Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
CC: Mauro Carvalho Chehab <mchehab@kernel.org>
CC: arozansk@redhat.com
CC: linux-edac <linux-edac@vger.kernel.org>
Link: http://lkml.kernel.org/r/1542353705-13531-1-git-send-email-qiuxu.zhuo@intel.com
drivers/edac/skx_edac.c

index 6d38701..93ef161 100644 (file)
@@ -921,52 +921,6 @@ static bool skx_decode(struct decoded_addr *res)
                skx_rir_decode(res) && skx_mad_decode(res);
 }
 
-#ifdef CONFIG_EDAC_DEBUG
-/*
- * Debug feature.
- * Exercise the address decode logic by writing an address to
- * /sys/kernel/debug/edac/skx_test/addr.
- */
-static struct dentry *skx_test;
-
-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 void setup_skx_debug(void)
-{
-       skx_test = edac_debugfs_create_dir("skx_test");
-       if (!skx_test)
-               return;
-
-       if (!edac_debugfs_create_file("addr", 0200, skx_test,
-                                     NULL, &fops_u64_wo)) {
-               debugfs_remove(skx_test);
-               skx_test = NULL;
-       }
-}
-
-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 bool skx_adxl_decode(struct decoded_addr *res)
 
 {
@@ -1171,6 +1125,54 @@ 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_test/addr.
+ */
+static struct dentry *skx_test;
+
+static int debugfs_u64_set(void *data, u64 val)
+{
+       struct mce m;
+
+       pr_warn_once("Fake error to 0x%llx injected via debugfs\n", val);
+
+       memset(&m, 0, sizeof(m));
+       /* ADDRV + MemRd + Unknown channel */
+       m.status = MCI_STATUS_ADDRV + 0x90;
+       /* One corrected error */
+       m.status |= BIT_ULL(MCI_STATUS_CEC_SHIFT);
+       m.addr = val;
+       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_test");
+       if (!skx_test)
+               return;
+
+       if (!edac_debugfs_create_file("addr", 0200, skx_test,
+                                     NULL, &fops_u64_wo)) {
+               debugfs_remove(skx_test);
+               skx_test = NULL;
+       }
+}
+
+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;