public inbox for linux-arch@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code.
@ 2008-05-05 22:37 Stephen Neuendorffer
  2008-05-05 22:37 ` Stephen Neuendorffer
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Stephen Neuendorffer @ 2008-05-05 22:37 UTC (permalink / raw)
  To: arnd, linux-arch, John Linn, john.williams, matthew, will.newton,
	drepper, microbl

Primarily, this patch implements the dma-coherent API.  In addition,
it cleans up some of the code that deals with caches, in order to
match the usage in dma-coherent.

In particular, the dcache in the microblaze is write through, so the
existing code is more easily thought of as 'invalidation' than
'flushing'.  In addition, some of the flush_* methods were old, and
some shouldn't need to be implemented (since currently no mmu is
supported).

I'd appreciate if someone would ACK my interpretation of
Documentation/cachetlb.txt.  In particular:

flush_cache_mm(mm) (NOOP because nommu)
flush_cache_range(mm, start, end) (Does this need to be implemented
since nommu?)
flush_cache_page(vma, vmaddr) (NOOP because nommu)
flush_dcache_page(page) (NOOP because write through cache.)
flush_dcache_range(start, end) (NOOP because write through cache.)
flush_dcache_mmap_lock(mapping) (NOOP because nommu)
flush_dcache_mmap_unlock(mapping) (NOOP because nommu)

flush_icache_page(vma,pg) (Does this need to be implemented? Doc is
unclear, but I assume it is used as flush_icache_range)
flush_icache_range(start, end) (Must be implemented because icache
doesn't snoop dcache on code loads)

Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
---
 arch/microblaze/kernel/cpu/cache.c  |   37 +---------
 arch/microblaze/kernel/setup.c      |    4 +-
 arch/microblaze/mm/dma-coherent.c   |  122
+++++++++++++++++++++++++++++++++++
 include/asm-microblaze/cacheflush.h |   71 +++++++++------------
 4 files changed, 158 insertions(+), 76 deletions(-)
 create mode 100644 arch/microblaze/mm/dma-coherent.c

diff --git a/arch/microblaze/kernel/cpu/cache.c
b/arch/microblaze/kernel/cpu/cache.c
index d6a1eab..1247b9e 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -129,7 +129,7 @@ void _invalidate_dcache(unsigned int addr)
 				: "r" (addr));
 }
 
-void __flush_icache_all(void)
+void __invalidate_icache_all(void)
 {
 	unsigned int i;
 	unsigned flags;
@@ -149,7 +149,7 @@ void __flush_icache_all(void)
 	}
 }
 
-void __flush_icache_range(unsigned long start, unsigned long end)
+void __invalidate_icache_range(unsigned long start, unsigned long end)
 {
 	unsigned int i;
 	unsigned flags;
@@ -177,24 +177,7 @@ void __flush_icache_range(unsigned long start,
unsigned long end)
 	}
 }
 
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	__flush_icache_all();
-}
-
-void __flush_icache_user_range(struct vm_area_struct *vma,
-				struct page *page, unsigned long adr,
-				int len)
-{
-	__flush_icache_all();
-}
-
-void __flush_cache_sigtramp(unsigned long addr)
-{
-	__flush_icache_range(addr, addr + 8);
-}
-
-void __flush_dcache_all(void)
+void __invalidate_dcache_all(void)
 {
 	unsigned int i;
 	unsigned flags;
@@ -216,7 +199,7 @@ void __flush_dcache_all(void)
 	}
 }
 
-void __flush_dcache_range(unsigned long start, unsigned long end)
+void __invalidate_dcache_range(unsigned long start, unsigned long end)
 {
 	unsigned int i;
 	unsigned flags;
@@ -242,15 +225,3 @@ void __flush_dcache_range(unsigned long start,
unsigned long end)
 		local_irq_restore(flags);
 	}
 }
-
-void __flush_dcache_page(struct vm_area_struct *vma, struct page *page)
-{
-	__flush_dcache_all();
-}
-
-void __flush_dcache_user_range(struct vm_area_struct *vma,
-				struct page *page, unsigned long adr,
-				int len)
-{
-	__flush_dcache_all();
-}
diff --git a/arch/microblaze/kernel/setup.c
b/arch/microblaze/kernel/setup.c
index 43d53d9..241fb21 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -51,10 +51,10 @@ void __init setup_arch(char **cmdline_p)
 	/* irq_early_init(); */
 	setup_cpuinfo();
 
-	__flush_icache_all();
+	__invalidate_icache_all();
 	__enable_icache();
 
-	__flush_dcache_all();
+	__invalidate_icache_all();
 	__enable_dcache();
 
 	panic_timeout = 120;
diff --git a/arch/microblaze/mm/dma-coherent.c
b/arch/microblaze/mm/dma-coherent.c
new file mode 100644
index 0000000..308654f
--- /dev/null
+++ b/arch/microblaze/mm/dma-coherent.c
@@ -0,0 +1,122 @@
+/*
+ *  Microblaze support for cache consistent memory.
+ *
+ *  Copyright (C) 2007 Xilinx, Inc.
+ *
+ *  Based on arch/microblaze/mm/consistent.c
+ *  Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
+ *  Based on arch/avr32/mm/dma-coherent.c
+ *  Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Consistent memory allocators.  Used for DMA devices that want to
+ * share memory with the processor core.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int
direction)
+{
+	switch (direction) {
+	case DMA_FROM_DEVICE:		/* invalidate only */
+		invalidate_dcache_range(vaddr, vaddr + size);
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		flush_dcache_range(vaddr, vaddr + size);
+		break;
+	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
+		invalidate_dcache_range(vaddr, vaddr + size);
+		flush_dcache_range(vaddr, vaddr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+EXPORT_SYMBOL(dma_cache_sync);
+
+static struct page *__dma_alloc(struct device *dev, size_t size,
+				dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page, *free, *end;
+	int order;
+
+	if (in_interrupt())
+		BUG();
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = alloc_pages(gfp, order);
+	if (!page)
+		return NULL;
+
+	split_page(page, order);
+
+	/*
+	 * When accessing physical memory with valid cache data, we
+	 * get a cache hit even if the virtual memory region is marked
+	 * as uncached.
+	 *
+	 * Since the memory is newly allocated, there is no point in
+	 * doing a writeback. If the previous owner cares, he should
+	 * have flushed the cache before releasing the memory.
+	 */
+	invalidate_dcache_range(phys_to_virt(page_to_phys(page)), size);
+
+	*handle = page_to_bus(page);
+	free = page + (size >> PAGE_SHIFT);
+	end = page + (1 << order);
+
+	/*
+	 * Free any unused pages
+	 */
+	while (free < end) {
+		__free_page(free);
+		free++;
+	}
+
+	return page;
+}
+
+static void __dma_free(struct device *dev, size_t size,
+		       struct page *page, dma_addr_t handle)
+{
+	struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
+
+	while (page < end)
+		__free_page(page++);
+}
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page;
+	void *ret = NULL;
+
+	page = __dma_alloc(dev, size, handle, gfp);
+	if (page) {
+		ret = (void *)page_to_phys(page);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+		       void *cpu_addr, dma_addr_t handle)
+{
+	void *addr;
+	struct page *page;
+
+	pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n",
+		 cpu_addr, (unsigned long)handle, (unsigned)size);
+	BUG_ON(!virt_addr_valid(addr));
+	page = virt_to_page(addr);
+	__dma_free(dev, size, page, handle);
+}
+EXPORT_SYMBOL(dma_free_coherent);
diff --git a/include/asm-microblaze/cacheflush.h
b/include/asm-microblaze/cacheflush.h
index ba7339d..782f01b 100644
--- a/include/asm-microblaze/cacheflush.h
+++ b/include/asm-microblaze/cacheflush.h
@@ -1,6 +1,7 @@
 /*
  * include/asm-microblaze/cacheflush.h
  *
+ * Copyright (C) 2008 Xilinx, Inc.
  * Copyright (C) 2007 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  * based on v850 version which was
@@ -15,58 +16,46 @@
 
 #ifndef _ASM_MICROBLAZE_CACHEFLUSH_H
 #define _ASM_MICROBLAZE_CACHEFLUSH_H
+#include <linux/kernel.h>	/* For min/max macros */
+#include <linux/mm.h>	/* For min/max macros */
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/cache.h>
 
-/* Somebody depends on this; sigh... */
-#include <linux/mm.h>
-
-#define flush_cache_all()			__flush_cache_all()
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	__flush_cache_all()
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
-
-#define flush_dcache_range(start, end)	__flush_dcache_range(start, end)
-#define flush_dcache_page(page)		do { } while (0)
-#define flush_dcache_mmap_lock(mapping)		do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+/*
+ * Cache handling functions.
+ * Microblaze has a write-through data cache, and no icache snooping of
dcache.
+ */
+#define flush_cache_mm(mm)			do { } while(0)
+#define flush_cache_range(mm, start, end)	invalidate_cache_all()
+#define flush_cache_page(vma, vmaddr)		do { } while(0)
 
-#define flush_icache_range(start, len)	__flush_icache_range(start, len)
-#define flush_icache_page(vma, pg)		do { } while (0)
-#define flush_icache_user_range(start, len)	do { } while (0)
+#define flush_dcache_page(page)			do { } while(0)
+#define flush_dcache_range(start, end)		do { } while(0)
+#define flush_dcache_mmap_lock(mapping)		do { } while(0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while(0)
 
-#define flush_cache_vmap(start, end)		do { } while (0)
-#define flush_cache_vunmap(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)
__invalidate_icache_all()
+#define flush_icache_range(start, end)
__invalidate_icache_range(start, end)
 
-struct page;
-struct mm_struct;
-struct vm_area_struct;
 
 /* see arch/microblaze/kernel/cache.c */
-extern void __flush_icache_all(void);
-extern void __flush_icache_range(unsigned long start, unsigned long
end);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page
*page);
-extern void __flush_icache_user_range(struct vm_area_struct *vma,
-				struct page *page,
-				unsigned long adr, int len);
-extern void __flush_cache_sigtramp(unsigned long addr);
-
-extern void __flush_dcache_all(void);
-extern void __flush_dcache_range(unsigned long start, unsigned long
end);
-extern void __flush_dcache_page(struct vm_area_struct *vma, struct page
*page);
-extern void __flush_dcache_user_range(struct vm_area_struct *vma,
-				struct page *page,
-				unsigned long adr, int len);
+void __invalidate_icache_all(void);
+void __invalidate_icache_range(unsigned long start, unsigned long end);
+void __invalidate_dcache_all(void);
+void __invalidate_dcache_range(unsigned long start, unsigned long end);
 
-extern inline void __flush_cache_all(void)
-{
-	__flush_icache_all();
-	__flush_dcache_all();
-}
+#define invalidate_cache_all()
__invalidate_icache_all(); __invalidate_dcache_all()
+#define invalidate_dcache()
__invalidate_dcache_all()
+#define invalidate_icache()
__invalidate_icache_all()
+#define invalidate_dcache_range(start, end)
__invalidate_dcache_range(start,end)
+#define invalidate_icache_range(start, end)
__invalidate_icache_range(start,end)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { memcpy(dst, src, len); \
-	flush_icache_user_range(vma, page, vaddr, len); \
+	flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len));
\
 } while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	memcpy((dst), (src), (len))
 
 #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
-- 
1.5.3.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code.
  2008-05-05 22:37 [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code Stephen Neuendorffer
@ 2008-05-05 22:37 ` Stephen Neuendorffer
  2008-05-05 22:57 ` John Williams
  2008-05-06  9:28 ` [PATCH] Microblaze: implement dma-coherent API and refactor cache " Michal Simek
  2 siblings, 0 replies; 9+ messages in thread
