2008-12-22 18:29:26

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 0 of 9] 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


2008-12-22 18:29:08

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 2 of 9] revert "swiotlb: factor out copy to/from device."

git commit 1b548f667c1487d92e794a9f7a67788f49b952d8

---
lib/swiotlb.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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;

2008-12-22 18:29:42

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 8 of 9] swiotlb: cleanups to swiotlb_bounce()

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

Signed-off-by: Jeremy Fitzhardinge <[email protected]>
---
lib/swiotlb.c | 61 +++++++++++++++++++++++++++++----------------------------
1 file changed, 32 insertions(+), 29 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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
}

/*

2008-12-22 18:29:57

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 7 of 9] swiotlb: Add support for systems with highmem

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.

Signed-off-by: Becky Bruce <[email protected]>
---
lib/swiotlb.c | 53 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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;

2008-12-22 18:30:30

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 1 of 9] revert "swiotlb: support bouncing of HighMem pages."

git commit ef9b189352f2eb78f14e52996f4780a523b04a49

---
lib/swiotlb.c | 122 +++++++++++++++------------------------------------------
1 file changed, 33 insertions(+), 89 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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);
}
}


2008-12-22 18:30:47

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 4 of 9] swiotlb: Drop SG_ENT_VIRT_ADDRESS macro

From: Becky Bruce <[email protected]>

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

Signed-off-by: Becky Bruce <[email protected]>
---
lib/swiotlb.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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);
}
}


2008-12-22 18:31:11

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 5 of 9] swiotlb: Rename SG_ENT_PHYS_ADDRESS to SG_ENT_BUS_ADDRESS

From: Becky Bruce <[email protected]>

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

Signed-off-by: Becky Bruce <[email protected]>
---
lib/swiotlb.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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)

2008-12-22 18:31:28

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 3 of 9] swiotlb: add hwdev to swiotlb_phys_to_bus

Some architectures need it.

Signed-off-by: Jeremy Fitzhardinge <[email protected]>
---
arch/x86/kernel/pci-swiotlb_64.c | 2 -
include/linux/swiotlb.h | 3 +-
lib/swiotlb.c | 45 +++++++++++++++-----------------------
3 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -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;
}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -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);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -125,7 +125,7 @@
return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
}

-dma_addr_t __weak swiotlb_phys_to_bus(phys_addr_t paddr)
+dma_addr_t __weak swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
{
return paddr;
}
@@ -135,9 +135,10 @@
return baddr;
}

-static dma_addr_t swiotlb_virt_to_bus(volatile void *address)
+static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
+ volatile void *address)
{
- return swiotlb_phys_to_bus(virt_to_phys(address));
+ return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
}

static void *swiotlb_bus_to_virt(dma_addr_t address)
@@ -153,27 +154,15 @@
static void swiotlb_print_info(unsigned long bytes)
{
phys_addr_t pstart, pend;
- dma_addr_t bstart, bend;

pstart = virt_to_phys(io_tlb_start);
pend = virt_to_phys(io_tlb_end);

- bstart = swiotlb_phys_to_bus(pstart);
- bend = swiotlb_phys_to_bus(pend);
-
printk(KERN_INFO "Placing %luMB software IO TLB between %p - %p\n",
bytes >> 20, io_tlb_start, io_tlb_end);
- if (pstart != bstart || pend != bend)
- printk(KERN_INFO "software IO TLB at phys %#llx - %#llx"
- " bus %#llx - %#llx\n",
- (unsigned long long)pstart,
- (unsigned long long)pend,
- (unsigned long long)bstart,
- (unsigned long long)bend);
- else
- printk(KERN_INFO "software IO TLB at phys %#llx - %#llx\n",
- (unsigned long long)pstart,
- (unsigned long long)pend);
+ printk(KERN_INFO "software IO TLB at phys %#llx - %#llx\n",
+ (unsigned long long)pstart,
+ (unsigned long long)pend);
}

/*
@@ -351,7 +340,7 @@
unsigned long max_slots;

mask = dma_get_seg_boundary(hwdev);
- start_dma_addr = swiotlb_virt_to_bus(io_tlb_start) & mask;
+ start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start) & mask;

offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;

@@ -528,7 +517,9 @@
dma_mask = hwdev->coherent_dma_mask;

ret = (void *)__get_free_pages(flags, order);
- if (ret && !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(ret), size)) {
+ if (ret &&
+ !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(hwdev, ret),
+ size)) {
/*
* The allocated memory isn't reachable by the device.
* Fall back on swiotlb_map_single().
@@ -549,7 +540,7 @@
}

memset(ret, 0, size);
- dev_addr = swiotlb_virt_to_bus(ret);
+ dev_addr = swiotlb_virt_to_bus(hwdev, ret);

/* Confirm address can be DMA'd by device */
if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
@@ -609,7 +600,7 @@
swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
int dir, struct dma_attrs *attrs)
{
- dma_addr_t dev_addr = swiotlb_virt_to_bus(ptr);
+ dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, ptr);
void *map;

BUG_ON(dir == DMA_NONE);
@@ -631,7 +622,7 @@
map = io_tlb_overflow_buffer;
}

- dev_addr = swiotlb_virt_to_bus(map);
+ dev_addr = swiotlb_virt_to_bus(hwdev, map);

/*
* Ensure that the address returned is DMA'ble
@@ -778,7 +769,7 @@

for_each_sg(sgl, sg, nelems, i) {
addr = SG_ENT_VIRT_ADDRESS(sg);
- dev_addr = swiotlb_virt_to_bus(addr);
+ dev_addr = swiotlb_virt_to_bus(hwdev, addr);
if (range_needs_mapping(sg_virt(sg), sg->length) ||
address_needs_mapping(hwdev, dev_addr, sg->length)) {
void *map = map_single(hwdev, addr, sg->length, dir);
@@ -791,7 +782,7 @@
sgl[0].dma_length = 0;
return 0;
}
- sg->dma_address = swiotlb_virt_to_bus(map);
+ sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
} else
sg->dma_address = dev_addr;
sg->dma_length = sg->length;
@@ -879,7 +870,7 @@
int
swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
{
- return (dma_addr == swiotlb_virt_to_bus(io_tlb_overflow_buffer));
+ return (dma_addr == swiotlb_virt_to_bus(hwdev, io_tlb_overflow_buffer));
}

/*
@@ -891,7 +882,7 @@
int
swiotlb_dma_supported(struct device *hwdev, u64 mask)
{
- return swiotlb_virt_to_bus(io_tlb_end - 1) <= mask;
+ return swiotlb_virt_to_bus(hwdev, io_tlb_end - 1) <= mask;
}

EXPORT_SYMBOL(swiotlb_map_single);

2008-12-22 18:31:44

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: [PATCH 6 of 9] swiotlb: Store phys address in io_tlb_orig_addr array

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.

Signed-off-by: Becky Bruce <[email protected]>
---
lib/swiotlb.c | 47 ++++++++++++++++++++++++-----------------------
1 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -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. */

2008-12-22 18:32:15

by Jeremy Fitzhardinge

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

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.

Signed-off-by: Becky Bruce <[email protected]>
---
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(-)

diff --git a/arch/ia64/dig/dig_vtd_iommu.c b/arch/ia64/dig/dig_vtd_iommu.c
--- a/arch/ia64/dig/dig_vtd_iommu.c
+++ b/arch/ia64/dig/dig_vtd_iommu.c
@@ -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);
}
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -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);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -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;
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -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);
}
diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
--- a/arch/ia64/include/asm/swiotlb.h
+++ b/arch/ia64/include/asm/swiotlb.h
@@ -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);
diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
--- a/arch/ia64/kernel/machvec.c
+++ b/arch/ia64/kernel/machvec.c
@@ -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();
}
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -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;
}
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -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);
}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -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 =
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -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;
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -25,32 +25,36 @@
void (*free_coherent)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
dma_addr_t (*map_single)(struct device *hwdev, phys_addr_t 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)(struct device *hwdev, u64 mask);
int is_phys;
};
@@ -91,7 +95,7 @@

static inline dma_addr_t
dma_map_single(struct device *hwdev, void *ptr, size_t size,
- int direction)
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -102,7 +106,7 @@

static inline void
dma_unmap_single(struct device *dev, dma_addr_t addr, size_t size,
- int direction)
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(dev);

@@ -113,7 +117,7 @@

static inline int
dma_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction)
+ int nents, enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -123,7 +127,7 @@

static inline void
dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
- int direction)
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -134,7 +138,7 @@

