Author: jhb
Date: Mon Oct  1 19:09:25 2012
New Revision: 241110
URL: http://svn.freebsd.org/changeset/base/241110

Log:
  MFC 239008,239020:
  Improve the handling of static DMA buffers that use non-default memory
  attributes (currently just BUS_DMA_NOCACHE):
  - Don't call pmap_change_attr() on the returned address, instead use
    kmem_alloc_contig() to ask the VM system for memory with the requested
    attribute.
  - As a result, always use kmem_alloc_contig() for non-default memory
    attributes, even for sub-page allocations.  This requires adjusting
    bus_dmamem_free()'s logic for determining which free routine to use.
  - For x86, add a new dummy bus_dmamap that is used for static DMA
    buffers allocated via kmem_alloc_contig().  bus_dmamem_free() can then
    use the map pointer to determine which free routine to use.
  - For powerpc, add a new flag to the allocated map (bus_dmamem_alloc()
    always creates a real map on powerpc) to indicate which free routine
    should be used.
  
  Note that the BUS_DMA_NOCACHE handling in powerpc is currently #ifdef'd out.
  I have left it disabled but updated it to match x86.

Modified:
  stable/9/sys/powerpc/powerpc/busdma_machdep.c
  stable/9/sys/x86/x86/busdma_machdep.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/amd64/include/xen/   (props changed)
  stable/9/sys/boot/   (props changed)
  stable/9/sys/boot/i386/efi/   (props changed)
  stable/9/sys/boot/ia64/efi/   (props changed)
  stable/9/sys/boot/ia64/ski/   (props changed)
  stable/9/sys/boot/powerpc/boot1.chrp/   (props changed)
  stable/9/sys/boot/powerpc/ofw/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)
  stable/9/sys/conf/   (props changed)
  stable/9/sys/contrib/dev/acpica/   (props changed)
  stable/9/sys/contrib/octeon-sdk/   (props changed)
  stable/9/sys/contrib/pf/   (props changed)
  stable/9/sys/contrib/x86emu/   (props changed)
  stable/9/sys/dev/   (props changed)
  stable/9/sys/dev/e1000/   (props changed)
  stable/9/sys/dev/isp/   (props changed)
  stable/9/sys/dev/ixgbe/   (props changed)
  stable/9/sys/dev/puc/   (props changed)
  stable/9/sys/fs/   (props changed)
  stable/9/sys/fs/ntfs/   (props changed)
  stable/9/sys/modules/   (props changed)

Modified: stable/9/sys/powerpc/powerpc/busdma_machdep.c
==============================================================================
--- stable/9/sys/powerpc/powerpc/busdma_machdep.c       Mon Oct  1 17:45:56 
2012        (r241109)
+++ stable/9/sys/powerpc/powerpc/busdma_machdep.c       Mon Oct  1 19:09:25 
2012        (r241110)
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 #include <vm/vm_map.h>
 
@@ -129,6 +131,7 @@ struct bus_dmamap {
        bus_dmamap_callback_t *callback;
        void                  *callback_arg;
        STAILQ_ENTRY(bus_dmamap) links;
+       int                    contigalloc;
 };
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
@@ -488,6 +491,7 @@ int
 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
                 bus_dmamap_t *mapp)
 {
+       vm_memattr_t attr;
        int mflags;
 
        if (flags & BUS_DMA_NOWAIT)
@@ -499,6 +503,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 
        if (flags & BUS_DMA_ZERO)
                mflags |= M_ZERO;
+#ifdef NOTYET
+       if (flags & BUS_DMA_NOCACHE)
+               attr = VM_MEMATTR_UNCACHEABLE;
+       else
+#endif
+               attr = VM_MEMATTR_DEFAULT;
 
        /* 
         * XXX:
@@ -510,7 +520,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
         */
        if ((dmat->maxsize <= PAGE_SIZE) &&
           (dmat->alignment < dmat->maxsize) &&
-           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
+           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+           attr == VM_MEMATTR_DEFAULT) {
                *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
        } else {
                /*
@@ -519,9 +530,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
                 *     multi-seg allocations yet though.
                 * XXX Certain AGP hardware does.
                 */
-               *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
-                   0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
-                   dmat->boundary);
+               *vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize,
+                   mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+                   dmat->alignment : 1ul, dmat->boundary, attr);
+               (*mapp)->contigalloc = 1;
        }
        if (*vaddr == NULL) {
                CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
@@ -530,11 +542,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
        } else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
                printf("bus_dmamem_alloc failed to align memory properly.\n");
        }
-#ifdef NOTYET
-       if (flags & BUS_DMA_NOCACHE)
-               pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
-                   VM_MEMATTR_UNCACHEABLE);
-#endif
        CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
            __func__, dmat, dmat->flags, 0);
        return (0);
