Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Nov 2008 18:11:26 +0100
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        freebsd-current@freebsd.org
Cc:        Jeremy Chadwick <koitsu@freebsd.org>
Subject:   Re: Kernel panic when copying data to umass device (USB4BSD) - problem found
Message-ID:  <200811071811.27181.hselasky@c2i.net>
In-Reply-To: <20081107082740.GA1334@icarus.home.lan>
References:  <20081107082740.GA1334@icarus.home.lan>

next in thread | previous in thread | raw e-mail | index | archive | help
On Friday 07 November 2008, Jeremy Chadwick wrote:
> Not sure if this is caused by problems with USB4BSD or not, as I can
> reproduce it on RELENG_7 (but there, the kernel does not panic; it just
> "wedges" in a loop/thread somewhere; SSH sessions remain up, but
> commands running stop; hitting Ctrl-T shows them in all sorts of
> different states, but the states never change; hitting Ctrl-Alt-Esc does
> in fact drop me to db>).
>

Hi Jeremy,

I've reproduced the issue with some mods to the usb2_busdma.c on 32-bit 
arcitecture and have made a fix for this problem.

Try the following patch and re-test! Some mem-stick benchmarks would be 
nice ...

My private SVN also has this patch in addition to P4.

--HPS

http://perforce.freebsd.org/chv.cgi?CH=152624
       
        Fix some problems related to busdma:
        Need to unload DMA maps before re-use!
        Fix a corner case when loading zero bytes.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_busdma.c#10 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_busdma.c#10 (text+ko) 
====

@@ -597,6 +597,12 @@
                        uptag = pc->tag_parent;
 
                        /*
+                        * We have to unload the previous loaded DMA
+                        * pages before trying to load a new one!
+                        */
+                       bus_dmamap_unload(pc->tag, pc->map);
+
+                       /*
                         * Try to load memory into DMA.
                         */
                        err = bus_dmamap_load(
@@ -612,6 +618,12 @@
                } else {
 
                        /*
+                        * We have to unload the previous loaded DMA
+                        * pages before trying to load a new one!
+                        */
+                       bus_dmamap_unload(pc->tag, pc->map);
+
+                       /*
                         * Try to load memory into DMA. The callback
                         * will be called in all cases:
                         */
@@ -639,6 +651,10 @@
 void
 usb2_pc_cpu_invalidate(struct usb2_page_cache *pc)
 {
+       if (pc->page_offset_end == pc->page_offset_buf) {
+               /* nothing has been loaded into this page cache! */
+               return;
+       }
        bus_dmamap_sync(pc->tag, pc->map,
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        return;
@@ -650,6 +666,10 @@
 void
 usb2_pc_cpu_flush(struct usb2_page_cache *pc)
 {
+       if (pc->page_offset_end == pc->page_offset_buf) {
+               /* nothing has been loaded into this page cache! */
+               return;
+       }
        bus_dmamap_sync(pc->tag, pc->map,
            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        return;
@@ -953,6 +973,12 @@
 
        if (size > 0) {
 
+               /*
+                * We have to unload the previous loaded DMA
+                * pages before trying to load a new one!
+                */
+               bus_dmamap_unload(pc->tag, pc->map);
+
                /* try to load memory into DMA using using no wait option */
                if (bus_dmamap_load(pc->tag, pc->map, pc->buffer,
                    size, NULL, BUS_DMA_NOWAIT)) {
@@ -990,6 +1016,10 @@
 
        len = pc->page_offset_end - pc->page_offset_buf;
 
+       if (len == 0) {
+               /* nothing has been loaded into this page cache */
+               return;
+       }
        bus_dmamap_sync(pc->tag, pc->map, 0, len,
            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
        return;
@@ -1005,6 +1035,10 @@
 
        len = pc->page_offset_end - pc->page_offset_buf;
 
+       if (len == 0) {
+               /* nothing has been loaded into this page cache */
+               return;
+       }
        bus_dmamap_sync(pc->tag, pc->map, 0, len,
            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
        return;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811071811.27181.hselasky>