From: Stephen Neuendorffer @ 2008-05-05 22:37 UTC (permalink / raw)
  To: arnd, linux-arch, John Linn, john.williams, matthew, will.newton,
	drepper, microblaze-uclinux, grant.likely, Michal Simek,
	linux-kernel

Primarily, this patch implements the dma-coherent API.  In addition,
it cleans up some of the code that deals with caches, in order to
match the usage in dma-coherent.

In particular, the dcache in the microblaze is write through, so the
existing code is more easily thought of as 'invalidation' than
'flushing'.  In addition, some of the flush_* methods were old, and
some shouldn't need to be implemented (since currently no mmu is
supported).

I'd appreciate if someone would ACK my interpretation of
Documentation/cachetlb.txt.  In particular:

flush_cache_mm(mm) (NOOP because nommu)
flush_cache_range(mm, start, end) (Does this need to be implemented
since nommu?)
flush_cache_page(vma, vmaddr) (NOOP because nommu)
flush_dcache_page(page) (NOOP because write through cache.)
flush_dcache_range(start, end) (NOOP because write through cache.)
flush_dcache_mmap_lock(mapping) (NOOP because nommu)
flush_dcache_mmap_unlock(mapping) (NOOP because nommu)

flush_icache_page(vma,pg) (Does this need to be implemented? Doc is
unclear, but I assume it is used as flush_icache_range)
flush_icache_range(start, end) (Must be implemented because icache
doesn't snoop dcache on code loads)

Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
---
 arch/microblaze/kernel/cpu/cache.c  |   37 +---------
 arch/microblaze/kernel/setup.c      |    4 +-
 arch/microblaze/mm/dma-coherent.c   |  122
+++++++++++++++++++++++++++++++++++
 include/asm-microblaze/cacheflush.h |   71 +++++++++------------
 4 files changed, 158 insertions(+), 76 deletions(-)
 create mode 100644 arch/microblaze/mm/dma-coherent.c

diff --git a/arch/microblaze/kernel/cpu/cache.c
b/arch/microblaze/kernel/cpu/cache.c
index d6a1eab..1247b9e 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -129,7 +129,7 @@ void _invalidate_dcache(unsigned int addr)
 				: "r" (addr));
 }
 
