Skip to contentSkip to conversation

swiotlb: use phys_addr_t for pages

PATCH In review Jeremy Fitzhardinge 5 participants 29 messages Dec 22, 2008 – Dec 28, 2008

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 swiotlb: use phys_addr_t for pages

Hi all,

Here's a work in progress series whcih does a partial revert of the previous swiotlb changes, and does a partial replacement with Becky Bruce's series.

The most important difference is Becky's use of phys_addr_t rather than page+offset to represent arbitrary pages. This turns out to be simpler.

I didn't replicate the map_single_page changes, since I'm not exactly sure of ppc's requirements here, and it seemed like something that could be easily added.

Quick testing showed no problems, but I haven't had the chance to do anything extensive.

I've made some small changes to Becky's patches to make them apply, but I've separated any functional changes into separate patches with appropriate authorship.

J

#1 lore raw

PATCH 1/1 revert "swiotlb: support bouncing of HighMem pages."

git commit ef9b189352f2eb78f14e52996f4780a523b04a49

---
 lib/swiotlb.c |  122 +++++++++++++++------------------------------------------
 1 file changed, 33 insertions(+), 89 deletions(-)
lib/swiotlb.c +33 -89
@@ -26,7 +26,6 @@
 #include <linux/swiotlb.h>
 #include <linux/types.h>
 #include <linux/ctype.h>
-#include <linux/highmem.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -39,6 +38,9 @@
 #define OFFSET(val,align) ((unsigned long)	\
 	                   ( (val) & ( (align) - 1)))
 
+#define SG_ENT_VIRT_ADDRESS(sg)	(sg_virt((sg)))
+#define SG_ENT_PHYS_ADDRESS(sg)	virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
+
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 
 /*
@@ -89,10 +91,7 @@
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
  */
-static struct swiotlb_phys_addr {
-	struct page *page;
-	unsigned int offset;
-} *io_tlb_orig_addr;
+static unsigned char **io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
@@ -151,11 +150,6 @@
 	return 0;
 }
 
-static dma_addr_t swiotlb_sg_to_bus(struct scatterlist *sg)
-{
-	return swiotlb_phys_to_bus(page_to_phys(sg_page(sg)) + sg->offset);
-}
-
 static void swiotlb_print_info(unsigned long bytes)
 {
 	phys_addr_t pstart, pend;
@@ -215,7 +209,7 @@
 	for (i = 0; i < io_tlb_nslabs; i++)
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
-	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr));
+	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
 
 	/*
 	 * Get the overflow emergency buffer
@@ -289,12 +283,12 @@
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
 
-	io_tlb_orig_addr = (struct swiotlb_phys_addr *)__get_free_pages(GFP_KERNEL,
-	                           get_order(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr)));
+	io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
+	                           get_order(io_tlb_nslabs * sizeof(char *)));
 	if (!io_tlb_orig_addr)
 		goto cleanup3;
 
-	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(struct swiotlb_phys_addr));
+	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
 
 	/*
 	 * Get the overflow emergency buffer
@@ -341,59 +335,20 @@
 	return addr >= io_tlb_start && addr < io_tlb_end;
 }
 
-static struct swiotlb_phys_addr swiotlb_bus_to_phys_addr(char *dma_addr)
+static void
+__sync_single(char *buffer, char *dma_addr, size_t size, int dir)
 {
-	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	struct swiotlb_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;
-}
-
-static void
-__sync_single(struct swiotlb_phys_addr buffer, char *dma_addr, size_t size, int dir)
-{
-	if (PageHighMem(buffer.page)) {
-		size_t len, bytes;
-		char *dev, *host, *kmp;
-
-		len = size;
-		while (len != 0) {
-			unsigned long flags;
-
-			bytes = len;
-			if ((bytes + buffer.offset) > PAGE_SIZE)
-				bytes = PAGE_SIZE - buffer.offset;
-			local_irq_save(flags); /* protects KM_BOUNCE_READ */
-			kmp  = kmap_atomic(buffer.page, KM_BOUNCE_READ);
-			dev  = dma_addr + size - len;
-			host = kmp + buffer.offset;
-			if (dir == DMA_FROM_DEVICE)
-				memcpy(host, dev, bytes);
-			else
-				memcpy(dev, host, bytes);
-			kunmap_atomic(kmp, KM_BOUNCE_READ);
-			local_irq_restore(flags);
-			len -= bytes;
-			buffer.page++;
-			buffer.offset = 0;
-		}
-	} else {
-		void *v = page_address(buffer.page) + buffer.offset;
-
-		if (dir == DMA_TO_DEVICE)
-			memcpy(dma_addr, v, size);
-		else
-			memcpy(v, dma_addr, size);
-	}
+	if (dir == DMA_TO_DEVICE)
+		memcpy(dma_addr, buffer, size);
+	else
+		memcpy(buffer, dma_addr, size);
 }
 
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single(struct device *hwdev, struct swiotlb_phys_addr buffer, size_t size, int dir)
+map_single(struct device *hwdev, char *buffer, size_t size, int dir)
 {
 	unsigned long flags;
 	char *dma_addr;
@@ -403,7 +358,6 @@
 	unsigned long mask;
 	unsigned long offset_slots;
 	unsigned long max_slots;
-	struct swiotlb_phys_addr slot_buf;
 
 	mask = dma_get_seg_boundary(hwdev);
 	start_dma_addr = swiotlb_virt_to_bus(io_tlb_start) & mask;
@@ -488,13 +442,8 @@
 	 * This is needed when we sync the memory.  Then we sync the buffer if
 	 * needed.
 	 */
-	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;
-	}
+	for (i = 0; i < nslots; i++)
+		io_tlb_orig_addr[index+i] = buffer + (i << IO_TLB_SHIFT);
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
 		__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
 
@@ -510,12 +459,12 @@
 	unsigned long flags;
 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr);
+	char *buffer = io_tlb_orig_addr[index];
 
 	/*
 	 * First, sync the memory before unmapping the entry
 	 */
-	if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+	if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
 		/*
 		 * bounce... copy the data back into the original buffer * and
 		 * delete the bounce buffer.
@@ -552,7 +501,10 @@
 sync_single(struct device *hwdev, char *dma_addr, size_t size,
 	    int dir, int target)
 {
-	struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr);
+	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
+	char *buffer = io_tlb_orig_addr[index];
+
+	buffer += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
 
 	switch (target) {
 	case SYNC_FOR_CPU:
@@ -600,10 +552,7 @@
 		 * swiotlb_map_single(), which will grab memory from
 		 * the lowest available address range.
 		 */
-		struct swiotlb_phys_addr buffer;
-		buffer.page = virt_to_page(NULL);
-		buffer.offset = 0;
-		ret = map_single(hwdev, buffer, size, DMA_FROM_DEVICE);
+		ret = map_single(hwdev, NULL, size, DMA_FROM_DEVICE);
 		if (!ret)
 			return NULL;
 	}
@@ -671,7 +620,6 @@
 {
 	dma_addr_t dev_addr = swiotlb_virt_to_bus(ptr);
 	void *map;
-	struct swiotlb_phys_addr buffer;
 
 	BUG_ON(dir == DMA_NONE);
 	/*
@@ -686,9 +634,7 @@
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
 	 */
-	buffer.page   = virt_to_page(ptr);
-	buffer.offset = (unsigned long)ptr & ~PAGE_MASK;
-	map = map_single(hwdev, buffer, size, dir);
+	map = map_single(hwdev, ptr, size, dir);
 	if (!map) {
 		swiotlb_full(hwdev, size, dir, 1);
 		map = io_tlb_overflow_buffer;
@@ -833,20 +779,18 @@
 		     int dir, struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
-	struct swiotlb_phys_addr buffer;
+	void *addr;
 	dma_addr_t dev_addr;
 	int i;
 
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		dev_addr = swiotlb_sg_to_bus(sg);
+		addr = SG_ENT_VIRT_ADDRESS(sg);
+		dev_addr = swiotlb_virt_to_bus(addr);
 		if (range_needs_mapping(sg_virt(sg), sg->length) ||
 		    address_needs_mapping(hwdev, dev_addr, sg->length)) {
-			void *map;
-			buffer.page   = sg_page(sg);
-			buffer.offset = sg->offset;
-			map = map_single(hwdev, buffer, sg->length, dir);
+			void *map = map_single(hwdev, addr, sg->length, dir);
 			if (!map) {
 				/* Don't panic here, we expect map_sg users
 				   to do proper error handling. */
@@ -886,11 +830,11 @@
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		if (sg->dma_address != swiotlb_sg_to_bus(sg))
+		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
 			unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				     sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
-			dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length);
+			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 	}
 }
 EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
@@ -919,11 +863,11 @@
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		if (sg->dma_address != swiotlb_sg_to_bus(sg))
+		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
 			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				    sg->dma_length, dir, target);
 		else if (dir == DMA_FROM_DEVICE)
-			dma_mark_clean(swiotlb_bus_to_virt(sg->dma_address), sg->dma_length);
+			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 	}
 }
 
#2 lore raw

PATCH 1/1 revert "swiotlb: factor out copy to/from device."

In reply to Jeremy Fitzhardinge

git commit 1b548f667c1487d92e794a9f7a67788f49b952d8

---
 lib/swiotlb.c |   17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)
lib/swiotlb.c +4 -13
@@ -335,15 +335,6 @@
 	return addr >= io_tlb_start && addr < io_tlb_end;
 }
 
-static void
-__sync_single(char *buffer, char *dma_addr, size_t size, int dir)
-{
-	if (dir == DMA_TO_DEVICE)
-		memcpy(dma_addr, buffer, size);
-	else
-		memcpy(buffer, dma_addr, size);
-}
-
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
@@ -445,7 +436,7 @@
 	for (i = 0; i < nslots; i++)
 		io_tlb_orig_addr[index+i] = buffer + (i << IO_TLB_SHIFT);
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-		__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
+		memcpy(dma_addr, buffer, size);
 
 	return dma_addr;
 }
@@ -469,7 +460,7 @@
 		 * bounce... copy the data back into the original buffer * and
 		 * delete the bounce buffer.
 		 */
