linux/drivers/base/dma-coherent.c
<<
>>
Prefs
   1/*
   2 * Coherent per-device memory handling.
   3 * Borrowed from i386
   4 */
   5#include <linux/slab.h>
   6#include <linux/kernel.h>
   7#include <linux/module.h>
   8#include <linux/dma-mapping.h>
   9
  10struct dma_coherent_mem {
  11        void            *virt_base;
  12        dma_addr_t      device_base;
  13        phys_addr_t     pfn_base;
  14        int             size;
  15        int             flags;
  16        unsigned long   *bitmap;
  17};
  18
  19int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
  20                                dma_addr_t device_addr, size_t size, int flags)
  21{
  22        void __iomem *mem_base = NULL;
  23        int pages = size >> PAGE_SHIFT;
  24        int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
  25
  26        if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
  27                goto out;
  28        if (!size)
  29                goto out;
  30        if (dev->dma_mem)
  31                goto out;
  32
  33        /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
  34
  35        mem_base = ioremap(bus_addr, size);
  36        if (!mem_base)
  37                goto out;
  38
  39        dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
  40        if (!dev->dma_mem)
  41                goto out;
  42        dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
  43        if (!dev->dma_mem->bitmap)
  44                goto free1_out;
  45
  46        dev->dma_mem->virt_base = mem_base;
  47        dev->dma_mem->device_base = device_addr;
  48        dev->dma_mem->pfn_base = PFN_DOWN(bus_addr);
  49        dev->dma_mem->size = pages;
  50        dev->dma_mem->flags = flags;
  51
  52        if (flags & DMA_MEMORY_MAP)
  53                return DMA_MEMORY_MAP;
  54
  55        return DMA_MEMORY_IO;
  56
  57 free1_out:
  58        kfree(dev->dma_mem);
  59 out:
  60        if (mem_base)
  61                iounmap(mem_base);
  62        return 0;
  63}
  64EXPORT_SYMBOL(dma_declare_coherent_memory);
  65
  66void dma_release_declared_memory(struct device *dev)
  67{
  68        struct dma_coherent_mem *mem = dev->dma_mem;
  69
  70        if (!mem)
  71                return;
  72        dev->dma_mem = NULL;
  73        iounmap(mem->virt_base);
  74        kfree(mem->bitmap);
  75        kfree(mem);
  76}
  77EXPORT_SYMBOL(dma_release_declared_memory);
  78
  79void *dma_mark_declared_memory_occupied(struct device *dev,
  80                                        dma_addr_t device_addr, size_t size)
  81{
  82        struct dma_coherent_mem *mem = dev->dma_mem;
  83        int pos, err;
  84
  85        size += device_addr & ~PAGE_MASK;
  86
  87        if (!mem)
  88                return ERR_PTR(-EINVAL);
  89
  90        pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
  91        err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
  92        if (err != 0)
  93                return ERR_PTR(err);
  94        return mem->virt_base + (pos << PAGE_SHIFT);
  95}
  96EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
  97
  98/**
  99 * dma_alloc_from_coherent() - try to allocate memory from the per-device coherent area
 100 *
 101 * @dev:        device from which we allocate memory
 102 * @size:       size of requested memory area
 103 * @dma_handle: This will be filled with the correct dma handle
 104 * @ret:        This pointer will be filled with the virtual address
 105 *              to allocated area.
 106 *
 107 * This function should be only called from per-arch dma_alloc_coherent()
 108 * to support allocation from per-device coherent memory pools.
 109 *
 110 * Returns 0 if dma_alloc_coherent should continue with allocating from
 111 * generic memory areas, or !0 if dma_alloc_coherent should return @ret.
 112 */
 113int dma_alloc_from_coherent(struct device *dev, ssize_t size,
 114                                       dma_addr_t *dma_handle, void **ret)
 115{
 116        struct dma_coherent_mem *mem;
 117        int order = get_order(size);
 118        int pageno;
 119
 120        if (!dev)
 121                return 0;
 122        mem = dev->dma_mem;
 123        if (!mem)
 124                return 0;
 125
 126        *ret = NULL;
 127
 128        if (unlikely(size > (mem->size << PAGE_SHIFT)))
 129                goto err;
 130
 131        pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
 132        if (unlikely(pageno < 0))
 133                goto err;
 134
 135        /*
 136         * Memory was found in the per-device area.
 137         */
 138        *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
 239        nt.c#L139" id="L139" class="line" name="L139"> 239     >size).c#L111" id="L111" class="line" namdrivers/base/dma1  * 12"> 134
 138        *dma_mem-1dma_mem" 1class="sref">dma_mem1)
  61<1       *dev-1ass="sref1">bitmap)