-void __flush_icache_all(void)
+void __invalidate_icache_all(void)
 {
 	unsigned int i;
 	unsigned flags;
@@ -149,7 +149,7 @@ void __flush_icache_all(void)
 	}
 }
 
-void __flush_icache_range(unsigned long start, unsigned long end)
+void __invalidate_icache_range(unsigned long start, unsigned long end)
 {
 	unsigned int i;
 	unsigned flags;
@@ -177,24 +177,7 @@ void __flush_icache_range(unsigned long start,
unsigned long end)
 	}
 }
 
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	__flush_icache_all();
-}
-
-void __flush_icache_user_range(struct vm_area_struct *vma,
-				struct page *page, unsigned long adr,
-				int len)
-{
-	__flush_icache_all();
-}
-
-void __flush_cache_sigtramp(unsigned long addr)
-{
-	__flush_icache_range(addr, addr + 8);
-}
-
-void __flush_dcache_all(void)
+void __invalidate_dcache_all(void)
 {
 	unsigned int i;
 	unsigned flags;
@@ -216,7 +199,7 @@ void __flush_dcache_all(void)
 	}
 }
 
-void __flush_dcache_range(unsigned long start, unsigned long end)
+void __invalidate_dcache_range(unsigned long start, unsigned long end)
 {
 	unsigned int i;
 	unsigned flags;
@@ -242,15 +225,3 @@ void __flush_dcache_range(unsigned long start,
unsigned long end)
 		local_irq_restore(flags);
 	}
 }