-		__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
+		memcpy(buffer, dma_addr, size);
 
 	/*
 	 * Return the buffer to the free list by setting the corresponding
@@ -509,13 +500,13 @@
 	switch (target) {
 	case SYNC_FOR_CPU:
 		if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-			__sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
+			memcpy(buffer, dma_addr, size);
 		else
 			BUG_ON(dir != DMA_TO_DEVICE);
 		break;
 	case SYNC_FOR_DEVICE:
 		if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-			__sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
+			memcpy(dma_addr, buffer, size);
 		else
 			BUG_ON(dir != DMA_FROM_DEVICE);
 		break;
#3 lore raw

PATCH 1/1 swiotlb: add hwdev to swiotlb_phys_to_bus

In reply to Jeremy Fitzhardinge

Some architectures need it.

---
 arch/x86/kernel/pci-swiotlb_64.c |    2 -
 include/linux/swiotlb.h          |    3 +-
 lib/swiotlb.c                    |   45 +++++++++++++++-----------------------
 3 files changed, 21 insertions(+), 29 deletions(-)
arch/x86/kernel/pci-swiotlb_64.c +1 -1
@@ -23,7 +23,7 @@
 	return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
 }
 
-dma_addr_t swiotlb_phys_to_bus(phys_addr_t paddr)
+dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
 {
 	return paddr;
 }
include/linux/swiotlb.h +2 -1
@@ -27,7 +27,8 @@
 extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
 extern void *swiotlb_alloc(unsigned order, unsigned long nslabs);
 
-extern dma_addr_t swiotlb_phys_to_bus(phys_addr_t address);
+extern dma_addr_t swiotlb_phys_to_bus(struct device *hwdev,
+				      phys_addr_t address);
 extern phys_addr_t swiotlb_bus_to_phys(dma_addr_t address);
 
 extern int swiotlb_arch_range_needs_mapping(void *ptr, size_t size);
lib/swiotlb.c +18 -27

124 lines not on this page · raw message

#4 lore raw

PATCH 1/1 swiotlb: Drop SG_ENT_VIRT_ADDRESS macro

In reply to Jeremy Fitzhardinge

From: Becky Bruce <[email protected]>

All SG_ENT_VIRT_ADDRESS does is call sg_virt(), get rid of this needless layer of complexity.

---
 lib/swiotlb.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)
lib/swiotlb.c +5 -6
@@ -38,8 +38,7 @@
 #define OFFSET(val,align) ((unsigned long)	\
 	                   ( (val) & ( (align) - 1)))
 
-#define SG_ENT_VIRT_ADDRESS(sg)	(sg_virt((sg)))
-#define SG_ENT_PHYS_ADDRESS(sg)	virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
+#define SG_ENT_PHYS_ADDRESS(sg)	virt_to_bus(sg_virt(sg))
 
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 
@@ -768,9 +767,9 @@
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		addr = SG_ENT_VIRT_ADDRESS(sg);
+		addr = sg_virt(sg);
 		dev_addr = swiotlb_virt_to_bus(hwdev, addr);
-		if (range_needs_mapping(sg_virt(sg), sg->length) ||
+		if (range_needs_mapping(addr, sg->length) ||
 		    address_needs_mapping(hwdev, dev_addr, sg->length)) {
 			void *map = map_single(hwdev, addr, sg->length, dir);
 			if (!map) {
@@ -816,7 +815,7 @@
 			unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				     sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
-			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+			dma_mark_clean(sg_virt(sg), sg->dma_length);
 	}
 }
 EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
@@ -849,7 +848,7 @@
 			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				    sg->dma_length, dir, target);
 		else if (dir == DMA_FROM_DEVICE)
-			dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+			dma_mark_clean(sg_virt(sg), sg->dma_length);
 	}
 }
#5 lore raw

PATCH 1/1 swiotlb: Rename SG_ENT_PHYS_ADDRESS to SG_ENT_BUS_ADDRESS

In reply to Jeremy Fitzhardinge

From: Becky Bruce <[email protected]>

Also add hwdev argument - some platforms will need this to calculate an actual bus address.

---
 lib/swiotlb.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
lib/swiotlb.c +3 -3
@@ -38,7 +38,7 @@
 #define OFFSET(val,align) ((unsigned long)	\
 	                   ( (val) & ( (align) - 1)))
 
-#define SG_ENT_PHYS_ADDRESS(sg)	virt_to_bus(sg_virt(sg))
+#define SG_ENT_BUS_ADDRESS(hwdev, sg)	swiotlb_virt_to_bus(hwdev, sg_virt(sg))
 
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 
@@ -811,7 +811,7 @@
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
+		if (sg->dma_address != SG_ENT_BUS_ADDRESS(hwdev, sg))
 			unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				     sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
@@ -844,7 +844,7 @@
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
+		if (sg->dma_address != SG_ENT_BUS_ADDRESS(hwdev, sg))
 			sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
 				    sg->dma_length, dir, target);
 		else if (dir == DMA_FROM_DEVICE)
#6 lore raw

PATCH 1/1 swiotlb: Store phys address in io_tlb_orig_addr array

In reply to Jeremy Fitzhardinge

From: Becky Bruce <[email protected]>

When we enable swiotlb for platforms that support HIGHMEM, we can no longer store the virtual address of the original dma buffer, because that buffer might not have a permament mapping. Change the iotlb code to instead store the physical address of the original buffer.

---
 lib/swiotlb.c |   47 ++++++++++++++++++++++++-----------------------
 1 files changed, 24 insertions(+), 23 deletions(-)
lib/swiotlb.c +26 -24
@@ -90,7 +90,7 @@
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
  */
-static unsigned char **io_tlb_orig_addr;
+static phys_addr_t *io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
@@ -197,7 +197,7 @@
 	for (i = 0; i < io_tlb_nslabs; i++)
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
-	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
+	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t));
 
 	/*
 	 * Get the overflow emergency buffer
@@ -271,12 +271,14 @@
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
 
-	io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
-	                           get_order(io_tlb_nslabs * sizeof(char *)));
+	io_tlb_orig_addr = (phys_addr_t *)
+		__get_free_pages(GFP_KERNEL,
+				 get_order(io_tlb_nslabs *
+					   sizeof(phys_addr_t)));
 	if (!io_tlb_orig_addr)
 		goto cleanup3;
 
-	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
+	memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(phys_addr_t));
 
 	/*
 	 * Get the overflow emergency buffer
@@ -291,8 +293,8 @@
 	return 0;
 
 cleanup4:
-	free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
-	                                                      sizeof(char *)));
+	free_pages((unsigned long)io_tlb_orig_addr,
+		   get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
 	io_tlb_orig_addr = NULL;
 cleanup3:
 	free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
@@ -327,7 +329,7 @@
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+map_single(struct device *hwdev, phys_addr_t phys, size_t size, int dir)
 {
 	unsigned long flags;
 	char *dma_addr;
@@ -422,9 +424,9 @@
 	 * needed.
 	 */
 	for (i = 0; i < nslots; i++)
-		io_tlb_orig_addr[index+i] = buffer + (i << IO_TLB_SHIFT);
+		io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-		memcpy(dma_addr, buffer, size);
+		memcpy(dma_addr, phys_to_virt(phys), size);
 
 	return dma_addr;
 }
@@ -438,17 +440,17 @@
 	unsigned long flags;
 	int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	char *buffer = io_tlb_orig_addr[index];
+	phys_addr_t phys = io_tlb_orig_addr[index];
 
 	/*
 	 * First, sync the memory before unmapping the entry
 	 */
-	if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+	if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
 		/*
 		 * bounce... copy the data back into the original buffer * and
 		 * delete the bounce buffer.
 		 */
-		memcpy(buffer, dma_addr, size);
+		memcpy(phys_to_virt(phys), dma_addr, size);
 
 	/*
 	 * Return the buffer to the free list by setting the corresponding
@@ -481,20 +483,20 @@
 	    int dir, int target)
 {
 	int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-	char *buffer = io_tlb_orig_addr[index];
+	phys_addr_t phys = io_tlb_orig_addr[index];
 
-	buffer += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
+	phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));
 
 	switch (target) {
 	case SYNC_FOR_CPU:
 		if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(buffer, dma_addr, size);
+			memcpy(phys_to_virt(phys), dma_addr, size);
 		else
 			BUG_ON(dir != DMA_TO_DEVICE);
 		break;
 	case SYNC_FOR_DEVICE:
 		if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(dma_addr, buffer, size);
+			memcpy(dma_addr, phys_to_virt(phys), size);
 		else
 			BUG_ON(dir != DMA_FROM_DEVICE);
 		break;
@@ -533,7 +535,7 @@
 		 * swiotlb_map_single(), which will grab memory from
 		 * the lowest available address range.
 		 */
-		ret = map_single(hwdev, NULL, size, DMA_FROM_DEVICE);
+		ret = map_single(hwdev, 0, size, DMA_FROM_DEVICE);
 		if (!ret)
 			return NULL;
 	}
@@ -615,7 +617,7 @@
 	/*
 	 * Oh well, have to allocate and map a bounce buffer.
 	 */
