PERFORCE change 133192 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Jan 13 06:58:22 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=133192
Change 133192 by hselasky at hselasky_laptop001 on 2008/01/13 14:58:20
Important patch. Sometimes the BUS-DMA framework
will not report all segments, even if the virtual
memory we load is crossing a segment! Because BUS-DMA
starts counting "maxsegsz" from the "aligned" memory
location, and when align=1 byte we are in for trouble.
I'm not sure sure if this is a bug in BUS-DMA.
Solution: Manually extend the last segment.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#86 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#86 (text+ko) ====
@@ -2269,6 +2269,7 @@
struct usbd_page *pg;
uint32_t rem;
uint8_t owned;
+ uint8_t ext_seg; /* extend last segment */
pc = arg;
xfer = pc->xfer;
@@ -2297,6 +2298,12 @@
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
+ if (nseg < ((pc->page_offset_end +
+ (USB_PAGE_SIZE - 1)) / USB_PAGE_SIZE)) {
+ ext_seg = 1;
+ } else {
+ ext_seg = 0;
+ }
nseg--;
while (nseg > 0) {
@@ -2306,6 +2313,14 @@
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
}
+ /*
+ * XXX The segments we get from BUS-DMA are not aligned,
+ * XXX so we need to extend the last segment if we are
+ * XXX unaligned and cross the segment boundary!
+ */
+ if (ext_seg) {
+ (pg + 1)->physaddr = pg->physaddr + USB_PAGE_SIZE;
+ }
if (xfer) {
owned = mtx_owned(xfer->priv_mtx);
if (!owned)
@@ -2572,6 +2587,7 @@
struct usbd_page *pg;
uint32_t rem;
uint8_t owned;
+ uint8_t ext_seg; /* extend last segment */
xfer = pc->xfer;
@@ -2599,6 +2615,12 @@
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
+ if (nseg < ((pc->page_offset_end +
+ (USB_PAGE_SIZE - 1)) / USB_PAGE_SIZE)) {
+ ext_seg = 1;
+ } else {
+ ext_seg = 0;
+ }
nseg--;
while (nseg > 0) {
@@ -2608,6 +2630,14 @@
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
}
+ /*
+ * XXX The segments we get from BUS-DMA are not aligned,
+ * XXX so we need to extend the last segment if we are
+ * XXX unaligned and cross the segment boundary!
+ */
+ if (ext_seg) {
+ (pg + 1)->physaddr = pg->physaddr + USB_PAGE_SIZE;
+ }
if (xfer) {
owned = mtx_owned(xfer->priv_mtx);
if (!owned)
More information about the p4-projects
mailing list