Re: [PATCH RFC]: Bus_dma eats all available memory

From: Piotr Ziêcik <kosmo_at_semihalf.com>
Date: Tue, 30 Jun 2009 15:29:42 +0200
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
_at__at_ -84,6 +84,7 _at__at_ 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;
_at__at_ -98,6 +99,7 _at__at_ 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;
 };
_at__at_ -201,7 +203,6 _at__at_ 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.
  */
_at__at_ -306,7 +307,7 _at__at_ 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) {
_at__at_ -417,7 +418,7 _at__at_ 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;
 
_at__at_ -427,9 +428,9 _at__at_ 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;
 			}
_at__at_ -994,6 +995,7 _at__at_ 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
_at__at_ -62,7 +62,6 _at__at_ __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;
 
_at__at_ -104,6 +103,7 _at__at_ 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;
_at__at_ -118,6 +118,7 _at__at_ 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;
 };
_at__at_ -427,7 +428,7 _at__at_ 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)
_at__at_ -523,7 +524,7 _at__at_ 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;
 
_at__at_ -533,9 +534,9 _at__at_ 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;
 			}
_at__at_ -1291,6 +1292,7 _at__at_ 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
_at__at_ -55,7 +55,6 _at__at_ __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;
 
_at__at_ -89,6 +88,7 _at__at_ 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;
_at__at_ -103,6 +103,7 _at__at_ 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;
 };
_at__at_ -319,7 +320,7 _at__at_ 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) {
_at__at_ -430,7 +431,7 _at__at_ 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;
 
_at__at_ -440,9 +441,9 _at__at_ 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;
 			}
_at__at_ -1012,6 +1013,7 _at__at_ 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
Received on Tue Jun 30 2009 - 11:29:44 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:50 UTC