-	map = map_single(hwdev, ptr, size, dir);
+	map = map_single(hwdev, virt_to_phys(ptr), size, dir);
 	if (!map) {
 		swiotlb_full(hwdev, size, dir, 1);
 		map = io_tlb_overflow_buffer;
@@ -760,18 +762,18 @@
 		     int dir, struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
-	void *addr;
-	dma_addr_t dev_addr;
 	int i;
 
 	BUG_ON(dir == DMA_NONE);
 
 	for_each_sg(sgl, sg, nelems, i) {
-		addr = sg_virt(sg);
-		dev_addr = swiotlb_virt_to_bus(hwdev, addr);
+		void *addr = sg_virt(sg);
+		dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, addr);
+
 		if (range_needs_mapping(addr, sg->length) ||
 		    address_needs_mapping(hwdev, dev_addr, sg->length)) {
-			void *map = map_single(hwdev, addr, sg->length, dir);
+			void *map = map_single(hwdev, sg_phys(sg),
+					       sg->length, dir);
 			if (!map) {
 				/* Don't panic here, we expect map_sg users
 				   to do proper error handling. */
#7 lore raw

PATCH 1/1 swiotlb: Add support for systems with highmem

In reply to Jeremy Fitzhardinge

From: Becky Bruce <[email protected]>

On highmem systems, the original dma buffer might not have a virtual mapping - we need to kmap it in to perform the bounce. Extract the code that does the actual copy into a function that does the kmap if highmem is enabled, and defaults to the normal swiotlb memcpy if not.

---
 lib/swiotlb.c |   53 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 8 deletions(-)
lib/swiotlb.c +45 -8
@@ -14,6 +14,7 @@
  * 04/07/.. ak		Better overflow handling. Assorted fixes.
  * 05/09/10 linville	Add support for syncing ranges, support syncing for
  *			DMA_BIDIRECTIONAL mappings, miscellaneous cleanup.
+ * 08/12/11 beckyb	Add highmem support
  */
 
 #include <linux/cache.h>
@@ -26,6 +27,7 @@
 #include <linux/swiotlb.h>
 #include <linux/types.h>
 #include <linux/ctype.h>
+#include <linux/highmem.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -326,6 +328,45 @@
 }
 
 /*
+ * Bounce: copy the swiotlb buffer back to the original dma location
+ */
+void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+		  enum dma_data_direction dir)
+{
+#ifdef CONFIG_HIGHMEM
+	/* The buffer may not have a mapping.  Map it in and copy */
+	unsigned int offset = ((unsigned long)phys &
+			       ((1 << PAGE_SHIFT) - 1));
+	char *buffer;
+	unsigned int sz = 0;
+	unsigned long flags;
+
+	while (size) {
+		sz = ((PAGE_SIZE - offset) > size) ? size :
+			PAGE_SIZE - offset;
+		local_irq_save(flags);
+		buffer = kmap_atomic(pfn_to_page(phys >> PAGE_SHIFT),
+				     KM_BOUNCE_READ);
+		if (dir == DMA_TO_DEVICE)
+			memcpy(dma_addr, buffer + offset, sz);
+		else
+			memcpy(buffer + offset, dma_addr, sz);
+		kunmap_atomic(buffer, KM_BOUNCE_READ);
+		local_irq_restore(flags);
+		size -= sz;
+		phys += sz;
+		dma_addr += sz;
+		offset = 0;
+	}
+#else
+	if (dir == DMA_TO_DEVICE)
+		memcpy(dma_addr, phys_to_virt(phys), size);
+	else
+		memcpy(phys_to_virt(phys), dma_addr, size);
+#endif
+}
+
+/*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
@@ -426,7 +467,7 @@
 	for (i = 0; i < nslots; i++)
 		io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-		memcpy(dma_addr, phys_to_virt(phys), size);
+		swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
 
 	return dma_addr;
 }
@@ -446,11 +487,7 @@
 	 * First, sync the memory before unmapping the entry
 	 */
 	if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
-		/*
-		 * bounce... copy the data back into the original buffer * and
-		 * delete the bounce buffer.
-		 */
-		memcpy(phys_to_virt(phys), dma_addr, size);
+		swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
 
 	/*
 	 * Return the buffer to the free list by setting the corresponding
@@ -490,13 +527,13 @@
 	switch (target) {
 	case SYNC_FOR_CPU:
 		if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(phys_to_virt(phys), dma_addr, size);
+			swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
 		else
 			BUG_ON(dir != DMA_TO_DEVICE);
 		break;
 	case SYNC_FOR_DEVICE:
 		if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-			memcpy(dma_addr, phys_to_virt(phys), size);
+			swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
 		else
 			BUG_ON(dir != DMA_FROM_DEVICE);
 		break;
#8 lore raw

PATCH 1/1 swiotlb: cleanups to swiotlb_bounce()

In reply to Jeremy Fitzhardinge

Make swiotlb_bounce test each page for highness rather than relying on CONFIG_HIGHMEM, and a couple of other cleanups.

---
 lib/swiotlb.c |   61 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 32 insertions(+), 29 deletions(-)
lib/swiotlb.c +32 -29
@@ -25,6 +25,7 @@
 #include <linux/swiotlb.h>
 #include <linux/string.h>
 #include <linux/swiotlb.h>
+#include <linux/pfn.h>
 #include <linux/types.h>
 #include <linux/ctype.h>
 #include <linux/highmem.h>
@@ -330,40 +331,42 @@
 /*
  * Bounce: copy the swiotlb buffer back to the original dma location
  */
-void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
-		  enum dma_data_direction dir)
+static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+			   enum dma_data_direction dir)
 {
-#ifdef CONFIG_HIGHMEM
-	/* The buffer may not have a mapping.  Map it in and copy */
-	unsigned int offset = ((unsigned long)phys &
-			       ((1 << PAGE_SHIFT) - 1));
-	char *buffer;
-	unsigned int sz = 0;
-	unsigned long flags;
+	unsigned long pfn = PFN_DOWN(phys);
 
-	while (size) {
-		sz = ((PAGE_SIZE - offset) > size) ? size :
-			PAGE_SIZE - offset;
-		local_irq_save(flags);
-		buffer = kmap_atomic(pfn_to_page(phys >> PAGE_SHIFT),
-				     KM_BOUNCE_READ);
+	if (PageHighMem(pfn_to_page(pfn))) {
+		/* The buffer does not have a mapping.  Map it in and copy */
+		unsigned int offset = phys & ~PAGE_MASK;
+		char *buffer;
+		unsigned int sz = 0;
+		unsigned long flags;
+
+		while (size) {
+			sz = min(PAGE_SIZE - offset, size);
+
+			local_irq_save(flags);
+			buffer = kmap_atomic(pfn_to_page(pfn),
+					     KM_BOUNCE_READ);
+			if (dir == DMA_TO_DEVICE)
+				memcpy(dma_addr, buffer + offset, sz);
+			else
+				memcpy(buffer + offset, dma_addr, sz);
+			kunmap_atomic(buffer, KM_BOUNCE_READ);
+			local_irq_restore(flags);
+
+			size -= sz;
+			pfn++;
+			dma_addr += sz;
+			offset = 0;
+		}
+	} else {
 		if (dir == DMA_TO_DEVICE)
-			memcpy(dma_addr, buffer + offset, sz);
+			memcpy(dma_addr, phys_to_virt(phys), size);
 		else
-			memcpy(buffer + offset, dma_addr, sz);
-		kunmap_atomic(buffer, KM_BOUNCE_READ);
-		local_irq_restore(flags);
-		size -= sz;
-		phys += sz;
-		dma_addr += sz;
-		offset = 0;
+			memcpy(phys_to_virt(phys), dma_addr, size);
 	}
-#else
-	if (dir == DMA_TO_DEVICE)
-		memcpy(dma_addr, phys_to_virt(phys), size);
-	else
-		memcpy(phys_to_virt(phys), dma_addr, size);
-#endif
 }
 
 /*
#9 lore raw

PATCH 1/1 ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

In reply to Jeremy Fitzhardinge

From: Becky Bruce <[email protected]>

SWIOTLB currently uses "int" as the type of the dma direction, not "enum dma_data_direction as documented in DMA_API.txt. Now that this code is about to become shared with powerpc, which uses the enum, update the swiotlb code to use the enum as well. Doing this requires changing all the arch's that use swiotlb use the enum also.

---
 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-
 arch/x86/include/asm/dma-mapping.h  |   50 ++++++++++++++++++--------------
 arch/x86/include/asm/swiotlb.h      |   24 +++++++++------
 arch/x86/include/asm/tce.h          |    3 +-
 arch/x86/kernel/amd_iommu.c         |   16 +++++-----
 arch/x86/kernel/pci-calgary_64.c    |   11 ++++---
 arch/x86/kernel/pci-gart_64.c       |   19 ++++++++----
 arch/x86/kernel/pci-nommu.c         |    4 +-
 arch/x86/kernel/pci-swiotlb_64.c    |    2 +-
 arch/x86/kernel/tce_64.c            |    3 +-
 drivers/pci/intel-iommu.c           |   13 ++++----
 include/linux/intel-iommu.h         |   12 +++++--
 include/linux/swiotlb.h             |   33 ++++++++++++---------
 lib/swiotlb.c                       |   54 ++++++++++++++++++++---------------
 23 files changed, 219 insertions(+), 159 deletions(-)
arch/ia64/dig/dig_vtd_iommu.c +5 -4
@@ -21,7 +21,7 @@
 
 dma_addr_t
 vtd_map_single_attrs(struct device *dev, void *addr, size_t size,
-		     int dir, struct dma_attrs *attrs)
+		     enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	return intel_map_single(dev, (phys_addr_t)addr, size, dir);
 }
@@ -29,7 +29,7 @@
 
 void
 vtd_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
-		       int dir, struct dma_attrs *attrs)
+		       enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	intel_unmap_single(dev, iova, size, dir);
 }
@@ -37,7 +37,7 @@
 
 int
 vtd_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
-		 int dir, struct dma_attrs *attrs)
+		 enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	return intel_map_sg(dev, sglist, nents, dir);
 }
@@ -45,7 +45,8 @@
 
 void
 vtd_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
-		   int nents, int dir, struct dma_attrs *attrs)
+		   int nents, enum dma_data_direction dir,
+		   struct dma_attrs *attrs)
 {
 	intel_unmap_sg(dev, sglist, nents, dir);
 }
arch/ia64/hp/common/hwsw_iommu.c +13 -9
@@ -91,8 +91,8 @@
 }
 
 dma_addr_t
-hwsw_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
-		       struct dma_attrs *attrs)
+hwsw_map_single_attrs(struct device *dev, void *addr, size_t size,
+		      enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	if (use_swiotlb(dev))
 		return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
@@ -103,7 +103,7 @@
 
 void
 hwsw_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
-			 int dir, struct dma_attrs *attrs)
+			 enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	if (use_swiotlb(dev))
 		return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs);
@@ -114,7 +114,7 @@
 
 int
 hwsw_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
-		   int dir, struct dma_attrs *attrs)
+		   enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	if (use_swiotlb(dev))
 		return swiotlb_map_sg_attrs(dev, sglist, nents, dir, attrs);
@@ -125,7 +125,7 @@
 
 void
 hwsw_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
-		     int dir, struct dma_attrs *attrs)
+		     enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	if (use_swiotlb(dev))
 		return swiotlb_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
@@ -135,7 +135,8 @@
 EXPORT_SYMBOL(hwsw_unmap_sg_attrs);
 
 void
-hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir)
+hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size,
+			  enum dma_data_direction dir)
 {
 	if (use_swiotlb(dev))
 		swiotlb_sync_single_for_cpu(dev, addr, size, dir);
@@ -144,7 +145,8 @@
 }
 
 void
-hwsw_sync_sg_for_cpu (struct device *dev, struct scatterlist *sg, int nelems, int dir)
+hwsw_sync_sg_for_cpu (struct device *dev, struct scatterlist *sg, int nelems,
+		      enum dma_data_direction dir)
 {
 	if (use_swiotlb(dev))
 		swiotlb_sync_sg_for_cpu(dev, sg, nelems, dir);
@@ -153,7 +155,8 @@
 }
 
 void
-hwsw_sync_single_for_device (struct device *dev, dma_addr_t addr, size_t size, int dir)
+hwsw_sync_single_for_device (struct device *dev, dma_addr_t addr, size_t size,
+			     enum dma_data_direction dir)
 {
 	if (use_swiotlb(dev))
 		swiotlb_sync_single_for_device(dev, addr, size, dir);
@@ -162,7 +165,8 @@
 }
 
 void
-hwsw_sync_sg_for_device (struct device *dev, struct scatterlist *sg, int nelems, int dir)
+hwsw_sync_sg_for_device (struct device *dev, struct scatterlist *sg, int nelems,
+			 enum dma_data_direction dir)
 {
 	if (use_swiotlb(dev))
 		swiotlb_sync_sg_for_device(dev, sg, nelems, dir);
arch/ia64/hp/common/sba_iommu.c +7 -5
@@ -909,8 +909,8 @@
  * See Documentation/DMA-mapping.txt
  */
 dma_addr_t
-sba_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
-		     struct dma_attrs *attrs)
+sba_map_single_attrs(struct device *dev, void *addr, size_t size,
+		     enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	struct ioc *ioc;
 	dma_addr_t iovp;
@@ -1027,7 +1027,8 @@
  * See Documentation/DMA-mapping.txt
  */
 void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
-			    int dir, struct dma_attrs *attrs)
+			    enum dma_data_direction dir,
+			    struct dma_attrs *attrs)
 {
 	struct ioc *ioc;
 #if DELAYED_RESOURCE_CNT > 0
@@ -1423,7 +1424,7 @@
  * See Documentation/DMA-mapping.txt
  */
 int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
-		     int dir, struct dma_attrs *attrs)
+		     enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	struct ioc *ioc;
 	int coalesced, filled = 0;
