Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2608

kernel-2.6.18-128.1.10.el5.src.rpm

From: Bill Burns <bburns@redhat.com>
Date: Thu, 20 Dec 2007 13:29:00 -0500
Subject: [xen] allow sync on offsets into dma-mapped region
Message-id: 20071220182900.7320.9303.sendpatchset@localhost.localdomain
O-Subject: [RHEL5.2 PATCH 4/6] Allow sync on arbitrary offsets into dma-mapped region
Bugzilla: 328321

# HG changeset patch
# User kfraser@localhost.localdomain
# Date 1184008553 -3600
# Node ID 656eb30f7c9bbb45e3cd20da8324fb10474d90e5
# Parent  f7eed71281eadea31909e2728d783f7c97af6ea8
swiotlb: Allow sync on arbitrary offsets into dma-mapped region.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6.18-xen changeset: 101:5684370b1c4d9911fd4118fdc472c3c7a9adfca3
linux-2.6.18-xen date: Mon Jul 09 20:15:53 2007 +0100

Acked-by: "David S. Miller" <davem@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>

diff --git a/arch/i386/kernel/swiotlb.c b/arch/i386/kernel/swiotlb.c
index 497ae67..0e73bb0 100644
--- a/arch/i386/kernel/swiotlb.c
+++ b/arch/i386/kernel/swiotlb.c
@@ -334,12 +334,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);
@@ -347,6 +345,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.
  */
@@ -356,7 +364,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
@@ -396,8 +404,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);
 }