-
-void __flush_dcache_page(struct vm_area_struct *vma, struct page *page)
-{
-	__flush_dcache_all();
-}
-
-void __flush_dcache_user_range(struct vm_area_struct *vma,
-				struct page *page, unsigned long adr,
-				int len)
-{
-	__flush_dcache_all();
-}
diff --git a/arch/microblaze/kernel/setup.c
b/arch/microblaze/kernel/setup.c
index 43d53d9..241fb21 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -51,10 +51,10 @@ void __init setup_arch(char **cmdline_p)
 	/* irq_early_init(); */
 	setup_cpuinfo();
 
-	__flush_icache_all();
+	__invalidate_icache_all();
 	__enable_icache();
 
-	__flush_dcache_all();
+	__invalidate_icache_all();
 	__enable_dcache();
 
 	panic_timeout = 120;
diff --git a/arch/microblaze/mm/dma-coherent.c
b/arch/microblaze/mm/dma-coherent.c
new file mode 100644
index 0000000..308654f
--- /dev/null
+++ b/arch/microblaze/mm/dma-coherent.c
@@ -0,0 +1,122 @@
+/*
+ *  Microblaze support for cache consistent memory.
+ *
+ *  Copyright (C) 2007 Xilinx, Inc.
+ *
+ *  Based on arch/microblaze/mm/consistent.c
+ *  Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
+ *  Based on arch/avr32/mm/dma-coherent.c
+ *  Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Consistent memory allocators.  Used for DMA devices that want to
+ * share memory with the processor core.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int
direction)
+{
+	switch (direction) {
+	case DMA_FROM_DEVICE:		/* invalidate only */
+		invalidate_dcache_range(vaddr, vaddr + size);
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		flush_dcache_range(vaddr, vaddr + size);
+		break;
+	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
+		invalidate_dcache_range(vaddr, vaddr + size);
+		flush_dcache_range(vaddr, vaddr + size);
+		break;
+	default:
+		BUG();
+	}
+}
+EXPORT_SYMBOL(dma_cache_sync);
+
+static struct page *__dma_alloc(struct device *dev, size_t size,
+				dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page, *free, *end;
+	int order;
+
+	if (in_interrupt())
+		BUG();
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = alloc_pages(gfp, order);
+	if (!page)
+		return NULL;
+
+	split_page(page, order);
+
+	/*
+	 * When accessing physical memory with valid cache data, we
+	 * get a cache hit even if the virtual memory region is marked
+	 * as uncached.
+	 *
+	 * Since the memory is newly allocated, there is no point in
+	 * doing a writeback. If the previous owner cares, he should
+	 * have flushed the cache before releasing the memory.
+	 */
+	invalidate_dcache_range(phys_to_virt(page_to_phys(page)), size);
+
+	*handle = page_to_bus(page);
+	free = page + (size >> PAGE_SHIFT);
+	end = page + (1 << order);
+
+	/*
+	 * Free any unused pages
+	 */
+	while (free < end) {
+		__free_page(free);
+		free++;
+	}
+
+	return page;
+}
+
+static void __dma_free(struct device *dev, size_t size,
+		       struct page *page, dma_addr_t handle)
+{
+	struct page *end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
+
+	while (page < end)
+		__free_page(page++);
+}
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page;
+	void *ret = NULL;
+
+	page = __dma_alloc(dev, size, handle, gfp);
+	if (page) {
+		ret = (void *)page_to_phys(page);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+		       void *cpu_addr, dma_addr_t handle)
+{
+	void *addr;
+	struct page *page;
+
+	pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n",
+		 cpu_addr, (unsigned long)handle, (unsigned)size);
+	BUG_ON(!virt_addr_valid(addr));
+	page = virt_to_page(addr);
+	__dma_free(dev, size, page, handle);
+}
+EXPORT_SYMBOL(dma_free_coherent);
diff --git a/include/asm-microblaze/cacheflush.h
b/include/asm-microblaze/cacheflush.h
index ba7339d..782f01b 100644
--- a/include/asm-microblaze/cacheflush.h
+++ b/include/asm-microblaze/cacheflush.h
@@ -1,6 +1,7 @@
 /*
  * include/asm-microblaze/cacheflush.h
  *
+ * Copyright (C) 2008 Xilinx, Inc.
  * Copyright (C) 2007 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  * based on v850 version which was
@@ -15,58 +16,46 @@
 
 #ifndef _ASM_MICROBLAZE_CACHEFLUSH_H
 #define _ASM_MICROBLAZE_CACHEFLUSH_H
+#include <linux/kernel.h>	/* For min/max macros */
+#include <linux/mm.h>	/* For min/max macros */
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/cache.h>
 
