mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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
5 changed files with 40 additions and 19 deletions
|
@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
|
||||||
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
|
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
|
||||||
extern void (*pcibios_disable_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 {
|
struct pci_raw_ops {
|
||||||
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
|
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
|
||||||
int reg, int len, u32 *val);
|
int reg, int len, u32 *val);
|
||||||
|
|
|
@ -711,20 +711,22 @@ int pcibios_add_device(struct pci_dev *dev)
|
||||||
return 0;
|
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)
|
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)
|
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)
|
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);
|
mp_unmap_irq(dev->irq);
|
||||||
dev->irq_managed = 0;
|
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;
|
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)
|
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);
|
mp_unmap_irq(dev->irq);
|
||||||
dev->irq = 0;
|
dev->irq = 0;
|
||||||
dev->irq_managed = 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)
|
if (!pin || !dev->irq_managed || dev->irq <= 0)
|
||||||
return;
|
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);
|
entry = acpi_pci_irq_lookup(dev, pin);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
|
@ -498,6 +506,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||||
if (gsi >= 0) {
|
if (gsi >= 0) {
|
||||||
acpi_unregister_gsi(gsi);
|
acpi_unregister_gsi(gsi);
|
||||||
dev->irq_managed = 0;
|
dev->irq_managed = 0;
|
||||||
dev->irq = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue