All of lore.kernel.org
 help / color / mirror / Atom feed
* file corruption with highmem kernel
@ 2010-08-02 13:29 Anoop P.A.
  2010-08-05 13:43 ` Anoop P.A.
  0 siblings, 1 reply; 4+ messages in thread
From: Anoop P.A. @ 2010-08-02 13:29 UTC (permalink / raw)
  To: linux-mips, Ralf Baechle

List,

I am running 2.6.18 (highmem) kernel in RM9000 based SOC with 2 Gig RAM.
I have observed file corruption and system hangs (Easily reproducible on
remounting file system) when doing file copy to SATA disk / USB disk (
SATA/ USB controller over PCI) . How ever when I limit memory with
option mem=512M from command line everything seems to be working fine.

Issue is reproducible with 2.6.18-stable lmo git sources .

I have modified dma-noncoherent.c as follows and I am no more
experiencing system hang. But file's are getting corrupted (observed bus
error / segmentation fault / illegal instruction error few times)
occasionally.  One more observation I have made is file corruption is
more if I use root file system from onboard USB flash, than running a
NFS root mount.


--- arch/mips/mm/dma-noncoherent.c.orig	2010-08-02 23:53:17.000000000
+0530
+++ arch/mips/mm/dma-noncoherent.c	2010-08-02 23:56:19.000000000
+0530
@@ -132,12 +132,13 @@
 	for (i = 0; i < nents; i++, sg++) {
 		unsigned long addr;
 
-		addr = (unsigned long) page_address(sg->page);
-		if (addr) {
-			__dma_sync(addr + sg->offset, sg->length,
direction);
-			sg->dma_address =
(dma_addr_t)page_to_phys(sg->page)
-					  + sg->offset;
-		}
+		addr = (unsigned long) page_address(sg->page) +
sg->offset;
+		if (addr) 
+			__dma_sync(addr, sg->length, direction);
+		
+		sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
+					+ sg->offset;
+		
 	}
 
 	return nents;
@@ -187,9 +188,9 @@
 		return;
 
 	for (i = 0; i < nhwentries; i++, sg++) {
-		addr = (unsigned long) page_address(sg->page);
+		addr = (unsigned long) page_address(sg->page) +
sg->offset;
 		if (addr)
-			__dma_sync(addr + sg->offset, sg->length,
direction);
+			__dma_sync(addr , sg->length, direction);
 	}
 }


It will be great if any body can give me some pointers / help to fix the
issue.

Thanks
Anoop

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

* RE: file corruption with highmem kernel
  2010-08-02 13:29 file corruption with highmem kernel Anoop P.A.
@ 2010-08-05 13:43 ` Anoop P.A.
  2010-08-05 18:25   ` Ralf Baechle
  0 siblings, 1 reply; 4+ messages in thread
From: Anoop P.A. @ 2010-08-05 13:43 UTC (permalink / raw)
  To: linux-mips, Ralf Baechle

List,

With a slightly modified patched (copied below) I have reached a point
where I am no more seeing errors like segmentation fault, bus error
(which was due to memory corruption I believe).
How ever I am still seeing some kind of file corruption. 

I believe this file corruption happening because cache is not getting
invalidated before a highmem dma. I am not sure which routine to call to
invalidate cache for a highmem address. 

Hope to see response from linux-mips gurus

Thank you,
Anoop   

--- arch/mips/mm/dma-noncoherent.c.orig	2010-08-02 23:53:17.000000000
+0530
+++ arch/mips/mm/dma-noncoherent.c	2010-08-06 00:17:21.000000000
+0530
@@ -131,13 +131,14 @@
 
 	for (i = 0; i < nents; i++, sg++) {
 		unsigned long addr;
-
-		addr = (unsigned long) page_address(sg->page);
-		if (addr) {
-			__dma_sync(addr + sg->offset, sg->length,
direction);
-			sg->dma_address =
(dma_addr_t)page_to_phys(sg->page)
-					  + sg->offset;
+		if (!PageHighMem(sg->page)){
+			addr = (unsigned long)page_address(sg->page) +
sg->offset;
+			__dma_sync(addr , sg->length, direction);
 		}
+
+		sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
+					+ sg->offset;
+		
 	}
 
 	return nents;
@@ -187,9 +188,10 @@
 		return;
 
 	for (i = 0; i < nhwentries; i++, sg++) {
-		addr = (unsigned long) page_address(sg->page);
-		if (addr)
-			__dma_sync(addr + sg->offset, sg->length,
direction);
+		if (!PageHighMem(sg->page)){
+			addr = (unsigned long)page_address(sg->page) +
sg->offset;
+			__dma_sync(addr , sg->length, direction);
+		}
 	}
 }

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

* Re: file corruption with highmem kernel
  2010-08-05 13:43 ` Anoop P.A.
@ 2010-08-05 18:25   ` Ralf Baechle
  2010-08-06 10:12     ` Anoop P.A.
  0 siblings, 1 reply; 4+ messages in thread
