Problems with dma_alloc_coherent()

John Whitney jwhitney-linuxppc at
Sat Apr 3 02:50:27 EST 2004

As an exemplification of the problem I am having with the current

I am developing a Generic DMA driver.  DMA providers register
themselves with it.  Clients ask the DMA core driver to please have a
registered driver transfer the data from one location to another, and
call them back when it is complete.

Now, let's look at my options:

1. The DMA-core API accepts physical addresses only for source and

This technically can't be done.  The virt_to_phys() API, I am told, is
deprecated and shouldn't be used by the kernel.  However, the client
code can't call dma_map_single() or dma_alloc_coherent(), because it
doesn't KNOW which providers are available and will be servicing the

2. Okay, we'll make the DMA-core API accept only virtual addresses,
which it can map itself to the final driver.

Okay... this works well for the local memory (__get_free_pages() and
all), but the client has a physical address of a device it wants to
write to... how does it get a virtual address?  ioremap().  Bzzt!  The
address returned by ioremap is fully virtual, which dma_map_single()
can't accept (as it calls virt_to_bus(), which doesn't handle
fully-virtual addresses).

3. Well, darn.  How about the client calls
dma_map_single/dma_alloc_coherent with a NULL device, to get a physical
address for allocated local memory to pass to the DMA core?

Well, that sort of works.  However, do ALL platforms add the PCI bus
address-map-offset to the value?  How does the core (processor
independent) code know what to subract off to get back to the base
physical address?  There is no bus_to_phys() to phys_to_bus() routines,
and these would be deprecated even if they did exist.  How does it know
what to add to get back a bus-offset-phys-address suitable for the DMA
controller?  I guess the DMA core COULD call bus_to_virt() (although it
is deprecated), and then call dma_map_single() for the appropriate

4. I suppose I COULD have a far more complicated dma_mem_to_dev() and
dma_dev_to_mem() and dma_dev_to_dev() and dma_mem_to_mem() kind of
interface, which mixed virtual and physical addresses.  Ugh.

Am I missing anything that should have made this all simpler?  If the
DMA/PCI API routines simply accepted ANY virtual address (fully-virtual
or semi-virtual), I wouldn't have this problem.  I'd simply accept
virtual addresses for the source and destination.


** Sent via the linuxppc-dev mail list. See

More information about the Linuxppc-dev mailing list