From 80a491e45089c6893e112e1ae9673c12adfcfb02 Mon Sep 17 00:00:00 2001
From: Michael Neumann <mneumann@ntecs.de>
Date: Sat, 9 Dec 2023 02:46:00 +0100
Subject: [PATCH] busdma - Remove filter functionality

- Prevent the use of filters with bus_dma_tag_create()
- All callers use NULL today for both filterfunc and filterarg
- Remove filter functionality internally
- Remove parent tag tracking
- Without filter functions, we do not need to keep track of tag ancestry.
  All inheritance of the parent tag's parameters occurs when creating the
  new child tag.
- rename run_filter() to addr_needs_bounce()

Obtained from: FreeBSD (commits 7cb028de, 900907f4, 1228b93b, 3933ff56)
---
 share/man/man9/bus_dma.9                      | 29 ++++----
 sys/platform/pc64/x86_64/busdma_machdep.c     | 73 +++++--------------
 .../vkernel64/platform/busdma_machdep.c       | 71 +++++-------------
 3 files changed, 53 insertions(+), 120 deletions(-)

diff --git a/share/man/man9/bus_dma.9 b/share/man/man9/bus_dma.9
index 66a4e83042..b47e4f1b00 100644
--- a/share/man/man9/bus_dma.9
+++ b/share/man/man9/bus_dma.9
@@ -194,6 +194,8 @@ to
 inclusive.
 The filter function should return zero for any mapping in this range
 that can be accommodated by the device and non-zero otherwise.
+.Pp
+.Em Note: The use of filters is no longer supported and will result in an error.
 .It Vt bus_dma_segment_t
 A machine-dependent type that describes individual
 DMA segments.
@@ -367,22 +369,11 @@ This area of
 is used to bounce requests that would otherwise conflict with
 the exclusion window.
 .It Fa filtfunc
-Optional filter function (may be NULL) to be called for any attempt to
-map memory into the window described by
-.Fa lowaddr
-and
-.Fa highaddr .
-A filter function is only required when the single window described
-by
-.Fa lowaddr
-and
-.Fa highaddr
-cannot adequately describe the constraints of the device.
-The filter function will be called for every machine page
-that overlaps the exclusion window.
+Formerly the optional filter function; must be
+.Dv NULL .
 .It Fa filtfuncarg
-Argument passed to all calls to the filter function for this tag.
-May be NULL.
+Must be
+.Dv NULL .
 .It Fa maxsize
 Maximum size, in bytes, of the sum of all segment lengths in a given
 DMA mapping associated with this tag.
@@ -464,6 +455,14 @@ Returns
 .Er ENOMEM
 if sufficient memory is not available for tag creation
 or allocating mapping resources.
+Returns
+.Er EINVAL
+if either
+.Fa filtfunc
+or
+.Fa filtarg
+arguments are not
+.Dv NULL .
 .It Fn bus_dma_tag_destroy "dmat"
 Deallocate the DMA tag
 .Fa dmat
diff --git a/sys/platform/pc64/x86_64/busdma_machdep.c b/sys/platform/pc64/x86_64/busdma_machdep.c
index d656887222..201e0edee2 100644
--- a/sys/platform/pc64/x86_64/busdma_machdep.c
+++ b/sys/platform/pc64/x86_64/busdma_machdep.c
@@ -62,18 +62,14 @@ struct bounce_zone;
 struct bus_dmamap;
 
 struct bus_dma_tag {
-	bus_dma_tag_t	parent;
 	bus_size_t	alignment;
 	bus_size_t	boundary;
 	bus_addr_t	lowaddr;
 	bus_addr_t	highaddr;
-	bus_dma_filter_t *filter;
-	void		*filterarg;
 	bus_size_t	maxsize;
 	u_int		nsegments;
 	bus_size_t	maxsegsz;
 	int		flags;
-	int		ref_count;
 	int		map_count;
 	bus_dma_segment_t *segments;
 	struct bounce_zone *bounce_zone;
@@ -181,22 +177,19 @@ SYSCTL_INT(_hw_busdma, OID_AUTO, max_bpages, CTLFLAG_RD, &max_bounce_pages,
 SYSCTL_INT(_hw_busdma, OID_AUTO, bounce_alignment, CTLFLAG_RD,
 	   &bounce_alignment, 0, "Obey alignment constraint");
 
+
+/*
+ * Returns true if the address falls within the tag's exclusion window, or
+ * fails to meet its alignment requirements.
+ */
 static __inline int
-run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+addr_needs_bounce(bus_dma_tag_t dmat, bus_addr_t paddr)
 {
-	int retval;
+	if ((paddr > dmat->lowaddr && paddr <= dmat->highaddr) ||
+	     (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0))
+        return (1);
 
-	retval = 0;
-	do {
-		if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr) ||
-		     (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0))
-		 && (dmat->filter == NULL ||
-		     dmat->filter(dmat->filterarg, paddr) != 0))
-			retval = 1;
-
-		dmat = dmat->parent;
-	} while (retval == 0 && dmat != NULL);
-	return (retval);
+	return (0);
 }
 
 static __inline
