diff options
-rw-r--r-- | drivers/pci/msi.c | 26 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
2 files changed, 27 insertions, 0 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9fab30af0e75..084587d7cd13 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -590,6 +590,20 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev) | |||
590 | return entry; | 590 | return entry; |
591 | } | 591 | } |
592 | 592 | ||
593 | static int msi_verify_entries(struct pci_dev *dev) | ||
594 | { | ||
595 | struct msi_desc *entry; | ||
596 | |||
597 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
598 | if (!dev->no_64bit_msi || !entry->msg.address_hi) | ||
599 | continue; | ||
600 | dev_err(&dev->dev, "Device has broken 64-bit MSI but arch" | ||
601 | " tried to assign one above 4G\n"); | ||
602 | return -EIO; | ||
603 | } | ||
604 | return 0; | ||
605 | } | ||
606 | |||
593 | /** | 607 | /** |
594 | * msi_capability_init - configure device's MSI capability structure | 608 | * msi_capability_init - configure device's MSI capability structure |
595 | * @dev: pointer to the pci_dev data structure of MSI device function | 609 | * @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) | |||
627 | return ret; | 641 | return ret; |
628 | } | 642 | } |
629 | 643 | ||
644 | ret = msi_verify_entries(dev); | ||
645 | if (ret) { | ||
646 | msi_mask_irq(entry, mask, ~mask); | ||
647 | free_msi_irqs(dev); | ||
648 | return ret; | ||
649 | } | ||
650 | |||
630 | ret = populate_msi_sysfs(dev); | 651 | ret = populate_msi_sysfs(dev); |
631 | if (ret) { | 652 | if (ret) { |
632 | msi_mask_irq(entry, mask, ~mask); | 653 | msi_mask_irq(entry, mask, ~mask); |
@@ -739,6 +760,11 @@ static int msix_capability_init(struct pci_dev *dev, | |||
739 | if (ret) | 760 | if (ret) |
740 | goto out_avail; | 761 | goto out_avail; |
741 | 762 | ||
763 | /* Check if all MSI entries honor device restrictions */ | ||
764 | ret = msi_verify_entries(dev); | ||
765 | if (ret) | ||
766 | goto out_free; | ||
767 | |||
742 | /* | 768 | /* |
743 | * Some devices require MSI-X to be enabled before we can touch the | 769 | * Some devices require MSI-X to be enabled before we can touch the |
744 | * MSI-X registers. We need to mask all the vectors to prevent | 770 | * MSI-X registers. We need to mask all the vectors to prevent |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 5be8db45e368..4c8ac5fcc224 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -331,6 +331,7 @@ struct pci_dev { | |||
331 | unsigned int is_added:1; | 331 | unsigned int is_added:1; |
332 | unsigned int is_busmaster:1; /* device is busmaster */ | 332 | unsigned int is_busmaster:1; /* device is busmaster */ |
333 | unsigned int no_msi:1; /* device may not use msi */ | 333 | unsigned int no_msi:1; /* device may not use msi */ |
334 | unsigned int no_64bit_msi:1; /* device may only use 32-bit MSIs */ | ||
334 | unsigned int block_cfg_access:1; /* config space access is blocked */ | 335 | unsigned int block_cfg_access:1; /* config space access is blocked */ |
335 | unsigned int broken_parity_status:1; /* Device generates false positive parity */ | 336 | unsigned int broken_parity_status:1; /* Device generates false positive parity */ |
336 | unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ | 337 | unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ |