# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1184008553 -3600
# Node ID 5684370b1c4d9911fd4118fdc472c3c7a9adfca3
# Parent 5a4e93508aa03799989b63f8413aeae7df87c576
swiotlb: Allow sync on arbitrary offsets into dma-mapped region.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
arch/i386/kernel/swiotlb.c | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
diff -r 5a4e93508aa0 -r 5684370b1c4d arch/i386/kernel/swiotlb.c
--- a/arch/i386/kernel/swiotlb.c Mon Jul 09 20:00:19 2007 +0100
+++ b/arch/i386/kernel/swiotlb.c Mon Jul 09 20:15:53 2007 +0100
@@ -378,17 +378,25 @@ map_single(struct device *hwdev, struct
*/
slot_buf = buffer;
for (i = 0; i < nslots; i++) {
+ slot_buf.page += slot_buf.offset >> PAGE_SHIFT;
+ slot_buf.offset &= PAGE_SIZE - 1;
io_tlb_orig_addr[index+i] = slot_buf;
slot_buf.offset += 1 << IO_TLB_SHIFT;
- if (slot_buf.offset >= PAGE_SIZE) {
- slot_buf.page++;
- slot_buf.offset -= PAGE_SIZE;
- }
}
if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL))
__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
return dma_addr;
+}
+
+struct phys_addr dma_addr_to_phys_addr(char *dma_addr)
+{
+ int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
+ struct phys_addr buffer = io_tlb_orig_addr[index];
+ buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1);
+ buffer.page += buffer.offset >> PAGE_SHIFT;
+ buffer.offset &= PAGE_SIZE - 1;
+ return buffer;
}
/*
@@ -400,7 +408,7 @@ unmap_single(struct device *hwdev, char
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
- struct phys_addr buffer = io_tlb_orig_addr[index];
+ struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
/*
* First, sync the memory before unmapping the entry
@@ -440,8 +448,7 @@ static void
static void
sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
{
- int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
- struct phys_addr buffer = io_tlb_orig_addr[index];
+ struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
__sync_single(buffer, dma_addr, size, dir);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|