login
Header Space

 
 

Re: [PATCH 0/20] dma_ops for i386

Score:
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: Glauber Costa <gcosta@...>
Cc: <linux-kernel@...>, <akpm@...>, <glommer@...>, <tglx@...>, <kvm-devel@...>, <avi@...>, <amit.shah@...>
Date: Wednesday, March 26, 2008 - 8:49 am

* Ingo Molnar <mingo@elte.hu> wrote:


Houston, we've got a problem! :-/

randconfig testing found that this patchset broke sendfile on certain 
.config's - DMA started returning all 0xfffffffff data, corrupting 
files. (config attached)

After some bisection fun it turns out that the conversions from struct 
page are wrong:

+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+                                     size_t offset, size_t size,
+                                     int direction)
+{
+       return dma_map_single(dev, page_address(page)+offset, size, direction);

because page_address() is not defined for highmem pages in general. (and 
even if it's defined, it will corrupt data)

changing it to page_to_phys() is not good because it goes via a 32-bit 
bottleneck that trims things on PAE:

       dma_addr_t      (*map_single)(struct device *hwdev, void *ptr,

the 'ptr' is 32-bit albeit it's a DMA target.

what i came up is the prototype 32-bit fix below - this works on 32-bit 
but breaks 64-bit because we pass in physical addresses instead of 
virtual direct addresses.

i'll fix the 64-bit side but that means materially touching all the 
dma_mapping_ops instantiations materially on the 64-bit side - not 
really something we wanted to do :-/

	Ingo

---------------->
Subject: x86: dma-ops on highmem fix
From: Ingo Molnar <mingo@elte.hu>

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
 arch/x86/kernel/pci-base_32.c |    4 ++--
 include/asm-x86/dma-mapping.h |   10 ++++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

Index: linux-x86.q/arch/x86/kernel/pci-base_32.c
===================================================================
--- linux-x86.q.orig/arch/x86/kernel/pci-base_32.c
+++ linux-x86.q/arch/x86/kernel/pci-base_32.c
@@ -4,12 +4,12 @@
 #include <linux/dma-mapping.h>
 #include <asm/dma-mapping.h>
 
-static dma_addr_t pci32_map_single(struct device *dev, void *ptr,
+static dma_addr_t pci32_map_single(struct device *dev, u64 ptr,
 				   size_t size, int direction)
 {
 	WARN_ON(size == 0);
 	flush_write_buffers();
-	return virt_to_phys(ptr);
+	return ptr;
 }
 
 static int pci32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
Index: linux-x86.q/include/asm-x86/dma-mapping.h
===================================================================
--- linux-x86.q.orig/include/asm-x86/dma-mapping.h
+++ linux-x86.q/include/asm-x86/dma-mapping.h
@@ -16,10 +16,10 @@ struct dma_mapping_ops {
 				dma_addr_t *dma_handle, gfp_t gfp);
 	void            (*free_coherent)(struct device *dev, size_t size,
 				void *vaddr, dma_addr_t dma_handle);
-	dma_addr_t      (*map_single)(struct device *hwdev, void *ptr,
+	dma_addr_t      (*map_single)(struct device *hwdev, u64 ptr,
 				size_t size, int direction);
 	/* like map_single, but doesn't check the device mask */
-	dma_addr_t      (*map_simple)(struct device *hwdev, char *ptr,
+	dma_addr_t      (*map_simple)(struct device *hwdev, u64 ptr,
 				size_t size, int direction);
 	void            (*unmap_single)(struct device *dev, dma_addr_t addr,
 				size_t size, int direction);
@@ -73,7 +73,7 @@ dma_map_single(struct device *hwdev, voi
 	       int direction)
 {
 	BUG_ON(!valid_dma_direction(direction));
-	return dma_ops->map_single(hwdev, ptr, size, direction);
+	return dma_ops->map_single(hwdev, virt_to_phys(ptr), size, direction);
 }
 
 static inline void
@@ -174,7 +174,9 @@ static inline dma_addr_t dma_map_page(st
 				      size_t offset, size_t size,
 				      int direction)
 {
-	return dma_map_single(dev, page_address(page)+offset, size, direction);
+	BUG_ON(!valid_dma_direction(direction));
+	return dma_ops->map_single(dev, page_to_phys(page)+offset,
+				   size, direction);
 }
 
 static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 0/20] dma_ops for i386, Glauber Costa, (Tue Mar 25, 5:36 pm)
Re: [PATCH 0/20] dma_ops for i386, Amit Shah, (Thu Mar 27, 5:49 am)
Re: [PATCH 0/20] dma_ops for i386, Avi Kivity, (Wed Mar 26, 6:01 am)
Re: [PATCH 0/20] dma_ops for i386, Glauber Costa, (Wed Mar 26, 8:03 am)
Re: [PATCH 0/20] dma_ops for i386, Ingo Molnar, (Wed Mar 26, 3:06 am)
Re: [PATCH 0/20] dma_ops for i386, Ingo Molnar, (Wed Mar 26, 8:49 am)
Re: [PATCH 0/20] dma_ops for i386, Ingo Molnar, (Wed Mar 26, 9:04 am)
Re: [PATCH 0/20] dma_ops for i386, Glauber Costa, (Wed Mar 26, 9:16 am)
[PATCH 03/20] x86: move dma_unmap_single to common header, Glauber Costa, (Tue Mar 25, 5:36 pm)
[PATCH 04/20] x86: move dma_map_sg to common header, Glauber Costa, (Tue Mar 25, 5:36 pm)
[PATCH 05/20] x86: move dma_unmap_sg to common header, Glauber Costa, (Tue Mar 25, 5:36 pm)
speck-geostationary