Kernel panic when copying data to umass device (USB4BSD) -
problem found
Hans Petter Selasky
hselasky at c2i.net
Fri Nov 7 09:09:23 PST 2008
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;
More information about the freebsd-current
mailing list