Commit fd5984d7c8e8e249aca0c515817ab1e7dee1502c

Authored by Linus Torvalds

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

Showing 7 changed files Side-by-side Diff

arch/x86/include/asm/io_apic.h
... ... @@ -227,6 +227,8 @@
227 227  
228 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 232 #else /* !CONFIG_X86_IO_APIC */
231 233  
232 234 #define io_apic_assign_pci_irqs 0
arch/x86/kernel/apic/io_apic.c
... ... @@ -1070,6 +1070,11 @@
1070 1070 }
1071 1071  
1072 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 1078 if (irq > 0)
1074 1079 info->count++;
1075 1080 else if (info->count == 0)
... ... @@ -3896,7 +3901,15 @@
3896 3901 info->polarity = 1;
3897 3902 }
3898 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 3914 set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
3902 3915 info->polarity);
... ... @@ -3944,6 +3957,18 @@
3944 3957 mutex_unlock(&ioapic_mutex);
3945 3958  
3946 3959 return ret;
  3960 +}
  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;
3947 3972 }
3948 3973  
3949 3974 /* Enable IOAPIC early just for system timer */
arch/x86/kernel/irqinit.c
... ... @@ -203,7 +203,7 @@
203 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 207 setup_irq(2, &irq2);
208 208  
209 209 #ifdef CONFIG_X86_32
arch/x86/kernel/time.c
... ... @@ -68,6 +68,8 @@
68 68  
69 69 void __init setup_default_timer_irq(void)
70 70 {
  71 + if (!nr_legacy_irqs())
  72 + return;
71 73 setup_irq(0, &irq0);
72 74 }
73 75  
arch/x86/pci/intel_mid_pci.c
... ... @@ -229,7 +229,7 @@
229 229  
230 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 233 mp_unmap_irq(dev->irq);
234 234 }
235 235  
... ... @@ -1256,7 +1256,7 @@
1256 1256  
1257 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 1260 dev->irq) {
1261 1261 mp_unmap_irq(dev->irq);
1262 1262 dev->irq = 0;
drivers/acpi/pci_irq.c
... ... @@ -484,6 +484,10 @@
484 484 /* Keep IOAPIC pin configuration when suspending */
485 485 if (dev->dev.power.is_prepared)
486 486 return;
  487 +#ifdef CONFIG_PM_RUNTIME
  488 + if (dev->dev.power.runtime_status == RPM_SUSPENDING)
  489 + return;
  490 +#endif
487 491  
488 492 entry = acpi_pci_irq_lookup(dev, pin);
489 493 if (!entry)