[PATCH] intel-iommu: Obey coherent_dma_mask for alloc_coherent onpassthrough

From: Alex Williamson
Date: Wed Nov 04 2009 - 18:03:26 EST


intel_alloc_coherent() needs to follow DMA mapping convention and
make use of the coherent_dma_mask of the device for identity mappings.
Without this, devices may get buffers they can't use. This patch
provides best effort allocations and fails the request if the mask
requirements are not met rather than returning an unusable buffer.

Signed-off-by: Alex Williamson <alex.williamson@xxxxxx>
---

This patch fixes a regression introduced since 2.6.31 that prevents
devices with a restricted coherent_dma_mask from working in passthrough
mode.

drivers/pci/intel-iommu.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index b1e97e6..8283df9 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -2582,7 +2582,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
BUG_ON(dir == DMA_NONE);

if (iommu_no_mapping(hwdev))
- return paddr;
+ return paddr + size > dma_mask ? 0 : paddr;

domain = get_valid_domain_for_dev(pdev);
if (!domain)
@@ -2767,7 +2767,15 @@ static void *intel_alloc_coherent(struct device *hwdev, size_t size,

size = PAGE_ALIGN(size);
order = get_order(size);
- flags &= ~(GFP_DMA | GFP_DMA32);
+
+ if (!iommu_no_mapping(hwdev))
+ flags &= ~(GFP_DMA | GFP_DMA32);
+ else if (hwdev->coherent_dma_mask != DMA_BIT_MASK(64)) {
+ if (hwdev->coherent_dma_mask < DMA_BIT_MASK(32))
+ flags |= GFP_DMA;
+ else
+ flags |= GFP_DMA32;
+ }

vaddr = (void *)__get_free_pages(flags, order);
if (!vaddr)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/