Author: jhb
Date: Thu Sep  6 20:16:59 2012
New Revision: 240177
URL: http://svn.freebsd.org/changeset/base/240177

Log:
  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.
  
  Discussed with:       scottl, gibbs
  Tested by:    stas (arm@)

Modified:
  head/sys/arm/arm/busdma_machdep.c
  head/sys/mips/mips/busdma_machdep.c

Modified: head/sys/arm/arm/busdma_machdep.c
==============================================================================
--- head/sys/arm/arm/busdma_machdep.c   Thu Sep  6 20:15:44 2012        
(r240176)
+++ head/sys/arm/arm/busdma_machdep.c   Thu Sep  6 20:16:59 2012        
(r240177)
@@ -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: head/sys/mips/mips/busdma_machdep.c
==============================================================================
--- head/sys/mips/mips/busdma_machdep.c Thu Sep  6 20:15:44 2012        
(r240176)
+++ head/sys/mips/mips/busdma_machdep.c Thu Sep  6 20:16:59 2012        
(r240177)
@@ -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);
        }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to