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:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to