Author: gonzo
Date: Fri Oct 30 01:19:04 2015
New Revision: 290176
URL: https://svnweb.freebsd.org/changeset/base/290176

Log:
  Fix BULK read transfer if destination buffer is not cache line-aligned.
  
  We can't use copyout because destination memory is userland address
  in another process but we have reference to respective page so map
  the page into kernel address space and copy fragments there

Modified:
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c

Modified: head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
==============================================================================
--- head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c Fri Oct 30 
01:18:07 2015        (r290175)
+++ head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c Fri Oct 30 
01:19:04 2015        (r290176)
@@ -109,6 +109,22 @@ vchiq_dmamap_cb(void *arg, bus_dma_segme
        *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
 }
 
+static int
+copyout_page(vm_page_t p, size_t offset, void *kaddr, size_t size)
+{
+        uint8_t *dst;
+
+        dst = pmap_mapdev(VM_PAGE_TO_PHYS(p), PAGE_SIZE);
+        if (!dst)
+                return ENOMEM;
+
+        memcpy(dst + offset, kaddr, size);
+
+        pmap_unmapdev((vm_offset_t)dst, PAGE_SIZE);
+
+        return 0;
+}
+
 int __init
 vchiq_platform_init(VCHIQ_STATE_T *state)
 {
@@ -560,15 +576,19 @@ free_pagelist(BULKINFO_T *bi, int actual
                        if (head_bytes > actual)
                                head_bytes = actual;
 
-                       memcpy((char *)bi->buf,
+                       copyout_page(pages[0],
+                               pagelist->offset,
                                fragments->headbuf,
                                head_bytes);
                }
 
                if ((actual >= 0) && (head_bytes < actual) &&
                        (tail_bytes != 0)) {
-                       memcpy((char *)bi->buf + actual - tail_bytes, 
-                                        fragments->tailbuf, tail_bytes);
+
+                       copyout_page(pages[num_pages-1],
+                               (((vm_offset_t)bi->buf + actual) % PAGE_SIZE) - 
tail_bytes,
+                               fragments->tailbuf,
+                               tail_bytes);
                }
 
                down(&g_free_fragments_mutex);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to