-/* Somebody depends on this; sigh... */
-#include <linux/mm.h>
-
-#define flush_cache_all()			__flush_cache_all()
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	__flush_cache_all()
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
-
-#define flush_dcache_range(start, end)	__flush_dcache_range(start, end)
-#define flush_dcache_page(page)		do { } while (0)
-#define flush_dcache_mmap_lock(mapping)		do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+/*
+ * Cache handling functions.
+ * Microblaze has a write-through data cache, and no icache snooping of
dcache.
+ */
+#define flush_cache_mm(mm)			do { } while(0)
+#define flush_cache_range(mm, start, end)	invalidate_cache_all()
+#define flush_cache_page(vma, vmaddr)		do { } while(0)
 
-#define flush_icache_range(start, len)	__flush_icache_range(start, len)
-#define flush_icache_page(vma, pg)		do { } while (0)
-#define flush_icache_user_range(start, len)	do { } while (0)
+#define flush_dcache_page(page)			do { } while(0)
+#define flush_dcache_range(start, end)		do { } while(0)
+#define flush_dcache_mmap_lock(mapping)		do { } while(0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while(0)
 
-#define flush_cache_vmap(start, end)		do { } while (0)
-#define flush_cache_vunmap(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)
__invalidate_icache_all()
+#define flush_icache_range(start, end)
__invalidate_icache_range(start, end)
 
-struct page;
-struct mm_struct;
-struct vm_area_struct;
 
 /* see arch/microblaze/kernel/cache.c */
-extern void __flush_icache_all(void);
-extern void __flush_icache_range(unsigned long start, unsigned long
end);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page
*page);
-extern void __flush_icache_user_range(struct vm_area_struct *vma,
-				struct page *page,
-				unsigned long adr, int len);
-extern void __flush_cache_sigtramp(unsigned long addr);
-
-extern void __flush_dcache_all(void);
-extern void __flush_dcache_range(unsigned long start, unsigned long
end);
-extern void __flush_dcache_page(struct vm_area_struct *vma, struct page
*page);
-extern void __flush_dcache_user_range(struct vm_area_struct *vma,
-				struct page *page,
-				unsigned long adr, int len);
+void __invalidate_icache_all(void);
+void __invalidate_icache_range(unsigned long start, unsigned long end);
+void __invalidate_dcache_all(void);
+void __invalidate_dcache_range(unsigned long start, unsigned long end);
 
-extern inline void __flush_cache_all(void)
-{
-	__flush_icache_all();
-	__flush_dcache_all();
-}
+#define invalidate_cache_all()
__invalidate_icache_all(); __invalidate_dcache_all()
+#define invalidate_dcache()
__invalidate_dcache_all()
+#define invalidate_icache()
__invalidate_icache_all()
+#define invalidate_dcache_range(start, end)
__invalidate_dcache_range(start,end)
+#define invalidate_icache_range(start, end)
__invalidate_icache_range(start,end)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { memcpy(dst, src, len); \
-	flush_icache_user_range(vma, page, vaddr, len); \
+	flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len));
\
 } while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	memcpy((dst), (src), (len))
 
 #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
