]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
swiotlb: Allow sync on arbitrary offsets into dma-mapped region.
authorkfraser <kfraser@localhost.localdomain>
Mon, 9 Jul 2007 19:15:53 +0000 (20:15 +0100)
committerkfraser <kfraser@localhost.localdomain>
Mon, 9 Jul 2007 19:15:53 +0000 (20:15 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
arch/i386/kernel/swiotlb.c

index dc03ca5c21adf198dd25e592cd9d57bd5cf62f44..8d3ab21e7664352191310cace6d6dd8f40b955c6 100644 (file)
@@ -378,12 +378,10 @@ map_single(struct device *hwdev, struct phys_addr buffer, size_t size, int dir)
         */
        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);
@@ -391,6 +389,16 @@ map_single(struct device *hwdev, struct phys_addr buffer, size_t size, int dir)
        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;
+}
+
 /*
  * dma_addr is the kernel virtual address of the bounce buffer to unmap.
  */
@@ -400,7 +408,7 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
        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 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
 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);
 }