Skip to content

Commit c149165

Browse files
bjorn-helgaasgregkh
authored andcommitted
Revert "PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()"
commit 6c777e8799a93e3bdb67bec622429e1b48dc90fb upstream. 991de2e ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") appeared in v4.3 and helps support IOAPIC hotplug. Олег reported that the Elcus-1553 TA1-PCI driver worked in v4.2 but not v4.3 and bisected it to 991de2e. Sunjin reported that the RocketRAID 272x driver worked in v4.2 but not v4.3. In both cases booting with "pci=routirq" is a workaround. I think the problem is that after 991de2e, we no longer call pcibios_enable_irq() for upstream bridges. Prior to 991de2e, when a driver called pci_enable_device(), we recursively called pcibios_enable_irq() for upstream bridges via pci_enable_bridge(). After 991de2e, we call pcibios_enable_irq() from pci_device_probe() instead of the pci_enable_device() path, which does *not* call pcibios_enable_irq() for upstream bridges. Revert 991de2e to fix these driver regressions. Link: https://bugzilla.kernel.org/show_bug.cgi?id=111211 Fixes: 991de2e ("PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()") Reported-and-tested-by: Олег Мороз <oleg.moroz@mcc.vniiem.ru> Reported-by: Sunjin Yang <fan4326@gmail.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rafael@kernel.org> CC: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 2d0d001 commit c149165

5 files changed

Lines changed: 37 additions & 16 deletions

File tree

arch/x86/include/asm/pci_x86.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
9393
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
9494
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
9595

96+
extern bool mp_should_keep_irq(struct device *dev);
97+
9698
struct pci_raw_ops {
9799
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
98100
int reg, int len, u32 *val);

arch/x86/pci/common.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -673,20 +673,22 @@ int pcibios_add_device(struct pci_dev *dev)
673673
return 0;
674674
}
675675

676-
int pcibios_alloc_irq(struct pci_dev *dev)
676+
int pcibios_enable_device(struct pci_dev *dev, int mask)
677677
{
678-
return pcibios_enable_irq(dev);
679-
}
678+
int err;
680679

681-
void pcibios_free_irq(struct pci_dev *dev)
682-
{
683-
if (pcibios_disable_irq)
684-
pcibios_disable_irq(dev);
680+
if ((err = pci_enable_resources(dev, mask)) < 0)
681+
return err;
682+
683+
if (!pci_dev_msi_enabled(dev))
684+
return pcibios_enable_irq(dev);
685+
return 0;
685686
}
686687

687-
int pcibios_enable_device(struct pci_dev *dev, int mask)
688+
void pcibios_disable_device (struct pci_dev *dev)
688689
{
689-
return pci_enable_resources(dev, mask);
690+
if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
691+
pcibios_disable_irq(dev);
690692
}
691693

692694
int pci_ext_cfg_avail(void)

arch/x86/pci/intel_mid_pci.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
256256

257257
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
258258
{
259-
if (dev->irq_managed && dev->irq > 0) {
259+
if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
260+
dev->irq > 0) {
260261
mp_unmap_irq(dev->irq);
261262
dev->irq_managed = 0;
262-
/*
263-
* Don't reset dev->irq here, otherwise
264-
* intel_mid_pci_irq_enable() will fail on next call.
265-
*/
266263
}
267264
}
268265

arch/x86/pci/irq.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,22 @@ static int pirq_enable_irq(struct pci_dev *dev)
12571257
return 0;
12581258
}
12591259

1260+
bool mp_should_keep_irq(struct device *dev)
1261+
{
1262+
if (dev->power.is_prepared)
1263+
return true;
1264+
#ifdef CONFIG_PM
1265+
if (dev->power.runtime_status == RPM_SUSPENDING)
1266+
return true;
1267+
#endif
1268+
1269+
return false;
1270+
}
1271+
12601272
static void pirq_disable_irq(struct pci_dev *dev)
12611273
{
1262-
if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
1274+
if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
1275+
dev->irq_managed && dev->irq) {
12631276
mp_unmap_irq(dev->irq);
12641277
dev->irq = 0;
12651278
dev->irq_managed = 0;

drivers/acpi/pci_irq.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
481481
if (!pin || !dev->irq_managed || dev->irq <= 0)
482482
return;
483483

484+
/* Keep IOAPIC pin configuration when suspending */
485+
if (dev->dev.power.is_prepared)
486+
return;
487+
#ifdef CONFIG_PM
488+
if (dev->dev.power.runtime_status == RPM_SUSPENDING)
489+
return;
490+
#endif
491+
484492
entry = acpi_pci_irq_lookup(dev, pin);
485493
if (!entry)
486494
return;
@@ -501,6 +509,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
501509
if (gsi >= 0) {
502510
acpi_unregister_gsi(gsi);
503511
dev->irq_managed = 0;
504-
dev->irq = 0;
505512
}
506513
}

0 commit comments

Comments
 (0)