-- 
1.5.3.4



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code.
  2008-05-05 22:37 [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code Stephen Neuendorffer
  2008-05-05 22:37 ` Stephen Neuendorffer
@ 2008-05-05 22:57 ` John Williams
  2008-05-05 23:12   ` [PATCH] Microblaze: implement dma-coherent API and refactorcache " Stephen Neuendorffer
  2008-05-06  9:28 ` [PATCH] Microblaze: implement dma-coherent API and refactor cache " Michal Simek
  2 siblings, 1 reply; 9+ messages in thread
From: John Williams @ 2008-05-05 22:57 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: arnd, linux-arch, John Linn, matthew, will.newton, drepper,
	microblaze-uclinux, grant.likely, Michal Simek, linux-kernel

Hi Steve,

On Mon, 2008-05-05 at 15:37 -0700, Stephen Neuendorffer wrote:

> In particular, the dcache in the microblaze is write through, so the
> existing code is more easily thought of as 'invalidation' than
> 'flushing'.  In addition, some of the flush_* methods were old, and
> some shouldn't need to be implemented (since currently no mmu is
> supported).

I agree - this renaming is a long time coming.

[snip]

Does the DMA API insist upon the dma_cache_sync call to guarantee
sensible results?  If so, your implementation looks fine.  If not, then
the results will clearly be bogus as there's nothing magical about the
memory being allocated in dma_alloc.

To that end, can it just call kmalloc(), and similarly kfree() for
dma_free?

I'd still like to see the uncached shadow stuff make a return one day,
it is an effective way of solving the problem, we'll just need to find a
cleaner way to implement it.  A linear walk through the cache to
invalidate is so slow, it destroys any benefit gained from DMA in the
first place.

Cheers,

John

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH] Microblaze: implement dma-coherent API and refactorcache flush code.
  2008-05-05 22:57 ` John Williams
@ 2008-05-05 23:12   ` Stephen Neuendorffer
  2008-05-06  0:14     ` John Williams
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Neuendorffer @ 2008-05-05 23:12 UTC (permalink / raw)
  To: John Williams
  Cc: arnd, linux-arch, John Linn, matthew, will.newton, drepper,
	microblaze-uclinux, grant.likely, Michal Simek, linux-kernel



> -----Original Message-----
> From: John Williams [mailto:john.williams@petalogix.com]
> Sent: Monday, May 05, 2008 3:57 PM
> To: Stephen Neuendorffer
> Cc: arnd@arndb.de; linux-arch@vger.kernel.org; John Linn;
matthew@wil.cx; will.newton@gmail.com;
> drepper@redhat.com; microblaze-uclinux@itee.uq.edu.au;
grant.likely@secretlab.ca; Michal Simek;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] Microblaze: implement dma-coherent API and
refactorcache flush code.
> 
> Hi Steve,
> 
> On Mon, 2008-05-05 at 15:37 -0700, Stephen Neuendorffer wrote:
> 
> > In particular, the dcache in the microblaze is write through, so the
> > existing code is more easily thought of as 'invalidation' than
> > 'flushing'.  In addition, some of the flush_* methods were old, and
> > some shouldn't need to be implemented (since currently no mmu is
> > supported).
> 
> I agree - this renaming is a long time coming.
> 
> [snip]
> 
> Does the DMA API insist upon the dma_cache_sync call to guarantee
> sensible results?  If so, your implementation looks fine.  If not,
then
> the results will clearly be bogus as there's nothing magical about the
> memory being allocated in dma_alloc.

Yes, in fact this is one of the keys to getting the lltemac driver to
work right.  see Documentation/DMA-API.txt

> To that end, can it just call kmalloc(), and similarly kfree() for
> dma_free?

My understanding is that on other architectures (x86, for instance)
'dma' memory ensures other things, like it's accessible in PCI memory
space.  On microblaze, there's nothing really special about dma memory,
but you get the API as a chunk.
 
> I'd still like to see the uncached shadow stuff make a return one day,
> it is an effective way of solving the problem, we'll just need to find
a
> cleaner way to implement it.  A linear walk through the cache to
> invalidate is so slow, it destroys any benefit gained from DMA in the
> first place.

I think it's definitely a simple way of solving the problem (in fact,
the version of the code that's currently at git.xilinx.com includes it).
Would it be better dealt with at the page level, rather than at the
address level, then one of the architecture-reserved flags could be used
for it?
If it really does have value, then I want to make sure it goes in, along
with bits in EDK that make it straightforward to use.  For me, the
biggest barrier to using it is understanding exactly what assumptions it
is making on the hardware, and making those assumptions bulletproof.

Steve

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH] Microblaze: implement dma-coherent API and refactorcache flush code.
  2008-05-05 23:12   ` [PATCH] Microblaze: implement dma-coherent API and refactorcache " Stephen Neuendorffer
@ 2008-05-06  0:14     ` John Williams
  2008-05-06  0:31       ` [PATCH] Microblaze: implement dma-coherent API andrefactorcache " Stephen Neuendorffer
  0 siblings, 1 reply; 9+ messages in thread
From: John Williams @ 2008-05-06  0:14 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: arnd, linux-arch, John Linn, matthew, will.newton, drepper,
	microblaze-uclinux, grant.likely, Michal Simek, linux-kernel


