Download raw body.
bus dma bounce buffer contiguous virtual address
Hi,
Together with hshoexer@ we found another bug in the bus dma bounce
buffer implementation. If the physical pages are contiguous,
_bus_dmamap_load_buffer() tries to merge the segments. In case of
mbuf chains, it can happen that the physical bounce buffers are
contiguous, but the virtual addresses the mbuf m_data are not. Then
during transmit _bus_dmamap_sync() tries to copy segments where it
cannot access the virtual source address which is mapped in a
different mbuf. So if bounce buffers are used, physical and virtual
buffer must be contigous, to merge a segment.
While there split the check and decrement of variable i in the for
loop to make the code readable.
ok?
bluhm
Index: arch/amd64/amd64/bus_dma.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/bus_dma.c,v
diff -u -p -r1.56 bus_dma.c
--- arch/amd64/amd64/bus_dma.c 20 Aug 2024 15:30:29 -0000 1.56
+++ arch/amd64/amd64/bus_dma.c 21 Aug 2024 16:37:31 -0000
@@ -499,7 +499,7 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm
if (!use_bounce_buffer)
return;
- for (i = map->_dm_segcnt, sg = map->dm_segs; size && i--; sg++) {
+ for (i = map->_dm_segcnt, sg = map->dm_segs; size && i; i--, sg++) {
if (off >= sg->ds_len) {
off -= sg->ds_len;
continue;
@@ -767,9 +767,11 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t,
map->_dm_maxsegsz &&
(map->_dm_boundary == 0 ||
(map->dm_segs[seg].ds_addr & bmask) ==
- (curaddr & bmask)))
+ (curaddr & bmask)) &&
+ (!use_bounce_buffer || (map->dm_segs[seg]._ds_va +
+ map->dm_segs[seg].ds_len) == vaddr)) {
map->dm_segs[seg].ds_len += sgsize;
- else {
+ } else {
if (++seg >= map->_dm_segcnt)
break;
map->dm_segs[seg].ds_addr = curaddr;
bus dma bounce buffer contiguous virtual address