diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2015-05-11 09:59:20 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2015-05-11 09:59:20 -0400 |
| commit | 4ed6a540fab8ea4388c1703b73ecfed68a2009d1 (patch) | |
| tree | dde73b1a39c9cc68e25480fb889834706f0cec4e | |
| parent | b787f68c36d49bb1d9236f403813641efa74a031 (diff) | |
iommu/vt-d: Fix passthrough mode with translation-disabled devices
When we use 'intel_iommu=igfx_off' to disable translation for the
graphics, and when we discover that the BIOS has misconfigured the DMAR
setup for I/OAT, we use a special DUMMY_DEVICE_DOMAIN_INFO value in
dev->archdata.iommu to indicate that translation is disabled.
With passthrough mode, we were attempting to dereference that as a
normal pointer to a struct device_domain_info when setting up an
identity mapping for the affected device.
This fixes the problem by making device_to_iommu() explicitly check for
the special value and indicate that no IOMMU was found to handle the
devices in question.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Cc: stable@vger.kernel.org (which means you can pick up 18436afdc now too)
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 68d43beccb7e..2ffe58969944 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -696,6 +696,11 @@ static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu | |||
| 696 | return &context[devfn]; | 696 | return &context[devfn]; |
| 697 | } | 697 | } |
| 698 | 698 | ||
| 699 | static int iommu_dummy(struct device *dev) | ||
| 700 | { | ||
| 701 | return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; | ||
| 702 | } | ||
| 703 | |||
| 699 | static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn) | 704 | static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn) |
| 700 | { | 705 | { |
| 701 | struct dmar_drhd_unit *drhd = NULL; | 706 | struct dmar_drhd_unit *drhd = NULL; |
| @@ -705,6 +710,9 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf | |||
| 705 | u16 segment = 0; | 710 | u16 segment = 0; |
| 706 | int i; | 711 | int i; |
| 707 | 712 | ||
| 713 | if (iommu_dummy(dev)) | ||
| 714 | return NULL; | ||
| 715 | |||
| 708 | if (dev_is_pci(dev)) { | 716 | if (dev_is_pci(dev)) { |
| 709 | pdev = to_pci_dev(dev); | 717 | pdev = to_pci_dev(dev); |
| 710 | segment = pci_domain_nr(pdev->bus); | 718 | segment = pci_domain_nr(pdev->bus); |
| @@ -2969,11 +2977,6 @@ static inline struct dmar_domain *get_valid_domain_for_dev(struct device *dev) | |||
| 2969 | return __get_valid_domain_for_dev(dev); | 2977 | return __get_valid_domain_for_dev(dev); |
| 2970 | } | 2978 | } |
| 2971 | 2979 | ||
| 2972 | static int iommu_dummy(struct device *dev) | ||
| 2973 | { | ||
| 2974 | return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; | ||
| 2975 | } | ||
| 2976 | |||
| 2977 | /* Check if the dev needs to go through non-identity map and unmap process.*/ | 2980 | /* Check if the dev needs to go through non-identity map and unmap process.*/ |
| 2978 | static int iommu_no_mapping(struct device *dev) | 2981 | static int iommu_no_mapping(struct device *dev) |
| 2979 | { | 2982 | { |