@@ -1515,7 +1516,8 @@
  * See Documentation/DMA-mapping.txt
  */
 void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
-			int nents, int dir, struct dma_attrs *attrs)
+			int nents, enum dma_data_direction dir,
+			struct dma_attrs *attrs)
 {
 #ifdef ASSERT_PDIR_SANITY
 	struct ioc *ioc;
arch/ia64/include/asm/dma-mapping.h +15 -14
@@ -17,32 +17,32 @@
 	void            (*free_coherent)(struct device *dev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
 	dma_addr_t      (*map_single)(struct device *hwdev, unsigned long ptr,
-				size_t size, int direction);
+				size_t size, enum dma_data_direction direction);
 	void            (*unmap_single)(struct device *dev, dma_addr_t addr,
-				size_t size, int direction);
+				size_t size, enum dma_data_direction direction);
 	void            (*sync_single_for_cpu)(struct device *hwdev,
 				dma_addr_t dma_handle, size_t size,
-				int direction);
+				enum dma_data_direction direction);
 	void            (*sync_single_for_device)(struct device *hwdev,
 				dma_addr_t dma_handle, size_t size,
-				int direction);
+				enum dma_data_direction direction);
 	void            (*sync_single_range_for_cpu)(struct device *hwdev,
 				dma_addr_t dma_handle, unsigned long offset,
-				size_t size, int direction);
+				size_t size, enum dma_data_direction direction);
 	void            (*sync_single_range_for_device)(struct device *hwdev,
 				dma_addr_t dma_handle, unsigned long offset,
-				size_t size, int direction);
+				size_t size, enum dma_data_direction direction);
 	void            (*sync_sg_for_cpu)(struct device *hwdev,
 				struct scatterlist *sg, int nelems,
-				int direction);
+				enum dma_data_direction direction);
 	void            (*sync_sg_for_device)(struct device *hwdev,
 				struct scatterlist *sg, int nelems,
-				int direction);
+				enum dma_data_direction direction);
 	int             (*map_sg)(struct device *hwdev, struct scatterlist *sg,
-				int nents, int direction);
+				int nents, enum dma_data_direction direction);
 	void            (*unmap_sg)(struct device *hwdev,
 				struct scatterlist *sg, int nents,
-				int direction);
+				enum dma_data_direction direction);
 	int             (*dma_supported_op)(struct device *hwdev, u64 mask);
 	int		is_phys;
 };
@@ -70,25 +70,26 @@
 }
 #define dma_map_single_attrs	platform_dma_map_single_attrs
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-					size_t size, int dir)
+					size_t size,
+					enum dma_data_direction dir)
 {
 	return dma_map_single_attrs(dev, cpu_addr, size, dir, NULL);
 }
 #define dma_map_sg_attrs	platform_dma_map_sg_attrs
 static inline int dma_map_sg(struct device *dev, struct scatterlist *sgl,
-			     int nents, int dir)
+			     int nents, enum dma_data_direction dir)
 {
 	return dma_map_sg_attrs(dev, sgl, nents, dir, NULL);
 }
 #define dma_unmap_single_attrs	platform_dma_unmap_single_attrs
 static inline void dma_unmap_single(struct device *dev, dma_addr_t cpu_addr,
-				    size_t size, int dir)
+				    size_t size, enum dma_data_direction dir)
 {
 	return dma_unmap_single_attrs(dev, cpu_addr, size, dir, NULL);
 }
 #define dma_unmap_sg_attrs	platform_dma_unmap_sg_attrs
 static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
-				int nents, int dir)
+				int nents, enum dma_data_direction dir)
 {
 	return dma_unmap_sg_attrs(dev, sgl, nents, dir, NULL);
 }
arch/ia64/include/asm/swiotlb.h +16 -10
@@ -6,35 +6,41 @@
 /* SWIOTLB interface */
 
 extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
-				     size_t size, int dir);
+				     size_t size,
+				     enum dma_data_direction  dir);
 extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 				    dma_addr_t *dma_handle, gfp_t flags);
 extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
-				 size_t size, int dir);
+				 size_t size,
+				 enum dma_data_direction  dir);
 extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
 					dma_addr_t dev_addr,
-					size_t size, int dir);
+					size_t size,
+					enum dma_data_direction dir);
 extern void swiotlb_sync_single_for_device(struct device *hwdev,
 					   dma_addr_t dev_addr,
-					   size_t size, int dir);
+					   size_t size,
+					   enum dma_data_direction dir);
 extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
 					      dma_addr_t dev_addr,
 					      unsigned long offset,
-					      size_t size, int dir);
+					      size_t size,
+					      enum dma_data_direction dir);
 extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
 						 dma_addr_t dev_addr,
 						 unsigned long offset,
-						 size_t size, int dir);
+						 size_t size,
+						 enum dma_data_direction dir);
 extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
 				    struct scatterlist *sg, int nelems,
-				    int dir);
+				    enum dma_data_direction dir);
 extern void swiotlb_sync_sg_for_device(struct device *hwdev,
 				       struct scatterlist *sg, int nelems,
-				       int dir);
+				       enum dma_data_direction dir);
 extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
-			  int nents, int direction);
+			  int nents, enum dma_data_direction direction);
 extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
-			     int nents, int direction);
+			     int nents, enum dma_data_direction direction);
 extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
 extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
 				  void *vaddr, dma_addr_t dma_handle);
arch/ia64/kernel/machvec.c +4 -2
@@ -75,14 +75,16 @@
 EXPORT_SYMBOL(machvec_timer_interrupt);
 
 void
-machvec_dma_sync_single (struct device *hwdev, dma_addr_t dma_handle, size_t size, int dir)
+machvec_dma_sync_single (struct device *hwdev, dma_addr_t dma_handle,
+			 size_t size, enum dma_data_direction dir)
 {
 	mb();
 }
 EXPORT_SYMBOL(machvec_dma_sync_single);
 
 void
-machvec_dma_sync_sg (struct device *hwdev, struct scatterlist *sg, int n, int dir)
+machvec_dma_sync_sg (struct device *hwdev, struct scatterlist *sg, int n,
+		     enum dma_data_direction dir)
 {
 	mb();
 }
arch/ia64/sn/kernel/io_common.c +2 -1
@@ -60,7 +60,8 @@
 }
 
 static void
-sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
+sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr,
+		     enum dma_data_direction direction)
 {
 	return;
 }
arch/ia64/sn/pci/pci_dma.c +13 -8
@@ -174,7 +174,8 @@
  *       figure out how to save dmamap handle so can use two step.
  */
 dma_addr_t sn_dma_map_single_attrs(struct device *dev, void *cpu_addr,
-				   size_t size, int direction,
+				   size_t size,
+				   enum dma_data_direction direction,
 				   struct dma_attrs *attrs)
 {
 	dma_addr_t dma_addr;
@@ -216,7 +217,8 @@
  * coherent, so we just need to free any ATEs associated with this mapping.
  */
 void sn_dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
-			       size_t size, int direction,
+			       size_t size,
+			       enum dma_data_direction direction,
 			       struct dma_attrs *attrs)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -239,7 +241,7 @@
  * Unmap a set of streaming mode DMA translations.
  */
 void sn_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
-			   int nhwentries, int direction,
+			   int nhwentries, enum dma_data_direction direction,
 			   struct dma_attrs *attrs)
 {
 	int i;
@@ -273,7 +275,8 @@
  * Maps each entry of @sg for DMA.
  */
 int sn_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
-			int nhwentries, int direction, struct dma_attrs *attrs)
+			int nhwentries, enum dma_data_direction direction,
+			struct dma_attrs *attrs)
 {
 	unsigned long phys_addr;
 	struct scatterlist *saved_sg = sgl, *sg;
@@ -323,28 +326,30 @@
 EXPORT_SYMBOL(sn_dma_map_sg_attrs);
 
 void sn_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-				size_t size, int direction)
