summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/kernel/pci.c7
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.c8
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.h8
-rw-r--r--arch/frv/mb93090-mb00/pci-vdk.c2
-rw-r--r--arch/ia64/pci/pci.c5
-rw-r--r--arch/microblaze/pci/pci-common.c9
-rw-r--r--arch/mips/pci/pci.c6
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.c22
-rw-r--r--arch/mn10300/unit-asb2305/pci-asb2305.h7
-rw-r--r--arch/mn10300/unit-asb2305/pci.c1
-rw-r--r--arch/powerpc/kernel/pci-common.c8
-rw-r--r--arch/sh/drivers/pci/pci-sh4.h8
-rw-r--r--arch/x86/include/asm/pci_x86.h2
-rw-r--r--arch/x86/pci/common.c21
-rw-r--r--arch/x86/pci/fixup.c13
-rw-r--r--arch/x86/pci/intel_mid_pci.c9
-rw-r--r--arch/x86/pci/irq.c23
-rw-r--r--arch/xtensa/kernel/pci.c4
-rw-r--r--drivers/acpi/pci_irq.c17
-rw-r--r--drivers/parisc/dino.c3
-rw-r--r--drivers/parisc/lba_pci.c1
-rw-r--r--drivers/pci/access.c84
-rw-r--r--drivers/pci/msi.c5
-rw-r--r--drivers/pci/pci-acpi.c2
-rw-r--r--drivers/pci/pci-driver.c26
-rw-r--r--drivers/pci/pci.c12
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/portdrv_core.c2
-rw-r--r--drivers/pci/probe.c8
-rw-r--r--drivers/pci/quirks.c108
-rw-r--r--include/linux/pci.h21
31 files changed, 239 insertions, 215 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 82f738e..cded02c 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-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index 0635bd6..34bb4b1 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -175,14 +175,6 @@ static void __init pcibios_assign_resources(void)
if (!r->start && r->end)
pci_assign_resource(dev, idx);
}
-
- if (pci_probe & PCI_ASSIGN_ROMS) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
- }
}
}
diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
index a7e487fe..d51992f 100644
--- a/arch/frv/mb93090-mb00/pci-frv.h
+++ b/arch/frv/mb93090-mb00/pci-frv.h
@@ -14,14 +14,6 @@
#define DBG(x...)
#endif
-#define PCI_PROBE_BIOS 0x0001
-#define PCI_PROBE_CONF1 0x0002
-#define PCI_PROBE_CONF2 0x0004
-#define PCI_NO_CHECKS 0x0400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-#define PCI_ASSIGN_ALL_BUSSES 0x4000
-
extern unsigned int __nongpreldata pci_probe;
/* pci-frv.c */
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index f211839..f9c86c4 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 7cc3be9..d89b601 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 ae838ed..6b8b752 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 b8a0bf5..c6996cf 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-asb2305.c b/arch/mn10300/unit-asb2305/pci-asb2305.c
index b5b036f..b7ab837 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.c
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.c
@@ -183,18 +183,16 @@ static int __init pcibios_assign_resources(void)
struct pci_dev *dev = NULL;
struct resource *r;
- if (!(pci_probe & PCI_ASSIGN_ROMS)) {
- /* Try to use BIOS settings for ROMs, otherwise let
- pci_assign_unassigned_resources() allocate the new
- addresses. */
- for_each_pci_dev(dev) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- if (!r->flags || !r->start)
- continue;
- if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
- r->end -= r->start;
- r->start = 0;
- }
+ /* Try to use BIOS settings for ROMs, otherwise let
+ pci_assign_unassigned_resources() allocate the new
+ addresses. */
+ for_each_pci_dev(dev) {
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (!r->flags || !r->start)
+ continue;
+ if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+ r->end -= r->start;
+ r->start = 0;
}
}
diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
index 9e17aca..96c484b 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.h
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
@@ -20,13 +20,6 @@
#define DBG(x...)
#endif
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
extern unsigned int pci_probe;
/* pci-asb2305.c */
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 3dfe2d3..deaa893 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 b9de34d..02c1d5d 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/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
index cbf763b..0288efc 100644
--- a/arch/sh/drivers/pci/pci-sh4.h
+++ b/arch/sh/drivers/pci/pci-sh4.h
@@ -11,14 +11,6 @@
#include <asm/io.h>
-/* startup values */
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
#define SH4_PCICR 0x100 /* PCI Control Register */
#define SH4_PCICR_PREFIX 0xA5000000 /* CR prefix for write */
#define SH4_PCICR_FTO 0x00000400 /* TRDY/IRDY Enable */
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 164e3f8..fa1195d 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 8fd6f44..09d3afc 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);
}
@@ -673,24 +672,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/fixup.c b/arch/x86/pci/fixup.c
index 9a2b710..e585655 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)
{
/*
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
index 2706230..22aaefb 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,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 (pci_has_managed_irq(dev)) {
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 9bd1154..32e7034 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;
@@ -1257,24 +1256,10 @@ 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 && 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/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index b848cc3..d27b4dc 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/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 304eccb..afa16c5 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,17 +480,9 @@ 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;
- /* 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;
@@ -511,6 +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;
+ pci_reset_managed_irq(dev);
}
}
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index a0580af..baec33c 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 dceb9dd..901e1a3 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/access.c b/drivers/pci/access.c
index d9b64a1..769f7e3 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -439,6 +439,56 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
.release = pci_vpd_pci22_release,
};
+static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
+ void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_read_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
+ const void *arg)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ ssize_t ret;
+
+ if (!tdev)
+ return -ENODEV;
+
+ ret = pci_write_vpd(tdev, pos, count, arg);
+ pci_dev_put(tdev);
+ return ret;
+}
+
+static const struct pci_vpd_ops pci_vpd_f0_ops = {
+ .read = pci_vpd_f0_read,
+ .write = pci_vpd_f0_write,
+ .release = pci_vpd_pci22_release,
+};
+
+static int pci_vpd_f0_dev_check(struct pci_dev *dev)
+{
+ struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ int ret = 0;
+
+ if (!tdev)
+ return -ENODEV;
+ if (!tdev->vpd || !tdev->multifunction ||
+ dev->class != tdev->class || dev->vendor != tdev->vendor ||
+ dev->device != tdev->device)
+ ret = -ENODEV;
+
+ pci_dev_put(tdev);
+ return ret;
+}
+
int pci_vpd_pci22_init(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd;
@@ -447,12 +497,21 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
if (!cap)
return -ENODEV;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
+ int ret = pci_vpd_f0_dev_check(dev);
+
+ if (ret)
+ return ret;
+ }
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
if (!vpd)
return -ENOMEM;
vpd->base.len = PCI_VPD_PCI22_SIZE;
- vpd->base.ops = &pci_vpd_pci22_ops;
+ if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
+ vpd->base.ops = &pci_vpd_f0_ops;
+ else
+ vpd->base.ops = &pci_vpd_pci22_ops;
mutex_init(&vpd->lock);
vpd->cap = cap;
vpd->busy = false;
@@ -531,6 +590,14 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
}
+static bool pcie_downstream_port(const struct pci_dev *dev)
+{
+ int type = pci_pcie_type(dev);
+
+ return type == PCI_EXP_TYPE_ROOT_PORT ||
+ type == PCI_EXP_TYPE_DOWNSTREAM;
+}
+
bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
{
int type = pci_pcie_type(dev);
@@ -546,10 +613,7 @@ bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
{
- int type = pci_pcie_type(dev);
-
- return (type == PCI_EXP_TYPE_ROOT_PORT ||
- type == PCI_EXP_TYPE_DOWNSTREAM) &&
+ return pcie_downstream_port(dev) &&
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
}
@@ -628,10 +692,9 @@ int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
* State bit in the Slot Status register of Downstream Ports,
* which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8)
*/
- if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA &&
- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+ if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+ pos == PCI_EXP_SLTSTA)
*val = PCI_EXP_SLTSTA_PDS;
- }
return 0;
}
@@ -657,10 +720,9 @@ int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
return ret;
}
- if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL &&
- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
+ if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
+ pos == PCI_EXP_SLTSTA)
*val = PCI_EXP_SLTSTA_PDS;
- }
return 0;
}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f66be86..bb74238 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -665,6 +665,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
pci_msi_set_enable(dev, 1);
dev->msi_enabled = 1;
+ pcibios_free_irq(dev);
dev->irq = entry->irq;
return 0;
}
@@ -792,9 +793,9 @@ static int msix_capability_init(struct pci_dev *dev,
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
-
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
+ pcibios_free_irq(dev);
return 0;
out_avail:
@@ -909,6 +910,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
/* Restore dev->irq to its default pin-assertion irq */
dev->irq = desc->msi_attrib.default_irq;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msi(struct pci_dev *dev)
@@ -1009,6 +1011,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
+ pcibios_alloc_irq(dev);
}
void pci_disable_msix(struct pci_dev *dev)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 314a625..a32ba75 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -594,7 +594,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
/**
* pci_acpi_optimize_delay - optimize PCI D3 and D3cold delay from ACPI
* @pdev: the PCI device whose delay is to be updated
- * @adev: the companion ACPI device of this PCI device
+ * @handle: ACPI handle of this device
*
* Update the d3_delay and d3cold_delay of a PCI device from the ACPI _DSM
* control method of either the device itself or the PCI host bridge.
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3cb2210..52a880c 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
return error;
}
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
+
static int pci_device_probe(struct device *dev)
{
- int error = 0;
- struct pci_driver *drv;
- struct pci_dev *pci_dev;
+ int error;
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct pci_driver *drv = to_pci_driver(dev->driver);
+
+ error = pcibios_alloc_irq(pci_dev);
+ if (error < 0)
+ return error;
- drv = to_pci_driver(dev->driver);
- pci_dev = to_pci_dev(dev);
pci_dev_get(pci_dev);
error = __pci_device_probe(drv, pci_dev);
- if (error)
+ if (error) {
+ pcibios_free_irq(pci_dev);
pci_dev_put(pci_dev);
+ }
return error;
}
@@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
drv->remove(pci_dev);
pm_runtime_put_noidle(dev);
}
+ pcibios_free_irq(pci_dev);
pci_dev->driver = NULL;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0008c95..8037c27 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -140,7 +140,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
EXPORT_SYMBOL_GPL(pci_ioremap_bar);
#endif
-#define PCI_FIND_CAP_TTL 48
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap, int *ttl)
@@ -196,8 +195,6 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,
return PCI_CAPABILITY_LIST;
case PCI_HEADER_TYPE_CARDBUS:
return PCI_CB_CAPABILITY_LIST;
- default:
- return 0;
}
return 0;
@@ -972,7 +969,7 @@ static int pci_save_pcix_state(struct pci_dev *dev)
struct pci_cap_saved_state *save_state;
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
- if (pos <= 0)
+ if (!pos)
return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
@@ -995,7 +992,7 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
- if (!save_state || pos <= 0)
+ if (!save_state || !pos)
return;
cap = (u16 *)&save_state->cap.data[0];
@@ -1092,6 +1089,9 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_pcix_state(dev);
pci_restore_msi_state(dev);
+
+ /* Restore ACS and IOV configuration state */
+ pci_enable_acs(dev);
pci_restore_iov_state(dev);
dev->state_saved = false;
@@ -2159,7 +2159,7 @@ static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
else
pos = pci_find_capability(dev, cap);
- if (pos <= 0)
+ if (!pos)
return 0;
save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4ff0ff1..24ba9dc 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -4,6 +4,8 @@
#define PCI_CFG_SPACE_SIZE 256
#define PCI_CFG_SPACE_EXP_SIZE 4096
+#define PCI_FIND_CAP_TTL 48
+
extern const unsigned char pcie_link_speed[];
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 2f0ce66..88122dc 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -448,7 +448,7 @@ static int resume_iter(struct device *dev, void *data)
}
/**
- * pcie_port_device_suspend - resume port services associated with a PCIe port
+ * pcie_port_device_resume - resume port services associated with a PCIe port
* @dev: PCI Express port to handle
*/
int pcie_port_device_resume(struct device *dev)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cefd636..0fb0c74 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 {
/*
@@ -1268,7 +1274,7 @@ int pci_setup_device(struct pci_dev *dev)
bad:
dev_err(&dev->dev, "ignoring class %#08x (doesn't match header type %02x)\n",
dev->class, dev->hdr_type);
- dev->class = PCI_CLASS_NOT_DEFINED;
+ dev->class = PCI_CLASS_NOT_DEFINED << 8;
}
/* We found a fine healthy device, go go go... */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e9fd0e9..b6af4b0 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -163,7 +163,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_
* VIA Apollo KT133 needs PCI latency patch
* Made according to a windows driver based patch by George E. Breese
* see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
- * and http://www.georgebreese.com/net/software/#PCI
* Also see http://www.au-ja.org/review-kt133a-1-en.phtml for
* the info on which Mr Breese based his work.
*
@@ -424,10 +423,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_
*/
static void quirk_amd_nl_class(struct pci_dev *pdev)
{
- /*
- * Use 'USB Device' (0x0c03fe) instead of PCI header provided
- */
- pdev->class = 0x0c03fe;
+ u32 class = pdev->class;
+
+ /* Use "USB Device (not host controller)" class */
+ pdev->class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe;
+ dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
+ class, pdev->class);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB,
quirk_amd_nl_class);
@@ -1894,6 +1895,15 @@ static void quirk_netmos(struct pci_dev *dev)
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
+static void quirk_f0_vpd_link(struct pci_dev *dev)
+{
+ if (!dev->multifunction || !PCI_FUNC(dev->devfn))
+ return;
+ dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+ PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
+
static void quirk_e100_interrupt(struct pci_dev *dev)
{
u16 command, pmcsr;
@@ -1986,14 +1996,18 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
static void fixup_rev1_53c810(struct pci_dev *dev)
{
- /* rev 1 ncr53c810 chips don't set the class at all which means
+ u32 class = dev->class;
+
+ /*
+ * rev 1 ncr53c810 chips don't set the class at all which means
* they don't get their resources remapped. Fix that here.
*/
+ if (class)
+ return;
- if (dev->class == PCI_CLASS_NOT_DEFINED) {
- dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
- dev->class = PCI_CLASS_STORAGE_SCSI;
- }
+ dev->class = PCI_CLASS_STORAGE_SCSI << 8;
+ dev_info(&dev->dev, "NCR 53c810 rev 1 PCI class overridden (%#08x -> %#08x)\n",
+ class, dev->class);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
@@ -2241,7 +2255,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
* return 1 if a HT MSI capability is found and enabled */
static int msi_ht_cap_enabled(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2300,7 +2314,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
/* Force enable MSI mapping capability on HT bridges */
static void ht_enable_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2379,7 +2393,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
static int ht_check_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
int found = 0;
/* check if there is HT MSI cap or enabled on this device */
@@ -2504,7 +2518,7 @@ out:
static void ht_disable_msi_mapping(struct pci_dev *dev)
{
- int pos, ttl = 48;
+ int pos, ttl = PCI_FIND_CAP_TTL;
pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
while (pos && ttl--) {
@@ -2829,12 +2843,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
static void fixup_ti816x_class(struct pci_dev *dev)
{
+ u32 class = dev->class;
+
/* TI 816x devices do not have class code set when in PCIe boot mode */
- dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
- dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
+ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8;
+ dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n",
+ class, dev->class);
}
DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
- PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class);
+ PCI_CLASS_NOT_DEFINED, 8, fixup_ti816x_class);
/* Some PCIe devices do not work reliably with the claimed maximum
* payload size supported.
@@ -3028,7 +3045,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);
-
+/* Intel Cherrytrail devices do not need 10ms d3_delay */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2280, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b0, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22d8, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22dc, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
/*
* Some devices may pass our check in pci_intx_mask_supported if
* PCI_COMMAND_INTX_DISABLE works though they actually do not properly
@@ -3326,28 +3352,6 @@ fs_initcall_sync(pci_apply_final_quirks);
* reset a single function if other methods (e.g. FLR, PM D0->D3) are
* not available.
*/
-static int reset_intel_generic_dev(struct pci_dev *dev, int probe)
-{
- int pos;
-
- /* only implement PCI_CLASS_SERIAL_USB at present */
- if (dev->class == PCI_CLASS_SERIAL_USB) {
- pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);
- if (!pos)
- return -ENOTTY;
-
- if (probe)
- return 0;
-
- pci_write_config_byte(dev, pos + 0x4, 1);
- msleep(100);
-
- return 0;
- } else {
- return -ENOTTY;
- }
-}
-
static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
{
/*
@@ -3506,8 +3510,6 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
reset_ivb_igd },
- { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
- reset_intel_generic_dev },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
{ 0 }
@@ -3655,6 +3657,28 @@ DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
/*
+ * Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
+ * class code. Fix it.
+ */
+static void quirk_tw686x_class(struct pci_dev *pdev)
+{
+ u32 class = pdev->class;
+
+ /* Use "Multimedia controller" class */
+ pdev->class = (PCI_CLASS_MULTIMEDIA_OTHER << 8) | 0x01;
+ dev_info(&pdev->dev, "TW686x PCI class overridden (%#08x -> %#08x)\n",
+ class, pdev->class);
+}
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6864, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6865, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6868, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8,
+ quirk_tw686x_class);
+
+/*
* AMD has indicated that the devices below do not support peer-to-peer
* in any system where they are found in the southbridge with an AMD
* IOMMU in the system. Multifunction devices that do not support
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8a0321a..66361df 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -180,6 +180,8 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6),
/* Do not use PM reset even if device advertises NoSoftRst- */
PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
+ /* Get VPD from function 0 VPD */
+ PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
};
enum pci_irq_reroute_variant {
@@ -963,6 +965,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;
@@ -1645,6 +1664,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
int pcibios_add_device(struct pci_dev *dev);
void pcibios_release_device(struct pci_dev *dev);
void pcibios_penalize_isa_irq(int irq, int active);
+int pcibios_alloc_irq(struct pci_dev *dev);
+void pcibios_free_irq(struct pci_dev *dev);
#ifdef CONFIG_HIBERNATE_CALLBACKS
extern struct dev_pm_ops pcibios_pm_ops;
OpenPOWER on IntegriCloud