@@ -236,6 +229,10 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 	bus_dma_tag_t newtag;
 	int error = 0;
 
+	/* Filters are no longer supported. */
+	if (filter != NULL || filterarg != NULL)
+		return (EINVAL);
+
 	/*
 	 * Sanity checks
 	 */
@@ -261,18 +258,14 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 	newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT | M_ZERO);
 
 	spin_init(&newtag->spin, "busdmacreate");
-	newtag->parent = parent;
 	newtag->alignment = alignment;
 	newtag->boundary = boundary;
 	newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
 	newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
-	newtag->filter = filter;
-	newtag->filterarg = filterarg;
 	newtag->maxsize = maxsize;
 	newtag->nsegments = nsegments;
 	newtag->maxsegsz = maxsegsz;
 	newtag->flags = flags;
-	newtag->ref_count = 1; /* Count ourself */
 	newtag->map_count = 0;
 	newtag->segments = NULL;
 	newtag->bounce_zone = NULL;
@@ -293,17 +286,6 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 		newtag->alignment = MAX(parent->alignment, newtag->alignment);
 #endif
 
-		if (newtag->filter == NULL) {
-			/*
-			 * Short circuit looking at our parent directly
-			 * since we have encapsulated all of its information
-			 */
-			newtag->filter = parent->filter;
-			newtag->filterarg = parent->filterarg;
-			newtag->parent = parent->parent;
-		}
-		if (newtag->parent != NULL)
-			parent->ref_count++;
 	}
 
 	if (newtag->lowaddr < ptoa(Maxmem))
@@ -360,25 +342,10 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 		if (dmat->map_count != 0)
 			return (EBUSY);
 
-		while (dmat != NULL) {
-			bus_dma_tag_t parent;
-
-			parent = dmat->parent;
-			dmat->ref_count--;
-			if (dmat->ref_count == 0) {
-				free_bounce_zone(dmat);
-				if (dmat->segments != NULL)
-					kfree(dmat->segments, M_DEVBUF);
-				kfree(dmat, M_DEVBUF);
-				/*
-				 * Last reference count, so
-				 * release our reference
-				 * count on our parent.
-				 */
-				dmat = parent;
-			} else
-				dmat = NULL;
-		}
+		free_bounce_zone(dmat);
+		if (dmat->segments != NULL)
+			kfree(dmat->segments, M_DEVBUF);
+		kfree(dmat, M_DEVBUF);
 	}
 	return (0);
 }
@@ -661,7 +628,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
 
 		while (vaddr < vendaddr) {
 			paddr = _bus_dma_extract(pmap, vaddr);
-			if (run_filter(dmat, paddr) != 0)
+			if (addr_needs_bounce(dmat, paddr))
 				map->pagesneeded++;
 			vaddr += (PAGE_SIZE - (vaddr & PAGE_MASK));
 		}
@@ -716,7 +683,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
 		size = PAGE_SIZE - (paddr & PAGE_MASK);
 		if (size > buflen)
 			size = buflen;
