Index: bus_dma.c =================================================================== RCS file: /cvs/src/sys/arch/landisk/landisk/bus_dma.c,v retrieving revision 1.13 diff -u -p -r1.13 bus_dma.c --- bus_dma.c 25 Jan 2015 11:36:41 -0000 1.13 +++ bus_dma.c 28 Jan 2015 06:53:05 -0000 @@ -145,56 +145,56 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, bus_dma_segment_t * const segs = map->dm_segs; bus_addr_t bmask = ~(map->_dm_boundary - 1); - int first = map->dm_mapsize == 0; int nseg = map->dm_nsegs; - paddr_t lastaddr = SH3_P2SEG_TO_PHYS(segs[nseg].ds_addr); + bus_addr_t dvaddr = SH3_PHYS_TO_P2SEG(paddr); + bus_size_t len = size; - map->dm_mapsize += size; + if (map->dm_mapsize == 0) + ; /* First segment */ + else if (segs[nseg].ds_addr + segs[nseg].ds_len == dvaddr) { + /* Coalesce */ + dvaddr = segs[nseg].ds_addr; + len += segs[nseg].ds_len; + vaddr = segs[nseg]._ds_vaddr; + } else { + /* Next segment */ + if (++nseg >= map->_dm_segcnt) + return (EFBIG); + } - do { - bus_size_t sgsize = size; + for (;;) { + bus_size_t sgsize = len; /* Make sure we don't cross any boundaries. */ if (map->_dm_boundary > 0) { bus_addr_t baddr; /* next boundary address */ - baddr = (paddr + map->_dm_boundary) & bmask; - if (sgsize > (baddr - paddr)) - sgsize = (baddr - paddr); + baddr = (dvaddr + map->_dm_boundary) & bmask; + if (sgsize > (baddr - dvaddr)) + sgsize = (baddr - dvaddr); } - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - /* first segment */ - segs[nseg].ds_addr = SH3_PHYS_TO_P2SEG(paddr); - segs[nseg].ds_len = sgsize; - segs[nseg]._ds_vaddr = vaddr; - first = 0; - } else if ((paddr == lastaddr) - && (segs[nseg].ds_len + sgsize <= map->_dm_maxsegsz) - && (map->_dm_boundary == 0 || - (segs[nseg].ds_addr & bmask) == (paddr & bmask))) { - /* coalesce */ - segs[nseg].ds_len += sgsize; - } else { - if (++nseg >= map->_dm_segcnt) - return (EFBIG); - - /* new segment */ - segs[nseg].ds_addr = SH3_PHYS_TO_P2SEG(paddr); - segs[nseg].ds_len = sgsize; - segs[nseg]._ds_vaddr = vaddr; - } + /* Make sure we dont exceed the max segment size. */ + if (sgsize > map->_dm_maxsegsz) + sgsize = map->_dm_maxsegsz; + + /* Insert chunk into a segment. */ + segs[nseg].ds_addr = dvaddr; + segs[nseg].ds_len = sgsize; + segs[nseg]._ds_vaddr = vaddr; + + len -= sgsize; + if (len == 0) + break; - lastaddr = paddr + sgsize; - paddr += sgsize; + if (++nseg >= map->_dm_segcnt) + return (EFBIG); + + dvaddr += sgsize; vaddr += sgsize; - size -= sgsize; - } while (size > 0); + } + map->dm_mapsize += size; map->dm_nsegs = nseg; return (0);