The functions that operate on io_tlb_list/io_tlb_start/io_tlb_orig_addr
have the prefix 'swiotlb_tbl' now.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
lib/swiotlb.c | 35 +++++++++++++++++++----------------
1 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 437eedb..1798814 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -60,8 +60,8 @@ enum dma_sync_target {
int swiotlb_force;
/*
- * Used to do a quick range check in unmap_single and
- * sync_single_*, to see if the memory was in fact allocated by this
+ * Used to do a quick range check in swiotlb_tbl_unmap_single and
+ * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
static char *io_tlb_start, *io_tlb_end;
@@ -364,7 +364,8 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
* 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)
+swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys, size_t size,
+ int dir)
{
unsigned long flags;
char *dma_addr;
@@ -470,7 +471,8 @@ found:
* dma_addr is the kernel virtual address of the bounce buffer to unmap.
*/
static void
-do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
+ int dir)
{
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -510,7 +512,7 @@ do_unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
}
static void
-sync_single(struct device *hwdev, char *dma_addr, size_t size,
+swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size,
int dir, int target)
{
int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
@@ -558,11 +560,11 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t ...We put the init, free, and functions dealing with the operations on
the SWIOTLB buffer at the top of the header. Also we export some of the
variables that are used by the dma_ops functions.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
include/linux/swiotlb.h | 33 +++++++++++++++++++++++++++++++++
lib/swiotlb.c | 42 ++++++++++++++++++++----------------------
2 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 2a98e6a..42df529 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -24,6 +24,39 @@ extern int swiotlb_force;
extern void swiotlb_init(int verbose);
+/* Internal book-keeping functions. Must be linked against the library
+ * to take advantage of them.*/
+#ifdef CONFIG_SWIOTLB
+/*
+ * Enumeration for sync targets
+ */
+enum dma_sync_target {
+ SYNC_FOR_CPU = 0,
+ SYNC_FOR_DEVICE = 1,
+};
+extern char *swiotlb_tbl_start;
+extern unsigned long swiotlb_tbl_nslabs;
+extern int is_swiotlb_buffer(phys_addr_t paddr);
+extern void *swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys,
+ unsigned long start_dma_addr, size_t size,
+ enum dma_data_direction dir);
+
+extern void swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr,
+ size_t size, enum dma_data_direction dir);
+
+extern void swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr,
+ size_t size, enum dma_data_direction dir,
+ enum dma_sync_target target);
+
+/* Accessory functions. */
+extern void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+ enum dma_data_direction dir);
+extern void swiotlb_full(struct device *dev, size_t size,
+ enum dma_data_direction dir, int do_panic);
+
+#endif
+
+/* swiotlb.c: dma_ops functions. */
extern void
*swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index ...Make the functions and variables that are now declared in the swiotlb.h header file visible by the linker. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> --- lib/swiotlb.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 5443ad5..48f1e94 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -58,12 +58,14 @@ int swiotlb_force; */ char *swiotlb_tbl_start; static char *io_tlb_end; +EXPORT_SYMBOL_GPL(swiotlb_tbl_start); /* * The number of IO TLB blocks (in groups of 64) betweeen swiotlb_tbl_start and * io_tlb_end. This is command line adjustable via setup_io_tlb_npages. */ unsigned long swiotlb_tbl_nslabs; +EXPORT_SYMBOL_GPL(swiotlb_tbl_nslabs); /* * When the IOMMU overflows we return a fallback buffer. This sets the size. @@ -313,6 +315,7 @@ int is_swiotlb_buffer(phys_addr_t paddr) return paddr >= virt_to_phys(swiotlb_tbl_start) && paddr < virt_to_phys(io_tlb_end); } +EXPORT_SYMBOL_GPL(is_swiotlb_buffer); /* * Bounce: copy the swiotlb buffer back to the original dma location @@ -354,6 +357,7 @@ void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size, memcpy(phys_to_virt(phys), dma_addr, size); } } +EXPORT_SYMBOL_GPL(swiotlb_bounce); /* * Allocates bounce buffer and returns its kernel virtual address. @@ -461,6 +465,7 @@ found: return dma_addr; } +EXPORT_SYMBOL_GPL(swiotlb_tbl_map_single); /* * dma_addr is the kernel virtual address of the bounce buffer to unmap. @@ -506,6 +511,7 @@ swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size, } spin_unlock_irqrestore(&io_tlb_lock, flags); } +EXPORT_SYMBOL_GPL(swiotlb_tbl_unmap_single); void swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size, @@ -534,6 +540,7 @@ swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size, BUG(); } } +EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single); void * ...
On Wed, 7 Apr 2010 16:29:29 -0400 Please don't. You create a new IOMMU implementation with the helper function. We don't want another IOMMU implementation that has broken 'overflow buffer' concept. swiotlb-xen should handle DMA mapping errors properly instead of calling swiotlb_full(). btw, if you try to push xen swiotlb stuff to mainline, please don't put xen swiotlb stuff to include/linux/swiotlb.h. --
Of course. Will remove that. Thanks again for your review, much OK. --
We prefix pertient book keeping functions and variables with the
'swiotlb_tbl' prefix.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
lib/swiotlb.c | 149 +++++++++++++++++++++++++++++---------------------------
1 files changed, 77 insertions(+), 72 deletions(-)
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index bc516bb..5451517 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -64,13 +64,13 @@ int swiotlb_force;
* swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
-static char *io_tlb_start, *io_tlb_end;
+static char *swiotlb_tbl_start, *io_tlb_end;
/*
- * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and
+ * The number of IO TLB blocks (in groups of 64) betweeen swiotlb_tbl_start and
* io_tlb_end. This is command line adjustable via setup_io_tlb_npages.
*/
-static unsigned long io_tlb_nslabs;
+static unsigned long swiotlb_tbl_nslabs;
/*
* When the IOMMU overflows we return a fallback buffer. This sets the size.
@@ -103,9 +103,9 @@ static int __init
setup_io_tlb_npages(char *str)
{
if (isdigit(*str)) {
- io_tlb_nslabs = simple_strtoul(str, &str, 0);
+ swiotlb_tbl_nslabs = simple_strtoul(str, &str, 0);
/* avoid tail segment of size < IO_TLB_SEGSIZE */
- io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+ swiotlb_tbl_nslabs = ALIGN(swiotlb_tbl_nslabs, IO_TLB_SEGSIZE);
}
if (*str == ',')
++str;
@@ -126,14 +126,14 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
void swiotlb_print_info(void)
{
- unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
+ unsigned long bytes = swiotlb_tbl_nslabs << IO_TLB_SHIFT;
phys_addr_t pstart, pend;
- pstart = virt_to_phys(io_tlb_start);
+ pstart = virt_to_phys(swiotlb_tbl_start);
pend = virt_to_phys(io_tlb_end);
printk(KERN_INFO "Placing %luMB software IO TLB between %p - %p\n",
- bytes >> 20, io_tlb_start, io_tlb_end);
+ bytes >> 20, swiotlb_tbl_start, .... to catch anybody doing something funky.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
include/linux/swiotlb.h | 4 ++--
lib/swiotlb.c | 22 ++++++++++++----------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index febedcf..2a98e6a 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -42,11 +42,11 @@ extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
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,
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 5451517..94fc749 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -367,7 +367,8 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
*/
static void *
swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys,
- unsigned long start_dma_addr, size_t size, int dir)
+ unsigned long start_dma_addr, size_t size,
+ enum dma_data_direction dir)
{
unsigned long flags;
char *dma_addr;
@@ -473,7 +474,7 @@ found:
*/
static void
swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
- int dir)
+ enum dma_data_direction dir)
{
unsigned long flags;
int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
@@ -515,7 +516,7 @@ swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
static void
swiotlb_tbl_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 - swiotlb_tbl_start) >> IO_TLB_SHIFT;
...On Wed, 7 Apr 2010 16:29:27 -0400
Can we create the swiotlb initialization function instead of lots of
renaming and exporting iotlb values?
=
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Subject: [PATCH 1/2] swiotlb: add the swiotlb initialization function
with iotlb memory
This enables the caller to initialize swiotlb with its own iotlb
memory.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
include/linux/swiotlb.h | 1 +
lib/swiotlb.c | 48 +++++++++++++++++++++++++++++-----------------
2 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index febedcf..17b5298 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -23,6 +23,7 @@ extern int swiotlb_force;
#define IO_TLB_SHIFT 11
extern void swiotlb_init(int verbose);
+extern void swiotlb_init_with_tlb(char *tlb, unsigned long nslabs, int verbose);
extern void
*swiotlb_alloc_coherent(struct device *hwdev, size_t size,
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 5fddf72..a37ee04 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -140,28 +140,14 @@ void swiotlb_print_info(void)
(unsigned long long)pend);
}
-/*
- * Statically reserve bounce buffer space and initialize bounce buffer data
- * structures for the software IO TLB used to implement the DMA API.
- */
-void __init
-swiotlb_init_with_default_size(size_t default_size, int verbose)
+void __init swiotlb_init_with_tlb(char *tlb, unsigned long nslabs, int verbose)
{
unsigned long i, bytes;
- if (!io_tlb_nslabs) {
- io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
- io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
- }
+ bytes = nslabs << IO_TLB_SHIFT;
- bytes = io_tlb_nslabs << IO_TLB_SHIFT;
-
- /*
- * Get IO TLB memory from the low pages
- */
- io_tlb_start = alloc_bootmem_low_pages(bytes);
- if (!io_tlb_start)
- panic("Cannot allocate SWIOTLB buffer");
+ io_tlb_nslabs = ...Yes, this would definitly do it! Let me rebase my tree on top of your patches. Thought I was thinking to modify your patches so they have the _tbl, instead --
On Mon, 10 May 2010 15:33:44 -0400 Yeah, please replace tlb with tbl. --
We want to move that function out of swiotlb_tbl_map_single so that the caller
of this function does the virt->phys->bus address translation.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
lib/swiotlb.c | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1798814..bc516bb 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -364,21 +364,19 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
* Allocates bounce buffer and returns its kernel virtual address.
*/
static void *
-swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys, size_t size,
- int dir)
+swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t phys,
+ unsigned long start_dma_addr, size_t size, int dir)
{
unsigned long flags;
char *dma_addr;
unsigned int nslots, stride, index, wrap;
int i;
- unsigned long start_dma_addr;
unsigned long mask;
unsigned long offset_slots;
unsigned long max_slots;
mask = dma_get_seg_boundary(hwdev);
- start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start) & mask;
-
+ start_dma_addr = start_dma_addr & mask;
offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
/*
@@ -546,6 +544,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
void *ret;
int order = get_order(size);
u64 dma_mask = DMA_BIT_MASK(32);
+ unsigned long start_dma_addr;
if (hwdev && hwdev->coherent_dma_mask)
dma_mask = hwdev->coherent_dma_mask;
@@ -564,7 +563,9 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
* GFP_DMA memory; fall back on swiotlb_tbl_map_single(), which
* will grab memory from the lowest available address range.
*/
- ret = swiotlb_tbl_map_single(hwdev, 0, size, DMA_FROM_DEVICE);
+ start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start);
+ ret = swiotlb_tbl_map_single(hwdev, 0, start_dma_addr, size,
+ DMA_FROM_DEVICE);
if (!ret)
...On Wed, 7 Apr 2010 16:29:26 -0400
It would be better to do something like that instead of spreading
swiotlb_virt_to_bus()?
=
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Subject: [PATCH] swiotlb: add swiotlb_tlb_map_single library function
swiotlb_tlb_map_single() takes the dma address of iotlb instead of
using swiotlb_virt_to_bus().
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
lib/swiotlb.c | 25 +++++++++++++++++--------
1 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index a37ee04..58f489a 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -373,25 +373,22 @@ static void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
}
}
-/*
- * 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)
+void *swiotlb_tlb_map_single(struct device *hwdev, u64 tlb_dma_addr,
+ phys_addr_t phys, size_t size, int dir)
{
unsigned long flags;
char *dma_addr;
unsigned int nslots, stride, index, wrap;
int i;
- unsigned long start_dma_addr;
unsigned long mask;
unsigned long offset_slots;
unsigned long max_slots;
mask = dma_get_seg_boundary(hwdev);
- 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;
+ tlb_dma_addr &= mask;
+
+ offset_slots = ALIGN(tlb_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
/*
* Carefully handle integer overflow which can occur when mask == ~0UL.
@@ -480,6 +477,18 @@ found:
}
/*
+ * 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)
+{
+ u64 start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start);
+
+ return swiotlb_tlb_map_single(hwdev, start_dma_addr, phys, size, dir);
+}
+
+/*
* dma_addr is the kernel ...Yes! Thought I am confused by the name. In the past you mentioned 'tbl', --
On Mon, 10 May 2010 15:31:18 -0400 Oops, yeah. I meant 'tbl' for 'table' since Calgary and POWERPC IOMMUs use 'iommu_table' struct to store the global info. Please replace 'tlb' with 'tbl'. --