static inline void
dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
- size_t size, int direction)
+ size_t size, enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -146,7 +150,7 @@

static inline void
dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
- size_t size, int direction)
+ size_t size, enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -158,7 +162,8 @@

static inline void
dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
- unsigned long offset, size_t size, int direction)
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -172,7 +177,7 @@
static inline void
dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
unsigned long offset, size_t size,
- int direction)
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -185,7 +190,7 @@

static inline void
dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
- int nelems, int direction)
+ int nelems, enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -197,7 +202,7 @@

static inline void
dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
- int nelems, int direction)
+ int nelems, enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(hwdev);

@@ -210,7 +215,7 @@

static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
- int direction)
+ enum dma_data_direction direction)
{
struct dma_mapping_ops *ops = get_dma_ops(dev);

@@ -220,7 +225,8 @@
}

static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
- size_t size, int direction)
+ size_t size,
+ enum dma_data_direction direction)
{
dma_unmap_single(dev, addr, size, direction);
}
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -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);
diff --git a/arch/x86/include/asm/tce.h b/arch/x86/include/asm/tce.h
--- a/arch/x86/include/asm/tce.h
+++ b/arch/x86/include/asm/tce.h
@@ -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);
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -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;
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -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;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -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;
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -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;
diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -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);
}
diff --git a/arch/x86/kernel/tce_64.c b/arch/x86/kernel/tce_64.c
--- a/arch/x86/kernel/tce_64.c
+++ b/arch/x86/kernel/tce_64.c
@@ -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;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -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;
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -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
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -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);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -373,7 +373,8 @@
* Allocates bounce buffer and returns its kernel virtual address.
*/
static void *
-map_single(struct device *hwdev, phys_addr_t phys, size_t size, int dir)
+map_single(struct device *hwdev, phys_addr_t phys, size_t size,
+ enum dma_data_direction dir)
{
unsigned long flags;
char *dma_addr;
@@ -479,7 +480,8 @@
* dma_addr is the kernel virtual address of the bounce buffer to unmap.
*/
static void
-unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+unmap_single(struct device *hwdev, char *dma_addr, size_t size,
+ enum dma_data_direction dir)
{
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -520,7 +522,7 @@

static void
sync_single(struct device *hwdev, char *dma_addr, size_t size,
- int dir, int target)
+ enum dma_data_direction dir, int target)
{
int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
phys_addr_t phys = io_tlb_orig_addr[index];
@@ -610,7 +612,8 @@
}

static void
-swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
+ int do_panic)
{
/*
* Ran out of IOMMU space for this operation. This is very bad.
@@ -639,7 +642,7 @@
*/
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)
{
dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, ptr);
void *map;
@@ -676,7 +679,8 @@
EXPORT_SYMBOL(swiotlb_map_single_attrs);

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)
{
return swiotlb_map_single_attrs(hwdev, ptr, size, dir, NULL);
}
@@ -691,7 +695,8 @@
*/
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)
{
char *dma_addr = swiotlb_bus_to_virt(dev_addr);

@@ -705,7 +710,7 @@

void
swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
- int dir)
+ enum dma_data_direction dir)
{
return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
}
@@ -721,7 +726,7 @@
*/
static void
swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
- size_t size, int dir, int target)
+ size_t size, enum dma_data_direction dir, int target)
{
char *dma_addr = swiotlb_bus_to_virt(dev_addr);

@@ -734,14 +739,14 @@

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)
{
swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU);
}

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)
{
swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE);
}
@@ -752,7 +757,7 @@
static void
swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
unsigned long offset, size_t size,
- int dir, int target)
+ enum dma_data_direction dir, int target)
{
char *dma_addr = swiotlb_bus_to_virt(dev_addr) + offset;

@@ -765,7 +770,8 @@

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)
{
swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir,
SYNC_FOR_CPU);
@@ -773,14 +779,15 @@

void
swiotlb_sync_single_range_for_device(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)
{
swiotlb_sync_single_range(hwdev, dev_addr, offset, size, dir,
SYNC_FOR_DEVICE);
}

