aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-02-17 13:26:42 -0500
committerBjorn Helgaas <bhelgaas@google.com>2016-02-27 09:52:20 -0500
commit6c777e8799a93e3bdb67bec622429e1b48dc90fb (patch)
tree8ae158e261d35760cacf63fb1b400eabf0e4d80f
parent67b4eab91caf2ad574cab1b17ae09180ea2e116e (diff)
Revert "PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()"
991de2e59090 ("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 991de2e59090. 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 991de2e59090, we no longer call pcibios_enable_irq() for upstream bridges. Prior to 991de2e59090, when a driver called pci_enable_device(), we recursively called pcibios_enable_irq() for upstream bridges via pci_enable_bridge(). After 991de2e59090, 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 991de2e59090 to fix these driver regressions. Link: https://bugzilla.kernel.org/show_bug.cgi?id=111211 Fixes: 991de2e59090 ("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>
-rw-r--r--arch/x86/include/asm/pci_x86.h2
-rw-r--r--arch/x86/pci/common.c20
-rw-r--r--arch/x86/pci/intel_mid_pci.c7
-rw-r--r--arch/x86/pci/irq.c15
-rw-r--r--drivers/acpi/pci_irq.c9
5 files changed, 37 insertions, 16 deletions
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 46873fbd44e1..d08eacd298c2 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
93extern int (*pcibios_enable_irq)(struct pci_dev *dev); 93extern int (*pcibios_enable_irq)(struct pci_dev *dev);
94extern void (*pcibios_disable_irq)(struct pci_dev *dev); 94extern void (*pcibios_disable_irq)(struct pci_dev *dev);
95 95
96extern bool mp_should_keep_irq(struct device *dev);
97
96struct pci_raw_ops { 98struct pci_raw_ops {
97 int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn, 99 int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
98 int reg, int len, u32 *val); 100 int reg, int len, u32 *val);
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index cb499c5b6ae5..d34b5118b4e8 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -711,20 +711,22 @@ int pcibios_add_device(struct pci_dev *dev)
711 return 0; 711 return 0;
712} 712}
713 713
714int pcibios_alloc_irq(struct pci_dev *dev) 714int pcibios_enable_device(struct pci_dev *dev, int mask)
715{ 715{
716 return pcibios_enable_irq(dev); 716 int err;
717}
718 717
719void pcibios_free_irq(struct pci_dev *dev) 718 if ((err = pci_enable_resources(dev, mask)) < 0)
720{ 719 return err;
721 if (pcibios_disable_irq) 720
722 pcibios_disable_irq(dev); 721 if (!pci_dev_msi_enabled(dev))
722 return pcibios_enable_irq(dev);
723 return 0;
723} 724}
724 725
725int pcibios_enable_device(struct pci_dev *dev, int mask) 726void pcibios_disable_device (struct pci_dev *dev)
726{ 727{
727 return pci_enable_resources(dev, mask); 728 if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
729 pcibios_disable_irq(dev);
728} 730}
729 731
730int pci_ext_cfg_avail(void) 732int pci_ext_cfg_avail(void)
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 8826ff593ebc..8b93e634af84 100644
--- a/arch/x86/pci/intel_mid_pci.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
256 256
257static void intel_mid_pci_irq_disable(struct pci_dev *dev) 257static void intel_mid_pci_irq_disable(struct pci_dev *dev)
258{ 258{
259 if (dev->irq_managed && dev->irq > 0) { 259 if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
260 dev->irq > 0) {
260 mp_unmap_irq(dev->irq); 261 mp_unmap_irq(dev->irq);
261 dev->irq_managed = 0; 262 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 */
266 } 263 }
267} 264}
268 265
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 72108f0b66b1..9bd115484745 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1257,9 +1257,22 @@ static int pirq_enable_irq(struct pci_dev *dev)
1257 return 0; 1257 return 0;
1258} 1258}
1259 1259
1260bool 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
1260static void pirq_disable_irq(struct pci_dev *dev) 1272static void pirq_disable_irq(struct pci_dev *dev)
1261{ 1273{
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) {
1263 mp_unmap_irq(dev->irq); 1276 mp_unmap_irq(dev->irq);
1264 dev->irq = 0; 1277 dev->irq = 0;
1265 dev->irq_managed = 0; 1278 dev->irq_managed = 0;
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 9032db7e4b3a..c8e169e46673 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -478,6 +478,14 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
478 if (!pin || !dev->irq_managed || dev->irq <= 0) 478 if (!pin || !dev->irq_managed || dev->irq <= 0)
479 return; 479 return;
480 480
481 /* Keep IOAPIC pin configuration when suspending */
482 if (dev->dev.power.is_prepared)
483 return;
484#ifdef CONFIG_PM
485 if (dev->dev.power.runtime_status == RPM_SUSPENDING)
486 return;
487#endif
488
481 entry = acpi_pci_irq_lookup(dev, pin); 489 entry = acpi_pci_irq_lookup(dev, pin);
482 if (!entry) 490 if (!entry)
483 return; 491 return;
@@ -498,6 +506,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
498 if (gsi >= 0) { 506 if (gsi >= 0) {
499 acpi_unregister_gsi(gsi); 507 acpi_unregister_gsi(gsi);
500 dev->irq_managed = 0; 508 dev->irq_managed = 0;
501 dev->irq = 0;
502 } 509 }
503} 510}