summaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/acpi/boot.c
diff options
context:
space:
mode:
authorLiu Ping Fan <kernelfans@gmail.com>2013-08-23 16:58:47 +0800
committerIngo Molnar <mingo@kernel.org>2013-08-26 12:58:00 +0200
commit25aa2957973d361081ac6c8b6e5a0d9d7a83fef6 (patch)
treead77338c9f70a2dd2f4c731e71e1a4cd12c29fee /arch/x86/kernel/acpi/boot.c
parent17405453f4ad0220721a29978692081be6392b8f (diff)
x86/ioapic: Check attr against the previous setting when programmed more than once
When programming ioapic pinX more than once, current code does not check whether the later attr (trigger & polarity) is the same as the former or not. This causes broken semantics which can be observed in a qemu q35 machine, where ioapic's ioredtbl[x] can never be set as low-active, even if the hpet driver registered it. And hpet driver may share a high-level active IRQ line with other devices. So in qemu, when hpet-dev asserts low-level as kernel expects, the kernel has no response. With this patch, we can observe an ioredtbl[x] set as low-active for hpet. Fix it by reporting -EBUSY to the caller, when attr is different. Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com> Cc: Kevin Hao <haokexin@gmail.com> Cc: Len Brown <len.brown@intel.com> Cc: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/1377248327-19633-1-git-send-email-pingfank@linux.vnet.ibm.com [ Made small readability edits to both the changelog and the code. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r--arch/x86/kernel/acpi/boot.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 872a2d255e4..81aa73b8ecf 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1120,6 +1120,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
int ioapic;
int ioapic_pin;
struct io_apic_irq_attr irq_attr;
+ int ret;
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -1149,7 +1150,9 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ if (ret < 0)
+ gsi = INT_MIN;
return gsi;
}