From: Ralf Baechle @ 2010-08-05 18:25 UTC (permalink / raw)
  To: Anoop P.A.; +Cc: linux-mips

On Thu, Aug 05, 2010 at 06:43:50AM -0700, Anoop P.A. wrote:

> With a slightly modified patched (copied below) I have reached a point
> where I am no more seeing errors like segmentation fault, bus error
> (which was due to memory corruption I believe).
> How ever I am still seeing some kind of file corruption. 
> 
> I believe this file corruption happening because cache is not getting
> invalidated before a highmem dma. I am not sure which routine to call to
> invalidate cache for a highmem address. 

Since you're running on an RM9000 class CPU, why don't just use a 64-bit
kernel?  Highmem is just so f*cking insane that you want to avoid it like
French kisses from a zombie suffering ebola.  If you have DMA restrictions
then you may consider reusing ZONE_DMA.

That said, a word on the history of the MIPS highmem code.  It was written
for a company who in the early stages of the 64-bit kernel didn't want to
be the first through the minefield in 2001.  That CPU had full coherency
and no cache aliases so arch/mips/mm/dma-*.c did not need any code to
support it at all and for many years after that everybody either had a
small 32-bit system that didn't need highmem or went 64-bit right away so
the gaps in the code while well known were never fixed up ...

I'm a bit surprised that the patch posted actually made things work better
for you since it entirely avoids flushing of highmem pages.  The code as it
was originally written using page_address() will perform cacheflushes
for highmem pages as well - but only for highmem pages are actually are
mapped.  That is your code will flush less pages than the existing code.

  Ralf

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

* RE: file corruption with highmem kernel
  2010-08-05 18:25   ` Ralf Baechle
@ 2010-08-06 10:12     ` Anoop P.A.
  0 siblings, 0 replies; 4+ messages in thread
From: Anoop P.A. @ 2010-08-06 10:12 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

> 
> Since you're running on an RM9000 class CPU, why don't just use a
64-bit
> kernel?  Highmem is just so f*cking insane that you want to avoid it
like
> French kisses from a zombie suffering ebola.  If you have DMA
restrictions
> then you may consider reusing ZONE_DMA.
[Anoop P.A.] I understand that I am working on 64 bit kernel in
parallel, DMA issue made me concentrate on highmem support as immediate
option.
 
> small 32-bit system that didn't need highmem or went 64-bit right away
so
> the gaps in the code while well known were never fixed up ...

[Anoop P.A.] I presume with decreased value of RAM, more 32 bit machines
will come with bulk of memory pretty soon to the world of highmem

> 
> I'm a bit surprised that the patch posted actually made things work
better
> for you since it entirely avoids flushing of highmem pages.  The code
as
> it
> was originally written using page_address() will perform cacheflushes
> for highmem pages as well - but only for highmem pages are actually
are
> mapped.  That is your code will flush less pages than the existing
code.

[Anoop P.A.] I confirmed it, calling __dma_sync for highmem map address
occasionally causes memory corruption ( reports bus error , segmentation
fault etc..) .

Blowing entire scache (I understand it is pain) for highmem pages fixed
my file corruption issue

--- linux-2.6.18/arch/mips/mm/dma-noncoherent.c	2006-08-23
23:16:07.000000000 +0530
+++ linux-2.6.18/arch/mips/mm/dma-noncoherent.c	2010-08-06
20:48:36.000000000 +0530
@@ -15,6 +15,7 @@
 
 #include <asm/cache.h>
 #include <asm/io.h>
+#include <asm/r4kcache.h>
 
 /*
  * Warning on the terminology - Linux calls an uncached area coherent;
@@ -131,13 +132,21 @@
 
 	for (i = 0; i < nents; i++, sg++) {
 		unsigned long addr;
+		if (!PageHighMem(sg->page))
+		{
+               		addr = (unsigned
long)page_address(sg->page) + sg->offset;
+               		__dma_sync(addr, sg->length, direction);
+		}
+		else
+		{ 
+		/*blasting entire cache for all	the highmem page's might
be over head 
+		  But __dma_sync is failing for mapped highmem pages, so
this is the 
+		  easiest solution for time being*/
+			blast_scache32(); /*RM9000 sc_line=32 */ 
+		}
 
-		addr = (unsigned long) page_address(sg->page);
-		if (addr) {
-			__dma_sync(addr + sg->offset, sg->length,
direction);
-			sg->dma_address =
(dma_addr_t)page_to_phys(sg->page)
+		sg->dma_address = (dma_addr_t)page_to_phys(sg->page)
 					  + sg->offset;
-		}
 	}
 
 	return nents;


Thanks
Anoop

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

end of thread, other threads:[~2010-08-06 10:12 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-02 13:29 file corruption with highmem kernel Anoop P.A.
2010-08-05 13:43 ` Anoop P.A.
2010-08-05 18:25   ` Ralf Baechle
2010-08-06 10:12     ` Anoop P.A.

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.