-		if (map->pagesneeded != 0 && run_filter(dmat, paddr)) {
+		if (map->pagesneeded != 0 && addr_needs_bounce(dmat, paddr)) {
 			/*
 			 * NOTE: paddr may have different in-page offset,
 			 *	 unless BUS_DMA_KEEP_PG_OFFSET is set.
diff --git a/sys/platform/vkernel64/platform/busdma_machdep.c b/sys/platform/vkernel64/platform/busdma_machdep.c
index 781e517779..023d553c5e 100644
--- a/sys/platform/vkernel64/platform/busdma_machdep.c
+++ b/sys/platform/vkernel64/platform/busdma_machdep.c
@@ -53,18 +53,14 @@ struct bounce_zone;
 struct bus_dmamap;
 
 struct bus_dma_tag {
-	bus_dma_tag_t	parent;
 	bus_size_t	alignment;
 	bus_size_t	boundary;
 	bus_addr_t	lowaddr;
 	bus_addr_t	highaddr;
-	bus_dma_filter_t *filter;
-	void		*filterarg;
 	bus_size_t	maxsize;
 	u_int		nsegments;
 	bus_size_t	maxsegsz;
 	int		flags;
-	int		ref_count;
 	int		map_count;
 	bus_dma_segment_t *segments;
 	struct bounce_zone *bounce_zone;
@@ -165,22 +161,19 @@ SYSCTL_INT(_hw_busdma, OID_AUTO, max_bpages, CTLFLAG_RD, &max_bounce_pages,
 SYSCTL_INT(_hw_busdma, OID_AUTO, bounce_alignment, CTLFLAG_RD,
 	   &bounce_alignment, 0, "Obey alignment constraint");
 
+
+/*
+ * Returns true if the address falls within the tag's exclusion window, or
+ * fails to meet its alignment requirements.
+ */
 static __inline int
-run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+addr_needs_bounce(bus_dma_tag_t dmat, bus_addr_t paddr)
 {
-	int retval;
+    if ((paddr > dmat->lowaddr && paddr <= dmat->highaddr) ||
+         (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0))
+        return (1);
 
-	retval = 0;
-	do {
-		if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr) ||
-		     (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0))
-		 && (dmat->filter == NULL ||
-		     dmat->filter(dmat->filterarg, paddr) != 0))
-			retval = 1;
-
-		dmat = dmat->parent;
-	} while (retval == 0 && dmat != NULL);
-	return (retval);
+    return (0);
 }
 
 /*
@@ -196,6 +189,10 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 	bus_dma_tag_t newtag;
 	int error = 0;
 
+	/* Filters are no longer supported. */
+	if (filter != NULL || filterarg != NULL)
+		return (EINVAL);
+
 	/*
 	 * Sanity checks
 	 */
@@ -220,18 +217,14 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 
 	newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT);
 
-	newtag->parent = parent;
 	newtag->alignment = alignment;
 	newtag->boundary = boundary;
 	newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
 	newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
-	newtag->filter = filter;
-	newtag->filterarg = filterarg;
 	newtag->maxsize = maxsize;
 	newtag->nsegments = nsegments;
 	newtag->maxsegsz = maxsegsz;
 	newtag->flags = flags;
-	newtag->ref_count = 1; /* Count ourself */
 	newtag->map_count = 0;
 	newtag->segments = NULL;
 	newtag->bounce_zone = NULL;
@@ -252,17 +245,6 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
 		newtag->alignment = MAX(parent->alignment, newtag->alignment);
 #endif
 
-		if (newtag->filter == NULL) {
-			/*
-			 * Short circuit looking at our parent directly
-			 * since we have encapsulated all of its information
-			 */
-			newtag->filter = parent->filter;
-			newtag->filterarg = parent->filterarg;
-			newtag->parent = parent->parent;
-		}
-		if (newtag->parent != NULL)
-			parent->ref_count++;
 	}
 
 	if (newtag->lowaddr < ptoa(Maxmem))
@@ -316,24 +298,9 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 		if (dmat->map_count != 0)
 			return (EBUSY);
 
-		while (dmat != NULL) {
-			bus_dma_tag_t parent;
-
-			parent = dmat->parent;
-			dmat->ref_count--;
-			if (dmat->ref_count == 0) {
-				if (dmat->segments != NULL)
-					kfree(dmat->segments, M_DEVBUF);
-				kfree(dmat, M_DEVBUF);
-				/*
-				 * Last reference count, so
-				 * release our reference
-				 * count on our parent.
-				 */
-				dmat = parent;
-			} else
-				dmat = NULL;
-		}
+        if (dmat->segments != NULL)
+            kfree(dmat->segments, M_DEVBUF);
+        kfree(dmat, M_DEVBUF);
 	}
 	return (0);
 }
@@ -597,7 +564,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
 
 		while (vaddr < vendaddr) {
 			paddr = _bus_dma_extract(pmap, vaddr);
-			if (run_filter(dmat, paddr) != 0)
+			if (addr_needs_bounce(dmat, paddr))
 				map->pagesneeded++;
 			vaddr += (PAGE_SIZE - (vaddr & PAGE_MASK));
 		}
@@ -652,7 +619,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
 		size = PAGE_SIZE - (paddr & PAGE_MASK);
 		if (size > buflen)
 			size = buflen;
-		if (map->pagesneeded != 0 && run_filter(dmat, paddr)) {
+		if (map->pagesneeded != 0 && addr_needs_bounce(dmat, paddr)) {
 			/*
 			 * note: this paddr has the same in-page offset
 			 * as vaddr and thus the paddr above, so the
-- 
2.42.0

