| From 49e4b84333f338d4f183f28f1f3c1131b9fb2b5a Mon Sep 17 00:00:00 2001 |
| From: Chen Yu <yu.c.chen@intel.com> |
| Date: Sun, 25 Oct 2015 01:02:19 +0800 |
| Subject: ACPI: Use correct IRQ when uninstalling ACPI interrupt handler |
| |
| commit 49e4b84333f338d4f183f28f1f3c1131b9fb2b5a upstream. |
| |
| Currently when the system is trying to uninstall the ACPI interrupt |
| handler, it uses acpi_gbl_FADT.sci_interrupt as the IRQ number. |
| However, the IRQ number that the ACPI interrupt handled is installed |
| for comes from acpi_gsi_to_irq() and that is the number that should |
| be used for the handler removal. |
| |
| Fix this problem by using the mapped IRQ returned from acpi_gsi_to_irq() |
| as appropriate. |
| |
| Acked-by: Lv Zheng <lv.zheng@intel.com> |
| Signed-off-by: Chen Yu <yu.c.chen@intel.com> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| [lizf: Backported to 3.4: adjust context] |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/acpi/osl.c | 9 ++++++--- |
| include/linux/acpi.h | 6 ++++++ |
| 2 files changed, 12 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/acpi/osl.c |
| +++ b/drivers/acpi/osl.c |
| @@ -85,6 +85,7 @@ static void *acpi_irq_context; |
| static struct workqueue_struct *kacpid_wq; |
| static struct workqueue_struct *kacpi_notify_wq; |
| struct workqueue_struct *kacpi_hotplug_wq; |
| +unsigned int acpi_sci_irq = INVALID_ACPI_IRQ; |
| EXPORT_SYMBOL(kacpi_hotplug_wq); |
| |
| /* |
| @@ -612,17 +613,19 @@ acpi_os_install_interrupt_handler(u32 gs |
| acpi_irq_handler = NULL; |
| return AE_NOT_ACQUIRED; |
| } |
| + acpi_sci_irq = irq; |
| |
| return AE_OK; |
| } |
| |
| -acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) |
| +acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler) |
| { |
| - if (irq != acpi_gbl_FADT.sci_interrupt) |
| + if (gsi != acpi_gbl_FADT.sci_interrupt || !acpi_sci_irq_valid()) |
| return AE_BAD_PARAMETER; |
| |
| - free_irq(irq, acpi_irq); |
| + free_irq(acpi_sci_irq, acpi_irq); |
| acpi_irq_handler = NULL; |
| + acpi_sci_irq = INVALID_ACPI_IRQ; |
| |
| return AE_OK; |
| } |
| --- a/include/linux/acpi.h |
| +++ b/include/linux/acpi.h |
| @@ -110,6 +110,12 @@ int acpi_unregister_ioapic(acpi_handle h |
| void acpi_irq_stats_init(void); |
| extern u32 acpi_irq_handled; |
| extern u32 acpi_irq_not_handled; |
| +extern unsigned int acpi_sci_irq; |
| +#define INVALID_ACPI_IRQ ((unsigned)-1) |
| +static inline bool acpi_sci_irq_valid(void) |
| +{ |
| + return acpi_sci_irq != INVALID_ACPI_IRQ; |
| +} |
| |
| extern int sbf_port; |
| extern unsigned long acpi_realmode_flags; |