aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2017-04-04 15:32:17 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-12 06:41:18 -0400
commitc1e94148f93c4319a1aea4ae29835cd1e2017ff9 (patch)
treecd59abdd479e707ca6683ab4c017748cfa951d8f
parent43cfff65c989c0ef722bfcd2335b07a48e09aab9 (diff)
ACPI / sysfs: Provide quirk mechanism to prevent GPE flooding
[ Upstream commit 9c4aa1eecb48cfac18ed5e3aca9d9ae58fbafc11 ] Sometimes, the users may require a quirk to be provided from ACPI subsystem core to prevent a GPE from flooding. Normally, if a GPE cannot be dispatched, ACPICA core automatically prevents the GPE from firing. But there are cases the GPE is dispatched by _Lxx/_Exx provided via AML table, and OSPM is lacking of the knowledge to get _Lxx/_Exx correctly executed to handle the GPE, thus the GPE flooding may still occur. The existing quirk mechanism can be enabled/disabled using the following commands to prevent such kind of GPE flooding during runtime: # echo mask > /sys/firmware/acpi/interrupts/gpe00 # echo unmask > /sys/firmware/acpi/interrupts/gpe00 To avoid GPE flooding during boot, we need a boot stage mechanism. This patch provides such a boot stage quirk mechanism to stop this kind of GPE flooding. This patch doesn't fix any feature gap but since the new feature gaps could be found in the future endlessly, and can disappear if the feature gaps are filled, providing a boot parameter rather than a DMI table should suffice. Link: https://bugzilla.kernel.org/show_bug.cgi?id=53071 Link: https://bugzilla.kernel.org/show_bug.cgi?id=117481 Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/887793 Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/kernel-parameters.txt10
-rw-r--r--drivers/acpi/internal.h1
-rw-r--r--drivers/acpi/scan.c1
-rw-r--r--drivers/acpi/sysfs.c56
4 files changed, 68 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 65b05ba6ef98..a6fadef92d6d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -305,6 +305,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
305 use by PCI 305 use by PCI
306 Format: <irq>,<irq>... 306 Format: <irq>,<irq>...
307 307
308 acpi_mask_gpe= [HW,ACPI]
309 Due to the existence of _Lxx/_Exx, some GPEs triggered
310 by unsupported hardware/firmware features can result in
311 GPE floodings that cannot be automatically disabled by
312 the GPE dispatcher.
313 This facility can be used to prevent such uncontrolled
314 GPE floodings.
315 Format: <int>
316 Support masking of GPEs numbered from 0x00 to 0x7f.
317
308 acpi_no_auto_serialize [HW,ACPI] 318 acpi_no_auto_serialize [HW,ACPI]
309 Disable auto-serialization of AML methods 319 Disable auto-serialization of AML methods
310 AML control methods that contain the opcodes to create 320 AML control methods that contain the opcodes to create
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 1b41a2739dac..0c452265c111 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -37,6 +37,7 @@ void acpi_amba_init(void);
37static inline void acpi_amba_init(void) {} 37static inline void acpi_amba_init(void) {}
38#endif 38#endif
39int acpi_sysfs_init(void); 39int acpi_sysfs_init(void);
40void acpi_gpe_apply_masked_gpes(void);
40void acpi_container_init(void); 41void acpi_container_init(void);
41void acpi_memory_hotplug_init(void); 42void acpi_memory_hotplug_init(void);
42#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC 43#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3d1856f1f4d0..5a2fdf156ec9 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2044,6 +2044,7 @@ int __init acpi_scan_init(void)
2044 } 2044 }
2045 } 2045 }
2046 2046
2047 acpi_gpe_apply_masked_gpes();
2047 acpi_update_all_gpes(); 2048 acpi_update_all_gpes();
2048 acpi_ec_ecdt_start(); 2049 acpi_ec_ecdt_start();
2049 2050
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 703c26e7022c..cf05ae973381 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -708,6 +708,62 @@ end:
708 return result ? result : size; 708 return result ? result : size;
709} 709}
710 710
711/*
712 * A Quirk Mechanism for GPE Flooding Prevention:
713 *
714 * Quirks may be needed to prevent GPE flooding on a specific GPE. The
715 * flooding typically cannot be detected and automatically prevented by
716 * ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
717 * the AML tables. This normally indicates a feature gap in Linux, thus
718 * instead of providing endless quirk tables, we provide a boot parameter
719 * for those who want this quirk. For example, if the users want to prevent
720 * the GPE flooding for GPE 00, they need to specify the following boot
721 * parameter:
722 * acpi_mask_gpe=0x00
723 * The masking status can be modified by the following runtime controlling
724 * interface:
725 * echo unmask > /sys/firmware/acpi/interrupts/gpe00
726 */
727
728/*
729 * Currently, the GPE flooding prevention only supports to mask the GPEs
730 * numbered from 00 to 7f.
731 */
732#define ACPI_MASKABLE_GPE_MAX 0x80
733
734static u64 __initdata acpi_masked_gpes;
735
736static int __init acpi_gpe_set_masked_gpes(char *val)
737{
738 u8 gpe;
739
740 if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
741 return -EINVAL;
742 acpi_masked_gpes |= ((u64)1<<gpe);
743
744 return 1;
745}
746__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
747
748void __init acpi_gpe_apply_masked_gpes(void)
749{
750 acpi_handle handle;
751 acpi_status status;
752 u8 gpe;
753
754 for (gpe = 0;
755 gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
756 gpe++) {
757 if (acpi_masked_gpes & ((u64)1<<gpe)) {
758 status = acpi_get_gpe_device(gpe, &handle);
759 if (ACPI_SUCCESS(status)) {
760 pr_info("Masking GPE 0x%x.\n", gpe);
761 (void)acpi_mask_gpe(handle, gpe, TRUE);
762 }
763 }
764 }
765}
766
711void acpi_irq_stats_init(void) 767void acpi_irq_stats_init(void)
712{ 768{
713 acpi_status status; 769 acpi_status status;