Revert "PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()"
991de2e590
("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 to991de2e590
. 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 after991de2e590
, we no longer call pcibios_enable_irq() for upstream bridges. Prior to991de2e590
, when a driver called pci_enable_device(), we recursively called pcibios_enable_irq() for upstream bridges via pci_enable_bridge(). After991de2e590
, 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. Revert991de2e590
to fix these driver regressions. Link: https://bugzilla.kernel.org/show_bug.cgi?id=111211 Fixes:991de2e590
("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>
This commit is contained in:
parent
67b4eab91c
commit
6c777e8799
@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
|
||||
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
|
||||
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
|
||||
|
||||
extern bool mp_should_keep_irq(struct device *dev);
|
||||
|
||||
struct pci_raw_ops {
|
||||
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
|
||||
int reg, int len, u32 *val);
|
||||
|
@ -711,20 +711,22 @@ int pcibios_add_device(struct pci_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_alloc_irq(struct pci_dev *dev)
|
||||
{
|
||||
return pcibios_enable_irq(dev);
|
||||
}
|
||||
|
||||
void pcibios_free_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (pcibios_disable_irq)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
return pci_enable_resources(dev, mask);
|
||||
int err;
|
||||
|
||||
if ((err = pci_enable_resources(dev, mask)) < 0)
|
||||
return err;
|
||||
|
||||
if (!pci_dev_msi_enabled(dev))
|
||||
return pcibios_enable_irq(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcibios_disable_device (struct pci_dev *dev)
|
||||
{
|
||||
if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pci_ext_cfg_avail(void)
|
||||
|
@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
||||
|
||||
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->irq_managed && dev->irq > 0) {
|
||||
if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
|
||||
dev->irq > 0) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
dev->irq_managed = 0;
|
||||
/*
|
||||
* Don't reset dev->irq here, otherwise
|
||||
* intel_mid_pci_irq_enable() will fail on next call.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,9 +1257,22 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mp_should_keep_irq(struct device *dev)
|
||||
{
|
||||
if (dev->power.is_prepared)
|
||||
return true;
|
||||
#ifdef CONFIG_PM
|
||||
if (dev->power.runtime_status == RPM_SUSPENDING)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pirq_disable_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
|
||||
if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
|
||||
dev->irq_managed && dev->irq) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
dev->irq = 0;
|
||||
dev->irq_managed = 0;
|
||||
|
@ -478,6 +478,14 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||
if (!pin || !dev->irq_managed || dev->irq <= 0)
|
||||
return;
|
||||
|
||||
/* Keep IOAPIC pin configuration when suspending */
|
||||
if (dev->dev.power.is_prepared)
|
||||
return;
|
||||
#ifdef CONFIG_PM
|
||||
if (dev->dev.power.runtime_status == RPM_SUSPENDING)
|
||||
return;
|
||||
#endif
|
||||
|
||||
entry = acpi_pci_irq_lookup(dev, pin);
|
||||
if (!entry)
|
||||
return;
|
||||
@ -498,6 +506,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||
if (gsi >= 0) {
|
||||
acpi_unregister_gsi(gsi);
|
||||
dev->irq_managed = 0;
|
||||
dev->irq = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user