> > Does the DMA API insist upon the dma_cache_sync call to guarantee
> > sensible results?  If so, your implementation looks fine.  If not,
> then
> > the results will clearly be bogus as there's nothing magical about the
> > memory being allocated in dma_alloc.
> 
> Yes, in fact this is one of the keys to getting the lltemac driver to
> work right.  see Documentation/DMA-API.txt
> 
> > To that end, can it just call kmalloc(), and similarly kfree() for
> > dma_free?
> 
> My understanding is that on other architectures (x86, for instance)
> 'dma' memory ensures other things, like it's accessible in PCI memory
> space.  On microblaze, there's nothing really special about dma memory,
> but you get the API as a chunk.

Sure - what I meant is can dma_alloc just call kmalloc to do it's work?
 
> > I'd still like to see the uncached shadow stuff make a return one day,
> > it is an effective way of solving the problem, we'll just need to find
> a
> > cleaner way to implement it.  A linear walk through the cache to
> > invalidate is so slow, it destroys any benefit gained from DMA in the
> > first place.
> 
> I think it's definitely a simple way of solving the problem (in fact,
> the version of the code that's currently at git.xilinx.com includes it).
> Would it be better dealt with at the page level, rather than at the
> address level, then one of the architecture-reserved flags could be used
> for it?
> If it really does have value, then I want to make sure it goes in, along
> with bits in EDK that make it straightforward to use.  For me, the
> biggest barrier to using it is understanding exactly what assumptions it
> is making on the hardware, and making those assumptions bulletproof.

I agree.  Michal did some work on that when he did the initial DTS stuff
with us over the (southern) summer this year.  We looked at ways to
validate the HW design and Kconfig params to make sure that
uncached_shadow worked as expected.

If forget now the outcome, there's plenty of ways to get it wrong.

It would be easy at runtime to do some validation tests - write to a
pointer, cache flush (noop..), read back from the twiddled pointer, make
sure it matches.  Repeat a few times until you're happy it wasn't a
fluke, that sort of thing.

John

> 
> Steve
> 
> 
-- 
John Williams, PhD, B.Eng, B.IT
PetaLogix - Linux Solutions for a Reconfigurable World
w: www.petalogix.com  p: +61-7-30090663  f: +61-7-30090663

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH] Microblaze: implement dma-coherent API andrefactorcache flush code.
  2008-05-06  0:14     ` John Williams
@ 2008-05-06  0:31       ` Stephen Neuendorffer
  2008-05-06  7:23         ` Geert Uytterhoeven
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Neuendorffer @ 2008-05-06  0:31 UTC (permalink / raw)
  To: John Williams
  Cc: arnd, linux-arch, John Linn, matthew, will.newton, drepper,
	microblaze-uclinux, grant.likely, Michal Simek, linux-kernel



> -----Original Message-----
> From: John Williams [mailto:john.williams@petalogix.com]
> Sent: Monday, May 05, 2008 5:15 PM
> To: Stephen Neuendorffer
> Cc: arnd@arndb.de; linux-arch@vger.kernel.org; John Linn;
matthew@wil.cx; will.newton@gmail.com;
> drepper@redhat.com; microblaze-uclinux@itee.uq.edu.au;
grant.likely@secretlab.ca; Michal Simek;
> linux-kernel@vger.kernel.org
> Subject: RE: [PATCH] Microblaze: implement dma-coherent API
andrefactorcache flush code.
> 
> 
> > > Does the DMA API insist upon the dma_cache_sync call to guarantee
> > > sensible results?  If so, your implementation looks fine.  If not,
> > then
> > > the results will clearly be bogus as there's nothing magical about
the
> > > memory being allocated in dma_alloc.
> >
> > Yes, in fact this is one of the keys to getting the lltemac driver
to
> > work right.  see Documentation/DMA-API.txt
> >
> > > To that end, can it just call kmalloc(), and similarly kfree() for
> > > dma_free?
> >
> > My understanding is that on other architectures (x86, for instance)
> > 'dma' memory ensures other things, like it's accessible in PCI
memory
> > space.  On microblaze, there's nothing really special about dma
memory,
> > but you get the API as a chunk.
> 
> Sure - what I meant is can dma_alloc just call kmalloc to do it's
work?

I scanned through Linux Device Drivers, and it appears that calling
get_free_pages is:
1) more efficient than kmalloc for large allocations
2) allocates physically contiguous memory, which kmalloc doesn't
necessarily do if there's an mmu.

Steve

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH] Microblaze: implement dma-coherent API andrefactorcache flush code.
  2008-05-06  0:31       ` [PATCH] Microblaze: implement dma-coherent API andrefactorcache " Stephen Neuendorffer
