From e6323e3c51601e5ccda24024ece3d7cd542378ea Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 19 Jun 2015 15:36:45 -0500 Subject: PCI: Fix generic NCR 53c810 class code quirk In the generic quirk fixup_rev1_53c810(), added by a5312e28c195 ("[PATCH] PCI: NCR 53c810 quirk"), we assigned "class = PCI_CLASS_STORAGE_SCSI". But PCI_CLASS_STORAGE_SCSI is only the two-byte base class/sub-class and needs to be shifted to make space for the low-order interface byte. Furthermore, we had a similar quirk, pci_fixup_ncr53c810(), for arch/x86, which assigned class correctly. The arch code is linked before the PCI core, so arch quirks run before generic quirks. Therefore, on x86, the x86 arch quirk ran first, and the generic quirk did nothing because it saw that dev->class was already set. But on other arches, the generic quirk set the wrong class code. Fix the generic quirk to set the correct class code and remove the now-unnecessary x86-specific quirk. Signed-off-by: Bjorn Helgaas CC: Matthew Wilcox --- arch/x86/pci/fixup.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 9a2b7101ae8a..e58565556703 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -62,19 +62,6 @@ static void pci_fixup_umc_ide(struct pci_dev *d) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide); -static void pci_fixup_ncr53c810(struct pci_dev *d) -{ - /* - * NCR 53C810 returns class code 0 (at least on some systems). - * Fix class to be PCI_CLASS_STORAGE_SCSI - */ - if (!d->class) { - dev_warn(&d->dev, "Fixing NCR 53C810 class code\n"); - d->class = PCI_CLASS_STORAGE_SCSI << 8; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); - static void pci_fixup_latency(struct pci_dev *d) { /* -- cgit v1.2.3 From dff22d2054b5dbb1889f20c03959dd0c494fab8c Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Thu, 9 Jul 2015 11:59:16 +0100 Subject: PCI: Call pci_read_bridge_bases() from core instead of arch code When we scan a PCI bus, we read PCI-PCI bridge window registers with pci_read_bridge_bases() so we can validate the resource hierarchy. Most architectures call pci_read_bridge_bases() from pcibios_fixup_bus(), but PCI-PCI bridges are not arch-specific, so this doesn't need to be in arch-specific code. Call pci_read_bridge_bases() directly from the PCI core instead of from arch code. For alpha and mips, we now call pci_read_bridge_bases() always; previously we only called it if PCI_PROBE_ONLY was set. [bhelgaas: changelog] Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Ralf Baechle CC: James E.J. Bottomley CC: Michael Ellerman CC: Bjorn Helgaas CC: Richard Henderson CC: Benjamin Herrenschmidt CC: David Howells CC: Russell King CC: Tony Luck CC: David S. Miller CC: Ingo Molnar CC: Guenter Roeck CC: Michal Simek CC: Chris Zankel --- arch/alpha/kernel/pci.c | 7 +------ arch/frv/mb93090-mb00/pci-vdk.c | 2 -- arch/ia64/pci/pci.c | 5 ++--- arch/microblaze/pci/pci-common.c | 9 +-------- arch/mips/pci/pci.c | 6 ------ arch/mn10300/unit-asb2305/pci.c | 1 - arch/powerpc/kernel/pci-common.c | 8 +------- arch/x86/pci/common.c | 1 - arch/xtensa/kernel/pci.c | 4 ---- drivers/parisc/dino.c | 3 --- drivers/parisc/lba_pci.c | 1 - drivers/pci/probe.c | 6 ++++++ 12 files changed, 11 insertions(+), 42 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 82f738e5d54c..cded02c890aa 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -242,12 +242,7 @@ pci_restore_srm_config(void) void pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_dev *dev = bus->self; - - if (pci_has_flag(PCI_PROBE_ONLY) && dev && - (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - pci_read_bridge_bases(bus); - } + struct pci_dev *dev; list_for_each_entry(dev, &bus->devices, bus_list) { pdev_save_srm_config(dev); diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index f211839e2cae..f9c86c475bbd 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -294,8 +294,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); #endif - pci_read_bridge_bases(bus); - if (bus->number == 0) { struct pci_dev *dev; list_for_each_entry(dev, &bus->devices, bus_list) { diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 7cc3be9fa7c6..d89b6013c941 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -533,10 +533,9 @@ void pcibios_fixup_bus(struct pci_bus *b) { struct pci_dev *dev; - if (b->self) { - pci_read_bridge_bases(b); + if (b->self) pcibios_fixup_bridge_resources(b->self); - } + list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); platform_pci_fixup_bus(b); diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ae838ed5fcf2..6b8b75266801 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -863,14 +863,7 @@ void pcibios_setup_bus_devices(struct pci_bus *bus) void pcibios_fixup_bus(struct pci_bus *bus) { - /* When called from the generic PCI probe, read PCI<->PCI bridge - * bases. This is -not- called when generating the PCI tree from - * the OF device-tree. - */ - if (bus->self != NULL) - pci_read_bridge_bases(bus); - - /* Now fixup the bus bus */ + /* Fixup the bus */ pcibios_setup_bus_self(bus); /* Now fixup devices on that bus */ diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index b8a0bf5766f2..c6996cf67a5c 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -311,12 +311,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) void pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_dev *dev = bus->self; - - if (pci_has_flag(PCI_PROBE_ONLY) && dev && - (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - pci_read_bridge_bases(bus); - } } EXPORT_SYMBOL(PCIBIOS_MIN_IO); diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 3dfe2d31c67b..deaa893efba5 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -324,7 +324,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) struct pci_dev *dev; if (bus->self) { - pci_read_bridge_bases(bus); pcibios_fixup_bridge_resources(bus->self); } diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index b9de34d44fcb..02c1d5dcee4d 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1044,13 +1044,7 @@ void pcibios_set_master(struct pci_dev *dev) void pcibios_fixup_bus(struct pci_bus *bus) { - /* When called from the generic PCI probe, read PCI<->PCI bridge - * bases. This is -not- called when generating the PCI tree from - * the OF device-tree. - */ - pci_read_bridge_bases(bus); - - /* Now fixup the bus bus */ + /* Fixup the bus */ pcibios_setup_bus_self(bus); /* Now fixup devices on that bus */ diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 8fd6f44aee83..3bff24438b00 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -166,7 +166,6 @@ void pcibios_fixup_bus(struct pci_bus *b) { struct pci_dev *dev; - pci_read_bridge_bases(b); list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); } diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index b848cc3dc913..d27b4dcf221f 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -210,10 +210,6 @@ subsys_initcall(pcibios_init); void pcibios_fixup_bus(struct pci_bus *bus) { - if (bus->parent) { - /* This is a subordinate bridge */ - pci_read_bridge_bases(bus); - } } void pcibios_set_master(struct pci_dev *dev) diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index a0580afe1713..baec33c4e698 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -560,9 +560,6 @@ dino_fixup_bus(struct pci_bus *bus) } else if (bus->parent) { int i; - pci_read_bridge_bases(bus); - - for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { if((bus->self->resource[i].flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index dceb9ddfd99a..901e1a3fa4e2 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -693,7 +693,6 @@ lba_fixup_bus(struct pci_bus *bus) if (bus->parent) { int i; /* PCI-PCI Bridge */ - pci_read_bridge_bases(bus); for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) pci_claim_bridge_resource(bus->self, i); } else { diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cefd636681b6..b996aefc1092 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -826,6 +826,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) child->bridge_ctl = bctl; } + /* Read and initialize bridge resources */ + pci_read_bridge_bases(child); + cmax = pci_scan_child_bus(child); if (cmax > subordinate) dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n", @@ -886,6 +889,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) if (!is_cardbus) { child->bridge_ctl = bctl; + + /* Read and initialize bridge resources */ + pci_read_bridge_bases(child); max = pci_scan_child_bus(child); } else { /* -- cgit v1.2.3 From 991de2e59090e55c65a7f59a049142e3c480f7bd Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 10 Jun 2015 16:54:59 +0800 Subject: PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq() To support IOAPIC hotplug, we need to allocate PCI IRQ resources on demand and free them when not used anymore. Implement pcibios_alloc_irq() and pcibios_free_irq() to dynamically allocate and free PCI IRQs. Remove mp_should_keep_irq(), which is no longer used. [bhelgaas: changelog] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Acked-by: Thomas Gleixner --- arch/x86/include/asm/pci_x86.h | 2 -- arch/x86/pci/common.c | 20 +++++++++----------- arch/x86/pci/intel_mid_pci.c | 7 +++++-- arch/x86/pci/irq.c | 15 +-------------- drivers/acpi/pci_irq.c | 9 +-------- 5 files changed, 16 insertions(+), 37 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index 164e3f8d3c3d..fa1195dae425 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -93,8 +93,6 @@ 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); diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 8fd6f44aee83..dc78a4a9a466 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -673,24 +673,22 @@ int pcibios_add_device(struct pci_dev *dev) return 0; } -int pcibios_enable_device(struct pci_dev *dev, int mask) +int pcibios_alloc_irq(struct pci_dev *dev) { - 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; + return pcibios_enable_irq(dev); } -void pcibios_disable_device (struct pci_dev *dev) +void pcibios_free_irq(struct pci_dev *dev) { - if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq) + 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 pci_ext_cfg_avail(void) { if (raw_pci_ext_ops) diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 27062303c881..fb7a1f96d80c 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c @@ -234,10 +234,13 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) static void intel_mid_pci_irq_disable(struct pci_dev *dev) { - if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed && - dev->irq > 0) { + if (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. + */ } } diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 9bd115484745..72108f0b66b1 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1257,22 +1257,9 @@ 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 && !mp_should_keep_irq(&dev->dev) && - dev->irq_managed && dev->irq) { + if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) { mp_unmap_irq(dev->irq); dev->irq = 0; dev->irq_managed = 0; diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 304eccb0ae5c..d1aad6900b4c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -484,14 +484,6 @@ 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; @@ -512,5 +504,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) if (gsi >= 0) { acpi_unregister_gsi(gsi); dev->irq_managed = 0; + dev->irq = 0; } } -- cgit v1.2.3 From 811a4e6fce09bc9239c664c6a1a53645a678c303 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 10 Jun 2015 16:55:00 +0800 Subject: PCI: Add helpers to manage pci_dev->irq and pci_dev->irq_managed Add pci_has_managed_irq(), pci_set_managed_irq(), and pci_reset_managed_irq() to simplify code. No functional change. [bhelgaas: changelog] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Acked-by: Thomas Gleixner --- arch/x86/pci/intel_mid_pci.c | 4 ++-- arch/x86/pci/irq.c | 10 ++++------ drivers/acpi/pci_irq.c | 10 ++++------ include/linux/pci.h | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 14 deletions(-) (limited to 'arch/x86/pci') diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index fb7a1f96d80c..22aaefb4f1ca 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c @@ -211,7 +211,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev) struct irq_alloc_info info; int polarity; - if (dev->irq_managed && dev->irq > 0) + if (pci_has_managed_irq(dev)) return 0; if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER) @@ -234,7 +234,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->irq_managed && dev->irq > 0) { + if (pci_has_managed_irq(dev)) { mp_unmap_irq(dev->irq); dev->irq_managed = 0; /* diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 72108f0b66b1..32e70343e6fd 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev) struct pci_dev *temp_dev; int irq; - if (dev->irq_managed && dev->irq > 0) + if (pci_has_managed_irq(dev)) return 0; irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, @@ -1230,8 +1230,7 @@ static int pirq_enable_irq(struct pci_dev *dev) } dev = temp_dev; if (irq >= 0) { - dev->irq_managed = 1; - dev->irq = irq; + pci_set_managed_irq(dev, irq); dev_info(&dev->dev, "PCI->APIC IRQ transform: " "INT %c -> IRQ %d\n", 'A' + pin - 1, irq); return 0; @@ -1259,9 +1258,8 @@ 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->irq_managed && dev->irq) { + if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) { mp_unmap_irq(dev->irq); - dev->irq = 0; - dev->irq_managed = 0; + pci_reset_managed_irq(dev); } } diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index d1aad6900b4c..afa16c557c17 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -412,7 +412,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) return 0; } - if (dev->irq_managed && dev->irq > 0) + if (pci_has_managed_irq(dev)) return 0; entry = acpi_pci_irq_lookup(dev, pin); @@ -457,8 +457,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) kfree(entry); return rc; } - dev->irq = rc; - dev->irq_managed = 1; + pci_set_managed_irq(dev, rc); if (link) snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); @@ -481,7 +480,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) u8 pin; pin = dev->pin; - if (!pin || !dev->irq_managed || dev->irq <= 0) + if (!pin || !pci_has_managed_irq(dev)) return; entry = acpi_pci_irq_lookup(dev, pin); @@ -503,7 +502,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); if (gsi >= 0) { acpi_unregister_gsi(gsi); - dev->irq_managed = 0; - dev->irq = 0; + pci_reset_managed_irq(dev); } } diff --git a/include/linux/pci.h b/include/linux/pci.h index b4832c92f23e..b7ab0c424ed6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -963,6 +963,23 @@ static inline int pci_is_managed(struct pci_dev *pdev) return pdev->is_managed; } +static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq) +{ + pdev->irq = irq; + pdev->irq_managed = 1; +} + +static inline void pci_reset_managed_irq(struct pci_dev *pdev) +{ + pdev->irq = 0; + pdev->irq_managed = 0; +} + +static inline bool pci_has_managed_irq(struct pci_dev *pdev) +{ + return pdev->irq_managed && pdev->irq > 0; +} + void pci_disable_device(struct pci_dev *dev); extern unsigned int pcibios_max_latency; -- cgit v1.2.3