|
@@ -590,6 +590,20 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
|
|
|
return entry;
|
|
|
}
|
|
|
|
|
|
+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
|
|
@@ -627,6 +641,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);
|
|
@@ -739,6 +760,11 @@ static int msix_capability_init(struct pci_dev *dev,
|
|
|
if (ret)
|
|
|
goto out_avail;
|
|
|
|
|
|
+ /* Check if all MSI entries honor device restrictions */
|
|
|
+ ret = msi_verify_entries(dev);
|
|
|
+ if (ret)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
/*
|
|
|
* 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
|