@ 2008-05-06  7:23         ` Geert Uytterhoeven
  2008-05-06  9:33           ` Michal Simek
  0 siblings, 1 reply; 9+ messages in thread
From: Geert Uytterhoeven @ 2008-05-06  7:23 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: John Williams, arnd, linux-arch, John Linn, matthew, will.newton,
	drepper, microblaze-uclinux, grant.likely, Michal Simek,
	linux-kernel

On Mon, 5 May 2008, Stephen Neuendorffer wrote:
> > -----Original Message-----
> > From: John Williams [mailto:john.williams@petalogix.com]
> > 
> > Sure - what I meant is can dma_alloc just call kmalloc to do it's
> work?
> 
> I scanned through Linux Device Drivers, and it appears that calling
> get_free_pages is:
> 1) more efficient than kmalloc for large allocations
> 2) allocates physically contiguous memory, which kmalloc doesn't
> necessarily do if there's an mmu.

kmalloc() allocates physically contiguous memory, vmalloc() doesn't.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code.
  2008-05-05 22:37 [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code Stephen Neuendorffer
  2008-05-05 22:37 ` Stephen Neuendorffer
  2008-05-05 22:57 ` John Williams
@ 2008-05-06  9:28 ` Michal Simek
  2 siblings, 0 replies; 9+ messages in thread
From: Michal Simek @ 2008-05-06  9:28 UTC (permalink / raw)
  To: Stephen Neuendorffer
  Cc: arnd, linux-arch, John Linn, john.williams, matthew, will.newton,
	drepper, microblaze-uclinux, grant.likely, linux-kernel

Hi Steve,

>  arch/microblaze/kernel/cpu/cache.c  |   37 +---------
>  arch/microblaze/kernel/setup.c      |    4 +-
>  arch/microblaze/mm/dma-coherent.c   |  122

dma-coherent.c is dead for now.

> diff --git a/arch/microblaze/kernel/setup.c
> b/arch/microblaze/kernel/setup.c
> index 43d53d9..241fb21 100644
> --- a/arch/microblaze/kernel/setup.c
> +++ b/arch/microblaze/kernel/setup.c
> @@ -51,10 +51,10 @@ void __init setup_arch(char **cmdline_p)
>  	/* irq_early_init(); */
>  	setup_cpuinfo();
>  
> -	__flush_icache_all();
> +	__invalidate_icache_all();
>  	__enable_icache();
>  
> -	__flush_dcache_all();
> +	__invalidate_icache_all();
>  	__enable_dcache();

here is bug.

>  	panic_timeout = 120;
> diff --git a/arch/microblaze/mm/dma-coherent.c
> b/arch/microblaze/mm/dma-coherent.c

removed.

M

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Microblaze: implement dma-coherent API andrefactorcache flush code.
  2008-05-06  7:23         ` Geert Uytterhoeven
@ 2008-05-06  9:33           ` Michal Simek
  0 siblings, 0 replies; 9+ messages in thread
From: Michal Simek @ 2008-05-06  9:33 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Stephen Neuendorffer, John Williams, arnd, linux-arch, John Linn,
	matthew, will.newton, drepper, microblaze-uclinux, grant.likely,
	linux-kernel

Hi John, Steve and others,

I'll only rename flush to invalidate. Thant's all for now.

Michal

> On Mon, 5 May 2008, Stephen Neuendorffer wrote:
>>> -----Original Message-----
>>> From: John Williams [mailto:john.williams@petalogix.com]
>>>
>>> Sure - what I meant is can dma_alloc just call kmalloc to do it's
>> work?
>>
>> I scanned through Linux Device Drivers, and it appears that calling
>> get_free_pages is:
>> 1) more efficient than kmalloc for large allocations
>> 2) allocates physically contiguous memory, which kmalloc doesn't
>> necessarily do if there's an mmu.
> 
> kmalloc() allocates physically contiguous memory, vmalloc() doesn't.
> 
> Gr{oetje,eeting}s,
> 
> 						Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> 							    -- Linus Torvalds
> 
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-05-06  9:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-05 22:37 [PATCH] Microblaze: implement dma-coherent API and refactor cache flush code Stephen Neuendorffer
2008-05-05 22:37 ` Stephen Neuendorffer
2008-05-05 22:57 ` John Williams
2008-05-05 23:12   ` [PATCH] Microblaze: implement dma-coherent API and refactorcache " Stephen Neuendorffer
2008-05-06  0:14     ` John Williams
2008-05-06  0:31       ` [PATCH] Microblaze: implement dma-coherent API andrefactorcache " Stephen Neuendorffer
2008-05-06  7:23         ` Geert Uytterhoeven
2008-05-06  9:33           ` Michal Simek
2008-05-06  9:28 ` [PATCH] Microblaze: implement dma-coherent API and refactor cache " Michal Simek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox