platform/chrome: cros_ec: Poll EC log on EC panic
authorRob Barnes <robbarnes@google.com>
Wed, 4 Jan 2023 01:15:23 +0000 (01:15 +0000)
committerTzung-Bi Shih <tzungbi@kernel.org>
Fri, 6 Jan 2023 03:48:06 +0000 (11:48 +0800)
Add handler for CrOS EC panic events. When a panic is reported,
immediately poll for EC log.

This should result in the log leading to the EC panic being
preserved.

ACPI_NOTIFY_CROS_EC_PANIC is defined in coreboot at
https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/master/src/ec/google/chromeec/acpi/ec.asl

Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-by: Prashant Malani <pmalani@chromium.org>
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20230104011524.369764-2-robbarnes@google.com
drivers/platform/chrome/cros_ec_debugfs.c
drivers/platform/chrome/cros_ec_lpc.c
include/linux/platform_data/cros_ec_proto.h

index 21d973fc6be2de4851a41cb14eb5939c8f5207ea..34f7b46f8761df5f3f22c7a1d9be641213280840 100644 (file)
@@ -49,6 +49,7 @@ struct cros_ec_debugfs {
        struct delayed_work log_poll_work;
        /* EC panicinfo */
        struct debugfs_blob_wrapper panicinfo_blob;
+       struct notifier_block notifier_panic;
 };
 
 /*
@@ -437,6 +438,22 @@ free:
        return ret;
 }
 
+static int cros_ec_debugfs_panic_event(struct notifier_block *nb,
+                                      unsigned long queued_during_suspend, void *_notify)
+{
+       struct cros_ec_debugfs *debug_info =
+               container_of(nb, struct cros_ec_debugfs, notifier_panic);
+
+       if (debug_info->log_buffer.buf) {
+               /* Force log poll work to run immediately */
+               mod_delayed_work(debug_info->log_poll_work.wq, &debug_info->log_poll_work, 0);
+               /* Block until log poll work finishes */
+               flush_delayed_work(&debug_info->log_poll_work);
+       }
+
+       return NOTIFY_DONE;
+}
+
 static int cros_ec_debugfs_probe(struct platform_device *pd)
 {
        struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent);
@@ -473,6 +490,12 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)
        debugfs_create_u16("suspend_timeout_ms", 0664, debug_info->dir,
                           &ec->ec_dev->suspend_timeout_ms);
 
+       debug_info->notifier_panic.notifier_call = cros_ec_debugfs_panic_event;
+       ret = blocking_notifier_chain_register(&ec->ec_dev->panic_notifier,
+                                              &debug_info->notifier_panic);
+       if (ret)
+               goto remove_debugfs;
+
        ec->debug_info = debug_info;
 
        dev_set_drvdata(&pd->dev, ec);
index 7fc8f82280ac83f945e2f3ee40a1594314638d5a..5738f1d25091520abf327e9ea42a4ad5b217d0bc 100644 (file)
@@ -320,6 +320,13 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
 
        ec_dev->last_event_time = cros_ec_get_time_ns();
 
+       if (value == ACPI_NOTIFY_CROS_EC_PANIC) {
+               dev_emerg(ec_dev->dev, "CrOS EC Panic Reported. Shutdown is imminent!");
+               blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev);
+               /* Do not query for other events after a panic is reported */
+               return;
+       }
+
        if (ec_dev->mkbp_event_supported)
                do {
                        ret = cros_ec_get_next_event(ec_dev, NULL,
index e43107e0bee162a736024d67a7b9934d9ec193f2..7fb2196f99b0a1472879b0afa0c235006588ed0c 100644 (file)
 #define EC_MAX_REQUEST_OVERHEAD                1
 #define EC_MAX_RESPONSE_OVERHEAD       32
 
+/*
+ * EC panic is not covered by the standard (0-F) ACPI notify values.
+ * Arbitrarily choosing B0 to notify ec panic, which is in the 84-BF
+ * device specific ACPI notify range.
+ */
+#define ACPI_NOTIFY_CROS_EC_PANIC 0xB0
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -176,6 +183,8 @@ struct cros_ec_device {
        /* The platform devices used by the mfd driver */
        struct platform_device *ec;
        struct platform_device *pd;
+
+       struct blocking_notifier_head panic_notifier;
 };
 
 /**