diff options
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 121 |
1 files changed, 115 insertions, 6 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 855dd7ca47f3..1840a0578a42 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -48,6 +48,7 @@ | |||
48 | 48 | ||
49 | #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) | 49 | #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) |
50 | #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) | 50 | #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) |
51 | #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) | ||
51 | 52 | ||
52 | #define IOAPIC_RANGE_START (0xfee00000) | 53 | #define IOAPIC_RANGE_START (0xfee00000) |
53 | #define IOAPIC_RANGE_END (0xfeefffff) | 54 | #define IOAPIC_RANGE_END (0xfeefffff) |
@@ -94,6 +95,7 @@ static inline unsigned long virt_to_dma_pfn(void *p) | |||
94 | /* global iommu list, set NULL for ignored DMAR units */ | 95 | /* global iommu list, set NULL for ignored DMAR units */ |
95 | static struct intel_iommu **g_iommus; | 96 | static struct intel_iommu **g_iommus; |
96 | 97 | ||
98 | static void __init check_tylersburg_isoch(void); | ||
97 | static int rwbf_quirk; | 99 | static int rwbf_quirk; |
98 | 100 | ||
99 | /* | 101 | /* |
@@ -1934,6 +1936,9 @@ error: | |||
1934 | } | 1936 | } |
1935 | 1937 | ||
1936 | static int iommu_identity_mapping; | 1938 | static int iommu_identity_mapping; |
1939 | #define IDENTMAP_ALL 1 | ||
1940 | #define IDENTMAP_GFX 2 | ||
1941 | #define IDENTMAP_AZALIA 4 | ||
1937 | 1942 | ||
1938 | static int iommu_domain_identity_map(struct dmar_domain *domain, | 1943 | static int iommu_domain_identity_map(struct dmar_domain *domain, |
1939 | unsigned long long start, | 1944 | unsigned long long start, |
@@ -2151,8 +2156,14 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2151 | 2156 | ||
2152 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | 2157 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) |
2153 | { | 2158 | { |
2154 | if (iommu_identity_mapping == 2) | 2159 | if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) |
2155 | return IS_GFX_DEVICE(pdev); | 2160 | return 1; |
2161 | |||
2162 | if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) | ||
2163 | return 1; | ||
2164 | |||
2165 | if (!(iommu_identity_mapping & IDENTMAP_ALL)) | ||
2166 | return 0; | ||
2156 | 2167 | ||
2157 | /* | 2168 | /* |
2158 | * We want to start off with all devices in the 1:1 domain, and | 2169 | * We want to start off with all devices in the 1:1 domain, and |
@@ -2332,11 +2343,14 @@ int __init init_dmars(void) | |||
2332 | } | 2343 | } |
2333 | 2344 | ||
2334 | if (iommu_pass_through) | 2345 | if (iommu_pass_through) |
2335 | iommu_identity_mapping = 1; | 2346 | iommu_identity_mapping |= IDENTMAP_ALL; |
2347 | |||
2336 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA | 2348 | #ifdef CONFIG_DMAR_BROKEN_GFX_WA |
2337 | else | 2349 | iommu_identity_mapping |= IDENTMAP_GFX; |
2338 | iommu_identity_mapping = 2; | ||
2339 | #endif | 2350 | #endif |
2351 | |||
2352 | check_tylersburg_isoch(); | ||
2353 | |||
2340 | /* | 2354 | /* |
2341 | * If pass through is not set or not enabled, setup context entries for | 2355 | * If pass through is not set or not enabled, setup context entries for |
2342 | * identity mappings for rmrr, gfx, and isa and may fall back to static | 2356 | * identity mappings for rmrr, gfx, and isa and may fall back to static |
@@ -2753,7 +2767,15 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size, | |||
2753 | 2767 | ||
2754 | size = PAGE_ALIGN(size); | 2768 | size = PAGE_ALIGN(size); |
2755 | order = get_order(size); | 2769 | order = get_order(size); |
2756 | flags &= ~(GFP_DMA | GFP_DMA32); | 2770 | |
2771 | if (!iommu_no_mapping(hwdev)) | ||
2772 | flags &= ~(GFP_DMA | GFP_DMA32); | ||
2773 | else if (hwdev->coherent_dma_mask < dma_get_required_mask(hwdev)) { | ||
2774 | if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32)) | ||
2775 | flags |= GFP_DMA; | ||
2776 | else | ||
2777 | flags |= GFP_DMA32; | ||
2778 | } | ||
2757 | 2779 | ||
2758 | vaddr = (void *)__get_free_pages(flags, order); | 2780 | vaddr = (void *)__get_free_pages(flags, order); |
2759 | if (!vaddr) | 2781 | if (!vaddr) |
@@ -3193,6 +3215,33 @@ static int __init init_iommu_sysfs(void) | |||
3193 | } | 3215 | } |
3194 | #endif /* CONFIG_PM */ | 3216 | #endif /* CONFIG_PM */ |
3195 | 3217 | ||
3218 | /* | ||
3219 | * Here we only respond to action of unbound device from driver. | ||
3220 | * | ||
3221 | * Added device is not attached to its DMAR domain here yet. That will happen | ||
3222 | * when mapping the device to iova. | ||
3223 | */ | ||
3224 | static int device_notifier(struct notifier_block *nb, | ||
3225 | unsigned long action, void *data) | ||
3226 | { | ||
3227 | struct device *dev = data; | ||
3228 | struct pci_dev *pdev = to_pci_dev(dev); | ||
3229 | struct dmar_domain *domain; | ||
3230 | |||
3231 | domain = find_domain(pdev); | ||
3232 | if (!domain) | ||
3233 | return 0; | ||
3234 | |||
3235 | if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) | ||
3236 | domain_remove_one_dev_info(domain, pdev); | ||
3237 | |||
3238 | return 0; | ||
3239 | } | ||
3240 | |||
3241 | static struct notifier_block device_nb = { | ||
3242 | .notifier_call = device_notifier, | ||
3243 | }; | ||
3244 | |||
3196 | int __init intel_iommu_init(void) | 3245 | int __init intel_iommu_init(void) |
3197 | { | 3246 | { |
3198 | int ret = 0; | 3247 | int ret = 0; |
@@ -3245,6 +3294,8 @@ int __init intel_iommu_init(void) | |||
3245 | 3294 | ||
3246 | register_iommu(&intel_iommu_ops); | 3295 | register_iommu(&intel_iommu_ops); |
3247 | 3296 | ||
3297 | bus_register_notifier(&pci_bus_type, &device_nb); | ||
3298 | |||
3248 | return 0; | 3299 | return 0; |
3249 | } | 3300 | } |
3250 | 3301 | ||
@@ -3670,3 +3721,61 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) | |||
3670 | } | 3721 | } |
3671 | 3722 | ||
3672 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); | 3723 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); |
3724 | |||
3725 | /* On Tylersburg chipsets, some BIOSes have been known to enable the | ||
3726 | ISOCH DMAR unit for the Azalia sound device, but not give it any | ||
3727 | TLB entries, which causes it to deadlock. Check for that. We do | ||
3728 | this in a function called from init_dmars(), instead of in a PCI | ||
3729 | quirk, because we don't want to print the obnoxious "BIOS broken" | ||
3730 | message if VT-d is actually disabled. | ||
3731 | */ | ||
3732 | static void __init check_tylersburg_isoch(void) | ||
3733 | { | ||
3734 | struct pci_dev *pdev; | ||
3735 | uint32_t vtisochctrl; | ||
3736 | |||
3737 | /* If there's no Azalia in the system anyway, forget it. */ | ||
3738 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL); | ||
3739 | if (!pdev) | ||
3740 | return; | ||
3741 | pci_dev_put(pdev); | ||
3742 | |||
3743 | /* System Management Registers. Might be hidden, in which case | ||
3744 | we can't do the sanity check. But that's OK, because the | ||
3745 | known-broken BIOSes _don't_ actually hide it, so far. */ | ||
3746 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL); | ||
3747 | if (!pdev) | ||
3748 | return; | ||
3749 | |||
3750 | if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) { | ||
3751 | pci_dev_put(pdev); | ||
3752 | return; | ||
3753 | } | ||
3754 | |||
3755 | pci_dev_put(pdev); | ||
3756 | |||
3757 | /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */ | ||
3758 | if (vtisochctrl & 1) | ||
3759 | return; | ||
3760 | |||
3761 | /* Drop all bits other than the number of TLB entries */ | ||
3762 | vtisochctrl &= 0x1c; | ||
3763 | |||
3764 | /* If we have the recommended number of TLB entries (16), fine. */ | ||
3765 | if (vtisochctrl == 0x10) | ||
3766 | return; | ||
3767 | |||
3768 | /* Zero TLB entries? You get to ride the short bus to school. */ | ||
3769 | if (!vtisochctrl) { | ||
3770 | WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n" | ||
3771 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
3772 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
3773 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
3774 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
3775 | iommu_identity_mapping |= IDENTMAP_AZALIA; | ||
3776 | return; | ||
3777 | } | ||
3778 | |||
3779 | printk(KERN_WARNING "DMAR: Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n", | ||
3780 | vtisochctrl); | ||
3781 | } | ||