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 | 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 |
| @@ -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 | 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, · 2820 unmodified lines | |||
| 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) · 43 unmodified lines | |||
| 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 | { |
| @@ -203,7 +203,7 @@ void __init native_init_IRQ(void) · 202 unmodified lines | |||
| 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 |
| @@ -68,6 +68,8 @@ static struct irqaction irq0 = { · 67 unmodified lines | |||
| 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 | ||
| @@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) · 228 unmodified lines | |||
| 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 | ||
| @@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev) · 1255 unmodified lines | |||
| 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; |
| @@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev) · 483 unmodified lines | |||
| 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) |