Index: sys/arch/mips/mips/bus_dma.c =================================================================== RCS file: /cvsroot/src/sys/arch/mips/mips/bus_dma.c,v retrieving revision 1.36 diff -u -p -r1.36 bus_dma.c --- sys/arch/mips/mips/bus_dma.c 22 Jul 2016 19:50:44 -0000 1.36 +++ sys/arch/mips/mips/bus_dma.c 29 Jul 2016 16:31:06 -0000 @@ -107,7 +107,8 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, int *segp, bool first) { paddr_t baddr, curaddr, lastaddr; - vaddr_t vaddr = (vaddr_t)buf, lastvaddr; + vaddr_t vaddr = (vaddr_t)buf; + register_t lastvaddr; bus_dma_segment_t *ds = &map->dm_segs[*segp]; bus_dma_segment_t * const eds = &map->dm_segs[map->_dm_segcnt]; const bus_addr_t bmask = ~(map->_dm_boundary - 1); @@ -166,12 +167,8 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, * Insert chunk into a segment, coalescing with * the previous segment if possible. */ - if (first) { - ds->ds_addr = curaddr; - ds->ds_len = sgsize; - ds->_ds_vaddr = vaddr; - first = false; - } else if (curaddr == lastaddr + if (!first + && curaddr == lastaddr && (d_cache_coherent #ifndef __mips_o32 || !MIPS_CACHE_VIRTUAL_ALIAS @@ -182,11 +179,12 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, || ((ds->ds_addr ^ curaddr) & bmask) == 0)) { ds->ds_len += sgsize; } else { - if (++ds >= eds) + if (!first && ++ds >= eds) break; ds->ds_addr = curaddr; ds->ds_len = sgsize; ds->_ds_vaddr = vaddr; + first = false; /* * If this segment uses the correct color, try to see * if we can use a direct-mapped VA for the segment. @@ -206,12 +204,15 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, MIPS_PHYS_TO_XKPHYS_CACHED(curaddr); #endif } + /* Make sure this is a valid kernel address */ + KASSERTMSG(((register_t)ds->_ds_vaddr) < 0, + "%"PRIxBUSADDR, ds->_ds_vaddr); } lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; - lastvaddr = vaddr; + lastvaddr += sgsize; } *segp = ds - map->dm_segs; @@ -851,13 +852,13 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm * Now at the first segment to sync; nail each segment until we * have exhausted the length. */ - register_t vaddr = (intptr_t)seg->_ds_vaddr + offset; + register_t vaddr = (register_t)seg->_ds_vaddr + offset; minlen = ulmin(len, seg->ds_len - offset); #ifdef BUS_DMA_DEBUG printf("bus_dmamap_sync: flushing segment %p " - "(0x%"PRIxBUSADDR"+%"PRIxBUSADDR - ", 0x%"PRIxBUSADDR"+0x%"PRIxBUSADDR + "(0x%"PRIxREGISTER"+%"PRIxBUSADDR + ", 0x%"PRIxREGISTER"+0x%"PRIxBUSADDR ") (olen = %"PRIxBUSADDR")...", seg, vaddr - offset, offset, vaddr - offset, offset + minlen - 1, len);