PCI: Check for PCI_HEADER_TYPE_BRIDGE equality, not bitmask
authorBjorn Helgaas <bhelgaas@google.com>
Thu, 3 Dec 2015 19:18:18 +0000 (13:18 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 11 Dec 2015 01:38:06 +0000 (19:38 -0600)
Bit 7 of the "Header Type" register indicates a multi-function device when
set.  Bits 0-6 contain encoded values, where 0x1 indicates a PCI-PCI
bridge.  It is incorrect to test this as though it were a mask.

For example, while the PCI 3.0 spec only defines values 0x0, 0x1, and 0x2,
it's conceivable that a future spec could define 0x3 to mean something
else; then tests for "(hdr_type & 0x7f) & PCI_HEADER_TYPE_BRIDGE" would
incorrectly succeed for this new 0x3 header type.

Test bits 0-6 of the Header Type for equality with PCI_HEADER_TYPE_BRIDGE.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
arch/powerpc/kernel/eeh_driver.c
drivers/pci/hotplug/ibmphp_pci.c
drivers/pci/pcie/aer/aerdrv_core.c

index 80dfe8965df9f7d49fc57a1f1d6773f0c5ffd736..44bca7892f6608b79d8d42f442821c8820ef7492 100644 (file)
@@ -400,7 +400,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
         * support EEH. So we just care about PCI devices for
         * simplicity here.
         */
-       if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+       if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE))
                return NULL;
 
        /*
index 814cea22a9fa5f599fdd44e0af479a0552d8f274..5824df538f72a5de03ab17a1203c89d3601dca2c 100644 (file)
@@ -1119,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func *func, u8 busno)
                                pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
 
                                debug ("hdr_type behind the bridge is %x\n", hdr_type);
-                               if (hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+                               if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
                                        err ("embedded bridges not supported for hot-plugging.\n");
                                        amount->not_correct = 1;
                                        return amount;
index fba785e9df75570b35a9b90e671bc8d5dbad6e91..712392504ed9b9f1a8992079f801cf2c271a0ae6 100644 (file)
@@ -246,7 +246,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                !dev->driver->err_handler ||
                !dev->driver->err_handler->error_detected) {
                if (result_data->state == pci_channel_io_frozen &&
-                       !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
+                       dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
                        /*
                         * In case of fatal recovery, if one of down-
                         * stream device has no driver. We might be
@@ -269,7 +269,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                 * without recovery.
                 */
 
-               if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
+               if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
                        vote = PCI_ERS_RESULT_NO_AER_DRIVER;
                else
                        vote = PCI_ERS_RESULT_NONE;
@@ -369,7 +369,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
        else
                result_data.result = PCI_ERS_RESULT_RECOVERED;
 
-       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                /*
                 * If the error is reported by a bridge, we think this error
                 * is related to the downstream link of the bridge, so we
@@ -440,7 +440,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev)
        pci_ers_result_t status;
        struct pcie_port_service_driver *driver;
 
-       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
                /* Reset this port for all subordinates */
                udev = dev;
        } else {
@@ -660,7 +660,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
                        &info->mask);
                if (!(info->status & ~info->mask))
                        return 0;
-       } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
+       } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
                info->severity == AER_NONFATAL) {
 
                /* Link is still healthy for IO reads */