PCI: Rely on config space header type, not class code
authorHonghui Zhang <honghui.zhang@mediatek.com>
Tue, 16 Oct 2018 10:44:43 +0000 (18:44 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 30 Jan 2019 16:57:08 +0000 (10:57 -0600)
The PCI configuration space header type tells us whether the device is a
bridge, a CardBus bridge, or a normal device, and defines the layout of the
rest of the header (PCI r3.0 sec 6.1, PCIe r4.0 sec 7.5.1.1.9).

When we rely on the header format, e.g., when we're dealing with bridge
windows, we should check the header type, not the class code.  The class
code is loosely related to the header type, but is often incorrect and the
spec doesn't actually require it to be related to the header format.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Honghui Zhang <honghui.zhang@mediatek.com>
[bhelgaas: changelog, keep the PCI_CLASS_BRIDGE_HOST check]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/setup-bus.c

index c9d8e3c837de785d7960897f511328e1399239ae..e9d938e14ba813a8f8e2d4dec13f976a622c3d27 100644 (file)
@@ -6000,8 +6000,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
         * to enable the kernel to reassign new resource
         * window later on.
         */
-       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
-           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
                        r = &dev->resource[i];
                        if (!(r->flags & IORESOURCE_MEM))
index 8e2e4154cdd97862212ab1c3a0801e3c204e1682..128459a0ffba8395255088ba8193cb2777703649 100644 (file)
@@ -1779,9 +1779,6 @@ int pci_setup_device(struct pci_dev *dev)
                break;
 
        case PCI_HEADER_TYPE_BRIDGE:                /* bridge header */
-               if (class != PCI_CLASS_BRIDGE_PCI)
-                       goto bad;
-
                /*
                 * The PCI-to-PCI bridge spec requires that subtractive
                 * decoding (i.e. transparent) bridge must have programming
index 1941bb0a6c137c400865d0ed49211b564872c7ce..ec44a0f3a7acf735c9456b00078d585a9c1907b8 100644 (file)
@@ -1186,12 +1186,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
                if (!b)
                        continue;
 
-               switch (dev->class >> 8) {
-               case PCI_CLASS_BRIDGE_CARDBUS:
+               switch (dev->hdr_type) {
+               case PCI_HEADER_TYPE_CARDBUS:
                        pci_bus_size_cardbus(b, realloc_head);
                        break;
 
-               case PCI_CLASS_BRIDGE_PCI:
+               case PCI_HEADER_TYPE_BRIDGE:
                default:
                        __pci_bus_size_bridges(b, realloc_head);
                        break;
@@ -1202,12 +1202,12 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
        if (pci_is_root_bus(bus))
                return;
 
-       switch (bus->self->class >> 8) {
-       case PCI_CLASS_BRIDGE_CARDBUS:
+       switch (bus->self->hdr_type) {
+       case PCI_HEADER_TYPE_CARDBUS:
                /* don't size cardbuses yet. */
                break;
 
-       case PCI_CLASS_BRIDGE_PCI:
+       case PCI_HEADER_TYPE_BRIDGE:
                pci_bridge_check_ranges(bus);
                if (bus->self->is_hotplug_bridge) {
                        additional_io_size  = pci_hotplug_io_size;
@@ -1356,13 +1356,13 @@ void __pci_bus_assign_resources(const struct pci_bus *bus,
 
                __pci_bus_assign_resources(b, realloc_head, fail_head);
 
-               switch (dev->class >> 8) {
-               case PCI_CLASS_BRIDGE_PCI:
+               switch (dev->hdr_type) {
+               case PCI_HEADER_TYPE_BRIDGE:
                        if (!pci_is_enabled(dev))
                                pci_setup_bridge(b);
                        break;
 
-               case PCI_CLASS_BRIDGE_CARDBUS:
+               case PCI_HEADER_TYPE_CARDBUS:
                        pci_setup_cardbus(b);
                        break;