Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9eabc99a authored by Jiang Liu's avatar Jiang Liu Committed by Thomas Gleixner
Browse files

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 3eec5952 "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: default avatarEmanueL Czirai <amanual@openmailbox.org>
Signed-off-by: default avatarJiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: EmanueL Czirai <amanual@openmailbox.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Grant Likely <grant.likely@linaro.org>
Link: http://lkml.kernel.org/r/1409304383-18806-1-git-send-email-jiang.liu@linux.intel.com


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent f395dcae
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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)