diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2016-12-12 11:25:02 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-12-12 11:25:02 -0600 |
commit | 2f0f3733c4c6376853bfc2f4801888bcbc99308f (patch) | |
tree | cad26b50b010b69f205f9e4f452fd20ad58f522c /drivers/pci | |
parent | 5e0ad9f68653b711f9f4bec9a7f4d579842fd796 (diff) | |
parent | fb26592301200dbbe4a9943fe188b57a46716900 (diff) | |
download | linux-2f0f3733c4c6376853bfc2f4801888bcbc99308f.tar.bz2 |
Merge branch 'pci/enumeration' into next
* pci/enumeration:
PCI: Warn on possible RW1C corruption for sub-32 bit config writes
PCI: Create revision file in sysfs
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/access.c | 16 | ||||
-rw-r--r-- | drivers/pci/host/pcie-hisi.c | 2 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rockchip.c | 3 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 2 |
4 files changed, 16 insertions, 7 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index d11cdbb8fba3..db239547fefd 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -142,10 +142,22 @@ int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn, if (size == 4) { writel(val, addr); return PCIBIOS_SUCCESSFUL; - } else { - mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); } + /* + * In general, hardware that supports only 32-bit writes on PCI is + * not spec-compliant. For example, software may perform a 16-bit + * write. If the hardware only supports 32-bit accesses, we must + * do a 32-bit read, merge in the 16 bits we intend to write, + * followed by a 32-bit write. If the 16 bits we *don't* intend to + * write happen to have any RW1C (write-one-to-clear) bits set, we + * just inadvertently cleared something we shouldn't have. + */ + dev_warn_ratelimited(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n", + size, pci_domain_nr(bus), bus->number, + PCI_SLOT(devfn), PCI_FUNC(devfn), where); + + mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); tmp = readl(addr) & mask; tmp |= val << ((where & 0x3) * 8); writel(tmp, addr); diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c index 9bfa1ab27365..07e82256efbf 100644 --- a/drivers/pci/host/pcie-hisi.c +++ b/drivers/pci/host/pcie-hisi.c @@ -293,8 +293,6 @@ static int hisi_pcie_probe(struct platform_device *pdev) if (ret) return ret; - dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n"); - return 0; } diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index e0b22dab9b7a..6419d8ca4a84 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c @@ -1187,9 +1187,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev) pcie_bus_configure_settings(child); pci_bus_add_devices(bus); - - dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n"); - return err; err_vpcie: diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index bcd10c795284..066628776e1b 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -50,6 +50,7 @@ pci_config_attr(vendor, "0x%04x\n"); pci_config_attr(device, "0x%04x\n"); pci_config_attr(subsystem_vendor, "0x%04x\n"); pci_config_attr(subsystem_device, "0x%04x\n"); +pci_config_attr(revision, "0x%02x\n"); pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); @@ -568,6 +569,7 @@ static struct attribute *pci_dev_attrs[] = { &dev_attr_device.attr, &dev_attr_subsystem_vendor.attr, &dev_attr_subsystem_device.attr, + &dev_attr_revision.attr, &dev_attr_class.attr, &dev_attr_irq.attr, &dev_attr_local_cpus.attr, |