diff options
author | Keshavamurthy, Anil S <anil.s.keshavamurthy@intel.com> | 2007-10-21 19:41:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-22 11:13:19 -0400 |
commit | 358dd8ac53a3bdafe62e3319e30627f3fef3a7b0 (patch) | |
tree | b31a6f707504f8b0257c27bcb3582190f2697c49 | |
parent | f76aec76ec7f68829a66624d11a50ed6cb404185 (diff) |
intel-iommu: fix for IOMMU early crash
pci_dev's->sysdata is highly overloaded and currently IOMMU is broken due
to IOMMU code depending on this field.
This patch introduces new field in pci_dev's dev.archdata struct to hold
IOMMU specific per device IOMMU private data.
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Greg KH <greg@kroah.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/pci/intel-iommu.c | 22 | ||||
-rw-r--r-- | include/asm-x86/device.h | 3 |
2 files changed, 14 insertions, 11 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index dab329f01584..8f372c8f3d87 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1348,7 +1348,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) | |||
1348 | list_del(&info->link); | 1348 | list_del(&info->link); |
1349 | list_del(&info->global); | 1349 | list_del(&info->global); |
1350 | if (info->dev) | 1350 | if (info->dev) |
1351 | info->dev->sysdata = NULL; | 1351 | info->dev->dev.archdata.iommu = NULL; |
1352 | spin_unlock_irqrestore(&device_domain_lock, flags); | 1352 | spin_unlock_irqrestore(&device_domain_lock, flags); |
1353 | 1353 | ||
1354 | detach_domain_for_dev(info->domain, info->bus, info->devfn); | 1354 | detach_domain_for_dev(info->domain, info->bus, info->devfn); |
@@ -1361,7 +1361,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) | |||
1361 | 1361 | ||
1362 | /* | 1362 | /* |
1363 | * find_domain | 1363 | * find_domain |
1364 | * Note: we use struct pci_dev->sysdata stores the info | 1364 | * Note: we use struct pci_dev->dev.archdata.iommu stores the info |
1365 | */ | 1365 | */ |
1366 | struct dmar_domain * | 1366 | struct dmar_domain * |
1367 | find_domain(struct pci_dev *pdev) | 1367 | find_domain(struct pci_dev *pdev) |
@@ -1369,7 +1369,7 @@ find_domain(struct pci_dev *pdev) | |||
1369 | struct device_domain_info *info; | 1369 | struct device_domain_info *info; |
1370 | 1370 | ||
1371 | /* No lock here, assumes no domain exit in normal case */ | 1371 | /* No lock here, assumes no domain exit in normal case */ |
1372 | info = pdev->sysdata; | 1372 | info = pdev->dev.archdata.iommu; |
1373 | if (info) | 1373 | if (info) |
1374 | return info->domain; | 1374 | return info->domain; |
1375 | return NULL; | 1375 | return NULL; |
@@ -1519,7 +1519,7 @@ found_domain: | |||
1519 | } | 1519 | } |
1520 | list_add(&info->link, &domain->devices); | 1520 | list_add(&info->link, &domain->devices); |
1521 | list_add(&info->global, &device_domain_list); | 1521 | list_add(&info->global, &device_domain_list); |
1522 | pdev->sysdata = info; | 1522 | pdev->dev.archdata.iommu = info; |
1523 | spin_unlock_irqrestore(&device_domain_lock, flags); | 1523 | spin_unlock_irqrestore(&device_domain_lock, flags); |
1524 | return domain; | 1524 | return domain; |
1525 | error: | 1525 | error: |
@@ -1579,7 +1579,7 @@ error: | |||
1579 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 1579 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
1580 | struct pci_dev *pdev) | 1580 | struct pci_dev *pdev) |
1581 | { | 1581 | { |
1582 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO) | 1582 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
1583 | return 0; | 1583 | return 0; |
1584 | return iommu_prepare_identity_map(pdev, rmrr->base_address, | 1584 | return iommu_prepare_identity_map(pdev, rmrr->base_address, |
1585 | rmrr->end_address + 1); | 1585 | rmrr->end_address + 1); |
@@ -1595,7 +1595,7 @@ static void __init iommu_prepare_gfx_mapping(void) | |||
1595 | int ret; | 1595 | int ret; |
1596 | 1596 | ||
1597 | for_each_pci_dev(pdev) { | 1597 | for_each_pci_dev(pdev) { |
1598 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO || | 1598 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || |
1599 | !IS_GFX_DEVICE(pdev)) | 1599 | !IS_GFX_DEVICE(pdev)) |
1600 | continue; | 1600 | continue; |
1601 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", | 1601 | printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", |
@@ -1836,7 +1836,7 @@ static dma_addr_t intel_map_single(struct device *hwdev, void *addr, | |||
1836 | int prot = 0; | 1836 | int prot = 0; |
1837 | 1837 | ||
1838 | BUG_ON(dir == DMA_NONE); | 1838 | BUG_ON(dir == DMA_NONE); |
1839 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO) | 1839 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
1840 | return virt_to_bus(addr); | 1840 | return virt_to_bus(addr); |
1841 | 1841 | ||
1842 | domain = get_valid_domain_for_dev(pdev); | 1842 | domain = get_valid_domain_for_dev(pdev); |
@@ -1900,7 +1900,7 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, | |||
1900 | unsigned long start_addr; | 1900 | unsigned long start_addr; |
1901 | struct iova *iova; | 1901 | struct iova *iova; |
1902 | 1902 | ||
1903 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO) | 1903 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
1904 | return; | 1904 | return; |
1905 | domain = find_domain(pdev); | 1905 | domain = find_domain(pdev); |
1906 | BUG_ON(!domain); | 1906 | BUG_ON(!domain); |
@@ -1974,7 +1974,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sg, | |||
1974 | size_t size = 0; | 1974 | size_t size = 0; |
1975 | void *addr; | 1975 | void *addr; |
1976 | 1976 | ||
1977 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO) | 1977 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
1978 | return; | 1978 | return; |
1979 | 1979 | ||
1980 | domain = find_domain(pdev); | 1980 | domain = find_domain(pdev); |
@@ -2032,7 +2032,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
2032 | unsigned long start_addr; | 2032 | unsigned long start_addr; |
2033 | 2033 | ||
2034 | BUG_ON(dir == DMA_NONE); | 2034 | BUG_ON(dir == DMA_NONE); |
2035 | if (pdev->sysdata == DUMMY_DEVICE_DOMAIN_INFO) | 2035 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
2036 | return intel_nontranslate_map_sg(hwdev, sg, nelems, dir); | 2036 | return intel_nontranslate_map_sg(hwdev, sg, nelems, dir); |
2037 | 2037 | ||
2038 | domain = get_valid_domain_for_dev(pdev); | 2038 | domain = get_valid_domain_for_dev(pdev); |
@@ -2234,7 +2234,7 @@ static void __init init_no_remapping_devices(void) | |||
2234 | for (i = 0; i < drhd->devices_cnt; i++) { | 2234 | for (i = 0; i < drhd->devices_cnt; i++) { |
2235 | if (!drhd->devices[i]) | 2235 | if (!drhd->devices[i]) |
2236 | continue; | 2236 | continue; |
2237 | drhd->devices[i]->sysdata = DUMMY_DEVICE_DOMAIN_INFO; | 2237 | drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; |
2238 | } | 2238 | } |
2239 | } | 2239 | } |
2240 | } | 2240 | } |
diff --git a/include/asm-x86/device.h b/include/asm-x86/device.h index d9ee5e52e91b..87a715367a1b 100644 --- a/include/asm-x86/device.h +++ b/include/asm-x86/device.h | |||
@@ -5,6 +5,9 @@ struct dev_archdata { | |||
5 | #ifdef CONFIG_ACPI | 5 | #ifdef CONFIG_ACPI |
6 | void *acpi_handle; | 6 | void *acpi_handle; |
7 | #endif | 7 | #endif |
8 | #ifdef CONFIG_DMAR | ||
9 | void *iommu; /* hook for IOMMU specific extension */ | ||
10 | #endif | ||
8 | }; | 11 | }; |
9 | 12 | ||
10 | #endif /* _ASM_X86_DEVICE_H */ | 13 | #endif /* _ASM_X86_DEVICE_H */ |