svn commit: r251868 - in stable/9/sys: arm/arm mips/mips

Scott Long scottl at FreeBSD.org
Mon Jun 17 20:40:17 UTC 2013


Author: scottl
Date: Mon Jun 17 20:40:16 2013
New Revision: 251868
URL: http://svnweb.freebsd.org/changeset/base/251868

Log:
  MFC r240177:
  
  Dynamically allocate the S/G lists passed to callback routines rather than
  allocating them on the stack of various bus_dmamap_load*() functions.  The
  S/G lists are stored in the DMA tags.  This matches the implementation on
  all other platforms.
  
  Submitted by:	jhb
  Approved by:	marius, adrian
  Obtained from:	Netflix

Modified:
  stable/9/sys/arm/arm/busdma_machdep.c
  stable/9/sys/mips/mips/busdma_machdep.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/arm/arm/busdma_machdep.c
==============================================================================
--- stable/9/sys/arm/arm/busdma_machdep.c	Mon Jun 17 20:27:20 2013	(r251867)
+++ stable/9/sys/arm/arm/busdma_machdep.c	Mon Jun 17 20:40:16 2013	(r251868)
@@ -81,6 +81,7 @@ struct bus_dma_tag {
 	int			map_count;
 	bus_dma_lock_t		*lockfunc;
 	void			*lockfuncarg;
+	bus_dma_segment_t	*segments;
 	/*
 	 * DMA range for this tag.  If the page doesn't fall within
 	 * one of these ranges, an error is returned.  The caller
@@ -374,6 +375,8 @@ bus_dma_tag_create(bus_dma_tag_t parent,
 		newtag->lockfunc = dflt_lock;
 		newtag->lockfuncarg = NULL;
 	}
+	newtag->segments = NULL;
+
         /*
 	 * Take into account any restrictions imposed by our parent tag
 	 */
@@ -447,7 +450,6 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 #endif
 
 	if (dmat != NULL) {
-		
                 if (dmat->map_count != 0)
                         return (EBUSY);
 		
@@ -457,6 +459,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
                         parent = dmat->parent;
                         atomic_subtract_int(&dmat->ref_count, 1);
                         if (dmat->ref_count == 0) {
+				if (dmat->segments != NULL)
+					free(dmat->segments, M_DEVBUF);
                                 free(dmat, M_DEVBUF);
                                 /*
                                  * Last reference count, so
@@ -484,6 +488,17 @@ bus_dmamap_create(bus_dma_tag_t dmat, in
 	bus_dmamap_t newmap;
 	int error = 0;
 
+	if (dmat->segments == NULL) {
+		dmat->segments = (bus_dma_segment_t *)malloc(
+		    sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
+		    M_NOWAIT);
+		if (dmat->segments == NULL) {
+			CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+			    __func__, dmat, ENOMEM);
+			return (ENOMEM);
+		}
+	}
+
 	newmap = _busdma_alloc_dmamap();
 	if (newmap == NULL) {
 		CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
@@ -585,6 +600,16 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 		mflags = M_NOWAIT;
 	else
 		mflags = M_WAITOK;
+	if (dmat->segments == NULL) {
+		dmat->segments = (bus_dma_segment_t *)malloc(
+		    sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
+		    mflags);
+		if (dmat->segments == NULL) {
+			CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+			    __func__, dmat, dmat->flags, ENOMEM);
+			return (ENOMEM);
+		}
+	}
 	if (flags & BUS_DMA_ZERO)
 		mflags |= M_ZERO;
 
@@ -883,11 +908,6 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
 {
      	vm_offset_t	lastaddr = 0;
 	int		error, nsegs = -1;
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 
 	KASSERT(dmat != NULL, ("dmatag is NULL"));
 	KASSERT(map != NULL, ("dmamap is NULL"));
@@ -898,14 +918,14 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
 	map->buffer = buf;
 	map->len = buflen;
 	error = bus_dmamap_load_buffer(dmat,
-	    dm_segments, map, buf, buflen, kernel_pmap,
+	    dmat->segments, map, buf, buflen, kernel_pmap,
 	    flags, &lastaddr, &nsegs);
 	if (error == EINPROGRESS)
 		return (error);
 	if (error)
 		(*callback)(callback_arg, NULL, 0, error);
 	else
-		(*callback)(callback_arg, dm_segments, nsegs + 1, error);
+		(*callback)(callback_arg, dmat->segments, nsegs + 1, error);
 	
 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
 	    __func__, dmat, dmat->flags, nsegs + 1, error);
@@ -921,11 +941,6 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
 		     bus_dmamap_callback2_t *callback, void *callback_arg,
 		     int flags)
 {
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 	int nsegs = -1, error = 0;
 
 	M_ASSERTPKTHDR(m0);
@@ -941,7 +956,7 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
 		for (m = m0; m != NULL && error == 0; m = m->m_next) {
 			if (m->m_len > 0) {
 				error = bus_dmamap_load_buffer(dmat,
-				    dm_segments, map, m->m_data, m->m_len,
+				    dmat->segments, map, m->m_data, m->m_len,
 				    pmap_kernel(), flags, &lastaddr, &nsegs);
 				map->len += m->m_len;
 			}
@@ -954,9 +969,9 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
 		/*
 		 * force "no valid mappings" on error in callback.
 		 */
-		(*callback)(callback_arg, dm_segments, 0, 0, error);
+		(*callback)(callback_arg, dmat->segments, 0, 0, error);
 	} else {
-		(*callback)(callback_arg, dm_segments, nsegs + 1,
+		(*callback)(callback_arg, dmat->segments, nsegs + 1,
 		    m0->m_pkthdr.len, error);
 	}
 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
@@ -1012,11 +1027,6 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
     int flags)
 {
 	vm_offset_t lastaddr = 0;
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 	int nsegs, i, error;
 	bus_size_t resid;
 	struct iovec *iov;
@@ -1048,8 +1058,8 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
 		caddr_t addr = (caddr_t) iov[i].iov_base;
 
 		if (minlen > 0) {
-			error = bus_dmamap_load_buffer(dmat, dm_segments, map,
-			    addr, minlen, pmap, flags, &lastaddr, &nsegs);
+			error = bus_dmamap_load_buffer(dmat, dmat->segments,
+			    map, addr, minlen, pmap, flags, &lastaddr, &nsegs);
 
 			map->len += minlen;
 			resid -= minlen;
@@ -1060,9 +1070,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
 		/*
 		 * force "no valid mappings" on error in callback.
 		 */
-		(*callback)(callback_arg, dm_segments, 0, 0, error);
+		(*callback)(callback_arg, dmat->segments, 0, 0, error);
 	} else {
-		(*callback)(callback_arg, dm_segments, nsegs+1,
+		(*callback)(callback_arg, dmat->segments, nsegs+1,
 		    uio->uio_resid, error);
 	}
 

Modified: stable/9/sys/mips/mips/busdma_machdep.c
==============================================================================
--- stable/9/sys/mips/mips/busdma_machdep.c	Mon Jun 17 20:27:20 2013	(r251867)
+++ stable/9/sys/mips/mips/busdma_machdep.c	Mon Jun 17 20:40:16 2013	(r251868)
@@ -80,6 +80,7 @@ struct bus_dma_tag {
 	int			map_count;
 	bus_dma_lock_t		*lockfunc;
 	void			*lockfuncarg;
+	bus_dma_segment_t	*segments;
 	struct bounce_zone *bounce_zone;
 };
 
@@ -352,6 +353,8 @@ bus_dma_tag_create(bus_dma_tag_t parent,
 		newtag->lockfunc = dflt_lock;
 		newtag->lockfuncarg = NULL;
 	}
+	newtag->segments = NULL;
+
 	/*
 	 * Take into account any restrictions imposed by our parent tag
 	 */
@@ -434,6 +437,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 			parent = dmat->parent;
 			atomic_subtract_int(&dmat->ref_count, 1);
 			if (dmat->ref_count == 0) {
+				if (dmat->segments != NULL)
+					free(dmat->segments, M_DEVBUF);
 				free(dmat, M_DEVBUF);
 				/*
 				 * Last reference count, so
@@ -442,7 +447,7 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
 				 */
 				dmat = parent;
 			} else
-			dmat = NULL;
+				dmat = NULL;
 		}
 	}
 	CTR2(KTR_BUSDMA, "%s tag %p", __func__, dmat_copy);
@@ -461,6 +466,17 @@ bus_dmamap_create(bus_dma_tag_t dmat, in
 	bus_dmamap_t newmap;
 	int error = 0;
 
+	if (dmat->segments == NULL) {
+		dmat->segments = (bus_dma_segment_t *)malloc(
+		    sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
+		    M_NOWAIT);
+		if (dmat->segments == NULL) {
+			CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+			    __func__, dmat, ENOMEM);
+			return (ENOMEM);
+		}
+	}
+
 	newmap = _busdma_alloc_dmamap();
 	if (newmap == NULL) {
 		CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM);
@@ -563,6 +579,16 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 		mflags = M_NOWAIT;
 	else
 		mflags = M_WAITOK;
+	if (dmat->segments == NULL) {
+		dmat->segments = (bus_dma_segment_t *)malloc(
+		    sizeof(bus_dma_segment_t) * dmat->nsegments, M_DEVBUF,
+		    mflags);
+		if (dmat->segments == NULL) {
+			CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
+			    __func__, dmat, dmat->flags, ENOMEM);
+			return (ENOMEM);
+		}
+	}
 	if (flags & BUS_DMA_ZERO)
 		mflags |= M_ZERO;
 
@@ -824,11 +850,6 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
 {
 	vm_offset_t	lastaddr = 0;
 	int		error, nsegs = -1;
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 
 	KASSERT(dmat != NULL, ("dmatag is NULL"));
 	KASSERT(map != NULL, ("dmamap is NULL"));
@@ -839,14 +860,14 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_
 	map->buffer = buf;
 	map->len = buflen;
 	error = bus_dmamap_load_buffer(dmat,
-	    dm_segments, map, buf, buflen, kernel_pmap,
+	    dmat->segments, map, buf, buflen, kernel_pmap,
 	    flags, &lastaddr, &nsegs);
 	if (error == EINPROGRESS)
 		return (error);
 	if (error)
 		(*callback)(callback_arg, NULL, 0, error);
 	else
-		(*callback)(callback_arg, dm_segments, nsegs + 1, error);
+		(*callback)(callback_arg, dmat->segments, nsegs + 1, error);
 	
 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
 	    __func__, dmat, dmat->flags, nsegs + 1, error);
@@ -862,11 +883,6 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
     bus_dmamap_callback2_t *callback, void *callback_arg,
     int flags)
 {
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 	int nsegs = -1, error = 0;
 
 	M_ASSERTPKTHDR(m0);
@@ -882,7 +898,7 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
 		for (m = m0; m != NULL && error == 0; m = m->m_next) {
 			if (m->m_len > 0) {
 				error = bus_dmamap_load_buffer(dmat,
-				    dm_segments, map, m->m_data, m->m_len, 
+				    dmat->segments, map, m->m_data, m->m_len, 
 				    kernel_pmap, flags, &lastaddr, &nsegs);
 				map->len += m->m_len;
 			}
@@ -895,9 +911,9 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat,
 		/* 
 		 * force "no valid mappings" on error in callback.
 		 */
-		(*callback)(callback_arg, dm_segments, 0, 0, error);
+		(*callback)(callback_arg, dmat->segments, 0, 0, error);
 	} else {
-		(*callback)(callback_arg, dm_segments, nsegs + 1,
+		(*callback)(callback_arg, dmat->segments, nsegs + 1,
 		    m0->m_pkthdr.len, error);
 	}
 	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
@@ -953,11 +969,6 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
     int flags)
 {
 	vm_offset_t lastaddr = 0;
-#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT
-	bus_dma_segment_t dm_segments[dmat->nsegments];
-#else
-	bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
-#endif
 	int nsegs, i, error;
 	bus_size_t resid;
 	struct iovec *iov;
@@ -990,8 +1001,8 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
 		caddr_t addr = (caddr_t) iov[i].iov_base;
 
 		if (minlen > 0) {
-			error = bus_dmamap_load_buffer(dmat, dm_segments, map,
-			    addr, minlen, pmap, flags, &lastaddr, &nsegs);
+			error = bus_dmamap_load_buffer(dmat, dmat->segments,
+			    map, addr, minlen, pmap, flags, &lastaddr, &nsegs);
 
 			map->len += minlen;
 			resid -= minlen;
@@ -1002,9 +1013,9 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, 
 		/* 
 		 * force "no valid mappings" on error in callback.
 		 */
-		(*callback)(callback_arg, dm_segments, 0, 0, error);
+		(*callback)(callback_arg, dmat->segments, 0, 0, error);
 	} else {
-		(*callback)(callback_arg, dm_segments, nsegs+1,
+		(*callback)(callback_arg, dmat->segments, nsegs+1,
 		    uio->uio_resid, error);
 	}
 


More information about the svn-src-stable-9 mailing list