Browse Source

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
Bjorn Helgaas 8 years ago
parent
commit
2f0f3733c4

+ 7 - 0
Documentation/ABI/testing/sysfs-bus-pci

@@ -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.

+ 2 - 0
Documentation/filesystems/sysfs-pci.txt

@@ -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)

+ 14 - 2
drivers/pci/access.c

@@ -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);

+ 0 - 2
drivers/pci/host/pcie-hisi.c

@@ -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;
 }
 }
 
 

+ 0 - 3
drivers/pci/host/pcie-rockchip.c

@@ -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:

+ 2 - 0
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(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,