From 80c343b215be744387082981af1857953d59caaa Mon Sep 17 00:00:00 2001 From: cognet Date: Mon, 9 Feb 2009 18:03:31 +0000 Subject: [PATCH] The bounce zone sees its page number increased if multiple dma maps use it in the same dma tag. However, it can happen multiple dma tags share the same bounce zone too, so add a per-bounce zone map counter, and check it instead of the dma tag map counter, to know if we have to alloc more pages. Reported by: miwi Reviewed by: scottl --- sys/amd64/amd64/busdma_machdep.c | 7 ++++++- sys/arm/arm/busdma_machdep.c | 7 ++++++- sys/i386/i386/busdma_machdep.c | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/sys/amd64/amd64/busdma_machdep.c b/sys/amd64/amd64/busdma_machdep.c index c8f689abc94f..c50fcc3cef9e 100644 --- a/sys/amd64/amd64/busdma_machdep.c +++ b/sys/amd64/amd64/busdma_machdep.c @@ -93,6 +93,7 @@ struct bounce_zone { int active_bpages; int total_bounced; int total_deferred; + int map_count; bus_size_t alignment; bus_size_t boundary; bus_addr_t lowaddr; @@ -418,7 +419,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) else maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr)); if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 - || (dmat->map_count > 0 && bz->total_bpages < maxpages)) { + || (bz->map_count > 0 && bz->total_bpages < maxpages)) { int pages; pages = MAX(atop(dmat->maxsize), 1); @@ -434,6 +435,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) error = 0; } } + bz->map_count++; } else { *mapp = NULL; } @@ -457,6 +459,8 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) __func__, dmat, EBUSY); return (EBUSY); } + if (dmat->bounce_zone) + dmat->bounce_zone->map_count--; free(map, M_DEVBUF); } dmat->map_count--; @@ -989,6 +993,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat) bz->lowaddr = dmat->lowaddr; bz->alignment = dmat->alignment; bz->boundary = dmat->boundary; + bz->map_count = 0; snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount); busdma_zonecount++; snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr); diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index fb14ab096f47..a7381724682d 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -112,6 +112,7 @@ struct bounce_zone { int active_bpages; int total_bounced; int total_deferred; + int map_count; bus_size_t alignment; bus_size_t boundary; bus_addr_t lowaddr; @@ -523,7 +524,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) */ maxpages = MAX_BPAGES; if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 - || (dmat->map_count > 0 && bz->total_bpages < maxpages)) { + || (bz->map_count > 0 && bz->total_bpages < maxpages)) { int pages; pages = MAX(atop(dmat->maxsize), 1); @@ -539,6 +540,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) error = 0; } } + bz->map_count++; } CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", __func__, dmat, dmat->flags, error); @@ -560,6 +562,8 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) __func__, dmat, EBUSY); return (EBUSY); } + if (dmat->bounce_zone) + dmat->bounce_zone->map_count--; dmat->map_count--; CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat); return (0); @@ -1277,6 +1281,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat) bz->lowaddr = dmat->lowaddr; bz->alignment = dmat->alignment; bz->boundary = dmat->boundary; + bz->map_count = 0; snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount); busdma_zonecount++; snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr); diff --git a/sys/i386/i386/busdma_machdep.c b/sys/i386/i386/busdma_machdep.c index 04844f98dcad..d4aa9b51c1c0 100644 --- a/sys/i386/i386/busdma_machdep.c +++ b/sys/i386/i386/busdma_machdep.c @@ -98,6 +98,7 @@ struct bounce_zone { int active_bpages; int total_bounced; int total_deferred; + int map_count; bus_size_t alignment; bus_size_t boundary; bus_addr_t lowaddr; @@ -431,7 +432,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) else maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr)); if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 - || (dmat->map_count > 0 && bz->total_bpages < maxpages)) { + || (bz->map_count > 0 && bz->total_bpages < maxpages)) { int pages; pages = MAX(atop(dmat->maxsize), 1); @@ -447,6 +448,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) error = 0; } } + bz->map_count++; } else { *mapp = NULL; } @@ -470,6 +472,8 @@ bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) __func__, dmat, EBUSY); return (EBUSY); } + if (dmat->bounce_zone) + dmat->bounce_zone->map_count--; free(map, M_DEVBUF); } dmat->map_count--; @@ -1007,6 +1011,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat) bz->lowaddr = dmat->lowaddr; bz->alignment = dmat->alignment; bz->boundary = dmat->boundary; + bz->map_count = 0; snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount); busdma_zonecount++; snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);