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
This commit is contained in:
Bjorn Helgaas 2016-12-12 11:25:02 -06:00
commit 2f0f3733c4
6 changed files with 25 additions and 7 deletions

View File

@ -294,3 +294,10 @@ Description:
a firmware bug to the system vendor. Writing to this file a firmware bug to the system vendor. Writing to this file
taints the kernel with TAINT_FIRMWARE_WORKAROUND, which taints the kernel with TAINT_FIRMWARE_WORKAROUND, which
reduces the supportability of your system. reduces the supportability of your system.
What: /sys/bus/pci/devices/.../revision
Date: November 2016
Contact: Emil Velikov <emil.l.velikov@gmail.com>
Description:
This file contains the revision field of the the PCI device.
The value comes from device config space. The file is read only.

View File

@ -17,6 +17,7 @@ that support it. For example, a given bus might look like this:
| |-- resource0 | |-- resource0
| |-- resource1 | |-- resource1
| |-- resource2 | |-- resource2
| |-- revision
| |-- rom | |-- rom
| |-- subsystem_device | |-- subsystem_device
| |-- subsystem_vendor | |-- subsystem_vendor
@ -41,6 +42,7 @@ files, each with their own function.
resource PCI resource host addresses (ascii, ro) resource PCI resource host addresses (ascii, ro)
resource0..N PCI resource N, if present (binary, mmap, rw[1]) resource0..N PCI resource N, if present (binary, mmap, rw[1])
resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap) resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap)
revision PCI revision (ascii, ro)
rom PCI ROM resource, if present (binary, ro) rom PCI ROM resource, if present (binary, ro)
subsystem_device PCI subsystem device (ascii, ro) subsystem_device PCI subsystem device (ascii, ro)
subsystem_vendor PCI subsystem vendor (ascii, ro) subsystem_vendor PCI subsystem vendor (ascii, ro)

View File

@ -142,10 +142,22 @@ int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
if (size == 4) { if (size == 4) {
writel(val, addr); writel(val, addr);
return PCIBIOS_SUCCESSFUL; 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 = readl(addr) & mask;
tmp |= val << ((where & 0x3) * 8); tmp |= val << ((where & 0x3) * 8);
writel(tmp, addr); writel(tmp, addr);

View File

@ -293,8 +293,6 @@ static int hisi_pcie_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n");
return 0; return 0;
} }

View File

@ -1187,9 +1187,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
pcie_bus_configure_settings(child); pcie_bus_configure_settings(child);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n");
return err; return err;
err_vpcie: err_vpcie:

View File

@ -50,6 +50,7 @@ pci_config_attr(vendor, "0x%04x\n");
pci_config_attr(device, "0x%04x\n"); pci_config_attr(device, "0x%04x\n");
pci_config_attr(subsystem_vendor, "0x%04x\n"); pci_config_attr(subsystem_vendor, "0x%04x\n");
pci_config_attr(subsystem_device, "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(class, "0x%06x\n");
pci_config_attr(irq, "%u\n"); pci_config_attr(irq, "%u\n");
@ -568,6 +569,7 @@ static struct attribute *pci_dev_attrs[] = {
&dev_attr_device.attr, &dev_attr_device.attr,
&dev_attr_subsystem_vendor.attr, &dev_attr_subsystem_vendor.attr,
&dev_attr_subsystem_device.attr, &dev_attr_subsystem_device.attr,
&dev_attr_revision.attr,
&dev_attr_class.attr, &dev_attr_class.attr,
&dev_attr_irq.attr, &dev_attr_irq.attr,
&dev_attr_local_cpus.attr, &dev_attr_local_cpus.attr,