-void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
- struct dma_attrs *);
+void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int,
+ enum dma_data_direction, struct dma_attrs *);
/*
* Map a set of buffers described by scatterlist in streaming mode for DMA.
* This is the scatter-gather version of the above swiotlb_map_single
@@ -799,7 +806,7 @@
*/
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)
{
struct scatterlist *sg;
int i;
@@ -834,7 +841,7 @@

int
swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
- int dir)
+ enum dma_data_direction dir)
{
return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
}
@@ -845,7 +852,8 @@
*/
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)
{
struct scatterlist *sg;
int i;
@@ -864,7 +872,7 @@

void
swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
- int dir)
+ enum dma_data_direction dir)
{
return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
}
@@ -878,7 +886,7 @@
*/
static void
swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
- int nelems, int dir, int target)
+ int nelems, enum dma_data_direction dir, int target)
{
struct scatterlist *sg;
int i;
@@ -896,14 +904,14 @@

void
swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
- int nelems, int dir)
+ int nelems, enum dma_data_direction dir)
{
swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU);
}

void
swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
- int nelems, int dir)
+ int nelems, enum dma_data_direction dir)
{
swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
}

2008-12-22 18:44:26

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

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.


> 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.

2008-12-27 10:49:12

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* 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.
>
> 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.

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

2008-12-27 15:06:58

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sat, 27 Dec 2008 11:48:23 +0100
Ingo Molnar <[email protected]> wrote:

>
> * 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.
> >
> > 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.
>
> 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


> 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/

2008-12-27 16:45:26

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

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 +-
>
> (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.

2008-12-27 16:57:02

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* FUJITA Tomonori <[email protected]> wrote:

> 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 +-
> >
> > (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.

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

Ingo

2008-12-27 17:04:19

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sat, 27 Dec 2008 17:56:22 +0100
Ingo Molnar <[email protected]> wrote:

>
> * FUJITA Tomonori <[email protected]> wrote:
>
> > 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 +-
> > >
> > > (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.
>
> 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.

2008-12-28 05:02:06

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

FUJITA Tomonori wrote:
> 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

2008-12-28 05:30:37

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 28 Dec 2008 02:03:37 +0900
FUJITA Tomonori <[email protected]> wrote:

> On Sat, 27 Dec 2008 17:56:22 +0100
> Ingo Molnar <[email protected]> wrote:
>
> >
> > * FUJITA Tomonori <[email protected]> wrote:
> >
> > > 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 +-
> > > >
> > > > (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.
> >
> > 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.

2008-12-28 07:30:46

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, Dec 28, 2008 at 02:29:54PM +0900, FUJITA Tomonori wrote:
> 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.

> 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)

2008-12-28 09:36:56

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 28 Dec 2008 02:30:12 -0500
Christoph Hellwig <[email protected]> wrote:

> On Sun, Dec 28, 2008 at 02:29:54PM +0900, FUJITA Tomonori wrote:
> > 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).

2008-12-28 09:38:34

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* FUJITA Tomonori <[email protected]> wrote:

> 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.

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

2008-12-28 09:50:29

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* Jeremy Fitzhardinge <[email protected]> wrote:

> FUJITA Tomonori wrote:
>> 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.

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

2008-12-28 10:02:54

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 28 Dec 2008 10:37:51 +0100
Ingo Molnar <[email protected]> wrote:

>
> * FUJITA Tomonori <[email protected]> wrote:
>
> > 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.
>
> 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.


> 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.


> 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.


> 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.

2008-12-28 10:34:50

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* FUJITA Tomonori <[email protected]> wrote:

> > 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.

> > 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?

> > 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.

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

2008-12-28 11:00:59

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 28 Dec 2008 11:34:19 +0100
Ingo Molnar <[email protected]> wrote:

>
> * FUJITA Tomonori <[email protected]> wrote:
>
> > > 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.

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)


> > > 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.


> 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.


> > > 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.
>
> 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.

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.

2008-12-28 11:57:00

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* FUJITA Tomonori <[email protected]> wrote:

> 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

2008-12-28 12:35:37

by FUJITA Tomonori

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 28 Dec 2008 12:56:21 +0100
Ingo Molnar <[email protected]> wrote:

>
> * FUJITA Tomonori <[email protected]> wrote:
>
> > 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.

2008-12-28 12:50:39

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages


* FUJITA Tomonori <[email protected]> wrote:

> 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

2008-12-28 21:44:00

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: [PATCH 0 of 9] swiotlb: use phys_addr_t for pages

On Sun, 2008-12-28 at 02:30 -0500, Christoph Hellwig wrote:
> 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.

> 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.