diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-09 18:48:15 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-24 10:07:54 -0400 |
commit | 0b9d9753155b9ed72e864592f9bf482a688c3c11 (patch) | |
tree | e46a9d1a8fa919ada2570492104b59254063c45e | |
parent | 146922ec798de6484897a43fc6180e49c425f183 (diff) |
iommu/vt-d: Handle RMRRs for non-PCI devices
Should hopefully never happen (RMRRs are an abomination) but while we're
busy eliminating all the PCI assumptions, we might as well do it.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/iommu/intel-iommu.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 1c5f656ff19d..7b2b9f321c74 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -2311,14 +2311,14 @@ static int iommu_domain_identity_map(struct dmar_domain *domain, | |||
2311 | DMA_PTE_READ|DMA_PTE_WRITE); | 2311 | DMA_PTE_READ|DMA_PTE_WRITE); |
2312 | } | 2312 | } |
2313 | 2313 | ||
2314 | static int iommu_prepare_identity_map(struct pci_dev *pdev, | 2314 | static int iommu_prepare_identity_map(struct device *dev, |
2315 | unsigned long long start, | 2315 | unsigned long long start, |
2316 | unsigned long long end) | 2316 | unsigned long long end) |
2317 | { | 2317 | { |
2318 | struct dmar_domain *domain; | 2318 | struct dmar_domain *domain; |
2319 | int ret; | 2319 | int ret; |
2320 | 2320 | ||
2321 | domain = get_domain_for_dev(&pdev->dev, DEFAULT_DOMAIN_ADDRESS_WIDTH); | 2321 | domain = get_domain_for_dev(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH); |
2322 | if (!domain) | 2322 | if (!domain) |
2323 | return -ENOMEM; | 2323 | return -ENOMEM; |
2324 | 2324 | ||
@@ -2328,13 +2328,13 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, | |||
2328 | up to start with in si_domain */ | 2328 | up to start with in si_domain */ |
2329 | if (domain == si_domain && hw_pass_through) { | 2329 | if (domain == si_domain && hw_pass_through) { |
2330 | printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n", | 2330 | printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n", |
2331 | pci_name(pdev), start, end); | 2331 | dev_name(dev), start, end); |
2332 | return 0; | 2332 | return 0; |
2333 | } | 2333 | } |
2334 | 2334 | ||
2335 | printk(KERN_INFO | 2335 | printk(KERN_INFO |
2336 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 2336 | "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", |
2337 | pci_name(pdev), start, end); | 2337 | dev_name(dev), start, end); |
2338 | 2338 | ||
2339 | if (end < start) { | 2339 | if (end < start) { |
2340 | WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n" | 2340 | WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n" |
@@ -2362,7 +2362,7 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, | |||
2362 | goto error; | 2362 | goto error; |
2363 | 2363 | ||
2364 | /* context entry init */ | 2364 | /* context entry init */ |
2365 | ret = domain_context_mapping(domain, &pdev->dev, CONTEXT_TT_MULTI_LEVEL); | 2365 | ret = domain_context_mapping(domain, dev, CONTEXT_TT_MULTI_LEVEL); |
2366 | if (ret) | 2366 | if (ret) |
2367 | goto error; | 2367 | goto error; |
2368 | 2368 | ||
@@ -2374,12 +2374,12 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, | |||
2374 | } | 2374 | } |
2375 | 2375 | ||
2376 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, | 2376 | static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, |
2377 | struct pci_dev *pdev) | 2377 | struct device *dev) |
2378 | { | 2378 | { |
2379 | if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) | 2379 | if (dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) |
2380 | return 0; | 2380 | return 0; |
2381 | return iommu_prepare_identity_map(pdev, rmrr->base_address, | 2381 | return iommu_prepare_identity_map(dev, rmrr->base_address, |
2382 | rmrr->end_address); | 2382 | rmrr->end_address); |
2383 | } | 2383 | } |
2384 | 2384 | ||
2385 | #ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA | 2385 | #ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA |
@@ -2393,7 +2393,7 @@ static inline void iommu_prepare_isa(void) | |||
2393 | return; | 2393 | return; |
2394 | 2394 | ||
2395 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); | 2395 | printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n"); |
2396 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024 - 1); | 2396 | ret = iommu_prepare_identity_map(&pdev->dev, 0, 16*1024*1024 - 1); |
2397 | 2397 | ||
2398 | if (ret) | 2398 | if (ret) |
2399 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " | 2399 | printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; " |
@@ -2495,7 +2495,7 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2495 | return 0; | 2495 | return 0; |
2496 | } | 2496 | } |
2497 | 2497 | ||
2498 | static bool device_has_rmrr(struct pci_dev *dev) | 2498 | static bool device_has_rmrr(struct device *dev) |
2499 | { | 2499 | { |
2500 | struct dmar_rmrr_unit *rmrr; | 2500 | struct dmar_rmrr_unit *rmrr; |
2501 | struct device *tmp; | 2501 | struct device *tmp; |
@@ -2509,7 +2509,7 @@ static bool device_has_rmrr(struct pci_dev *dev) | |||
2509 | */ | 2509 | */ |
2510 | for_each_active_dev_scope(rmrr->devices, | 2510 | for_each_active_dev_scope(rmrr->devices, |
2511 | rmrr->devices_cnt, i, tmp) | 2511 | rmrr->devices_cnt, i, tmp) |
2512 | if (tmp == &dev->dev) { | 2512 | if (tmp == dev) { |
2513 | rcu_read_unlock(); | 2513 | rcu_read_unlock(); |
2514 | return true; | 2514 | return true; |
2515 | } | 2515 | } |
@@ -2529,7 +2529,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | |||
2529 | * from this process due to their usage of RMRRs that are known | 2529 | * from this process due to their usage of RMRRs that are known |
2530 | * to not be needed after BIOS hand-off to OS. | 2530 | * to not be needed after BIOS hand-off to OS. |
2531 | */ | 2531 | */ |
2532 | if (device_has_rmrr(pdev) && | 2532 | if (device_has_rmrr(&pdev->dev) && |
2533 | (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) | 2533 | (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) |
2534 | return 0; | 2534 | return 0; |
2535 | 2535 | ||
@@ -2766,9 +2766,7 @@ static int __init init_dmars(void) | |||
2766 | /* some BIOS lists non-exist devices in DMAR table. */ | 2766 | /* some BIOS lists non-exist devices in DMAR table. */ |
2767 | for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt, | 2767 | for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt, |
2768 | i, dev) { | 2768 | i, dev) { |
2769 | if (!dev_is_pci(dev)) | 2769 | ret = iommu_prepare_rmrr_dev(rmrr, dev); |
2770 | continue; | ||
2771 | ret = iommu_prepare_rmrr_dev(rmrr, to_pci_dev(dev)); | ||
2772 | if (ret) | 2770 | if (ret) |
2773 | printk(KERN_ERR | 2771 | printk(KERN_ERR |
2774 | "IOMMU: mapping reserved region failed\n"); | 2772 | "IOMMU: mapping reserved region failed\n"); |