Merge tag 'v3.10.104' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / pci / msi.c
index d40bed7267695fba2ed344cf1d28de56eac8659a..402063ff889e651611299d7178385b00abc8c7c1 100644 (file)
@@ -530,6 +530,20 @@ out_unroll:
        return ret;
 }
 
+static int msi_verify_entries(struct pci_dev *dev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (!dev->no_64bit_msi || !entry->msg.address_hi)
+                       continue;
+               dev_err(&dev->dev, "Device has broken 64-bit MSI but arch"
+                       " tried to assign one above 4G\n");
+               return -EIO;
+       }
+       return 0;
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -563,8 +577,10 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
        entry->msi_attrib.default_irq   = dev->irq;     /* Save IOAPIC IRQ */
        entry->msi_attrib.pos           = dev->msi_cap;
 
-       entry->mask_pos = dev->msi_cap + (control & PCI_MSI_FLAGS_64BIT) ?
-               PCI_MSI_MASK_64 : PCI_MSI_MASK_32;
+       if (control & PCI_MSI_FLAGS_64BIT)
+               entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
+       else
+               entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
        /* All MSIs are unmasked by default, Mask them all */
        if (entry->msi_attrib.maskbit)
                pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
@@ -581,6 +597,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
                return ret;
        }
 
+       ret = msi_verify_entries(dev);
+       if (ret) {
+               msi_mask_irq(entry, mask, ~mask);
+               free_msi_irqs(dev);
+               return ret;
+       }
+
        ret = populate_msi_sysfs(dev);
        if (ret) {
                msi_mask_irq(entry, mask, ~mask);
@@ -696,6 +719,11 @@ static int msix_capability_init(struct pci_dev *dev,
        if (ret)
                goto error;
 
+       /* Check if all MSI entries honor device restrictions */
+       ret = msi_verify_entries(dev);
+       if (ret)
+               goto error;
+
        /*
         * Some devices require MSI-X to be enabled before we can touch the
         * MSI-X registers.  We need to mask all the vectors to prevent