+				size_t size,
+				enum dma_data_direction direction)
 {
 	BUG_ON(dev->bus != &pci_bus_type);
 }
 EXPORT_SYMBOL(sn_dma_sync_single_for_cpu);
 
 void sn_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-				   size_t size, int direction)
+				   size_t size,
+				   enum dma_data_direction direction)
 {
 	BUG_ON(dev->bus != &pci_bus_type);
 }
 EXPORT_SYMBOL(sn_dma_sync_single_for_device);
 
 void sn_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-			    int nelems, int direction)
+			    int nelems, enum dma_data_direction direction)
 {
 	BUG_ON(dev->bus != &pci_bus_type);
 }
 EXPORT_SYMBOL(sn_dma_sync_sg_for_cpu);
 
 void sn_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
-			       int nelems, int direction)
+			       int nelems, enum dma_data_direction direction)
 {
 	BUG_ON(dev->bus != &pci_bus_type);
 }
arch/ia64/sn/pci/pcibr/pcibr_dma.c +2 -1
@@ -205,7 +205,8 @@
  * DMA mappings for Direct 64 and 32 do not have any DMA maps.
  */
 void
-pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
+pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle,
+		enum dma_data_direction direction)
 {
 	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
 	struct pcibus_info *pcibus_info =
arch/ia64/sn/pci/tioca_provider.c +2 -1
@@ -467,7 +467,8 @@
  * resources to release.
  */
 static void
-tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
+tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr,
+		enum dma_data_direction dir)
 {
 	int i, entry;
 	struct tioca_common *tioca_common;
arch/x86/include/asm/dma-mapping.h +28 -22

144 lines not on this page · raw message

arch/x86/include/asm/swiotlb.h +14 -10
@@ -6,35 +6,39 @@
 /* SWIOTLB interface */
 
 extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
-				     size_t size, int dir);
+				     size_t size, enum dma_data_direction dir);
 extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 				    dma_addr_t *dma_handle, gfp_t flags);
 extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
-				 size_t size, int dir);
+				 size_t size, enum dma_data_direction dir);
 extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
 					dma_addr_t dev_addr,
-					size_t size, int dir);
+					size_t size,
+					enum dma_data_direction dir);
 extern void swiotlb_sync_single_for_device(struct device *hwdev,
 					   dma_addr_t dev_addr,
-					   size_t size, int dir);
+					   size_t size,
+					   enum dma_data_direction dir);
 extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
 					      dma_addr_t dev_addr,
 					      unsigned long offset,
-					      size_t size, int dir);
+					      size_t size,
+					      enum dma_data_direction dir);
 extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
 						 dma_addr_t dev_addr,
 						 unsigned long offset,
-						 size_t size, int dir);
+						 size_t size,
+						 enum dma_data_direction dir);
 extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
 				    struct scatterlist *sg, int nelems,
-				    int dir);
+				    enum dma_data_direction dir);
 extern void swiotlb_sync_sg_for_device(struct device *hwdev,
 				       struct scatterlist *sg, int nelems,
-				       int dir);
+				       enum dma_data_direction dir);
 extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
-			  int nents, int direction);
+			  int nents, enum dma_data_direction direction);
 extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
-			     int nents, int direction);
+			     int nents, enum dma_data_direction direction);
 extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
 extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
 				  void *vaddr, dma_addr_t dma_handle);
arch/x86/include/asm/tce.h +2 -1
@@ -39,7 +39,8 @@
 #define TCE_RPN_MASK     0x0000fffffffff000ULL
 
 extern void tce_build(struct iommu_table *tbl, unsigned long index,
-		      unsigned int npages, unsigned long uaddr, int direction);
+		      unsigned int npages, unsigned long uaddr,
+		      enum dma_data_direction direction);
 extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages);
 extern void * __init alloc_tce_table(void);
 extern void __init free_tce_table(void *tbl);
arch/x86/kernel/amd_iommu.c +8 -8
@@ -873,7 +873,7 @@
 				     struct dma_ops_domain *dom,
 				     unsigned long address,
 				     phys_addr_t paddr,
-				     int direction)
+				     enum dma_data_direction direction)
 {
 	u64 *pte, __pte;
 
@@ -933,7 +933,7 @@
 			       struct dma_ops_domain *dma_dom,
 			       phys_addr_t paddr,
 			       size_t size,
-			       int dir,
+			       enum dma_data_direction dir,
 			       bool align,
 			       u64 dma_mask)
 {
@@ -980,7 +980,7 @@
 			   struct dma_ops_domain *dma_dom,
 			   dma_addr_t dma_addr,
 			   size_t size,
-			   int dir)
+			   enum dma_data_direction dir)
 {
 	dma_addr_t i, start;
 	unsigned int pages;
@@ -1010,7 +1010,7 @@
  * The exported map_single function for dma_ops.
  */
 static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
-			     size_t size, int dir)
+			     size_t size, enum dma_data_direction dir)
 {
 	unsigned long flags;
 	struct amd_iommu *iommu;
@@ -1048,7 +1048,7 @@
  * The exported unmap_single function for dma_ops.
  */
 static void unmap_single(struct device *dev, dma_addr_t dma_addr,
-			 size_t size, int dir)
+			 size_t size, enum dma_data_direction dir)
 {
 	unsigned long flags;
 	struct amd_iommu *iommu;
@@ -1074,7 +1074,7 @@
  * device which is not handled by an AMD IOMMU in the system.
  */
 static int map_sg_no_iommu(struct device *dev, struct scatterlist *sglist,
-			   int nelems, int dir)
+			   int nelems, enum dma_data_direction dir)
 {
 	struct scatterlist *s;
 	int i;
@@ -1092,7 +1092,7 @@
  * lists).
  */
 static int map_sg(struct device *dev, struct scatterlist *sglist,
-		  int nelems, int dir)
+		  int nelems, enum dma_data_direction dir)
 {
 	unsigned long flags;
 	struct amd_iommu *iommu;
@@ -1154,7 +1154,7 @@
  * lists).
  */
 static void unmap_sg(struct device *dev, struct scatterlist *sglist,
-		     int nelems, int dir)
+		     int nelems, enum dma_data_direction dir)
 {
 	unsigned long flags;
 	struct amd_iommu *iommu;
arch/x86/kernel/pci-calgary_64.c +6 -5
@@ -297,7 +297,8 @@
 }
 
 static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
-			      void *vaddr, unsigned int npages, int direction)
+			      void *vaddr, unsigned int npages,
+			      enum dma_data_direction direction)
 {
 	unsigned long entry;
 	dma_addr_t ret = bad_dma_address;
@@ -381,7 +382,7 @@
 }
 
 static void calgary_unmap_sg(struct device *dev,
-	struct scatterlist *sglist, int nelems, int direction)
+	struct scatterlist *sglist, int nelems, enum dma_data_direction dir)
 {
 	struct iommu_table *tbl = find_iommu_table(dev);
 	struct scatterlist *s;
@@ -404,7 +405,7 @@
 }
 
 static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
-	int nelems, int direction)
+	int nelems, enum dma_data_direction direction)
 {
 	struct iommu_table *tbl = find_iommu_table(dev);
 	struct scatterlist *s;
@@ -446,7 +447,7 @@
 }
 
 static dma_addr_t calgary_map_single(struct device *dev, phys_addr_t paddr,
-	size_t size, int direction)
+	size_t size, enum dma_data_direction direction)
 {
 	void *vaddr = phys_to_virt(paddr);
 	unsigned long uaddr;
@@ -460,7 +461,7 @@
 }
 
 static void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
-	size_t size, int direction)
+	size_t size, enum dma_data_direction direction)
 {
 	struct iommu_table *tbl = find_iommu_table(dev);
 	unsigned int npages;
arch/x86/kernel/pci-gart_64.c +12 -7
@@ -188,7 +188,8 @@
 # define CLEAR_LEAK(x)
 #endif
 
-static void iommu_full(struct device *dev, size_t size, int dir)
+static void
+iommu_full(struct device *dev, size_t size, enum dma_data_direction dir)
 {
 	/*
 	 * Ran out of IOMMU space for this operation. This is very bad.
@@ -231,7 +232,8 @@
  * Caller needs to check if the iommu is needed and flush.
  */
 static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
-				size_t size, int dir, unsigned long align_mask)
+			       size_t size, enum dma_data_direction dir,
+			       unsigned long align_mask)
 {
 	unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
 	unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
@@ -256,7 +258,8 @@
 
 /* Map a single area into the IOMMU */
 static dma_addr_t
-gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir)
+gart_map_single(struct device *dev, phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	unsigned long bus;
 
@@ -276,7 +279,7 @@
  * Free a DMA mapping.
  */
 static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
-			      size_t size, int direction)
+			      size_t size, enum dma_data_direction direction)
 {
 	unsigned long iommu_page;
 	int npages;
@@ -299,7 +302,8 @@
  * Wrapper for pci_unmap_single working with scatterlists.
  */
 static void
-gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
+gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+	      enum dma_data_direction dir)
 {
 	struct scatterlist *s;
 	int i;
@@ -313,7 +317,7 @@
 
 /* Fallback for dma_map_sg in case of overflow */
 static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
-			       int nents, int dir)
+			       int nents, enum dma_data_direction dir)
 {
 	struct scatterlist *s;
 	int i;
@@ -401,7 +405,8 @@
  * Merge chunks that have page aligned sizes into a continuous mapping.
  */
 static int
-gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
+gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	    enum dma_data_direction dir)
 {
 	struct scatterlist *s, *ps, *start_sg, *sgmap;
 	int need = 0, nextneed, i, out, start;
arch/x86/kernel/pci-nommu.c +2 -2
@@ -27,7 +27,7 @@
 
 static dma_addr_t
 nommu_map_single(struct device *hwdev, phys_addr_t paddr, size_t size,
-	       int direction)
+		 enum dma_data_direction direction)
 {
 	dma_addr_t bus = paddr;
 	WARN_ON(size == 0);
@@ -54,7 +54,7 @@
  * the same here.
  */
 static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
-	       int nents, int direction)
+			int nents, enum dma_data_direction direction)
 {
 	struct scatterlist *s;
 	int i;
arch/x86/kernel/pci-swiotlb_64.c +1 -1
@@ -40,7 +40,7 @@
 
 static dma_addr_t
 swiotlb_map_single_phys(struct device *hwdev, phys_addr_t paddr, size_t size,
-			int direction)
+			enum dma_data_direction direction)
 {
 	return swiotlb_map_single(hwdev, phys_to_virt(paddr), size, direction);
 }
