svn commit: r244535 - head/sys/dev/usb
Hans Petter Selasky
hselasky at FreeBSD.org
Fri Dec 21 14:17:40 UTC 2012
Author: hselasky
Date: Fri Dec 21 14:17:39 2012
New Revision: 244535
URL: http://svnweb.freebsd.org/changeset/base/244535
Log:
Regression issue:
Use a boundary of zero, hence a PAGE_SIZE boundary
is implied by all memory allocations.
Background:
Busdma has problems to allocate more than PAGE_SIZE
bytes when the boundary is PAGE_SIZE bytes too.
Initially it was thought that a boundary of PAGE_SIZE
bytes will only affect loading of DMA memory, so that
segments get split correctly, but it also affects
allocation of DMA'able memory.
Solution:
USB can detect big segments and split them as required
by the USB code.
MFC after: 1 week
Reported by: gonzo
Modified:
head/sys/dev/usb/usb_busdma.c
Modified: head/sys/dev/usb/usb_busdma.c
==============================================================================
--- head/sys/dev/usb/usb_busdma.c Fri Dec 21 13:14:12 2012 (r244534)
+++ head/sys/dev/usb/usb_busdma.c Fri Dec 21 14:17:39 2012 (r244535)
@@ -358,8 +358,7 @@ usb_dma_tag_create(struct usb_dma_tag *u
if (bus_dma_tag_create
( /* parent */ udt->tag_parent->tag,
/* alignment */ align,
- /* boundary */ (align == 1) ?
- USB_PAGE_SIZE : 0,
+ /* boundary */ 0,
/* lowaddr */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
/* highaddr */ BUS_SPACE_MAXADDR,
/* filter */ NULL,
@@ -418,6 +417,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_
struct usb_page_cache *pc;
struct usb_page *pg;
usb_size_t rem;
+ bus_size_t off;
uint8_t owned;
pc = arg;
@@ -433,6 +433,8 @@ usb_pc_common_mem_cb(void *arg, bus_dma_
if (error) {
goto done;
}
+
+ off = 0;
pg = pc->page_start;
pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
@@ -450,10 +452,16 @@ usb_pc_common_mem_cb(void *arg, bus_dma_
}
#endif
while (nseg > 0) {
- nseg--;
- segs++;
+ off += USB_PAGE_SIZE;
+ if (off >= (segs->ds_len + rem)) {
+ /* page crossing */
+ nseg--;
+ segs++;
+ off = 0;
+ rem = 0;
+ }
pg++;
- pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
+ pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
}
done:
More information about the svn-src-head
mailing list