@@ -547,18 +554,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 void
 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
 {
-       bus_dmamap_destroy(dmat, map);
 
-#ifdef NOTYET
-       pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, VM_MEMATTR_DEFAULT);
-#endif
-       if ((dmat->maxsize <= PAGE_SIZE) &&
-          (dmat->alignment < dmat->maxsize) &&
-           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+       if (!map->contigalloc)
                free(vaddr, M_DEVBUF);
-       else {
-               contigfree(vaddr, dmat->maxsize, M_DEVBUF);
-       }
+       else
+               kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize);
+       bus_dmamap_destroy(dmat, map);
        CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
 }
 

Modified: stable/9/sys/x86/x86/busdma_machdep.c
==============================================================================
--- stable/9/sys/x86/x86/busdma_machdep.c       Mon Oct  1 17:45:56 2012        
(r241109)
+++ stable/9/sys/x86/x86/busdma_machdep.c       Mon Oct  1 19:09:25 2012        
(r241110)
@@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 #include <vm/vm_map.h>
 
@@ -131,7 +133,7 @@ struct bus_dmamap {
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
-static struct bus_dmamap nobounce_dmamap;
+static struct bus_dmamap nobounce_dmamap, contig_dmamap;
 
 static void init_bounce_pages(void *dummy);
 static int alloc_bounce_zone(bus_dma_tag_t dmat);
@@ -473,7 +475,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in
 int
 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
 {
-       if (map != NULL && map != &nobounce_dmamap) {
+       if (map != NULL && map != &nobounce_dmamap && map != &contig_dmamap) {
                if (STAILQ_FIRST(&map->bpages) != NULL) {
                        CTR3(KTR_BUSDMA, "%s: tag %p error %d",
                            __func__, dmat, EBUSY);
@@ -498,6 +500,7 @@ int
 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
                 bus_dmamap_t *mapp)
 {
+       vm_memattr_t attr;
        int mflags;
 
        if (flags & BUS_DMA_NOWAIT)
@@ -520,6 +523,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
        }
        if (flags & BUS_DMA_ZERO)
                mflags |= M_ZERO;
+       if (flags & BUS_DMA_NOCACHE)
+               attr = VM_MEMATTR_UNCACHEABLE;
+       else
+               attr = VM_MEMATTR_DEFAULT;
 
        /* 
         * XXX:
@@ -531,7 +538,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
         */
        if ((dmat->maxsize <= PAGE_SIZE) &&
           (dmat->alignment < dmat->maxsize) &&
-           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
+           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+           attr == VM_MEMATTR_DEFAULT) {
                *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
        } else {
                /*
@@ -540,9 +548,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
                 *     multi-seg allocations yet though.
                 * XXX Certain AGP hardware does.
                 */
-               *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
-                   0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
-                   dmat->boundary);
+               *vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize,
+                   mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+                   dmat->alignment : 1ul, dmat->boundary, attr);
+               *mapp = &contig_dmamap;
        }
        if (*vaddr == NULL) {
                CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
@@ -551,9 +560,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
        } else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
                printf("bus_dmamem_alloc failed to align memory properly.\n");
        }
-       if (flags & BUS_DMA_NOCACHE)
-               pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
-                   PAT_UNCACHEABLE);
        CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
            __func__, dmat, dmat->flags, 0);
        return (0);
@@ -568,18 +574,15 @@ bus_dmamem_free(bus_dma_tag_t dmat, void
 {
        /*
         * dmamem does not need to be bounced, so the map should be
-        * NULL
+        * NULL if malloc() was used and contig_dmamap if
+        * kmem_alloc_contig() was used.
         */
-       if (map != NULL)
+       if (!(map == NULL || map == &contig_dmamap))
                panic("bus_dmamem_free: Invalid map freed\n");
-       pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, PAT_WRITE_BACK);
-       if ((dmat->maxsize <= PAGE_SIZE) &&
-          (dmat->alignment < dmat->maxsize) &&
-           dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+       if (map == NULL)
                free(vaddr, M_DEVBUF);
-       else {
-               contigfree(vaddr, dmat->maxsize, M_DEVBUF);
-       }
+       else
+               kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize);
        CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
 }
 
@@ -670,7 +673,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
        vm_offset_t vaddr;
        int seg, error;
 
-       if (map == NULL)
+       if (map == NULL || map == &contig_dmamap)
                map = &nobounce_dmamap;
 
        if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
@@ -1147,7 +1150,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_
        struct bounce_page *bpage;
 
        KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
-       KASSERT(map != NULL && map != &nobounce_dmamap,
+       KASSERT(map != NULL && map != &nobounce_dmamap && map != &contig_dmamap,
            ("add_bounce_page: bad map %p", map));
 
        bz = dmat->bounce_zone;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to