aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@chromium.org>2018-10-12 12:04:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-10-15 14:32:26 -0400
commit8942b2d5094b01e4509f0118a7940bb07350e128 (patch)
treeb074d50547c90928068c778cb20870326c46b92d
parentd31655ba89575a2d1559a345642338eecd49c96d (diff)
gsmi: Add GSMI commands to log S0ix info
Add new GSMI commands (GSMI_CMD_LOG_S0IX_SUSPEND = 0xa, GSMI_CMD_LOG_S0IX_RESUME = 0xb) that allow firmware to log any information during S0ix suspend/resume paths. Traditional ACPI suspend S3 involves BIOS both during the suspend and the resume paths. However, modern suspend type like S0ix does not involve firmware on either of the paths. This command gives the firmware an opportunity to log any required information about the suspend and resume operations e.g. wake sources. Additionally, this change adds a module parameter to allow platforms to specifically enable S0ix logging if required. This prevents any other platforms from unnecessarily making a GSMI call which could have any side-effects. Tested by verifying that wake sources are correctly logged in eventlog. Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Rajat Jain <rajatja@chromium.org> Signed-off-by: Furquan Shaikh <furquan@google.com> Tested-by: Furquan Shaikh <furquan@chromium.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org> [zwisler: update changelog for upstream] Signed-off-by: Ross Zwisler <zwisler@google.com> Reviewed-by: Guenter Roeck <groeck@chromium.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/firmware/google/gsmi.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
index 170996764edd..82ce1e6d261e 100644
--- a/drivers/firmware/google/gsmi.c
+++ b/drivers/firmware/google/gsmi.c
@@ -29,6 +29,7 @@
29#include <linux/efi.h> 29#include <linux/efi.h>
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/ucs2_string.h> 31#include <linux/ucs2_string.h>
32#include <linux/suspend.h>
32 33
33#define GSMI_SHUTDOWN_CLEAN 0 /* Clean Shutdown */ 34#define GSMI_SHUTDOWN_CLEAN 0 /* Clean Shutdown */
34/* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */ 35/* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */
@@ -70,6 +71,8 @@
70#define GSMI_CMD_SET_NVRAM_VAR 0x03 71#define GSMI_CMD_SET_NVRAM_VAR 0x03
71#define GSMI_CMD_SET_EVENT_LOG 0x08 72#define GSMI_CMD_SET_EVENT_LOG 0x08
72#define GSMI_CMD_CLEAR_EVENT_LOG 0x09 73#define GSMI_CMD_CLEAR_EVENT_LOG 0x09
74#define GSMI_CMD_LOG_S0IX_SUSPEND 0x0a
75#define GSMI_CMD_LOG_S0IX_RESUME 0x0b
73#define GSMI_CMD_CLEAR_CONFIG 0x20 76#define GSMI_CMD_CLEAR_CONFIG 0x20
74#define GSMI_CMD_HANDSHAKE_TYPE 0xC1 77#define GSMI_CMD_HANDSHAKE_TYPE 0xC1
75 78
@@ -122,7 +125,6 @@ struct gsmi_log_entry_type_1 {
122 u32 instance; 125 u32 instance;
123} __packed; 126} __packed;
124 127
125
126/* 128/*
127 * Some platforms don't have explicit SMI handshake 129 * Some platforms don't have explicit SMI handshake
128 * and need to wait for SMI to complete. 130 * and need to wait for SMI to complete.
@@ -133,6 +135,15 @@ module_param(spincount, uint, 0600);
133MODULE_PARM_DESC(spincount, 135MODULE_PARM_DESC(spincount,
134 "The number of loop iterations to use when using the spin handshake."); 136 "The number of loop iterations to use when using the spin handshake.");
135 137
138/*
139 * Platforms might not support S0ix logging in their GSMI handlers. In order to
140 * avoid any side-effects of generating an SMI for S0ix logging, use the S0ix
141 * related GSMI commands only for those platforms that explicitly enable this
142 * option.
143 */
144static bool s0ix_logging_enable;
145module_param(s0ix_logging_enable, bool, 0600);
146
136static struct gsmi_buf *gsmi_buf_alloc(void) 147static struct gsmi_buf *gsmi_buf_alloc(void)
137{ 148{
138 struct gsmi_buf *smibuf; 149 struct gsmi_buf *smibuf;
@@ -781,6 +792,78 @@ static const struct platform_device_info gsmi_dev_info = {
781 .dma_mask = DMA_BIT_MASK(32), 792 .dma_mask = DMA_BIT_MASK(32),
782}; 793};
783 794
795#ifdef CONFIG_PM
796static void gsmi_log_s0ix_info(u8 cmd)
797{
798 unsigned long flags;
799
800 /*
801 * If platform has not enabled S0ix logging, then no action is
802 * necessary.
803 */
804 if (!s0ix_logging_enable)
805 return;
806
807 spin_lock_irqsave(&gsmi_dev.lock, flags);
808
809 memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length);
810
811 gsmi_exec(GSMI_CALLBACK, cmd);
812
813 spin_unlock_irqrestore(&gsmi_dev.lock, flags);
814}
815
816static int gsmi_log_s0ix_suspend(struct device *dev)
817{
818 /*
819 * If system is not suspending via firmware using the standard ACPI Sx
820 * types, then make a GSMI call to log the suspend info.
821 */
822 if (!pm_suspend_via_firmware())
823 gsmi_log_s0ix_info(GSMI_CMD_LOG_S0IX_SUSPEND);
824
825 /*
826 * Always return success, since we do not want suspend
827 * to fail just because of logging failure.
828 */
829 return 0;
830}
831
832static int gsmi_log_s0ix_resume(struct device *dev)
833{
834 /*
835 * If system did not resume via firmware, then make a GSMI call to log
836 * the resume info and wake source.
837 */
838 if (!pm_resume_via_firmware())
839 gsmi_log_s0ix_info(GSMI_CMD_LOG_S0IX_RESUME);
840
841 /*
842 * Always return success, since we do not want resume
843 * to fail just because of logging failure.
844 */
845 return 0;
846}
847
848static const struct dev_pm_ops gsmi_pm_ops = {
849 .suspend_noirq = gsmi_log_s0ix_suspend,
850 .resume_noirq = gsmi_log_s0ix_resume,
851};
852
853static int gsmi_platform_driver_probe(struct platform_device *dev)
854{
855 return 0;
856}
857
858static struct platform_driver gsmi_driver_info = {
859 .driver = {
860 .name = "gsmi",
861 .pm = &gsmi_pm_ops,
862 },
863 .probe = gsmi_platform_driver_probe,
864};
865#endif
866
784static __init int gsmi_init(void) 867static __init int gsmi_init(void)
785{ 868{
786 unsigned long flags; 869 unsigned long flags;
@@ -792,6 +875,14 @@ static __init int gsmi_init(void)
792 875
793 gsmi_dev.smi_cmd = acpi_gbl_FADT.smi_command; 876 gsmi_dev.smi_cmd = acpi_gbl_FADT.smi_command;
794 877
878#ifdef CONFIG_PM
879 ret = platform_driver_register(&gsmi_driver_info);
880 if (unlikely(ret)) {
881 printk(KERN_ERR "gsmi: unable to register platform driver\n");
882 return ret;
883 }
884#endif
885
795 /* register device */ 886 /* register device */
796 gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info); 887 gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info);
797 if (IS_ERR(gsmi_dev.pdev)) { 888 if (IS_ERR(gsmi_dev.pdev)) {