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 of 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 check and decrement of variable i in a for loop
to make the code readable.
with and OK hshoexer@
-/* $OpenBSD: bus_dma.c,v 1.56 2024/08/20 15:30:29 bluhm Exp $ */
+/* $OpenBSD: bus_dma.c,v 1.57 2024/08/22 11:36:24 bluhm Exp $ */
/* $NetBSD: bus_dma.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
/*-
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;
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;