svn commit: r368697 - head/sys/arm64/arm64

Michal Meloun mmel at FreeBSD.org
Wed Dec 16 14:36:58 UTC 2020


Author: mmel
Date: Wed Dec 16 14:36:57 2020
New Revision: 368697
URL: https://svnweb.freebsd.org/changeset/base/368697

Log:
  Allocate right number of pages for the bounced buffers crossing the page.
  
  One of the disadvantages of our current busdma code is the fact that
  we process the bounced buffer in a page-by-page manner. This means that
  the short (subpage) buffer allocated across page boundaries is bounced
  to 2 separate pages.
  
  This suboptimal behavior is consistent across all platforms and can be
  related to (probably unimplementable or incompatible with bouncing)
  BUS_DMA_KEEP_PG_OFFSET flag.
  
  Therefore, allocate one additional page to be fully comply with this
  requirement.
  
  Discused with:	markj
  PR:		251018

Modified:
  head/sys/arm64/arm64/busdma_bounce.c

Modified: head/sys/arm64/arm64/busdma_bounce.c
==============================================================================
--- head/sys/arm64/arm64/busdma_bounce.c	Wed Dec 16 14:01:04 2020	(r368696)
+++ head/sys/arm64/arm64/busdma_bounce.c	Wed Dec 16 14:36:57 2020	(r368697)
@@ -297,6 +297,12 @@ bounce_bus_dma_tag_create(bus_dma_tag_t parent, bus_si
 
 	if ((flags & BUS_DMA_ALLOCNOW) != 0) {
 		struct bounce_zone *bz;
+		/*
+		 * Round size up to a full page, and add one more page because
+		 * there can always be one more boundary crossing than the
+		 * number of pages in a transfer.
+		 */
+		maxsize = roundup2(maxsize, PAGE_SIZE) + PAGE_SIZE;
 
 		/* Must bounce */
 		if ((error = alloc_bounce_zone(newtag)) != 0) {
@@ -308,7 +314,7 @@ bounce_bus_dma_tag_create(bus_dma_tag_t parent, bus_si
 		if (ptoa(bz->total_bpages) < maxsize) {
 			int pages;
 
-			pages = atop(round_page(maxsize)) - bz->total_bpages;
+			pages = atop(maxsize) + 1 - bz->total_bpages;
 
 			/* Add pages to our bounce pool */
 			if (alloc_bounce_pages(newtag, pages) < pages)
@@ -436,8 +442,10 @@ bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags
 	bz = dmat->bounce_zone;
 
 	/*
-	 * Attempt to add pages to our pool on a per-instance
-	 * basis up to a sane limit.
+	 * Attempt to add pages to our pool on a per-instancebasis up to a sane
+	 * limit. Even if the tag isn't subject of bouncing due to alignment
+	 * and boundary constraints, it could still auto-bounce due to
+	 * cacheline alignment, which requires at most two bounce pages.
 	 */
 	if (dmat->common.alignment > 1)
 		maxpages = MAX_BPAGES;
@@ -446,9 +454,9 @@ bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags
 		    atop(dmat->common.lowaddr));
 	if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0 ||
 	    (bz->map_count > 0 && bz->total_bpages < maxpages)) {
-		pages = MAX(atop(dmat->common.maxsize), 1);
+		pages = atop(roundup2(dmat->common.maxsize, PAGE_SIZE)) + 1;
 		pages = MIN(maxpages - bz->total_bpages, pages);
-		pages = MAX(pages, 1);
+		pages = MAX(pages, 2);
 		if (alloc_bounce_pages(dmat, pages) < pages)
 			error = ENOMEM;
 		if ((dmat->bounce_flags & BF_MIN_ALLOC_COMP) == 0) {


More information about the svn-src-all mailing list