# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1183985110 -3600
# Node ID 08cf42135056cbc07a6d790d4851e0e4b160f847
# Parent f833757672a70ee43afd0bfbfaa22cec3b132445
x86: dma_map_sg() must handle multi-page segments.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
arch/i386/kernel/pci-dma-xen.c | 5 ++++-
arch/i386/kernel/swiotlb.c | 6 ++++--
include/asm-i386/mach-xen/asm/dma-mapping.h | 6 +++---
3 files changed, 11 insertions(+), 6 deletions(-)
diff -r f833757672a7 -r 08cf42135056 arch/i386/kernel/pci-dma-xen.c
--- a/arch/i386/kernel/pci-dma-xen.c Sat Jul 07 11:44:16 2007 +0100
+++ b/arch/i386/kernel/pci-dma-xen.c Mon Jul 09 13:45:10 2007 +0100
@@ -97,6 +97,9 @@ dma_map_sg(struct device *hwdev, struct
BUG_ON(!sg[i].page);
IOMMU_BUG_ON(address_needs_mapping(
hwdev, sg[i].dma_address));
+ IOMMU_BUG_ON(range_straddles_page_boundary(
+ page_to_pseudophys(sg[i].page) + sg[i].offset,
+ sg[i].length));
}
rc = nents;
}
@@ -338,7 +341,7 @@ dma_map_single(struct device *dev, void
} else {
dma = gnttab_dma_map_page(virt_to_page(ptr)) +
offset_in_page(ptr);
- IOMMU_BUG_ON(range_straddles_page_boundary(ptr, size));
+ IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size));
IOMMU_BUG_ON(address_needs_mapping(dev, dma));
}
diff -r f833757672a7 -r 08cf42135056 arch/i386/kernel/swiotlb.c
--- a/arch/i386/kernel/swiotlb.c Sat Jul 07 11:44:16 2007 +0100
+++ b/arch/i386/kernel/swiotlb.c Mon Jul 09 13:45:10 2007 +0100
@@ -480,7 +480,7 @@ swiotlb_map_single(struct device *hwdev,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
- if (!range_straddles_page_boundary(ptr, size) &&
+ if (!range_straddles_page_boundary(__pa(ptr), size) &&
!address_needs_mapping(hwdev, dev_addr))
return dev_addr;
@@ -577,7 +577,9 @@ swiotlb_map_sg(struct device *hwdev, str
for (i = 0; i < nelems; i++, sg++) {
dev_addr = gnttab_dma_map_page(sg->page) + sg->offset;
- if (address_needs_mapping(hwdev, dev_addr)) {
+ if (range_straddles_page_boundary(page_to_pseudophys(sg->page)
+ + sg->offset, sg->length)
+ || address_needs_mapping(hwdev, dev_addr)) {
gnttab_dma_unmap_page(dev_addr);
buffer.page = sg->page;
buffer.offset = sg->offset;
diff -r f833757672a7 -r 08cf42135056 include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/include/asm-i386/mach-xen/asm/dma-mapping.h Sat Jul 07 11:44:16
2007 +0100
+++ b/include/asm-i386/mach-xen/asm/dma-mapping.h Mon Jul 09 13:45:10
2007 +0100
@@ -23,11 +23,11 @@ address_needs_mapping(struct device *hwd
}
static inline int
-range_straddles_page_boundary(void *p, size_t size)
+range_straddles_page_boundary(paddr_t p, size_t size)
{
extern unsigned long *contiguous_bitmap;
- return (((((unsigned long)p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
- !test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap));
+ return ((((p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
+ !test_bit(p >> PAGE_SHIFT, contiguous_bitmap));
}
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|