diff options
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 49 |
1 files changed, 18 insertions, 31 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f8074236bcce..11a23201445a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -2323,43 +2323,31 @@ static inline unsigned long aligned_nrpages(unsigned long host_addr, | |||
2323 | return host_addr >> VTD_PAGE_SHIFT; | 2323 | return host_addr >> VTD_PAGE_SHIFT; |
2324 | } | 2324 | } |
2325 | 2325 | ||
2326 | struct iova * | 2326 | static struct iova *intel_alloc_iova(struct device *dev, |
2327 | iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) | 2327 | struct dmar_domain *domain, |
2328 | { | 2328 | unsigned long nrpages, uint64_t dma_mask) |
2329 | struct iova *piova; | ||
2330 | |||
2331 | /* Make sure it's in range */ | ||
2332 | end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); | ||
2333 | if (!size || (IOVA_START_ADDR + size > end)) | ||
2334 | return NULL; | ||
2335 | |||
2336 | piova = alloc_iova(&domain->iovad, | ||
2337 | size >> PAGE_SHIFT, IOVA_PFN(end), 1); | ||
2338 | return piova; | ||
2339 | } | ||
2340 | |||
2341 | static struct iova * | ||
2342 | __intel_alloc_iova(struct device *dev, struct dmar_domain *domain, | ||
2343 | size_t size, u64 dma_mask) | ||
2344 | { | 2329 | { |
2345 | struct pci_dev *pdev = to_pci_dev(dev); | 2330 | struct pci_dev *pdev = to_pci_dev(dev); |
2346 | struct iova *iova = NULL; | 2331 | struct iova *iova = NULL; |
2347 | 2332 | ||
2348 | if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac) | 2333 | /* Restrict dma_mask to the width that the iommu can handle */ |
2349 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2334 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
2350 | else { | 2335 | |
2336 | if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) { | ||
2351 | /* | 2337 | /* |
2352 | * First try to allocate an io virtual address in | 2338 | * First try to allocate an io virtual address in |
2353 | * DMA_BIT_MASK(32) and if that fails then try allocating | 2339 | * DMA_BIT_MASK(32) and if that fails then try allocating |
2354 | * from higher range | 2340 | * from higher range |
2355 | */ | 2341 | */ |
2356 | iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32)); | 2342 | iova = alloc_iova(&domain->iovad, nrpages, |
2357 | if (!iova) | 2343 | IOVA_PFN(DMA_BIT_MASK(32)), 1); |
2358 | iova = iommu_alloc_iova(domain, size, dma_mask); | 2344 | if (iova) |
2359 | } | 2345 | return iova; |
2360 | 2346 | } | |
2361 | if (!iova) { | 2347 | iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1); |
2362 | printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); | 2348 | if (unlikely(!iova)) { |
2349 | printk(KERN_ERR "Allocating %ld-page iova for %s failed", | ||
2350 | nrpages, pci_name(pdev)); | ||
2363 | return NULL; | 2351 | return NULL; |
2364 | } | 2352 | } |
2365 | 2353 | ||
@@ -2464,7 +2452,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2464 | iommu = domain_get_iommu(domain); | 2452 | iommu = domain_get_iommu(domain); |
2465 | size = aligned_nrpages(paddr, size); | 2453 | size = aligned_nrpages(paddr, size); |
2466 | 2454 | ||
2467 | iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, pdev->dma_mask); | 2455 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
2468 | if (!iova) | 2456 | if (!iova) |
2469 | goto error; | 2457 | goto error; |
2470 | 2458 | ||
@@ -2753,8 +2741,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2753 | for_each_sg(sglist, sg, nelems, i) | 2741 | for_each_sg(sglist, sg, nelems, i) |
2754 | size += aligned_nrpages(sg->offset, sg->length); | 2742 | size += aligned_nrpages(sg->offset, sg->length); |
2755 | 2743 | ||
2756 | iova = __intel_alloc_iova(hwdev, domain, size << VTD_PAGE_SHIFT, | 2744 | iova = intel_alloc_iova(hwdev, domain, size, pdev->dma_mask); |
2757 | pdev->dma_mask); | ||
2758 | if (!iova) { | 2745 | if (!iova) { |
2759 | sglist->dma_length = 0; | 2746 | sglist->dma_length = 0; |
2760 | return 0; | 2747 | return 0; |