arch/x86/kernel/tce_64.c +2 -1
@@ -46,7 +46,8 @@
 }
 
 void tce_build(struct iommu_table *tbl, unsigned long index,
-	unsigned int npages, unsigned long uaddr, int direction)
+	unsigned int npages, unsigned long uaddr,
+	enum dma_data_direction direction)
 {
 	u64* tp;
 	u64 t;
drivers/pci/intel-iommu.c +7 -6
@@ -1819,7 +1819,8 @@
 }
 
 static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
-				     size_t size, int dir, u64 dma_mask)
+				     size_t size,
+				     enum dma_data_direction dir, u64 dma_mask)
 {
 	struct pci_dev *pdev = to_pci_dev(hwdev);
 	struct dmar_domain *domain;
@@ -1881,7 +1882,7 @@
 }
 
 dma_addr_t intel_map_single(struct device *hwdev, phys_addr_t paddr,
-			    size_t size, int dir)
+			    size_t size, enum dma_data_direction dir)
 {
 	return __intel_map_single(hwdev, paddr, size, dir,
 				  to_pci_dev(hwdev)->dma_mask);
@@ -1946,7 +1947,7 @@
 }
 
 void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
-			int dir)
+			enum dma_data_direction dir)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
@@ -2026,7 +2027,7 @@
 #define SG_ENT_VIRT_ADDRESS(sg)	(sg_virt((sg)))
 
 void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
-		    int nelems, int dir)
+		    int nelems, enum dma_data_direction dir)
 {
 	int i;
 	struct pci_dev *pdev = to_pci_dev(hwdev);
@@ -2066,7 +2067,7 @@
 }
 
 static int intel_nontranslate_map_sg(struct device *hddev,
-	struct scatterlist *sglist, int nelems, int dir)
+	struct scatterlist *sglist, int nelems, enum dma_data_direction dir)
 {
 	int i;
 	struct scatterlist *sg;
@@ -2080,7 +2081,7 @@
 }
 
 int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
-		 int dir)
+		 enum dma_data_direction dir)
 {
 	void *addr;
 	int i;
include/linux/intel-iommu.h +8 -4
@@ -355,9 +355,13 @@
 
 extern void *intel_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
 extern void intel_free_coherent(struct device *, size_t, void *, dma_addr_t);
-extern dma_addr_t intel_map_single(struct device *, phys_addr_t, size_t, int);
-extern void intel_unmap_single(struct device *, dma_addr_t, size_t, int);
-extern int intel_map_sg(struct device *, struct scatterlist *, int, int);
-extern void intel_unmap_sg(struct device *, struct scatterlist *, int, int);
+extern dma_addr_t intel_map_single(struct device *, phys_addr_t, size_t,
+				   enum dma_data_direction);
+extern void intel_unmap_single(struct device *, dma_addr_t, size_t,
+			       enum dma_data_direction);
+extern int intel_map_sg(struct device *, struct scatterlist *, int,
+			enum dma_data_direction);
+extern void intel_unmap_sg(struct device *, struct scatterlist *, int,
+			   enum dma_data_direction);
 
 #endif
include/linux/swiotlb.h +19 -14
@@ -42,60 +42,65 @@
 		      void *vaddr, dma_addr_t dma_handle);
 
 extern dma_addr_t
-swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir);
+swiotlb_map_single(struct device *hwdev, void *ptr, size_t size,
+		   enum dma_data_direction dir);
 
 extern void
 swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
-		     size_t size, int dir);
+		     size_t size, enum dma_data_direction dir);
 
 extern dma_addr_t
 swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
-			 int dir, struct dma_attrs *attrs);
+			 enum dma_data_direction dir,
+			 struct dma_attrs *attrs);
 
 extern void
 swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
-			   size_t size, int dir, struct dma_attrs *attrs);
+			   size_t size, enum dma_data_direction dir,
+			   struct dma_attrs *attrs);
 
 extern int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
-	       int direction);
+	       enum dma_data_direction direction);
 
 extern void
 swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
-		 int direction);
+		 enum dma_data_direction direction);
 
 extern int
 swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
-		     int dir, struct dma_attrs *attrs);
+		     enum dma_data_direction dir, struct dma_attrs *attrs);
 
 extern void
 swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
-		       int nelems, int dir, struct dma_attrs *attrs);
+		       int nelems, enum dma_data_direction dir,
+		       struct dma_attrs *attrs);
 
 extern void
 swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
-			    size_t size, int dir);
+			    size_t size, enum dma_data_direction dir);
 
 extern void
 swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
-			int nelems, int dir);
+			int nelems, enum dma_data_direction dir);
 
 extern void
 swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
-			       size_t size, int dir);
+			       size_t size, enum dma_data_direction dir);
 
 extern void
 swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
-			   int nelems, int dir);
+			   int nelems, enum dma_data_direction dir);
 
 extern void
 swiotlb_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
-				  unsigned long offset, size_t size, int dir);
+				  unsigned long offset, size_t size,
+				  enum dma_data_direction dir);
 
 extern void
 swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
 				     unsigned long offset, size_t size,
-				     int dir);
+				     enum dma_data_direction dir);
 
 extern int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
lib/swiotlb.c +31 -23

185 lines not on this page · raw message

#10 lore raw
In reply to Jeremy Fitzhardinge
Quoted 9 lines · On Mon, 22 Dec 2008 10:26:02 -0800 Jeremy Fitzhardinge <[email protected]> wrote:

Hi all,

Here's a work in progress series whcih does a partial revert of the previous swiotlb changes, and does a partial replacement with Becky Bruce's series.

The most important difference is Becky's use of phys_addr_t rather than page+offset to represent arbitrary pages. This turns out to be simpler.

Great, thanks a lot!

But I think that we should just drop the previous patchset completely and start cleanly.

Quoted 3 lines

I didn't replicate the map_single_page changes, since I'm not exactly sure of ppc's requirements here, and it seemed like something that could be easily added.

I think the patch is not necessary. Just exporting map_single should be fine.

#11 lore raw
In reply to Jeremy Fitzhardinge
Quoted 13 lines · Jeremy Fitzhardinge

Hi all,

Here's a work in progress series whcih does a partial revert of the previous swiotlb changes, and does a partial replacement with Becky Bruce's series.

The most important difference is Becky's use of phys_addr_t rather than page+offset to represent arbitrary pages. This turns out to be simpler.

I didn't replicate the map_single_page changes, since I'm not exactly sure of ppc's requirements here, and it seemed like something that could be easily added.

Quoted 6 lines

Quick testing showed no problems, but I haven't had the chance to do anything extensive.

I've made some small changes to Becky's patches to make them apply, but I've separated any functional changes into separate patches with appropriate authorship.

looks good to me in principle. Fujita-san, do you have any principal objections against these generalizations?

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-

(Tony Cc:-ed)

Ingo

#12 lore raw
Quoted 19 lines · On Sat, 27 Dec 2008 11:48:23 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 16 lines · Jeremy Fitzhardinge

Hi all,

Here's a work in progress series whcih does a partial revert of the previous swiotlb changes, and does a partial replacement with Becky Bruce's series.

The most important difference is Becky's use of phys_addr_t rather than page+offset to represent arbitrary pages. This turns out to be simpler.

I didn't replicate the map_single_page changes, since I'm not exactly sure of ppc's requirements here, and it seemed like something that could be easily added.

Quick testing showed no problems, but I haven't had the chance to do anything extensive.

Quoted 6 lines
Quoted 3 lines

I've made some small changes to Becky's patches to make them apply, but I've separated any functional changes into separate patches with appropriate authorship.

looks good to me in principle. Fujita-san, do you have any principal objections against these generalizations?

Well, I asked Jeremy to use Becky's approach so I don't have though this patchset isn't enough for Becky (possibly for Xen too) since Jeremy didn't put Becky's map_single_page changes. These changes are necessary to support map_map_page with highmem. I think that we can do it simpler than his patch. I'll send patches to that in a different way soon.

It's not principal objection, but as I said, the patches to revert Jeremy's highmem patches in this patchset like the following are pointless.

Commit e58c866b9b74a825771e2024d4a059bd07359d75

Author: Jeremy Fitzhardinge <[email protected]>
Date:   Mon Dec 22 10:26:03 2008 -0800

revert "swiotlb: support bouncing of HighMem pages."

git commit ef9b189352f2eb78f14e52996f4780a523b04a49

This doesn't explain why we reverted it. The two approaches are different so there is no point to merge these patch in this way.

There is no patches in tip/core/iommu except for this swiotlb stuff. The end result is exactly same (I just reordered patches). So there is nothing to worry. You can safely replace tip/core/iommu with this tree.

git://git.kernel.org/pub/scm/linux/kernel/git/tomo/linux-2.6-misc.git swiotlb

Quoted 27 lines

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-

(Tony Cc:-ed)

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

#15 lore raw
In reply to Ingo Molnar
Quoted 19 lines · On Sat, 27 Dec 2008 11:48:23 +0100 Ingo Molnar <[email protected]> wrote:

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-
Quoted 1 line

(Tony Cc:-ed)

BTW, the above patch breaks IA64 build.

It's fixable but I think that it would be better to just drop this huge patch and add some cast in powerpc code. the types of SWIOTBL function arguments don't need to mach to DAM_API.txt though it might be nice if so. There are other type mismatches. If we really want to do this cleanups, we should fix up all the mismatches.

#16 lore raw
Quoted 24 lines · FUJITA Tomonori
Quoted 19 lines · On Sat, 27 Dec 2008 11:48:23 +0100 Ingo Molnar <[email protected]> wrote:

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-
Quoted 1 line

(Tony Cc:-ed)

Quoted 7 lines

BTW, the above patch breaks IA64 build.

It's fixable but I think that it would be better to just drop this huge patch and add some cast in powerpc code. the types of SWIOTBL function arguments don't need to mach to DAM_API.txt though it might be nice if so. There are other type mismatches. If we really want to do this cleanups, we should fix up all the mismatches.

