aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2016-08-25 08:25:12 -0400
committerJoerg Roedel <jroedel@suse.de>2016-09-05 07:00:28 -0400
commit76208356a0ab357a1fb9f43bedb7fd1046ad8ece (patch)
tree6b469fc7770e831ed032723c9935c2bdec47952c
parentc6935931c1894ff857616ff8549b61236a19148f (diff)
iommu/vt-d: Split up get_domain_for_dev function
Split out the search for an already existing domain and the context mapping of the device to the new domain. This allows to map possible RMRR regions into the domain before it is context mapped. Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/intel-iommu.c76
1 files changed, 55 insertions, 21 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index ebb5bf3ddbd9..bcdbe9de7560 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2452,20 +2452,15 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2452 return 0; 2452 return 0;
2453} 2453}
2454 2454
2455/* domain is initialized */ 2455static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
2456static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2457{ 2456{
2458 struct device_domain_info *info = NULL; 2457 struct device_domain_info *info = NULL;
2459 struct dmar_domain *domain, *tmp; 2458 struct dmar_domain *domain = NULL;
2460 struct intel_iommu *iommu; 2459 struct intel_iommu *iommu;
2461 u16 req_id, dma_alias; 2460 u16 req_id, dma_alias;
2462 unsigned long flags; 2461 unsigned long flags;
2463 u8 bus, devfn; 2462 u8 bus, devfn;
2464 2463
2465 domain = find_domain(dev);
2466 if (domain)
2467 return domain;
2468
2469 iommu = device_to_iommu(dev, &bus, &devfn); 2464 iommu = device_to_iommu(dev, &bus, &devfn);
2470 if (!iommu) 2465 if (!iommu)
2471 return NULL; 2466 return NULL;
@@ -2487,9 +2482,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2487 } 2482 }
2488 spin_unlock_irqrestore(&device_domain_lock, flags); 2483 spin_unlock_irqrestore(&device_domain_lock, flags);
2489 2484
2490 /* DMA alias already has a domain, uses it */ 2485 /* DMA alias already has a domain, use it */
2491 if (info) 2486 if (info)
2492 goto found_domain; 2487 goto out;
2493 } 2488 }
2494 2489
2495 /* Allocate and initialize new domain for the device */ 2490 /* Allocate and initialize new domain for the device */
@@ -2501,28 +2496,67 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2501 return NULL; 2496 return NULL;
2502 } 2497 }
2503 2498
2504 /* register PCI DMA alias device */ 2499out:
2505 if (dev_is_pci(dev) && req_id != dma_alias) {
2506 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2507 dma_alias & 0xff, NULL, domain);
2508 2500
2509 if (!tmp || tmp != domain) { 2501 return domain;
2510 domain_exit(domain); 2502}
2511 domain = tmp;
2512 }
2513 2503
2514 if (!domain) 2504static struct dmar_domain *set_domain_for_dev(struct device *dev,
2515 return NULL; 2505 struct dmar_domain *domain)
2506{
2507 struct intel_iommu *iommu;
2508 struct dmar_domain *tmp;
2509 u16 req_id, dma_alias;
2510 u8 bus, devfn;
2511
2512 iommu = device_to_iommu(dev, &bus, &devfn);
2513 if (!iommu)
2514 return NULL;
2515
2516 req_id = ((u16)bus << 8) | devfn;
2517
2518 if (dev_is_pci(dev)) {
2519 struct pci_dev *pdev = to_pci_dev(dev);
2520
2521 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2522
2523 /* register PCI DMA alias device */
2524 if (req_id != dma_alias) {
2525 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2526 dma_alias & 0xff, NULL, domain);
2527
2528 if (!tmp || tmp != domain)
2529 return tmp;
2530 }
2516 } 2531 }
2517 2532
2518found_domain:
2519 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain); 2533 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
2534 if (!tmp || tmp != domain)
2535 return tmp;
2536
2537 return domain;
2538}
2520 2539
2521 if (!tmp || tmp != domain) { 2540static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
2541{
2542 struct dmar_domain *domain, *tmp;
2543
2544 domain = find_domain(dev);
2545 if (domain)
2546 goto out;
2547
2548 domain = find_or_alloc_domain(dev, gaw);
2549 if (!domain)
2550 goto out;
2551
2552 tmp = set_domain_for_dev(dev, domain);
2553 if (!tmp || domain != tmp) {
2522 domain_exit(domain); 2554 domain_exit(domain);
2523 domain = tmp; 2555 domain = tmp;
2524 } 2556 }
2525 2557
2558out:
2559
2526 return domain; 2560 return domain;
2527} 2561}
2528 2562