ACPI, APEI, Report GHES error information via printk
authorHuang Ying <ying.huang@intel.com>
Tue, 7 Dec 2010 02:22:31 +0000 (10:22 +0800)
committerLen Brown <len.brown@intel.com>
Tue, 14 Dec 2010 04:42:39 +0000 (23:42 -0500)
printk is one of the methods to report hardware errors to user space.
This patch implements hardware error reporting for GHES via printk.

Signed-off-by: Huang Ying <ying.huang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/apei/ghes.c

index 0d505e59214df73dfb40b67b7d5fc45a2d48e127..51905d07a4d94a4904bdb526cd5aa419ac026db5 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/kdebug.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
+#include <linux/ratelimit.h>
 #include <acpi/apei.h>
 #include <acpi/atomicio.h>
 #include <acpi/hed.h>
@@ -255,11 +256,26 @@ static void ghes_do_proc(struct ghes *ghes)
                }
 #endif
        }
+}
 
-       if (!processed && printk_ratelimit())
-               pr_warning(GHES_PFX
-               "Unknown error record from generic hardware error source: %d\n",
-                          ghes->generic->header.source_id);
+static void ghes_print_estatus(const char *pfx, struct ghes *ghes)
+{
+       /* Not more than 2 messages every 5 seconds */
+       static DEFINE_RATELIMIT_STATE(ratelimit, 5*HZ, 2);
+
+       if (pfx == NULL) {
+               if (ghes_severity(ghes->estatus->error_severity) <=
+                   GHES_SEV_CORRECTED)
+                       pfx = KERN_WARNING HW_ERR;
+               else
+                       pfx = KERN_ERR HW_ERR;
+       }
+       if (__ratelimit(&ratelimit)) {
+               printk(
+       "%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
+       pfx, ghes->generic->header.source_id);
+               apei_estatus_print(pfx, ghes->estatus);
+       }
 }
 
 static int ghes_proc(struct ghes *ghes)
@@ -269,6 +285,7 @@ static int ghes_proc(struct ghes *ghes)
        rc = ghes_read_estatus(ghes, 0);
        if (rc)
                goto out;
+       ghes_print_estatus(NULL, ghes);
        ghes_do_proc(ghes);
 
 out: