[PATCH RFC]: Bus_dma eats all available memory
Piotr Zięcik
kosmo at semihalf.com
Tue Jun 30 13:29:44 UTC 2009
Friday 26 June 2009 16:01:17 Scott Long napisał(a):
>
> Tags and maps should be allocated at driver initialization time, not
> every time a request comes in. The problem here isn't the MAX() test,
> it's that the MIN_ALLOC_COMP test is getting fooled because the tag
> keeps on getting recycled. The correct fix is likely to move the flag
> into the bounce zone object. But in general, you should not be
> allocating and freeing tags and maps so often, they are meant to have a
> long lifespan.
>
I have fixed my driver and updated patch for bus_dma. Could I ask you for
review ? Patch was successfully tested on ARM.
diff --git a/sys/amd64/amd64/busdma_machdep.c
b/sys/amd64/amd64/busdma_machdep.c
index 775f142..dde9159 100644
--- a/sys/amd64/amd64/busdma_machdep.c
+++ b/sys/amd64/amd64/busdma_machdep.c
@@ -84,6 +84,7 @@ struct bounce_page {
int busdma_swi_pending;
+#define BZ_MIN_ALLOC_COMP 0x01
struct bounce_zone {
STAILQ_ENTRY(bounce_zone) links;
STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -98,6 +99,7 @@ struct bounce_zone {
bus_addr_t lowaddr;
char zoneid[8];
char lowaddrid[20];
+ int flags;
struct sysctl_ctx_list sysctl_tree;
struct sysctl_oid *sysctl_tree_top;
};
@@ -201,7 +203,6 @@ dflt_lock(void *arg, bus_dma_lock_op_t op)
}
#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
-#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
/*
* Allocate a device specific dma_tag.
*/
@@ -306,7 +307,7 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t
alignment,
error = ENOMEM;
}
/* Performed initial allocation */
- newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
}
if (error != 0) {
@@ -417,7 +418,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
maxpages = MAX_BPAGES;
else
maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr));
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0
|| (bz->map_count > 0 && bz->total_bpages < maxpages)) {
int pages;
@@ -427,9 +428,9 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
if (alloc_bounce_pages(dmat, pages) < pages)
error = ENOMEM;
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0) {
if (error == 0)
- dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
} else {
error = 0;
}
@@ -994,6 +995,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat)
bz->lowaddr = dmat->lowaddr;
bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
bz->map_count = 0;
+ bz->flags = 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 a8b2de9..bbda08b 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -62,7 +62,6 @@ __FBSDID("$FreeBSD: src/sys/arm/arm/busdma_machdep.c,v 1.47
2009/04/23 20:24:19
#define MAX_BPAGES 64
#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
-#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
struct bounce_zone;
@@ -104,6 +103,7 @@ struct bounce_page {
int busdma_swi_pending;
+#define BZ_MIN_ALLOC_COMP 0x01
struct bounce_zone {
STAILQ_ENTRY(bounce_zone) links;
STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -118,6 +118,7 @@ struct bounce_zone {
bus_addr_t lowaddr;
char zoneid[8];
char lowaddrid[20];
+ int flags;
struct sysctl_ctx_list sysctl_tree;
struct sysctl_oid *sysctl_tree_top;
};
@@ -427,7 +428,7 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t
alignment,
error = ENOMEM;
}
/* Performed initial allocation */
- newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
} else
newtag->bounce_zone = NULL;
if (error != 0)
@@ -523,7 +524,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
* basis up to a sane limit.
*/
maxpages = MAX_BPAGES;
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0
|| (bz->map_count > 0 && bz->total_bpages < maxpages)) {
int pages;
@@ -533,9 +534,9 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
if (alloc_bounce_pages(dmat, pages) < pages)
error = ENOMEM;
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0) {
if (error == 0)
- dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
} else {
error = 0;
}
@@ -1291,6 +1292,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat)
bz->lowaddr = dmat->lowaddr;
bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
bz->map_count = 0;
+ bz->flags = 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 50c1545..4ceaa05 100644
--- a/sys/i386/i386/busdma_machdep.c
+++ b/sys/i386/i386/busdma_machdep.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD: src/sys/i386/i386/busdma_machdep.c,v
1.99 2009/04/23 20:24:1
#define MAX_BPAGES 512
#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
-#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
struct bounce_zone;
@@ -89,6 +88,7 @@ struct bounce_page {
int busdma_swi_pending;
+#define BZ_MIN_ALLOC_COMP 0x01
struct bounce_zone {
STAILQ_ENTRY(bounce_zone) links;
STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -103,6 +103,7 @@ struct bounce_zone {
bus_addr_t lowaddr;
char zoneid[8];
char lowaddrid[20];
+ int flags;
struct sysctl_ctx_list sysctl_tree;
struct sysctl_oid *sysctl_tree_top;
};
@@ -319,7 +320,7 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t
alignment,
error = ENOMEM;
}
/* Performed initial allocation */
- newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
}
if (error != 0) {
@@ -430,7 +431,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
maxpages = MAX_BPAGES;
else
maxpages = MIN(MAX_BPAGES, Maxmem -atop(dmat->lowaddr));
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0
|| (bz->map_count > 0 && bz->total_bpages < maxpages)) {
int pages;
@@ -440,9 +441,9 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
if (alloc_bounce_pages(dmat, pages) < pages)
error = ENOMEM;
- if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+ if ((bz->flags & BZ_MIN_ALLOC_COMP) == 0) {
if (error == 0)
- dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ bz->flags |= BZ_MIN_ALLOC_COMP;
} else {
error = 0;
}
@@ -1012,6 +1013,7 @@ alloc_bounce_zone(bus_dma_tag_t dmat)
bz->lowaddr = dmat->lowaddr;
bz->alignment = MAX(dmat->alignment, PAGE_SIZE);
bz->map_count = 0;
+ bz->flags = 0;
snprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
busdma_zonecount++;
snprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
--
Best Regards,
Piotr Ziecik
More information about the freebsd-current
mailing list