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
Unified · Split
| @@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned · 226 unmodified lines | ||
| 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 |
| @@ -1070,6 +1070,11 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, · 1069 unmodified lines | ||
| 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 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq, · 2820 unmodified lines | ||
| 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); |
| @@ -3946,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node) · 43 unmodified lines | ||
| 3946 | 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 | 3974 | /* Enable IOAPIC early just for system timer */ |
| 3950 | 3975 | void __init pre_init_apic_IRQ0(void) |
| 3951 | 3976 | { |
| @@ -203,7 +203,7 @@ void __init native_init_IRQ(void) · 202 unmodified lines | ||
| 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 |
| @@ -68,6 +68,8 @@ static struct irqaction irq0 = { · 67 unmodified lines | ||
| 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 | |
| @@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) · 228 unmodified lines | ||
| 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 @@ static int pirq_enable_irq(struct pci_dev *dev) · 1255 unmodified lines | ||
| 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; |
| @@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev) · 483 unmodified lines | ||
| 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) |