All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors
@ 2010-09-08 23:02 ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: dediao, dvomlehn, sshtylyov, linux-mips, linux-kernel

[v2: Formatting changes only.]

The MIPS DMA coherency functions do not work properly (i.e. kernel oops)
when HIGHMEM pages are passed in as arguments.  This patch uses the PPC
approach of calling kmap_atomic() with IRQs disabled to temporarily map
high pages, in order to flush them out to memory.

Signed-off-by: Dezhong Diao <dediao@cisco.com>
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 arch/mips/mm/dma-default.c |  159 ++++++++++++++++++++++----------------------
 1 files changed, 80 insertions(+), 79 deletions(-)

diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 469d401..79dfb9c 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -15,18 +15,18 @@
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 
 #include <asm/cache.h>
 #include <asm/io.h>
 
 #include <dma-coherence.h>
 
-static inline unsigned long dma_addr_to_virt(struct device *dev,
+static inline struct page *dma_addr_to_page(struct device *dev,
 	dma_addr_t dma_addr)
 {
-	unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
-
-	return (unsigned long)phys_to_virt(addr);
+	return pfn_to_page(
+		plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
 }
 
 /*
@@ -153,20 +153,20 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 
 EXPORT_SYMBOL(dma_free_coherent);
 
-static inline void __dma_sync(unsigned long addr, size_t size,
+static inline void __dma_sync_virtual(void *addr, size_t size,
 	enum dma_data_direction direction)
 {
 	switch (direction) {
 	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
+		dma_cache_wback((unsigned long)addr, size);
 		break;
 
 	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
+		dma_cache_inv((unsigned long)addr, size);
 		break;
 
 	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
+		dma_cache_wback_inv((unsigned long)addr, size);
 		break;
 
 	default:
@@ -174,13 +174,53 @@ static inline void __dma_sync(unsigned long addr, size_t size,
 	}
 }
 
+/*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+static inline void __dma_sync(struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	size_t left = size;
+
+	BUG_ON(direction == DMA_NONE);
+
+	do {
+		size_t len = left;
+
+		if (PageHighMem(page)) {
+			unsigned long flags;
+			void *addr;
+
+			if (offset + len > PAGE_SIZE) {
+				if (offset >= PAGE_SIZE) {
+					page += offset >> PAGE_SHIFT;
+					offset &= ~PAGE_MASK;
+				}
+				len = PAGE_SIZE - offset;
+			}
+
+			local_irq_save(flags);
+			addr = kmap_atomic(page, KM_SYNC_DCACHE);
+			__dma_sync_virtual(addr + offset, len, direction);
+			kunmap_atomic(addr, KM_SYNC_DCACHE);
+			local_irq_restore(flags);
+		} else
+			__dma_sync_virtual(page_address(page) + offset,
+				size, direction);
+		offset = 0;
+		page++;
+		left -= len;
+	} while (left);
+}
+
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 	enum dma_data_direction direction)
 {
-	unsigned long addr = (unsigned long) ptr;
-
 	if (!plat_device_is_coherent(dev))
-		__dma_sync(addr, size, direction);
+		__dma_sync_virtual(ptr, size, direction);
 
 	return plat_map_dma_mem(dev, ptr, size);
 }
@@ -191,8 +231,8 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 	enum dma_data_direction direction)
 {
 	if (cpu_is_noncoherent_r10000(dev))
-		__dma_sync(dma_addr_to_virt(dev, dma_addr), size,
-		           direction);
+		__dma_sync(dma_addr_to_page(dev, dma_addr),
+			   dma_addr & ~PAGE_MASK, size, direction);
 
 	plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
@@ -204,16 +244,12 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
-
-		addr = (unsigned long) sg_virt(sg);
-		if (!plat_device_is_coherent(dev) && addr)
-			__dma_sync(addr, sg->length, direction);
-		sg->dma_address = plat_map_dma_mem(dev,
-				                   (void *)addr, sg->length);
+		if (!plat_device_is_coherent(dev))
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
+		sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
+				  sg->offset;
 	}
 
 	return nents;
@@ -224,14 +260,8 @@ EXPORT_SYMBOL(dma_map_sg);
 dma_addr_t dma_map_page(struct device *dev, struct page *page,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = (unsigned long) page_address(page) + offset;
-		__dma_sync(addr, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(page, offset, size, direction);
 
 	return plat_map_dma_mem_page(dev, page) + offset;
 }
@@ -241,18 +271,13 @@ EXPORT_SYMBOL(dma_map_page);
 void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	enum dma_data_direction direction)
 {
-	unsigned long addr;
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nhwentries; i++, sg++) {
 		if (!plat_device_is_coherent(dev) &&
-		    direction != DMA_TO_DEVICE) {
-			addr = (unsigned long) sg_virt(sg);
-			if (addr)
-				__dma_sync(addr, sg->length, direction);
-		}
+		    direction != DMA_TO_DEVICE)
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 		plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
 	}
 }
@@ -262,14 +287,9 @@ EXPORT_SYMBOL(dma_unmap_sg);
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_for_cpu);
@@ -277,15 +297,10 @@ EXPORT_SYMBOL(dma_sync_single_for_cpu);
 void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_for_device);
@@ -293,14 +308,9 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
 void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
+			   direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
@@ -308,15 +318,10 @@ EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
 void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
+			   direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_range_for_device);
@@ -326,13 +331,11 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (cpu_is_noncoherent_r10000(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -343,13 +346,11 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (!plat_device_is_coherent(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -376,7 +377,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 
 	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
-		__dma_sync((unsigned long)vaddr, size, direction);
+		__dma_sync_virtual(vaddr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_cache_sync);
-- 
1.7.0.4


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

* [PATCH v2 1/3] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors
@ 2010-09-08 23:02 ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: dediao, dvomlehn, sshtylyov, linux-mips, linux-kernel

[v2: Formatting changes only.]

The MIPS DMA coherency functions do not work properly (i.e. kernel oops)
when HIGHMEM pages are passed in as arguments.  This patch uses the PPC
approach of calling kmap_atomic() with IRQs disabled to temporarily map
high pages, in order to flush them out to memory.

Signed-off-by: Dezhong Diao <dediao@cisco.com>
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 arch/mips/mm/dma-default.c |  159 ++++++++++++++++++++++----------------------
 1 files changed, 80 insertions(+), 79 deletions(-)

diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 469d401..79dfb9c 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -15,18 +15,18 @@
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 
 #include <asm/cache.h>
 #include <asm/io.h>
 
 #include <dma-coherence.h>
 
-static inline unsigned long dma_addr_to_virt(struct device *dev,
+static inline struct page *dma_addr_to_page(struct device *dev,
 	dma_addr_t dma_addr)
 {
-	unsigned long addr = plat_dma_addr_to_phys(dev, dma_addr);
-
-	return (unsigned long)phys_to_virt(addr);
+	return pfn_to_page(
+		plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
 }
 
 /*
@@ -153,20 +153,20 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 
 EXPORT_SYMBOL(dma_free_coherent);
 
-static inline void __dma_sync(unsigned long addr, size_t size,
+static inline void __dma_sync_virtual(void *addr, size_t size,
 	enum dma_data_direction direction)
 {
 	switch (direction) {
 	case DMA_TO_DEVICE:
-		dma_cache_wback(addr, size);
+		dma_cache_wback((unsigned long)addr, size);
 		break;
 
 	case DMA_FROM_DEVICE:
-		dma_cache_inv(addr, size);
+		dma_cache_inv((unsigned long)addr, size);
 		break;
 
 	case DMA_BIDIRECTIONAL:
-		dma_cache_wback_inv(addr, size);
+		dma_cache_wback_inv((unsigned long)addr, size);
 		break;
 
 	default:
@@ -174,13 +174,53 @@ static inline void __dma_sync(unsigned long addr, size_t size,
 	}
 }
 
+/*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+static inline void __dma_sync(struct page *page,
+	unsigned long offset, size_t size, enum dma_data_direction direction)
+{
+	size_t left = size;
+
+	BUG_ON(direction == DMA_NONE);
+
+	do {
+		size_t len = left;
+
+		if (PageHighMem(page)) {
+			unsigned long flags;
+			void *addr;
+
+			if (offset + len > PAGE_SIZE) {
+				if (offset >= PAGE_SIZE) {
+					page += offset >> PAGE_SHIFT;
+					offset &= ~PAGE_MASK;
+				}
+				len = PAGE_SIZE - offset;
+			}
+
+			local_irq_save(flags);
+			addr = kmap_atomic(page, KM_SYNC_DCACHE);
+			__dma_sync_virtual(addr + offset, len, direction);
+			kunmap_atomic(addr, KM_SYNC_DCACHE);
+			local_irq_restore(flags);
+		} else
+			__dma_sync_virtual(page_address(page) + offset,
+				size, direction);
+		offset = 0;
+		page++;
+		left -= len;
+	} while (left);
+}
+
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 	enum dma_data_direction direction)
 {
-	unsigned long addr = (unsigned long) ptr;
-
 	if (!plat_device_is_coherent(dev))
-		__dma_sync(addr, size, direction);
+		__dma_sync_virtual(ptr, size, direction);
 
 	return plat_map_dma_mem(dev, ptr, size);
 }
@@ -191,8 +231,8 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 	enum dma_data_direction direction)
 {
 	if (cpu_is_noncoherent_r10000(dev))
-		__dma_sync(dma_addr_to_virt(dev, dma_addr), size,
-		           direction);
+		__dma_sync(dma_addr_to_page(dev, dma_addr),
+			   dma_addr & ~PAGE_MASK, size, direction);
 
 	plat_unmap_dma_mem(dev, dma_addr, size, direction);
 }
@@ -204,16 +244,12 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nents; i++, sg++) {
-		unsigned long addr;
-
-		addr = (unsigned long) sg_virt(sg);
-		if (!plat_device_is_coherent(dev) && addr)
-			__dma_sync(addr, sg->length, direction);
-		sg->dma_address = plat_map_dma_mem(dev,
-				                   (void *)addr, sg->length);
+		if (!plat_device_is_coherent(dev))
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
+		sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
+				  sg->offset;
 	}
 
 	return nents;
@@ -224,14 +260,8 @@ EXPORT_SYMBOL(dma_map_sg);
 dma_addr_t dma_map_page(struct device *dev, struct page *page,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = (unsigned long) page_address(page) + offset;
-		__dma_sync(addr, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(page, offset, size, direction);
 
 	return plat_map_dma_mem_page(dev, page) + offset;
 }
@@ -241,18 +271,13 @@ EXPORT_SYMBOL(dma_map_page);
 void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	enum dma_data_direction direction)
 {
-	unsigned long addr;
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nhwentries; i++, sg++) {
 		if (!plat_device_is_coherent(dev) &&
-		    direction != DMA_TO_DEVICE) {
-			addr = (unsigned long) sg_virt(sg);
-			if (addr)
-				__dma_sync(addr, sg->length, direction);
-		}
+		    direction != DMA_TO_DEVICE)
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 		plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
 	}
 }
@@ -262,14 +287,9 @@ EXPORT_SYMBOL(dma_unmap_sg);
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_for_cpu);
@@ -277,15 +297,10 @@ EXPORT_SYMBOL(dma_sync_single_for_cpu);
 void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle),
+			   dma_handle & ~PAGE_MASK, size, direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_for_device);
@@ -293,14 +308,9 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
 void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	if (cpu_is_noncoherent_r10000(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
+	if (cpu_is_noncoherent_r10000(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
+			   direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
@@ -308,15 +318,10 @@ EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
 void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-
 	plat_extra_sync_for_device(dev);
-	if (!plat_device_is_coherent(dev)) {
-		unsigned long addr;
-
-		addr = dma_addr_to_virt(dev, dma_handle);
-		__dma_sync(addr + offset, size, direction);
-	}
+	if (!plat_device_is_coherent(dev))
+		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
+			   direction);
 }
 
 EXPORT_SYMBOL(dma_sync_single_range_for_device);
@@ -326,13 +331,11 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (cpu_is_noncoherent_r10000(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -343,13 +346,11 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
 		if (!plat_device_is_coherent(dev))
-			__dma_sync((unsigned long)page_address(sg_page(sg)),
-			           sg->length, direction);
+			__dma_sync(sg_page(sg), sg->offset, sg->length,
+				   direction);
 	}
 }
 
@@ -376,7 +377,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 
 	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
-		__dma_sync((unsigned long)vaddr, size, direction);
+		__dma_sync_virtual(vaddr, size, direction);
 }
 
 EXPORT_SYMBOL(dma_cache_sync);
-- 
1.7.0.4

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

* [PATCH 2/3] MIPS: Allow UserLocal on MIPS_R1 processors
@ 2010-09-08 23:02   ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel

Some MIPS32R1 processors implement UserLocal (RDHWR $29) to accelerate
programs that make extensive use of thread-local storage.  Therefore,
setting up the HWRENA register should not depend on cpu_has_mips_r2.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 arch/mips/kernel/traps.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 03ec001..ec6cbd2 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1469,6 +1469,7 @@ void __cpuinit per_cpu_trap_init(void)
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned int status_set = ST0_CU0;
+	unsigned int hwrena = cpu_hwrena_impl_bits;
 #ifdef CONFIG_MIPS_MT_SMTC
 	int secondaryTC = 0;
 	int bootTC = (cpu == 0);
@@ -1501,14 +1502,14 @@ void __cpuinit per_cpu_trap_init(void)
 	change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 			 status_set);
 
-	if (cpu_has_mips_r2) {
-		unsigned int enable = 0x0000000f | cpu_hwrena_impl_bits;
+	if (cpu_has_mips_r2)
+		hwrena |= 0x0000000f;
 
-		if (!noulri && cpu_has_userlocal)
-			enable |= (1 << 29);
+	if (!noulri && cpu_has_userlocal)
+		hwrena |= (1 << 29);
 
-		write_c0_hwrena(enable);
-	}
+	if (hwrena)
+		write_c0_hwrena(hwrena);
 
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (!secondaryTC) {
-- 
1.7.0.4


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

* [PATCH 2/3] MIPS: Allow UserLocal on MIPS_R1 processors
@ 2010-09-08 23:02   ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel

Some MIPS32R1 processors implement UserLocal (RDHWR $29) to accelerate
programs that make extensive use of thread-local storage.  Therefore,
setting up the HWRENA register should not depend on cpu_has_mips_r2.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 arch/mips/kernel/traps.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 03ec001..ec6cbd2 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1469,6 +1469,7 @@ void __cpuinit per_cpu_trap_init(void)
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned int status_set = ST0_CU0;
+	unsigned int hwrena = cpu_hwrena_impl_bits;
 #ifdef CONFIG_MIPS_MT_SMTC
 	int secondaryTC = 0;
 	int bootTC = (cpu == 0);
@@ -1501,14 +1502,14 @@ void __cpuinit per_cpu_trap_init(void)
 	change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 			 status_set);
 
-	if (cpu_has_mips_r2) {
-		unsigned int enable = 0x0000000f | cpu_hwrena_impl_bits;
+	if (cpu_has_mips_r2)
+		hwrena |= 0x0000000f;
 
-		if (!noulri && cpu_has_userlocal)
-			enable |= (1 << 29);
+	if (!noulri && cpu_has_userlocal)
+		hwrena |= (1 << 29);
 
-		write_c0_hwrena(enable);
-	}
+	if (hwrena)
+		write_c0_hwrena(hwrena);
 
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (!secondaryTC) {
-- 
1.7.0.4

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

* [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
@ 2010-09-08 23:02   ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel

On noncoherent processors with a readahead cache, an extra platform-
specific invalidation is required during the dma_sync_*_for_cpu()
operations to keep drivers from seeing stale prefetched data.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 .../include/asm/mach-cavium-octeon/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-generic/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-ip27/dma-coherence.h    |   13 +++++++++++++
 arch/mips/include/asm/mach-ip32/dma-coherence.h    |   13 +++++++++++++
 arch/mips/include/asm/mach-jazz/dma-coherence.h    |   13 +++++++++++++
 .../mips/include/asm/mach-loongson/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-powertv/dma-coherence.h |   13 +++++++++++++
 arch/mips/mm/dma-default.c                         |    3 +++
 8 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 17d5794..8192683 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	mb();
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 1;
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 8da9807..20728eb 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index d3d0401..b1cb862 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -62,6 +62,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 3785595..c870003 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -84,6 +84,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index f93aee5..dd7b8e3 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 981c75f..7565bbc 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -58,6 +58,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
index f76029c..1134961 100644
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -105,6 +105,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 79dfb9c..ed1baaf 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -287,6 +287,7 @@ EXPORT_SYMBOL(dma_unmap_sg);
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
+	plat_extra_sync_for_cpu(dev, dma_handle, 0, size, direction);
 	if (cpu_is_noncoherent_r10000(dev))
 		__dma_sync(dma_addr_to_page(dev, dma_handle),
 			   dma_handle & ~PAGE_MASK, size, direction);
@@ -308,6 +309,7 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
 void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
+	plat_extra_sync_for_cpu(dev, dma_handle, offset, size, direction);
 	if (cpu_is_noncoherent_r10000(dev))
 		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
 			   direction);
@@ -333,6 +335,7 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
+		plat_extra_sync_for_cpu_sg(dev, sg, direction);
 		if (cpu_is_noncoherent_r10000(dev))
 			__dma_sync(sg_page(sg), sg->offset, sg->length,
 				   direction);
-- 
1.7.0.4


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

* [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
@ 2010-09-08 23:02   ` Kevin Cernekee
  0 siblings, 0 replies; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-08 23:02 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips, linux-kernel

On noncoherent processors with a readahead cache, an extra platform-
specific invalidation is required during the dma_sync_*_for_cpu()
operations to keep drivers from seeing stale prefetched data.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 .../include/asm/mach-cavium-octeon/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-generic/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-ip27/dma-coherence.h    |   13 +++++++++++++
 arch/mips/include/asm/mach-ip32/dma-coherence.h    |   13 +++++++++++++
 arch/mips/include/asm/mach-jazz/dma-coherence.h    |   13 +++++++++++++
 .../mips/include/asm/mach-loongson/dma-coherence.h |   13 +++++++++++++
 arch/mips/include/asm/mach-powertv/dma-coherence.h |   13 +++++++++++++
 arch/mips/mm/dma-default.c                         |    3 +++
 8 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 17d5794..8192683 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	mb();
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 1;
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 8da9807..20728eb 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index d3d0401..b1cb862 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -62,6 +62,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 3785595..c870003 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -84,6 +84,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index f93aee5..dd7b8e3 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 981c75f..7565bbc 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -58,6 +58,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
index f76029c..1134961 100644
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -105,6 +105,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
 	return;
 }
 
+static inline void plat_extra_sync_for_cpu(struct device *dev,
+	dma_addr_t dma_handle, unsigned long offset, size_t size,
+	enum dma_data_direction direction)
+{
+	return;
+}
+
+static inline void plat_extra_sync_for_cpu_sg(struct device *dev,
+	struct scatterlist *sg, enum dma_data_direction direction)
+{
+	return;
+}
+
 static inline int plat_dma_mapping_error(struct device *dev,
 					 dma_addr_t dma_addr)
 {
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 79dfb9c..ed1baaf 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -287,6 +287,7 @@ EXPORT_SYMBOL(dma_unmap_sg);
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	size_t size, enum dma_data_direction direction)
 {
+	plat_extra_sync_for_cpu(dev, dma_handle, 0, size, direction);
 	if (cpu_is_noncoherent_r10000(dev))
 		__dma_sync(dma_addr_to_page(dev, dma_handle),
 			   dma_handle & ~PAGE_MASK, size, direction);
@@ -308,6 +309,7 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
 void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
 	unsigned long offset, size_t size, enum dma_data_direction direction)
 {
+	plat_extra_sync_for_cpu(dev, dma_handle, offset, size, direction);
 	if (cpu_is_noncoherent_r10000(dev))
 		__dma_sync(dma_addr_to_page(dev, dma_handle), offset, size,
 			   direction);
@@ -333,6 +335,7 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
 
 	/* Make sure that gcc doesn't leave the empty loop body.  */
 	for (i = 0; i < nelems; i++, sg++) {
+		plat_extra_sync_for_cpu_sg(dev, sg, direction);
 		if (cpu_is_noncoherent_r10000(dev))
 			__dma_sync(sg_page(sg), sg->offset, sg->length,
 				   direction);
-- 
1.7.0.4

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-08 23:02   ` Kevin Cernekee
  (?)
@ 2010-09-09  9:34   ` Sergei Shtylyov
  2010-09-09 12:39     ` Kevin Cernekee
  -1 siblings, 1 reply; 14+ messages in thread
From: Sergei Shtylyov @ 2010-09-09  9:34 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: Ralf Baechle, linux-mips, linux-kernel

Hello.

On 09-09-2010 3:02, Kevin Cernekee wrote:

> On noncoherent processors with a readahead cache, an extra platform-
> specific invalidation is required during the dma_sync_*_for_cpu()
> operations to keep drivers from seeing stale prefetched data.

> Signed-off-by: Kevin Cernekee<cernekee@gmail.com>
[...]
> diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
> index 17d5794..8192683 100644
> --- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
> @@ -52,6 +52,19 @@ static inline void plat_extra_sync_for_device(struct device *dev)
>   	mb();
>   }
>
> +static inline void plat_extra_sync_for_cpu(struct device *dev,
> +	dma_addr_t dma_handle, unsigned long offset, size_t size,
> +	enum dma_data_direction direction)
> +{
> +	return;

    Why not just empty function bodies?

WBR, Sergei

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

* Re: [PATCH 2/3] MIPS: Allow UserLocal on MIPS_R1 processors
  2010-09-08 23:02   ` Kevin Cernekee
  (?)
@ 2010-09-09  9:53   ` Ralf Baechle
  -1 siblings, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2010-09-09  9:53 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: linux-mips, linux-kernel

On Wed, Sep 08, 2010 at 04:02:14PM -0700, Kevin Cernekee wrote:

> Some MIPS32R1 processors implement UserLocal (RDHWR $29) to accelerate
> programs that make extensive use of thread-local storage.  Therefore,
> setting up the HWRENA register should not depend on cpu_has_mips_r2.

Interesting - which R1 processor has RDHWR?  When UserLocal was conceived
R2 was already long released.

  Ralf

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-09  9:34   ` Sergei Shtylyov
@ 2010-09-09 12:39     ` Kevin Cernekee
  2011-05-19 13:30       ` Ralf Baechle
  0 siblings, 1 reply; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-09 12:39 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Ralf Baechle, linux-mips, linux-kernel

On Thu, Sep 9, 2010 at 2:34 AM, Sergei Shtylyov <sshtylyov@mvista.com> wrote:
>> +static inline void plat_extra_sync_for_cpu(struct device *dev,
>> +       dma_addr_t dma_handle, unsigned long offset, size_t size,
>> +       enum dma_data_direction direction)
>> +{
>> +       return;
>
>   Why not just empty function bodies?

For consistency with plat_extra_sync_for_device().

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-08 23:02   ` Kevin Cernekee
  (?)
  (?)
@ 2010-09-09 17:10   ` David Daney
  2010-09-09 17:34     ` Thomas Bogendoerfer
  -1 siblings, 1 reply; 14+ messages in thread
From: David Daney @ 2010-09-09 17:10 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: Ralf Baechle, linux-mips, linux-kernel

On 09/08/2010 04:02 PM, Kevin Cernekee wrote:
> On noncoherent processors with a readahead cache, an extra platform-
> specific invalidation is required during the dma_sync_*_for_cpu()
> operations to keep drivers from seeing stale prefetched data.
>
> Signed-off-by: Kevin Cernekee<cernekee@gmail.com>
> ---
>   .../include/asm/mach-cavium-octeon/dma-coherence.h |   13 +++++++++++++
>   arch/mips/include/asm/mach-generic/dma-coherence.h |   13 +++++++++++++
>   arch/mips/include/asm/mach-ip27/dma-coherence.h    |   13 +++++++++++++
>   arch/mips/include/asm/mach-ip32/dma-coherence.h    |   13 +++++++++++++
>   arch/mips/include/asm/mach-jazz/dma-coherence.h    |   13 +++++++++++++
>   .../mips/include/asm/mach-loongson/dma-coherence.h |   13 +++++++++++++
>   arch/mips/include/asm/mach-powertv/dma-coherence.h |   13 +++++++++++++
>   arch/mips/mm/dma-default.c                         |    3 +++
>   8 files changed, 94 insertions(+), 0 deletions(-)
>
[...]

But as far as I can see, none of your plat_extra_sync_for_cpu() do anything.

Perhaps adding this hook should be deferred until there is actually a user.

David Daney

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-09 17:10   ` David Daney
@ 2010-09-09 17:34     ` Thomas Bogendoerfer
  2010-09-09 18:35       ` Kevin Cernekee
  0 siblings, 1 reply; 14+ messages in thread
From: Thomas Bogendoerfer @ 2010-09-09 17:34 UTC (permalink / raw)
  To: David Daney; +Cc: Kevin Cernekee, Ralf Baechle, linux-mips, linux-kernel

On Thu, Sep 09, 2010 at 10:10:00AM -0700, David Daney wrote:
> On 09/08/2010 04:02 PM, Kevin Cernekee wrote:
>> On noncoherent processors with a readahead cache, an extra platform-
>> specific invalidation is required during the dma_sync_*_for_cpu()
>> operations to keep drivers from seeing stale prefetched data.
>
> But as far as I can see, none of your plat_extra_sync_for_cpu() do anything.
>
> Perhaps adding this hook should be deferred until there is actually a user.

looks like this is doing what the non_coherent_r10000 case does. So IMHO
either which make non_coheren check more generic or could use the new
plat_sync thingie for IP28 and other non coherent r10k boxes.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea.                                                [ RFC1925, 2.3 ]

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-09 17:34     ` Thomas Bogendoerfer
@ 2010-09-09 18:35       ` Kevin Cernekee
  2010-09-09 18:58         ` David Daney
  0 siblings, 1 reply; 14+ messages in thread
From: Kevin Cernekee @ 2010-09-09 18:35 UTC (permalink / raw)
  To: Thomas Bogendoerfer; +Cc: David Daney, Ralf Baechle, linux-mips, linux-kernel

On Thu, Sep 9, 2010 at 10:34 AM, Thomas Bogendoerfer
<tsbogend@alpha.franken.de> wrote:
> looks like this is doing what the non_coherent_r10000 case does. So IMHO

My code is not currently in the tree, but I have 3 different hooks for
3 different processor types.  The generic __dma_sync() workaround used
on R10K is not sufficient.

> either which make non_coheren check more generic or could use the new
> plat_sync thingie for IP28 and other non coherent r10k boxes.

That is a good idea.  One thing I'd like to do is continue sharing the
same R10K code for IP27 / IP28 / IP32 / SNI_RM, and move all of it out
of dma-default.c .  Do you have any suggestions on how to define the
plat_* handlers on a per-cpu-type basis instead of making 4 identical
copies of the R10K workaround?

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-09 18:35       ` Kevin Cernekee
@ 2010-09-09 18:58         ` David Daney
  0 siblings, 0 replies; 14+ messages in thread
From: David Daney @ 2010-09-09 18:58 UTC (permalink / raw)
  To: Kevin Cernekee
  Cc: Thomas Bogendoerfer, Ralf Baechle, linux-mips, linux-kernel

On 09/09/2010 11:35 AM, Kevin Cernekee wrote:
> On Thu, Sep 9, 2010 at 10:34 AM, Thomas Bogendoerfer
> <tsbogend@alpha.franken.de>  wrote:
>> looks like this is doing what the non_coherent_r10000 case does. So IMHO
>
> My code is not currently in the tree, but I have 3 different hooks for
> 3 different processor types.  The generic __dma_sync() workaround used
> on R10K is not sufficient.
>
>> either which make non_coheren check more generic or could use the new
>> plat_sync thingie for IP28 and other non coherent r10k boxes.
>
> That is a good idea.  One thing I'd like to do is continue sharing the
> same R10K code for IP27 / IP28 / IP32 / SNI_RM, and move all of it out
> of dma-default.c .  Do you have any suggestions on how to define the
> plat_* handlers on a per-cpu-type basis instead of making 4 identical
> copies of the R10K workaround?
>

I am working on patches that use asm-generic/dma-mapping-common.h.  This 
dispatches all DMA operations via a dma_map_ops vector.

It adds some function call overhead, but makes it easy to mix and match 
different implementations.

My main motivation is to integrate the swiotlb.c bounce buffer 
management for devices that have small dma_masks.

It is still a work in progress, and is not ready to publish yet.

I foresee a lot of churn in this area in the near future.

David Daney

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

* Re: [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu()
  2010-09-09 12:39     ` Kevin Cernekee
@ 2011-05-19 13:30       ` Ralf Baechle
  0 siblings, 0 replies; 14+ messages in thread
From: Ralf Baechle @ 2011-05-19 13:30 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: Sergei Shtylyov, linux-mips

On Thu, Sep 09, 2010 at 05:39:32AM -0700, Kevin Cernekee wrote:

> On Thu, Sep 9, 2010 at 2:34 AM, Sergei Shtylyov <sshtylyov@mvista.com> wrote:
> >> +static inline void plat_extra_sync_for_cpu(struct device *dev,
> >> +       dma_addr_t dma_handle, unsigned long offset, size_t size,
> >> +       enum dma_data_direction direction)
> >> +{
> >> +       return;
> >
> >   Why not just empty function bodies?
> 
> For consistency with plat_extra_sync_for_device().

Consistency is good - but let's just stop the madness.  The lone return
in a void function doesn't help readability and I'm not sure how it ever
got into the code.  I just went through all the MIPS includes and cleaned
all instances I found.

  Ralf

MIPS: Remove pointless return statement from empty void functions.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

 arch/mips/include/asm/irq.h                         |    1 -
 arch/mips/include/asm/mach-generic/dma-coherence.h  |    1 -
 arch/mips/include/asm/mach-ip27/dma-coherence.h     |    1 -
 arch/mips/include/asm/mach-jazz/dma-coherence.h     |    1 -
 arch/mips/include/asm/mach-loongson/dma-coherence.h |    1 -
 arch/mips/include/asm/mach-powertv/dma-coherence.h  |    1 -
 6 files changed, 6 deletions(-)

Index: linux-queue/arch/mips/include/asm/mach-ip27/dma-coherence.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ linux-queue/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -60,7 +60,6 @@ static inline int plat_dma_supported(str
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
Index: linux-queue/arch/mips/include/asm/irq.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/irq.h
+++ linux-queue/arch/mips/include/asm/irq.h
@@ -18,7 +18,6 @@
 
 static inline void irq_dispose_mapping(unsigned int virq)
 {
-	return;
 }
 
 #ifdef CONFIG_I8259
Index: linux-queue/arch/mips/include/asm/mach-generic/dma-coherence.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ linux-queue/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -49,7 +49,6 @@ static inline int plat_dma_supported(str
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
Index: linux-queue/arch/mips/include/asm/mach-jazz/dma-coherence.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ linux-queue/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -50,7 +50,6 @@ static inline int plat_dma_supported(str
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
Index: linux-queue/arch/mips/include/asm/mach-loongson/dma-coherence.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ linux-queue/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -55,7 +55,6 @@ static inline int plat_dma_supported(str
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,
Index: linux-queue/arch/mips/include/asm/mach-powertv/dma-coherence.h
===================================================================
--- linux-queue.orig/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ linux-queue/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -102,7 +102,6 @@ static inline int plat_dma_supported(str
 
 static inline void plat_extra_sync_for_device(struct device *dev)
 {
-	return;
 }
 
 static inline int plat_dma_mapping_error(struct device *dev,

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

end of thread, other threads:[~2011-05-19 13:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-08 23:02 [PATCH v2 1/3] MIPS: HIGHMEM DMA on noncoherent MIPS32 processors Kevin Cernekee
2010-09-08 23:02 ` Kevin Cernekee
2010-09-08 23:02 ` [PATCH 2/3] MIPS: Allow UserLocal on MIPS_R1 processors Kevin Cernekee
2010-09-08 23:02   ` Kevin Cernekee
2010-09-09  9:53   ` Ralf Baechle
2010-09-08 23:02 ` [PATCH 3/3] MIPS: DMA: Add plat_extra_sync_for_cpu() Kevin Cernekee
2010-09-08 23:02   ` Kevin Cernekee
2010-09-09  9:34   ` Sergei Shtylyov
2010-09-09 12:39     ` Kevin Cernekee
2011-05-19 13:30       ` Ralf Baechle
2010-09-09 17:10   ` David Daney
2010-09-09 17:34     ` Thomas Bogendoerfer
2010-09-09 18:35       ` Kevin Cernekee
2010-09-09 18:58         ` David Daney

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.