lkml.org 
[lkml]   [2009]   [Jun]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [PATCH] asm-generic: add dma-mapping-linear.h
    From
    On Thu, 4 Jun 2009 12:35:34 +0000
    Arnd Bergmann <arnd@arndb.de> wrote:

    > > > I do have branches in there that convert x86 and microblaze to use
    > >
    > > x86? How can it use asm-generic-linear.h?
    >
    > Not dma-mapping-linear.h, but a lot of other files in asm-generic. I have
    > a set of all the common header files in my tree, and x86 can e.g. use
    > ioctls.h, ipcbuf.h, mman.h, or types.h. For x86, it amounts to 15 files,
    > microblaze can use almost 50 of the generic files.

    I see, but I'm not sure why dma-mapping-linear needs to be merged with
    them together.


    > > > I made this up in order to deal with the different requirements of
    > > > the architectures I converted. In SH, it's truly device specific
    > > > (pci may be coherent, others are never), on cris it returns false
    > > > and on most others always true.
    > >
    > > I know what you are trying here.
    > >
    > > However, dma_cache_sync() is an exported function to drivers; which
    > > should be used only with a buffer returned by dma_alloc_noncoherent()
    > > (see DMA-API.txt). So using dma_cache_sync() in this way is confusing
    > > to me.
    >
    > I think it is technically correct, but there are two plausible ways of
    > doing it, I chose the one that requires slightly less code.
    >
    > I call dma_cache_sync() for streaming mappings on dma_map_* and
    > dma_sync_*_for_device iff the mapping is noncoherent. AFAICT, this
    > is the same case as dma_alloc_noncoherent, which is expected to give
    > out a noncoherent mapping.

    If I correctly understand DMA-API.txt, dma_alloc_noncoherent can
    return either consistent or non-consistent memory. On architectures
    that return consistent memory via dma_alloc_noncoherent,
    dma_cache_sync should be null. dma_cache_sync() is supposed to be used
    only with the returned buffers of dma_alloc_noncoherent().


    > It is done the same way in the existing code for avr32 and sh. The
    > alternative (implemented in mn10300, and xtensa) is to define a
    > new function for flushing a data range before a DMA and call that
    > unconditionally from dma_cache_sync and for noncoherent mappings
    > in dma_map* and dma_sync_*_for_device.
    >
    > > > Architectures like x86 and frv could use this hook to do th
    > > > global flush_write_buffers() but still return zero so that
    > > > dma_sync_sg_for_device does not have to iterate all SG
    > > > elements doing nothing for them.
    > > >
    > > > Maybe it should be named __dma_coherent_dev() to make clear
    > > > that it is a helper internal to dma_mapping.h and not supposed to
    > > > be used by device drivers.
    > >
    > > Might be. However, we have dma_is_consistent() for a different purpose
    >
    > I tried (ab)using that, but since dma_is_consistent takes a memory range,
    > dma_sync_sg_for_device would have to use less efficient code:
    >
    > (1)
    > static inline void
    > dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
    > int nents, enum dma_data_direction direction)
    > {
    > struct scatterlist *sg;
    > int i;
    >
    > if (!dma_coherent_dev(dev))
    > for_each_sg(sglist, sg, nents, i)
    > dma_cache_sync(dev, sg_virt(sg), sg->length, direction);
    >
    > debug_dma_sync_sg_for_device(dev, sg, nents, direction);
    > }
    >
    > (2)
    > static inline void
    > dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
    > int nents, enum dma_data_direction direction)
    > {
    > struct scatterlist *sg;
    > int i;
    >
    > for_each_sg(sglist, sg, nents, i)
    > if (!dma_is_consistent(dev, sg_virt(sg)))
    > dma_cache_sync(dev, sg_virt(sg), sg->length, direction);

    I don't think you can do such; dma_is_consistent can be used only with
    dma_alloc_noncoherent.

    >
    > debug_dma_sync_sg_for_device(dev, sg, nents, direction);
    > }
    >
    > In (1), gcc can completely eliminate the object code if dma_coherent_dev()
    > returns 1, or do a single branch on a nonconstant return value. In (2), we will
    > walk the full sg list. In some cases, gcc may be able to optimize this as well,
    > but not in general.


    \
     
     \ /
      Last update: 2009-06-04 17:09    [W:0.024 / U:32.500 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site