summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2009-02-09 18:03:31 +0000
committercognet <cognet@FreeBSD.org>2009-02-09 18:03:31 +0000
commit80c343b215be744387082981af1857953d59caaa (patch)
treeadfec8c0b329cd78c9ade68562452706b01e85a8
parentb885a20f24ffe00abb3c58aabcb468b34ac7cd0b (diff)
downloadFreeBSD-src-80c343b215be744387082981af1857953d59caaa.zip
FreeBSD-src-80c343b215be744387082981af1857953d59caaa.tar.gz
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
-rw-r--r--sys/amd64/amd64/busdma_machdep.c7
-rw-r--r--sys/arm/arm/busdma_machdep.c7
-rw-r--r--sys/i386/i386/busdma_machdep.c7
3 files changed, 18 insertions, 3 deletions
diff --git a/sys/amd64/amd64/busdma_machdep.c b/sys/amd64/amd64/busdma_machdep.c
index c8f689a..c50fcc3 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 fb14ab0..a738172 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 04844f9..d4aa9b5 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);
OpenPOWER on IntegriCloud