aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/pci_of_scan.c2
-rw-r--r--arch/sparc/kernel/pci.c2
-rw-r--r--arch/x86/pci/acpi.c7
-rw-r--r--drivers/acpi/pci_root.c7
-rw-r--r--drivers/pci/ioapic.c13
-rw-r--r--drivers/pci/pci-acpi.c4
-rw-r--r--drivers/pci/pci-sysfs.c18
-rw-r--r--drivers/pci/pci.c2
-rw-r--r--drivers/pci/pcie/aspm.c29
-rw-r--r--drivers/pci/probe.c31
-rw-r--r--drivers/pci/quirks.c25
-rw-r--r--include/uapi/linux/pci_regs.h2
12 files changed, 93 insertions, 49 deletions
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 2a67e9baa59f..d2d407d65344 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -165,7 +165,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
pr_debug(" class: 0x%x\n", dev->class);
pr_debug(" revision: 0x%x\n", dev->revision);
- dev->current_state = 4; /* unknown power state */
+ dev->current_state = PCI_UNKNOWN; /* unknown power state */
dev->error_state = pci_channel_io_normal;
dev->dma_mask = 0xffffffff;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index baf4366e2d6a..972892a0aa11 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -327,7 +327,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
pci_set_master(dev);
- dev->current_state = 4; /* unknown power state */
+ dev->current_state = PCI_UNKNOWN; /* unknown power state */
dev->error_state = pci_channel_io_normal;
dev->dma_mask = 0xffffffff;
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 3e724256dbee..d641897a1f4e 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -324,14 +324,11 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
res->start = start;
res->end = end;
info->res_offset[info->res_num] = addr.translation_offset;
+ info->res_num++;
- if (!pci_use_crs) {
+ if (!pci_use_crs)
dev_printk(KERN_DEBUG, &info->bridge->dev,
"host bridge window %pR (ignored)\n", res);
- return AE_OK;
- }
-
- info->res_num++;
return AE_OK;
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 27020882eb97..122b4dc7b0fa 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -96,13 +96,12 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
struct resource *res = data;
struct acpi_resource_address64 address;
+ acpi_status status;
- if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
- resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
- resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
+ status = acpi_resource_to_address64(resource, &address);
+ if (ACPI_FAILURE(status))
return AE_OK;
- acpi_resource_to_address64(resource, &address);
if ((address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
res->start = address.minimum;
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 3c6bbdd059a4..1b90579b233a 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -113,17 +113,6 @@ static struct pci_driver ioapic_driver = {
.remove = ioapic_remove,
};
-static int __init ioapic_init(void)
-{
- return pci_register_driver(&ioapic_driver);
-}
-
-static void __exit ioapic_exit(void)
-{
- pci_unregister_driver(&ioapic_driver);
-}
-
-module_init(ioapic_init);
-module_exit(ioapic_exit);
+module_pci_driver(ioapic_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index e4b1fb2c0f5d..6c15d6a96935 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -376,12 +376,12 @@ static int __init acpi_pci_init(void)
int ret;
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) {
- printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
+ pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n");
pci_no_msi();
}
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
- printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
+ pr_info("ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
pcie_no_aspm();
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5b4a9d9cd200..0b56e0865f38 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -66,7 +66,7 @@ static ssize_t broken_parity_status_store(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
pdev->broken_parity_status = !!val;
@@ -188,7 +188,7 @@ static ssize_t is_enabled_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- ssize_t result = strict_strtoul(buf, 0, &val);
+ ssize_t result = kstrtoul(buf, 0, &val);
if (result < 0)
return result;
@@ -259,7 +259,7 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
/* bad things may happen if the no_msi flag is changed
@@ -291,7 +291,7 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
unsigned long val;
struct pci_bus *b = NULL;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -315,7 +315,7 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr,
unsigned long val;
struct pci_dev *pdev = to_pci_dev(dev);
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -342,7 +342,7 @@ remove_store(struct device *dev, struct device_attribute *dummy,
int ret = 0;
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
/* An attribute cannot be unregistered by one of its own methods,
@@ -362,7 +362,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
unsigned long val;
struct pci_bus *bus = to_pci_bus(dev);
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -384,7 +384,7 @@ static ssize_t d3cold_allowed_store(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
pdev->d3cold_allowed = !!val;
@@ -1236,7 +1236,7 @@ static ssize_t reset_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- ssize_t result = strict_strtoul(buf, 0, &val);
+ ssize_t result = kstrtoul(buf, 0, &val);
if (result < 0)
return result;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a899d8bb190d..e5f4e55d407d 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2421,7 +2421,7 @@ bool pci_acs_path_enabled(struct pci_dev *start,
/**
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
* @dev: the PCI device
- * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
*
* Perform INTx swizzling for a device behind one level of bridge. This is
* required by section 9.1 of the PCI-to-PCI bridge specification for devices
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index d320df6375a2..403a44374ed5 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -714,19 +714,12 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
up_read(&pci_bus_sem);
}
-/*
- * pci_disable_link_state - disable pci device's link state, so the link will
- * never enter specific states
- */
static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
bool force)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;
- if (aspm_disabled && !force)
- return;
-
if (!pci_is_pcie(pdev))
return;
@@ -736,6 +729,19 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
if (!parent || !parent->link_state)
return;
+ /*
+ * A driver requested that ASPM be disabled on this device, but
+ * if we don't have permission to manage ASPM (e.g., on ACPI
+ * systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
+ * the _OSC method), we can't honor that request. Windows has
+ * a similar mechanism using "PciASPMOptOut", which is also
+ * ignored in this situation.
+ */
+ if (aspm_disabled && !force) {
+ dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n");
+ return;
+ }
+
if (sem)
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
@@ -761,6 +767,15 @@ void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
}
EXPORT_SYMBOL(pci_disable_link_state_locked);
+/**
+ * pci_disable_link_state - Disable device's link state, so the link will
+ * never enter specific states. Note that if the BIOS didn't grant ASPM
+ * control to the OS, this does nothing because we can't touch the LNKCTL
+ * register.
+ *
+ * @pdev: PCI device
+ * @state: ASPM link state to disable
+ */
void pci_disable_link_state(struct pci_dev *pdev, int state)
{
__pci_disable_link_state(pdev, state, true, false);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 70f10fa3c1b2..fe5b50bd7536 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -170,7 +170,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
{
u32 l, sz, mask;
u16 orig_cmd;
- struct pci_bus_region region;
+ struct pci_bus_region region, inverted_region;
bool bar_too_big = false, bar_disabled = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
@@ -250,12 +250,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
pci_write_config_dword(dev, pos + 4, 0);
region.start = 0;
region.end = sz64;
- pcibios_bus_to_resource(dev, res, &region);
bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
- pcibios_bus_to_resource(dev, res, &region);
}
} else {
sz = pci_size(l, sz, mask);
@@ -265,7 +263,28 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = l;
region.end = l + sz;
- pcibios_bus_to_resource(dev, res, &region);
+ }
+
+ pcibios_bus_to_resource(dev, res, &region);
+ pcibios_resource_to_bus(dev, &inverted_region, res);
+
+ /*
+ * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
+ * the corresponding resource address (the physical address used by
+ * the CPU. Converting that resource address back to a bus address
+ * should yield the original BAR value:
+ *
+ * resource_to_bus(bus_to_resource(A)) == A
+ *
+ * If it doesn't, CPU accesses to "bus_to_resource(A)" will not
+ * be claimed by the device.
+ */
+ if (inverted_region.start != region.start) {
+ dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n",
+ pos, &region.start);
+ res->flags |= IORESOURCE_UNSET;
+ res->end -= res->start;
+ res->start = 0;
}
goto out;
@@ -278,9 +297,9 @@ out:
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big)
- dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+ dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos);
if (res->flags && !bar_disabled)
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+ dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7d68aeebf56b..7f492574dcf4 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2865,6 +2865,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
+/*
+ * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. To
+ * work around this, query the size it should be configured to by the device and
+ * modify the resource end to correspond to this new size.
+ */
+static void quirk_intel_ntb(struct pci_dev *dev)
+{
+ int rc;
+ u8 val;
+
+ rc = pci_read_config_byte(dev, 0x00D0, &val);
+ if (rc)
+ return;
+
+ dev->resource[2].end = dev->resource[2].start + ((u64) 1 << val) - 1;
+
+ rc = pci_read_config_byte(dev, 0x00D1, &val);
+ if (rc)
+ return;
+
+ dev->resource[4].end = dev->resource[4].start + ((u64) 1 << val) - 1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb);
+
static ktime_t fixup_debug_start(struct pci_dev *dev,
void (*fn)(struct pci_dev *dev))
{
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 864e324da80d..c3cc01d474b0 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -468,7 +468,7 @@
#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
#define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */
-#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* L1 Clock Power Management */
+#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* Clock Power Management */
#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */
#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */
#define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */