if we have to bounce a buffer, clear our anything already setup in the map before trying again. riastradh@ noticed that a map had two types of mbuf types, and this seems to avoid it as seen on eqos(4) on quartz64. add a couple more event counts for bus dma events. Index: sys/arch/arm/arm32/bus_dma.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/arm32/bus_dma.c,v retrieving revision 1.134 diff -p -u -r1.134 bus_dma.c --- sys/arch/arm/arm32/bus_dma.c 20 Dec 2021 13:58:58 -0000 1.134 +++ sys/arch/arm/arm32/bus_dma.c 6 Feb 2022 09:27:28 -0000 @@ -71,6 +71,8 @@ static struct evcnt bus_dma_write_bounce EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "write bounces"); static struct evcnt bus_dma_bounced_unloads = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced unloads"); +static struct evcnt bus_dma_bounced_mbuf_loads = + EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "bounced mbuf loads"); static struct evcnt bus_dma_unloads = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "unloads"); static struct evcnt bus_dma_bounced_destroys = @@ -93,6 +95,8 @@ static struct evcnt bus_dma_sync_postrea EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "sync postreadwrite"); static struct evcnt bus_dma_sync_postwrite = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "sync postwrite"); +static struct evcnt bus_dma_inrange_fail = + EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "inrange check failed"); static struct evcnt bus_dma_sync_coherent_prereadwrite = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "busdma", "sync coherent prereadwrite"); @@ -118,6 +122,7 @@ EVCNT_ATTACH_STATIC(bus_dma_unloads); EVCNT_ATTACH_STATIC(bus_dma_bounced_unloads); EVCNT_ATTACH_STATIC(bus_dma_destroys); EVCNT_ATTACH_STATIC(bus_dma_bounced_destroys); +EVCNT_ATTACH_STATIC(bus_dma_bounced_mbuf_loads); EVCNT_ATTACH_STATIC(bus_dma_sync_prereadwrite); EVCNT_ATTACH_STATIC(bus_dma_sync_preread_begin); EVCNT_ATTACH_STATIC(bus_dma_sync_preread); @@ -126,6 +131,7 @@ EVCNT_ATTACH_STATIC(bus_dma_sync_prewrit EVCNT_ATTACH_STATIC(bus_dma_sync_postread); EVCNT_ATTACH_STATIC(bus_dma_sync_postreadwrite); EVCNT_ATTACH_STATIC(bus_dma_sync_postwrite); +EVCNT_ATTACH_STATIC(bus_dma_inrange_fail); EVCNT_ATTACH_STATIC(bus_dma_sync_coherent_prereadwrite); EVCNT_ATTACH_STATIC(bus_dma_sync_coherent_preread); @@ -210,8 +216,10 @@ _bus_dmamap_load_paddr(bus_dma_tag_t t, /* XXX cache last result? */ const struct arm32_dma_range * const dr = _bus_dma_paddr_inrange(t->_ranges, t->_nranges, paddr); - if (dr == NULL) + if (dr == NULL) { + STAT_INCR(inrange_fail); return EINVAL; + } /* * If this region is coherent, mark the segment as coherent. @@ -310,6 +318,7 @@ _bus_dma_load_bouncebuf(bus_dma_tag_t t, */ cookie->id_origbuf = buf; cookie->id_origbuflen = buflen; + KASSERT(map->dm_nsegs == 0); error = _bus_dmamap_load_buffer(t, map, cookie->id_bouncebuf, buflen, vm, flags); if (error) @@ -552,6 +561,11 @@ _bus_dmamap_load(bus_dma_tag_t t, bus_dm #ifdef _ARM32_NEED_BUS_DMA_BOUNCE struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie; if (cookie != NULL && (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) { + /* Since we're trying again, clear the previous attempt. */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID; + map->_dm_flags |= _BUS_DMAMAP_COHERENT; error = _bus_dma_load_bouncebuf(t, map, buf, buflen, _BUS_DMA_BUFTYPE_LINEAR, flags); } @@ -696,8 +710,14 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b #ifdef _ARM32_NEED_BUS_DMA_BOUNCE struct arm32_bus_dma_cookie * const cookie = map->_dm_cookie; if (cookie != NULL && (cookie->id_flags & _BUS_DMA_MIGHT_NEED_BOUNCE)) { + /* Since we're trying again, clear the previous attempt. */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + map->_dm_buftype = _BUS_DMA_BUFTYPE_INVALID; + map->_dm_flags |= _BUS_DMAMAP_COHERENT; error = _bus_dma_load_bouncebuf(t, map, m0, m0->m_pkthdr.len, _BUS_DMA_BUFTYPE_MBUF, flags); + STAT_INCR(bounced_mbuf_loads); } #endif return error;