hm, we shouldnt do ugly typecasts - lets fix all the places. As Jeremy indicated, this is work in progress.

Ingo

#17 lore raw
Quoted 29 lines · On Sat, 27 Dec 2008 17:56:22 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 26 lines · FUJITA Tomonori
Quoted 19 lines · On Sat, 27 Dec 2008 11:48:23 +0100 Ingo Molnar <[email protected]> wrote:

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-
Quoted 1 line

(Tony Cc:-ed)

BTW, the above patch breaks IA64 build.

Quoted 8 lines
Quoted 5 lines

It's fixable but I think that it would be better to just drop this huge patch and add some cast in powerpc code. the types of SWIOTBL function arguments don't need to mach to DAM_API.txt though it might be nice if so. There are other type mismatches. If we really want to do this cleanups, we should fix up all the mismatches.

hm, we shouldnt do ugly typecasts - lets fix all the places. As Jeremy indicated, this is work in progress.

It's not about this patchset, swiotlb. I'm talking about all the mismatches of dma mapping operations. But it need huge patches (touching lots of the architectures). I'm not sure it is worth doing it. Even if we want, it's not the job that this swiotlb patches does.

#13 lore raw
In reply to FUJITA Tomonori
Quoted 11 lines · FUJITA Tomonori

Well, I asked Jeremy to use Becky's approach so I don't have though this patchset isn't enough for Becky (possibly for Xen too) since Jeremy didn't put Becky's map_single_page changes. These changes are necessary to support map_map_page with highmem. I think that we can do it simpler than his patch. I'll send patches to that in a different way soon.

It's not principal objection, but as I said, the patches to revert Jeremy's highmem patches in this patchset like the following are pointless.

I don't mind either way. I was hoping to go with something that I've actually tested, but I don't see any reason why Becky's patches won't work in principle for Xen. I'm on vacation at the moment, but I can test things out when I get back in a couple of weeks and apply whatever fixes are needed at whatever stage we're at then.

J

#18 lore raw
In reply to FUJITA Tomonori
Quoted 38 lines · On Sun, 28 Dec 2008 02:03:37 +0900 FUJITA Tomonori…
Quoted 35 lines · On Sat, 27 Dec 2008 17:56:22 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 31 lines · FUJITA Tomonori
Quoted 19 lines · On Sat, 27 Dec 2008 11:48:23 +0100 Ingo Molnar <[email protected]> wrote:

Also, this patch will interact with ia64 materially:

Subject: [PATCH 9 of 9] ia64/x86/swiotlb: use enum dma_data_direciton in dma_ops

So we'll need a bit more confidence in the testing status of this queue, and we probably want to wait until Tony merged the pending .29 ia64 changes, and also get an Ack from Tony for these bits:

 arch/ia64/dig/dig_vtd_iommu.c       |    9 +++--
 arch/ia64/hp/common/hwsw_iommu.c    |   22 ++++++++------
 arch/ia64/hp/common/sba_iommu.c     |   12 ++++---
 arch/ia64/include/asm/dma-mapping.h |   29 +++++++++---------
 arch/ia64/include/asm/swiotlb.h     |   26 ++++++++++------
 arch/ia64/kernel/machvec.c          |    6 ++-
 arch/ia64/sn/kernel/io_common.c     |    3 +-
 arch/ia64/sn/pci/pci_dma.c          |   21 ++++++++-----
 arch/ia64/sn/pci/pcibr/pcibr_dma.c  |    3 +-
 arch/ia64/sn/pci/tioca_provider.c   |    3 +-
Quoted 1 line

(Tony Cc:-ed)

BTW, the above patch breaks IA64 build.

It's fixable but I think that it would be better to just drop this huge patch and add some cast in powerpc code. the types of SWIOTBL function arguments don't need to mach to DAM_API.txt though it might be nice if so. There are other type mismatches. If we really want to do this cleanups, we should fix up all the mismatches.

Quoted 7 lines
Quoted 2 lines

hm, we shouldnt do ugly typecasts - lets fix all the places. As Jeremy indicated, this is work in progress.

It's not about this patchset, swiotlb. I'm talking about all the mismatches of dma mapping operations. But it need huge patches (touching lots of the architectures). I'm not sure it is worth doing it. Even if we want, it's not the job that this swiotlb patches does.

If we really want to clean up the dma mapping operations, we should define struct dma_mapping_ops in a generic place (such as include/linux/dma-mapping.h) instead each architecture define the own struct dma_mapping_ops. These dma_mapping_ops structures are very similar but a bit different. That's the root cause of the dma mapping operation ugliness.

If we do, X86 and IA64 can share swiotlb and intel VTD code cleanly, X86, IA64, and POWERPC can share swiotlb cleanly too. For example, we can define swiotlb_dma_ops in lib/swiotlb.c and then everyone can share it. Currently, X86 and IA64 define the own swiotlb_dma_ops (and X86 needs swiotlb_map_single_phys hack). It doesn't make sense.

If we want to clean up all the dma mapping operation ugliness, the above patch is wrong.

#19 lore raw
Quoted 6 lines · FUJITA Tomonori

If we really want to clean up the dma mapping operations, we should define struct dma_mapping_ops in a generic place (such as include/linux/dma-mapping.h) instead each architecture define the own struct dma_mapping_ops. These dma_mapping_ops structures are very similar but a bit different. That's the root cause of the dma mapping operation ugliness.

Yes, please. For people hacking on different architectures occasionally the current setup with per-arch ops (and sometimes none at all) is pain.

Quoted 5 lines

If we do, X86 and IA64 can share swiotlb and intel VTD code cleanly, X86, IA64, and POWERPC can share swiotlb cleanly too. For example, we can define swiotlb_dma_ops in lib/swiotlb.c and then everyone can share it. Currently, X86 and IA64 define the own swiotlb_dma_ops (and X86 needs swiotlb_map_single_phys hack). It doesn't make sense.

Also the calgary iommu is very similar to those used on some pseries machines, but I'd have to look at the code if the interface actually still is similar, or if the PPC firmware adds too much abstractions inbetween.

Also the older IA64 altixens have a slightly updated version of the iommu used on MIPS IP27 (and the same as on MIPS IP35 which we'll hopefully support one day)

#20 lore raw
Quoted 10 lines · On Sun, 28 Dec 2008 02:30:12 -0500 Christoph Hellwig <[email protected]> wrote:
Quoted 6 lines · FUJITA Tomonori

If we really want to clean up the dma mapping operations, we should define struct dma_mapping_ops in a generic place (such as include/linux/dma-mapping.h) instead each architecture define the own struct dma_mapping_ops. These dma_mapping_ops structures are very similar but a bit different. That's the root cause of the dma mapping operation ugliness.

Yes, please. For people hacking on different architectures occasionally the current setup with per-arch ops (and sometimes none at all) is pain.

The biggest obstacle is IA64's way to handle multiple dma mapping operations (artistic define magics).

I'll take care of the cleanups if Tony lets me change IA64 to handle multiple dma mapping operations as other architectures do (x86 and powerpc).

#22 lore raw
In reply to FUJITA Tomonori
Quoted 7 lines · FUJITA Tomonori

If we really want to clean up the dma mapping operations, we should define struct dma_mapping_ops in a generic place (such as include/linux/dma-mapping.h) instead each architecture define the own struct dma_mapping_ops. These dma_mapping_ops structures are very similar but a bit different. That's the root cause of the dma mapping operation ugliness.

Quoted 5 lines

If we do, X86 and IA64 can share swiotlb and intel VTD code cleanly, X86, IA64, and POWERPC can share swiotlb cleanly too. For example, we can define swiotlb_dma_ops in lib/swiotlb.c and then everyone can share it. Currently, X86 and IA64 define the own swiotlb_dma_ops (and X86 needs swiotlb_map_single_phys hack). It doesn't make sense.

Sure.

Note that we went through this process (of unifying dma_mapping_ops) recently on x86 recently - 32-bit and 64-bit x86 had such differences.

Note that the main complication wasnt even the small variations in signatures, but the different _semantics_: one dma_mapping_ops implementation passed in kernel-virtual addresses, the other physical addresses. Unifying that was invasive and non-trivial, and it can break stuff not at the build level but at the runtime level. We can expect similar complications when done over 20 architectures as well.

But yes, it's all desired. Obviously extending swiotlb to highmem and using it on xen and powerpc is an essential first step in the direction of generalizing all this code.

Ingo

#14 lore raw
In reply to Jeremy Fitzhardinge
Quoted 13 lines · Jeremy Fitzhardinge
Quoted 11 lines · FUJITA Tomonori

Well, I asked Jeremy to use Becky's approach so I don't have though this patchset isn't enough for Becky (possibly for Xen too) since Jeremy didn't put Becky's map_single_page changes. These changes are necessary to support map_map_page with highmem. I think that we can do it simpler than his patch. I'll send patches to that in a different way soon.

It's not principal objection, but as I said, the patches to revert Jeremy's highmem patches in this patchset like the following are pointless.

Quoted 5 lines

I don't mind either way. I was hoping to go with something that I've actually tested, but I don't see any reason why Becky's patches won't work in principle for Xen. I'm on vacation at the moment, but I can test things out when I get back in a couple of weeks and apply whatever fixes are needed at whatever stage we're at then.

yes, obviously we prefer append-only - i kept your patches and added the Becky lineup and Fujita's cleanups on top of that. If they break your Xen swiotlb use it should all be easily bisectable.

Ingo

#23 lore raw
In reply to Ingo Molnar
Quoted 16 lines · On Sun, 28 Dec 2008 10:37:51 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 7 lines · FUJITA Tomonori

If we really want to clean up the dma mapping operations, we should define struct dma_mapping_ops in a generic place (such as include/linux/dma-mapping.h) instead each architecture define the own struct dma_mapping_ops. These dma_mapping_ops structures are very similar but a bit different. That's the root cause of the dma mapping operation ugliness.

Quoted 5 lines

If we do, X86 and IA64 can share swiotlb and intel VTD code cleanly, X86, IA64, and POWERPC can share swiotlb cleanly too. For example, we can define swiotlb_dma_ops in lib/swiotlb.c and then everyone can share it. Currently, X86 and IA64 define the own swiotlb_dma_ops (and X86 needs swiotlb_map_single_phys hack). It doesn't make sense.

Quoted 4 lines

Sure.

Note that we went through this process (of unifying dma_mapping_ops) recently on x86 recently - 32-bit and 64-bit x86 had such differences.

Not really. x86_32 did not use the dma_ops scheme.

Quoted 4 lines

Note that the main complication wasnt even the small variations in signatures, but the different _semantics_: one dma_mapping_ops implementation passed in kernel-virtual addresses, the other physical addresses. Unifying that was invasive and non-trivial, and it can break

I guess that you are talking about the dma_map_single difference between x86_32 and x86_64. As far as I know, Only x64_64 uses physical address with dma_map_single.

Quoted 2 lines

stuff not at the build level but at the runtime level. We can expect similar complications when done over 20 architectures as well.

We don't need to touch 20 architectures. We are talking about unifying dma_mapping_ops. Only architectures that need to handle multiple dma mapping operations use the dma_mapping_ops scheme; X86, IA64, POWERPC, SPARC, and PARISC. Unifying X86, IA64 and POWERPC is a must since they actually share dma_mapping_ops.

Quoted 3 lines

But yes, it's all desired. Obviously extending swiotlb to highmem and using it on xen and powerpc is an essential first step in the direction of generalizing all this code.

No, it's not about swiotlb highmem patchset.

Due to this problem, IA64 and X86_64 share swiotlb in a very hacky way. We added more hacky code due to this problem again when we added VT-d support to IA64.

This problem has been for long time. We added ugly hacks again and again instead of fixing the root cause.

#24 lore raw
Quoted 9 lines · FUJITA Tomonori
Quoted 5 lines

Note that the main complication wasnt even the small variations in signatures, but the different _semantics_: one dma_mapping_ops implementation passed in kernel-virtual addresses, the other physical addresses. Unifying that was invasive and non-trivial, and it can break

I guess that you are talking about the dma_map_single difference between x86_32 and x86_64. As far as I know, Only x64_64 uses physical address with dma_map_single.

yes - dma_map_single() has this signature:

static inline dma_addr_t
dma_map_single(struct device *hwdev, void *ptr, size_t size, int direction)

on x86 dma_mapping_ops.map_single has this signature:

dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t ptr,
size_t size, int direction);

