Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 Dec 2008 12:07:44 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 154181 for review
Message-ID:  <200812061207.mB6C7iS1064198@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=154181

Change 154181 by hselasky@hselasky_laptop001 on 2008/12/06 12:07:36

	
	Fix problem with busdma, bounce pages and USB. Needs review.

Affected files ...

.. //depot/projects/usb/src/sys/amd64/amd64/busdma_machdep.c#9 edit
.. //depot/projects/usb/src/sys/arm/arm/busdma_machdep.c#10 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_busdma.c#14 edit
.. //depot/projects/usb/src/sys/i386/i386/busdma_machdep.c#12 edit
.. //depot/projects/usb/src/sys/ia64/ia64/busdma_machdep.c#8 edit
.. //depot/projects/usb/src/sys/sys/bus_dma.h#6 edit

Differences ...

==== //depot/projects/usb/src/sys/amd64/amd64/busdma_machdep.c#9 (text+ko) ====

@@ -1128,6 +1128,17 @@
 	bz->active_bpages++;
 	mtx_unlock(&bounce_lock);
 
+	/* reset page offset */
+	bpage->vaddr &= ~PAGE_MASK;
+	bpage->busaddr &= ~PAGE_MASK;
+
+	if (BUS_DMA_NO_REALIGN(dmat->alignment, dmat->boundary,
+	    dmat->maxsegsz)) {
+		/* preserve page offset */
+		bpage->vaddr |= vaddr & PAGE_MASK;
+		bpage->busaddr |= vaddr & PAGE_MASK;
+	}
+
 	bpage->datavaddr = vaddr;
 	bpage->datacount = size;
 	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);

==== //depot/projects/usb/src/sys/arm/arm/busdma_machdep.c#10 (text+ko) ====

@@ -1416,6 +1416,17 @@
 	bz->active_bpages++;
 	mtx_unlock(&bounce_lock);
 
+	/* reset page offset */
+	bpage->vaddr &= ~PAGE_MASK;
+	bpage->busaddr &= ~PAGE_MASK;
+
+	if (BUS_DMA_NO_REALIGN(dmat->alignment, dmat->boundary,
+	    dmat->maxsegsz)) {
+		/* preserve page offset */
+		bpage->vaddr |= vaddr & PAGE_MASK;
+		bpage->busaddr |= vaddr & PAGE_MASK;
+	}
+
 	bpage->datavaddr = vaddr;
 	bpage->datacount = size;
 	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);

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

@@ -29,12 +29,15 @@
 #include <dev/usb2/include/usb2_standard.h>
 #include <dev/usb2/include/usb2_defs.h>
 
+#define	USB_DEBUG_VAR usb2_debug
+
 #include <dev/usb2/core/usb2_core.h>
 #include <dev/usb2/core/usb2_busdma.h>
 #include <dev/usb2/core/usb2_process.h>
 #include <dev/usb2/core/usb2_transfer.h>
 #include <dev/usb2/core/usb2_device.h>
 #include <dev/usb2/core/usb2_util.h>
+#include <dev/usb2/core/usb2_debug.h>
 
 #include <dev/usb2/controller/usb2_controller.h>
 #include <dev/usb2/controller/usb2_bus.h>
@@ -428,7 +431,16 @@
 	pc->page_offset_buf = rem;
 	pc->page_offset_end += rem;
 	nseg--;
-
+#if (USB_DEBUG != 0)
+	if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
+		/*
+		 * This check verifies that the physical address is correct:
+		 */
+		DPRINTFN(0, "Page offset was not preserved!\n");
+		error = 1;
+		goto done;
+	}
+#endif
 	while (nseg > 0) {
 		nseg--;
 		segs++;
@@ -805,7 +817,16 @@
 		ext_seg = 0;
 	}
 	nseg--;
-
+#if (USB_DEBUG != 0)
+	if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
+		/*
+		 * This check verifies that the physical address is correct:
+		 */
+		DPRINTFN(0, "Page offset was not preserved!\n");
+		error = 1;
+		goto done;
+	}
+#endif
 	while (nseg > 0) {
 		nseg--;
 		segs++;

==== //depot/projects/usb/src/sys/i386/i386/busdma_machdep.c#12 (text+ko) ====

@@ -1146,6 +1146,17 @@
 	bz->active_bpages++;
 	mtx_unlock(&bounce_lock);
 
+	/* reset page offset */
+	bpage->vaddr &= ~PAGE_MASK;
+	bpage->busaddr &= ~PAGE_MASK;
+
+	if (BUS_DMA_NO_REALIGN(dmat->alignment, dmat->boundary,
+	    dmat->maxsegsz)) {
+		/* preserve page offset */
+		bpage->vaddr |= vaddr & PAGE_MASK;
+		bpage->busaddr |= vaddr & PAGE_MASK;
+	}
+
 	bpage->datavaddr = vaddr;
 	bpage->datacount = size;
 	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);

==== //depot/projects/usb/src/sys/ia64/ia64/busdma_machdep.c#8 (text+ko) ====

@@ -936,6 +936,17 @@
 	active_bpages++;
 	mtx_unlock(&bounce_lock);
 
+	/* reset page offset */
+	bpage->vaddr &= ~PAGE_MASK;
+	bpage->busaddr &= ~PAGE_MASK;
+
+	if (BUS_DMA_NO_REALIGN(dmat->alignment, dmat->boundary,
+	    dmat->maxsegsz)) {
+		/* preserve page offset */
+		bpage->vaddr |= vaddr & PAGE_MASK;
+		bpage->busaddr |= vaddr & PAGE_MASK;
+	}
+
 	bpage->datavaddr = vaddr;
 	bpage->datacount = size;
 	STAILQ_INSERT_TAIL(&(map->bpages), bpage, links);

==== //depot/projects/usb/src/sys/sys/bus_dma.h#6 (text+ko) ====

@@ -133,6 +133,23 @@
 #define	BUS_DMASYNC_POSTWRITE	8
 
 /*
+ * Background: Some kinds of DMA hardware only store the full
+ * physical address of the first memory page when multiple memory
+ * pages are loaded into DMA. For consecutive memory pages, only the
+ * non-offset part of the physical address is updated. The hardware
+ * computes the amount of data that should be stored in the first
+ * memory page from the minimum of the total transfer length and
+ * PAGE_SIZE, minus the initial page offset. When the initial page
+ * offset is not preserved, the hardware ends up transferring an
+ * invalid number of bytes to or from the initial memory page.
+ *
+ * The following macro returns true when the initial page offset must
+ * be preserved:
+ */
+#define	BUS_DMA_NO_REALIGN(align,boundary,maxsegsz) \
+  (((align) == 1) && ((boundary) == PAGE_SIZE) && ((maxsegsz) == PAGE_SIZE))
+
+/*
  *	bus_dma_segment_t
  *
  *	Describes a single contiguous DMA transaction.  Values



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