err;
  44           1     144"> 134
notrents="csfiid="L106"L1ref">err;
/*->err;
 s="line" 3constraints3clasw iuld continue with allocating from
d1ma_mem-> 136      "+code=de1v" class="sref">dev-1><1 href="+code=dL93">  93                return flags;
flagsunlikely(dev-&g1t;virt_base + (PAGE_SHIFT);
1)
);
  53                return 1  76s/base/dma-coherent.c#L98"> 1="L13span clalass="coment"> * This function should be onlyared_memory_occupied);
  54
/*  55        retur1n 
( 10 clas#alass="coared_memory_occupied);
  5615" class="line" name="L107"> 10@vt 10alass="com class=ed_memory_occupied);
d1ne" name="L58">  58 1     15" id="L108" class="line" name="L108"> 108 * to sup>="L108"> 108 * to sup&ode=dev"1t" class="sref">out:1
 ction should be only a5" if so, 76">  7sne"ahould beld continue with allocating from
 d continue with allocating from
iounmap(  7d0"L13span ccommet"> d continue with allocating from
1rs/base/dma-coherent.c#L162" i16" id="L103" class="line" name=e="L76">  76e/dma-coherlloc_coproce* @dma_h76">  ="L1" class="lid continue with allocating from
  53  64 136      ef="+code1=dma_release_declared_me1mory"1class= @ret.
  76s/base/dma-coherent.c#L112" id="76">  76s/base/dma-coname="L112"> 112 */
d36"> 136      e  * Memorhref="+code=device" clas1s="sr1f">devlass="sref">dma_addr_t *dma_coherent1_mem<16sref">device_a href="+code=size" class="sref">size)
  81{
mem)
 125