ia64 and powerpc uses kernel-virt addresses for map_single(). So there's material semantic differences between the dma_mapping_ops implementations.

Quoted 8 lines
Quoted 2 lines

stuff not at the build level but at the runtime level. We can expect similar complications when done over 20 architectures as well.

We don't need to touch 20 architectures. We are talking about unifying dma_mapping_ops. Only architectures that need to handle multiple dma mapping operations use the dma_mapping_ops scheme; X86, IA64, POWERPC, SPARC, and PARISC. Unifying X86, IA64 and POWERPC is a must since they actually share dma_mapping_ops.

if it's just dma_mapping_ops - then it's those 3 architectures. But there's no reason why the various DMA bouncing implementations in other architectures couldnt use the common code - for example couldnt arch/arm/common/dmabounce.c use the swiotlb too?

Quoted 4 lines
Quoted 3 lines

But yes, it's all desired. Obviously extending swiotlb to highmem and using it on xen and powerpc is an essential first step in the direction of generalizing all this code.

Quoted 8 lines

No, it's not about swiotlb highmem patchset.

Due to this problem, IA64 and X86_64 share swiotlb in a very hacky way. We added more hacky code due to this problem again when we added VT-d support to IA64.

This problem has been for long time. We added ugly hacks again and again instead of fixing the root cause.

well the swiotlb highmem patches are what enable xen (and now powerpc too) to make full use of the swiotlb dma bouncing facilities. And that gives a common platform for unifying all the rest of the lowlevel DMA mapping APIs as well.

Without that, the swiotlb code is limited, life is going on in separate islands, with everyone doing their own private variations and hacks. We would still probably be nowhere with this had Jeremy not sent the highmem patches.

Ingo

#25 lore raw
Quoted 18 lines · On Sun, 28 Dec 2008 11:34:19 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 9 lines · FUJITA Tomonori
Quoted 5 lines

Note that the main complication wasnt even the small variations in signatures, but the different _semantics_: one dma_mapping_ops implementation passed in kernel-virtual addresses, the other physical addresses. Unifying that was invasive and non-trivial, and it can break

I guess that you are talking about the dma_map_single difference between x86_32 and x86_64. As far as I know, Only x64_64 uses physical address with dma_map_single.

yes - dma_map_single() has this signature:

static inline dma_addr_t
dma_map_single(struct device *hwdev, void *ptr, size_t size, int direction)

Quoted 7 lines

on x86 dma_mapping_ops.map_single has this signature:

dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t ptr,
size_t size, int direction);

ia64 and powerpc uses kernel-virt addresses for map_single(). So there's material semantic differences between the dma_mapping_ops implementations.

I know. And as I wrote, as far as I know, only x86 use physical addresses with map_single.

I think except for x86, all other archs use cpu addresses because we define dma_map_single() in the following way:

dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)

Quoted 10 lines
Quoted 8 lines
Quoted 2 lines

stuff not at the build level but at the runtime level. We can expect similar complications when done over 20 architectures as well.

We don't need to touch 20 architectures. We are talking about unifying dma_mapping_ops. Only architectures that need to handle multiple dma mapping operations use the dma_mapping_ops scheme; X86, IA64, POWERPC, SPARC, and PARISC. Unifying X86, IA64 and POWERPC is a must since they actually share dma_mapping_ops.

if it's just dma_mapping_ops - then it's those 3 architectures. But

Well, there are 5 architectures at least, as I wrote.

Quoted 3 lines

there's no reason why the various DMA bouncing implementations in other architectures couldnt use the common code - for example couldnt arch/arm/common/dmabounce.c use the swiotlb too?

Well, it's a different issue. I and hch are talking about dma_mapping_ops unification.

You brought up a different topic, DMA bouncing implementations unification. DMA bouncing implementations unification is a very nice cleanup. But it's not related with Becky's patch to break IA64 build at all.

Quoted 18 lines
Quoted 4 lines
Quoted 3 lines

But yes, it's all desired. Obviously extending swiotlb to highmem and using it on xen and powerpc is an essential first step in the direction of generalizing all this code.

Quoted 8 lines

No, it's not about swiotlb highmem patchset.

Due to this problem, IA64 and X86_64 share swiotlb in a very hacky way. We added more hacky code due to this problem again when we added VT-d support to IA64.

This problem has been for long time. We added ugly hacks again and again instead of fixing the root cause.

well the swiotlb highmem patches are what enable xen (and now powerpc too) to make full use of the swiotlb dma bouncing facilities. And that gives a common platform for unifying all the rest of the lowlevel DMA mapping APIs as well.

Quoted 4 lines

Without that, the swiotlb code is limited, life is going on in separate islands, with everyone doing their own private variations and hacks. We would still probably be nowhere with this had Jeremy not sent the highmem patches.

Again, you are talking about a different issue, which is not related with Becky's patch to break IA64 build.

As I wrote, Becky's patch is a workaround for the problem that has been for long time. It's not just about swiotlb.

#26 lore raw
Quoted 4 lines · FUJITA Tomonori

You brought up a different topic, DMA bouncing implementations unification. DMA bouncing implementations unification is a very nice cleanup. But it's not related with Becky's patch to break IA64 build at all.

All i'm saying is that obviously neither Jeremy's nor Becky's patches were created in a vacuum, and had it not been for the need and desire to extend swiotlb we'd not have seen Becky's 9/9 cleanup patch either.

Ingo

#27 lore raw
Quoted 11 lines · On Sun, 28 Dec 2008 12:56:21 +0100 Ingo Molnar <[email protected]> wrote:
Quoted 4 lines · FUJITA Tomonori

You brought up a different topic, DMA bouncing implementations unification. DMA bouncing implementations unification is a very nice cleanup. But it's not related with Becky's patch to break IA64 build at all.

All i'm saying is that obviously neither Jeremy's nor Becky's patches were created in a vacuum, and had it not been for the need and desire to extend swiotlb we'd not have seen Becky's 9/9 cleanup patch either.

As I wrote, Becky's 9/9 cleanup path is not about swiotlb highmem extention. We had known about the need to clean up the dma mapping operation ugliness. But we has ignored it and added workarounds again and again. We haven't seen something like his 9/9 because we added workarounds in architecture-specific code.

Anyway, his 9/9 patch is wrong if we want to fix the root cause. If we don't fix the root cause, the lots of changes of his 9/9 patch don't make sense. Probably, it would better to add some workarounds in architecture-specific code (POWERPC in this case) as we have done in the past.

Ok, I'll try to fix the root cause. We need lots of changes to IA64 especially. Hopefully, I can get Tony's ACK on these changes.

#28 lore raw
Quoted 2 lines · FUJITA Tomonori

Ok, I'll try to fix the root cause. We need lots of changes to IA64 especially. Hopefully, I can get Tony's ACK on these changes.

great - let me know if you need testing help on the x86 side as well. I.e. we can test some preliminary patch series from you as well, without committing it to anything stable (i.e. keeping open the ability to rebase/redo it) - while waiting for Tony's ACK.

Ingo

#21 lore raw
In reply to Christoph Hellwig
Quoted 4 lines · Christoph Hellwig

Also the calgary iommu is very similar to those used on some pseries machines, but I'd have to look at the code if the interface actually still is similar, or if the PPC firmware adds too much abstractions inbetween.

Well, we have basically two backends... in the same file but they are really different and I may split them one of these days. One is "native", used in theory only on POWER4 (and internal bare-metal stuff) and one is purely via hypervisor calls.

Quoted 3 lines

Also the older IA64 altixens have a slightly updated version of the iommu used on MIPS IP27 (and the same as on MIPS IP35 which we'll hopefully support one day)

BTW. On a tangent here, but I do prefer in the long run switching DMA ops mostly away from struct page * + offset and toward phys_addr_t (even if we won't change the SG variant).

The reason is sneaky :-) But there are cases, especially in embedded space, where it would be nice to be able to DMA to/from MMIO areas or in general areas not covered by struct pages. Currently doing so requires hacking all the way through the stack, it might be possible to do it more nicely with arch custom DMA ops provided we can pass around addresses an not struct page*.

Cheers,
Ben.