diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-29 20:22:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-29 20:22:27 -0400 |
commit | fd5984d7c8e8e249aca0c515817ab1e7dee1502c (patch) | |
tree | 9997f5b130fe54f067824f0ff22900b2c99c03d5 | |
parent | ad6ede80a0ad0eba6e0f77e35ab7753c60ed1e87 (diff) | |
parent | 9eabc99a635a77cbf0948ce17d3cbc2b51680d4a (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Peter Anvin:
"One patch to avoid assigning interrupts we don't actually have on
non-PC platforms, and two patches that addresses bugs in the new
IOAPIC assignment code"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, irq, PCI: Keep IRQ assignment for runtime power management
x86: irq: Fix bug in setting IOAPIC pin attributes
x86: Fix non-PC platform kernel crash on boot due to NULL dereference
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 27 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/intel_mid_pci.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 2 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 4 |
7 files changed, 37 insertions, 4 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 0aeed5ca356e..478c490f3654 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned | |||
227 | 227 | ||
228 | extern void io_apic_eoi(unsigned int apic, unsigned int vector); | 228 | extern void io_apic_eoi(unsigned int apic, unsigned int vector); |
229 | 229 | ||
230 | extern bool mp_should_keep_irq(struct device *dev); | ||
231 | |||
230 | #else /* !CONFIG_X86_IO_APIC */ | 232 | #else /* !CONFIG_X86_IO_APIC */ |
231 | 233 | ||
232 | #define io_apic_assign_pci_irqs 0 | 234 | #define io_apic_assign_pci_irqs 0 |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 29290f554e79..337ce5a9b15c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1070,6 +1070,11 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, | |||
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | if (flags & IOAPIC_MAP_ALLOC) { | 1072 | if (flags & IOAPIC_MAP_ALLOC) { |
1073 | /* special handling for legacy IRQs */ | ||
1074 | if (irq < nr_legacy_irqs() && info->count == 1 && | ||
1075 | mp_irqdomain_map(domain, irq, pin) != 0) | ||
1076 | irq = -1; | ||
1077 | |||
1073 | if (irq > 0) | 1078 | if (irq > 0) |
1074 | info->count++; | 1079 | info->count++; |
1075 | else if (info->count == 0) | 1080 | else if (info->count == 0) |
@@ -3896,7 +3901,15 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq, | |||
3896 | info->polarity = 1; | 3901 | info->polarity = 1; |
3897 | } | 3902 | } |
3898 | info->node = NUMA_NO_NODE; | 3903 | info->node = NUMA_NO_NODE; |
3899 | info->set = 1; | 3904 | |
3905 | /* | ||
3906 | * setup_IO_APIC_irqs() programs all legacy IRQs with default | ||
3907 | * trigger and polarity attributes. Don't set the flag for that | ||
3908 | * case so the first legacy IRQ user could reprogram the pin | ||
3909 | * with real trigger and polarity attributes. | ||
3910 | */ | ||
3911 | if (virq >= nr_legacy_irqs() || info->count) | ||
3912 | info->set = 1; | ||
3900 | } | 3913 | } |
3901 | set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger, | 3914 | set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger, |
3902 | info->polarity); | 3915 | info->polarity); |
@@ -3946,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node) | |||
3946 | return ret; | 3959 | return ret; |
3947 | } | 3960 | } |
3948 | 3961 | ||
3962 | bool mp_should_keep_irq(struct device *dev) | ||
3963 | { | ||
3964 | if (dev->power.is_prepared) | ||
3965 | return true; | ||
3966 | #ifdef CONFIG_PM_RUNTIME | ||
3967 | if (dev->power.runtime_status == RPM_SUSPENDING) | ||
3968 | return true; | ||
3969 | #endif | ||
3970 | |||
3971 | return false; | ||
3972 | } | ||
3973 | |||
3949 | /* Enable IOAPIC early just for system timer */ | 3974 | /* Enable IOAPIC early just for system timer */ |
3950 | void __init pre_init_apic_IRQ0(void) | 3975 | void __init pre_init_apic_IRQ0(void) |
3951 | { | 3976 | { |
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 1e6cff5814fa..44f1ed42fdf2 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -203,7 +203,7 @@ void __init native_init_IRQ(void) | |||
203 | set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); | 203 | set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); |
204 | } | 204 | } |
205 | 205 | ||
206 | if (!acpi_ioapic && !of_ioapic) | 206 | if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) |
207 | setup_irq(2, &irq2); | 207 | setup_irq(2, &irq2); |
208 | 208 | ||
209 | #ifdef CONFIG_X86_32 | 209 | #ifdef CONFIG_X86_32 |
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index bf7ef5ce29df..0fa29609b2c4 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c | |||
@@ -68,6 +68,8 @@ static struct irqaction irq0 = { | |||
68 | 68 | ||
69 | void __init setup_default_timer_irq(void) | 69 | void __init setup_default_timer_irq(void) |
70 | { | 70 | { |
71 | if (!nr_legacy_irqs()) | ||
72 | return; | ||
71 | setup_irq(0, &irq0); | 73 | setup_irq(0, &irq0); |
72 | } | 74 | } |
73 | 75 | ||
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 3865116c51fb..b9958c364075 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c | |||
@@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) | |||
229 | 229 | ||
230 | static void intel_mid_pci_irq_disable(struct pci_dev *dev) | 230 | static void intel_mid_pci_irq_disable(struct pci_dev *dev) |
231 | { | 231 | { |
232 | if (!dev->dev.power.is_prepared && dev->irq > 0) | 232 | if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0) |
233 | mp_unmap_irq(dev->irq); | 233 | mp_unmap_irq(dev->irq); |
234 | } | 234 | } |
235 | 235 | ||
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index bc1a2c341891..eb500c2592ad 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev) | |||
1256 | 1256 | ||
1257 | static void pirq_disable_irq(struct pci_dev *dev) | 1257 | static void pirq_disable_irq(struct pci_dev *dev) |
1258 | { | 1258 | { |
1259 | if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared && | 1259 | if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && |
1260 | dev->irq) { | 1260 | dev->irq) { |
1261 | mp_unmap_irq(dev->irq); | 1261 | mp_unmap_irq(dev->irq); |
1262 | dev->irq = 0; | 1262 | dev->irq = 0; |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index c96887d5289e..6e6b80eb0bba 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev) | |||
484 | /* Keep IOAPIC pin configuration when suspending */ | 484 | /* Keep IOAPIC pin configuration when suspending */ |
485 | if (dev->dev.power.is_prepared) | 485 | if (dev->dev.power.is_prepared) |
486 | return; | 486 | return; |
487 | #ifdef CONFIG_PM_RUNTIME | ||
488 | if (dev->dev.power.runtime_status == RPM_SUSPENDING) | ||
489 | return; | ||
490 | #endif | ||
487 | 491 | ||
488 | entry = acpi_pci_irq_lookup(dev, pin); | 492 | entry = acpi_pci_irq_lookup(dev, pin); |
489 | if (!entry) | 493 | if (!entry) |