x86, irq, PCI: Keep IRQ assignment for runtime power management

Now IOAPIC driver dynamically allocates IRQ numbers for IOAPIC pins.
We need to keep IRQ assignment for PCI devices during runtime power
management, otherwise it may cause failure of device wakeups.

Commit 3eec595235 "x86, irq, PCI: Keep IRQ assignment for PCI
devices during suspend/hibernation" has fixed the issue for suspend/
hibernation, we also need the same fix for runtime device sleep too.

Fix: https://bugzilla.kernel.org/show_bug.cgi?id=83271
Reported-and-Tested-by: EmanueL Czirai <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
Cc: Konrad Rzeszutek Wilk <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Joerg Roedel <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: EmanueL Czirai <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: Randy Dunlap <[email protected]>
Cc: Yinghai Lu <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Grant Likely <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
This commit is contained in:
Jiang Liu authored and Thomas Gleixner committed 2014-08-29 13:38:00 +02:00
1 parent f395dcae7a
commit 9eabc99a63
5 files changed
+20 -2

No files matched your search

+2
View File
@@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
extern void io_apic_eoi(unsigned int apic, unsigned int vector);
extern bool mp_should_keep_irq(struct device *dev);
#else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0
+12
View File
@@ -3959,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
return ret;
}
bool mp_should_keep_irq(struct device *dev)
{
if (dev->power.is_prepared)
return true;
#ifdef CONFIG_PM_RUNTIME
if (dev->power.runtime_status == RPM_SUSPENDING)
return true;
#endif
return false;
}
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
+1 -1
View File
@@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
{
if (!dev->dev.power.is_prepared && dev->irq > 0)
if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
mp_unmap_irq(dev->irq);
}
+1 -1
View File
@@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
static void pirq_disable_irq(struct pci_dev *dev)
{
if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared &&
if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
dev->irq) {
mp_unmap_irq(dev->irq);
dev->irq = 0;
+4
View File
@@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
/* Keep IOAPIC pin configuration when suspending */
if (dev->dev.power.is_prepared)
return;
#ifdef CONFIG_PM_RUNTIME
if (dev->dev.power.runtime_status == RPM_SUSPENDING)
return;
#endif
entry = acpi_pci_irq_lookup(dev, pin);
if (!entry)