Commit 2f0f3733 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

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
parents 5e0ad9f6 fb265923
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -294,3 +294,10 @@ Description:
		a firmware bug to the system vendor.  Writing to this file
		taints the kernel with TAINT_FIRMWARE_WORKAROUND, which
		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.
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ that support it. For example, a given bus might look like this:
     |   |-- resource0
     |   |-- resource1
     |   |-- resource2
     |   |-- revision
     |   |-- rom
     |   |-- subsystem_device
     |   |-- subsystem_vendor
@@ -41,6 +42,7 @@ files, each with their own function.
       resource		   PCI resource host addresses (ascii, ro)
       resource0..N	   PCI resource N, if present (binary, mmap, rw[1])
       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)
       subsystem_device	   PCI subsystem device (ascii, ro)
       subsystem_vendor	   PCI subsystem vendor (ascii, ro)
+14 −2
Original line number Diff line number Diff line
@@ -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);
+0 −2
Original line number Diff line number Diff line
@@ -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;
}

+0 −3
Original line number Diff line number Diff line
@@ -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:
Loading