dev17ivers/base/dma-coherent.c#L129" id="L129" cla id="L69"1 class="line" name="L69"1>  691/a>
"linesref">pageno << PAGE_SHIFT);
"llnux/module.h" class="fref">linux/module.h1name="L701">  70        if (!<1a hre1="+code=mem" ccccccccccccdma_mem" class="sref">dma_mem = NULL;
 128        if (  721     17ame="L132"> 132  " class="sref">orderse/dma-coherent.edma-coherent.c#L89"v="sref">""line" name="L89">  89
NULL;
pos = (devic1ine" name1="L73">  73        <1a hre17ivers/base/dma-coherent.c#L133" id="L133" cla" class="1line" name="L74">  74    1     76id="L130" class="line" name=76">  76id="L1 131        bitmap_find_free_region(mem->  61<1       *flags;
 116lass="sref">virt_base + (  77virt_base + (PAGE_SHIFT);
  76s/base/dma-coherent.c#L112" id="76">  76s/base/dma-coname="+code=mem" class="sref">mem->dma_addr_t <1a hre18ef="+code=dma_mem" class="sref">dma_mem-1/a>, );
dma_coherent1_mem<18ma-coherent.c#L102" id="L102" e" naame="/base/dma-coherent.c#L98aame="L13span clalass="coment"ared_memory_occupied);
pa">="L108"> 108 * to sup>        1int   851        pa"> class="line" name="L100"> 100device_addr &a18ocated area.
 100  16        unsigef="18" class="line" name="L107"> 10@ine" name="L101"> 10"L13span clbufferlalass="combyref="drivers/base/dma-co"line" name="L100"> 100  97
 103 *
ERR19" name="L99">  99 * dma_alloc_from_coherent() - tre_addr -  riverchecks wdm"L1r0"L13span clt.c#alass="cos="line" name="L98">="L108"> 108 * to sup"+code=bi1tmap" class="sref">bitma1p19rent.c#L101" id="L101" class="ction should be only a5" if so,  clsne"ahould be#L98e" narovidcosvmacalled from per-arch dma_alloc_coherent()="+code=s1ize" class="sref">size));19ma-coherent.c#L102" id="L102"alled from per-arch dma_alloc_coherent()=ne" name1coherent.c#L93" id="L93"1 clas19" id="L103" class="line" name=rivers/b1 if wlass="comly  clp7d0"L13span ccommet"> ="L13cvll1r0lloc_called from per-arch dma_alloc_coherent()=        1->pos <1;<19vers/base/dma-coherent.c#L105name="L136"> 136      me="L96">1  96 112 */
 112;
 136      m" name="Ldma_mark_declared_memory1_occu19a>
="drivers/base/dma-coherent.c#L20" id="L20" class="line" name="L20">  20                     a-coherent.c#L114" id="L114" class="line" name="L114"> 114                    se/dma-co1herent.c#L97" id="L97" c1lass=1line" ef="+code=size_t" class="sref">size_te/dma-coh2rent.c#L99" id="L99" cla2s="li20href="+code=da href="+code=size" class="sref">size)
  81{
mem)
 125
<2y to allo2ate memory from the per-2evice20ef="+code=dma_mem" class="sref">dma_mem-2"> *
"linesref">pageno << PAGE_SHIFT);
"+>, err;"L12=code=dma_mem" class="sref">dma_mem-2"3 *ze" class="sref">size 132   ccdma_mem" class="sref">dma_mem = NULL;
 128        if (bitmap_ff_free_regionff="L81">  81{
;
 125
<2y5a href=2d/a>->
se/dma-coherent.edma-coherent.c#L89"v="sref">""line" name="L89">  89
NULL;
pos = (devic2th the vi2tual address

se/dma-coherent.emaNULL;
""line" name="L89"emaNULL;
        pos = (devic2t7 the vi2t 96
a-coherent.c#L128" id="L128" class="line" na        pos = (devic2t8 the vi2tma_mark_declared_memory2d="L120ode=EXPORT_SYMBOL" class="sref">EXPORT_SYMBO2
mem + (devic2port allo2ation from per-device co2erent21sref">dma_mark_declarode=mem" class="sre_ff_free_regionff="L81"L128"> 128     rsucoL71" class="linrsuco="L81ef="def="drivers/base/dma-us/aersucoL71" class="linus/aersuco="L81"L12=8"> 128     rsucoL71" class="linrsuco="L81"line" name="L89"_ff_free_regionff="L8ease/dma-coherent.c#L9" id="L9" class="lin2="drivers2base/dma-coherent.c#L1102 id="21href="drivers/base/dm/base/dmunsigecomref="+code=pagerf130" class="linerf1="L81">a-coherent.c#L1>  89
, , devic2p> * + (;
 136     2reas, or 20 if dma_alloc_coherent 2hould21ame="L132"> 132   ccccccccccccccccccccccccccccccivers/base/dma-us/aersucoL71" class="linus/aersuco="L81"L12"L128"> 128        if ( 136     2rd2vice<2a> *dev,ccccccccivers/base/dma-vmaNULL;
mem->virt_base + (dma_han2le  61<1       * 116lass="sref">virt_base + ( 117        int2
size);
2a hre21d_memlass="sref">virt_base + ( 118 2     22sref"f="+code=PAGE_SHIFT" class="sref">PAGE_SHIFT);
mem-> 1192/a>
<2 href=


TL13>(iginal LXR softwarembyr"L13code=mem"http://sourceforge.net/projects/lxr">LXR rentunityrs/b htiverexperit.c#al ass=commbyrcode=mem"mailto:lxr@e="ux.no">lxr@e="ux.nors/b.
lxr.e="ux.no kindly hos"combyrcode=mem"http://www.redpill-e="pro.no">Redpill L="pro ASrs/b harovidc > 10L="ux3consule="L1a5" oper="coms s/an>