linux-mips
[Top] [All Lists]

file corruption with highmem kernel

To: "linux-mips" <linux-mips@linux-mips.org>, "Ralf Baechle" <ralf@linux-mips.org>
Subject: file corruption with highmem kernel
From: "Anoop P.A." <Anoop_P.A@pmc-sierra.com>
Date: Mon, 2 Aug 2010 06:29:56 -0700
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
Thread-index: AcsyRsvJtdIm2QULSF2xEZbUAQ5rPA==
Thread-topic: file corruption with highmem kernel
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

<Prev in Thread] Current Thread [Next in Thread>