diff options
author | Lv Zheng <lv.zheng@intel.com> | 2016-08-04 16:43:39 +0800 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-08-13 03:09:33 +0200 |
commit | 2af52c2bd20c50e80b121e15cd50a579e364485a (patch) | |
tree | 3bc9e680c4c65462569794ce2ce5c269d2767c38 /drivers/acpi/acpica/evxfgpe.c | |
parent | 9556ec4ec1d3575090f1f110c558169c5f0973a9 (diff) | |
download | linux-2af52c2bd20c50e80b121e15cd50a579e364485a.tar.gz linux-2af52c2bd20c50e80b121e15cd50a579e364485a.tar.bz2 linux-2af52c2bd20c50e80b121e15cd50a579e364485a.zip |
ACPICA: Events: Introduce acpi_mask_gpe() to implement GPE masking mechanism
ACPICA commit 23a417ca406a527e7ae1710893e59a8b6db30e14
There is a facility in Linux, developers can control the enabling/disabling
of a GPE via /sys/firmware/acpi/interrupts/gpexx. This is mainly for
debugging purposes.
But many users expect to use this facility to implement quirks to mask a
specific GPE when there is a gap in Linux causing this GPE to flood. This
is not working correctly because currently this facility invokes
enabling/disabling counting based GPE driver APIs:
acpi_enable_gpe()/acpi_disable_gpe()
and the GPE drivers can still affect the count to mess up the GPE
masking purposes.
However, most of the IRQ chip designs allow masking/unmasking IRQs via a
masking bit which is different from the enabled bit to achieve the same
purpose. But the GPE hardware doesn't contain such a feature, this brings
the trouble.
In this patch, we introduce a software mechanism to implement the GPE
masking feature, and acpi_mask_gpe() are provided to the OSPMs to
mask/unmask GPEs in the above mentioned situation instead of
acpi_enable_gpe()/acpi_disable_gpe(). ACPICA BZ 1102. Lv Zheng.
Link: https://github.com/acpica/acpica/commit/23a417ca
Link: https://bugs.acpica.org/show_bug.cgi?id=1102
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/evxfgpe.c')
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 17cfef721d00..d7a3b2775505 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -235,11 +235,13 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) case ACPI_GPE_ENABLE: status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); + gpe_event_info->disable_for_dispatch = FALSE; break; case ACPI_GPE_DISABLE: status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); + gpe_event_info->disable_for_dispatch = TRUE; break; default: @@ -257,6 +259,47 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe) /******************************************************************************* * + * FUNCTION: acpi_mask_gpe + * + * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 + * gpe_number - GPE level within the GPE block + * is_masked - Whether the GPE is masked or not + * + * RETURN: Status + * + * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to + * prevent a GPE flooding. + * + ******************************************************************************/ +acpi_status acpi_mask_gpe(acpi_handle gpe_device, u32 gpe_number, u8 is_masked) +{ + struct acpi_gpe_event_info *gpe_event_info; + acpi_status status; + acpi_cpu_flags flags; + + ACPI_FUNCTION_TRACE(acpi_mask_gpe); + + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); + + /* Ensure that we have a valid GPE number */ + + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (!gpe_event_info) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ev_mask_gpe(gpe_event_info, is_masked); + +unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_mask_gpe) + +/******************************************************************************* + * * FUNCTION: acpi_mark_gpe_for_wake * * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |