Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/vchiq/dist/interface/vchiq_arm Actually han...



details:   https://anonhg.NetBSD.org/src/rev/6d44a3296a06
branches:  trunk
changeset: 786322:6d44a3296a06
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Apr 26 16:56:42 2013 +0000

description:
Actually handle any fragments in vchiq_complete_bulk

diffstat:

 sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c |  68 +++++++++-
 1 files changed, 64 insertions(+), 4 deletions(-)

diffs (110 lines):

diff -r 8f276c43a7f0 -r 6d44a3296a06 sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c
--- a/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c  Fri Apr 26 15:56:45 2013 +0000
+++ b/sys/external/bsd/vchiq/dist/interface/vchiq_arm/vchiq_2835_arm.c  Fri Apr 26 16:56:42 2013 +0000
@@ -248,7 +248,7 @@
        bus_size_t      pagelist_size;
        bus_dmamap_t    pagelist_map;
        bus_dmamap_t    dmamap;
-       struct vmspace *vmspace;
+       struct proc     *proc;
        void            *buf;
        int             size;
 } BULKINFO_T;
@@ -281,7 +281,7 @@
        bi->size = size;
        bi->pagelist_size = sizeof(PAGELIST_T) +
            (maxsegs * sizeof(unsigned long));
-       bi->vmspace = curproc->p_vmspace;
+       bi->proc = curproc;
 
        ret = bus_dmamem_alloc(&bcm2835_bus_dma_tag, bi->pagelist_size,
            0 /*CACHE_LINE_SIZE*/, 0, bi->pagelist_sgs,
@@ -316,7 +316,7 @@
         * Need to wire the buffer pages in.
         */
        if (IS_USER_ADDRESS(buf)) {
-               ret = uvm_vslock(curproc->p_vmspace, buf, size, uvmflags);
+               ret = uvm_vslock(bi->proc->p_vmspace, buf, size, uvmflags);
                if (ret != 0) {
                        printf("%s: uvm_vslock failed (%d)\n", __func__, ret);
                        goto fail5;
@@ -368,6 +368,9 @@
                up(&g_free_fragments_mutex);
                pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
                    (fragments - g_fragments_base);
+               bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map,
+                   (char *)fragments - g_slot_mem, sizeof(*fragments),
+                   BUS_DMASYNC_PREREAD);
        }
 
        /*
@@ -417,11 +420,68 @@
 {
        if (bulk && bulk->remote_data && bulk->actual) {
                BULKINFO_T *bi = bulk->remote_data;
+               PAGELIST_T *pagelist = bi->pagelist;
+
+               /* Deal with any partial cache lines (fragments) */
+               if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
+                       FRAGMENTS_T *fragments = g_fragments_base +
+                               (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS);
+                       int head_bytes, tail_bytes;
+                       int actual = bulk->actual;
+
+                       bus_dmamap_sync(&bcm2835_bus_dma_tag, dma_map,
+                           (char *)fragments - g_slot_mem, sizeof(*fragments),
+                           BUS_DMASYNC_POSTREAD);
+
+                       head_bytes = (arm_dcache_align - pagelist->offset) &
+                               (arm_dcache_align - 1);
+                       tail_bytes = (pagelist->offset + actual) &
+                               (arm_dcache_align - 1);
+
+                       if ((actual >= 0) && (head_bytes != 0)) {
+                               if (head_bytes > actual)
+                                       head_bytes = actual;
+
+                               if (IS_USER_ADDRESS(bi->buf)) {
+                                       copyout_proc(bi->proc,
+                                           fragments->headbuf, bi->buf,
+                                           head_bytes);
+                               } else {
+                                       kcopy(fragments->headbuf, bi->buf,
+                                           head_bytes);
+                               }
+                       }
+                       if ((actual >= 0) && (head_bytes < actual) &&
+                           (tail_bytes != 0)) {
+                               void *t = (char *)bi->buf + bi->size -
+                                   tail_bytes;
+
+                                if (IS_USER_ADDRESS(bi->buf)) {
+                                       copyout_proc(bi->proc,
+                                           fragments->tailbuf, t, tail_bytes);
+                               } else {
+                                       kcopy(fragments->tailbuf, t,
+                                           tail_bytes);
+                               }
+                       }
+
+                       down(&g_free_fragments_mutex);
+                       *(FRAGMENTS_T **) fragments = g_free_fragments;
+                       g_free_fragments = fragments;
+                       up(&g_free_fragments_mutex);
+                       up(&g_free_fragments_sema);
+               }
+               bus_dmamap_sync(&bcm2835_bus_dma_tag, bi->pagelist_map, 0,
+                   bi->pagelist_size, BUS_DMASYNC_POSTREAD);
+
+               bus_dmamap_sync(&bcm2835_bus_dma_tag, bi->dmamap, 0, bi->size,
+                   pagelist->type == PAGELIST_WRITE ?
+                   BUS_DMASYNC_POSTWRITE : BUS_DMASYNC_POSTREAD);
 
                bus_dmamap_unload(&bcm2835_bus_dma_tag, bi->dmamap);
                bus_dmamap_destroy(&bcm2835_bus_dma_tag, bi->dmamap);
                if (IS_USER_ADDRESS(bi->buf))
-                       uvm_vsunlock(bi->vmspace, bi->buf, bi->size);
+                       uvm_vsunlock(bi->proc->p_vmspace, bi->buf, bi->size);
 
                bus_dmamap_unload(&bcm2835_bus_dma_tag, bi->pagelist_map);
                bus_dmamap_destroy(&bcm2835_bus_dma_tag, bi->pagelist_map);



Home | Main Index | Thread Index | Old Index