Subject: Re: Problems with dma_alloc_coherent()

From: "Michael R. Zucca" <[email-masked]>
Date: Fri, 02 Apr 2004 15:20:01 -0500

John Whitney wrote:

> I'm not trying to handle wierd bus scenarios... I'm just trying to
> figure out how to go from a virtual address to a DMA-controller specific
> one, with the constraints I have been told about with the LinuxPPC
> kernel, in an abstracted interface.  As I outlined in the previous
> message, I can't see a way to do this.

This is an approach that might have been good a number of years ago, but
I don't think it's going to cut it these days. DMA engines can be
anywhere and there can be a lot of intervening bridges. You can't always
assume that programming a DMA engine is just a matter of doing
virt_to_phys() and, voila, you're done. These days, you might have lots
of bridges in the way that might need to have mappings setup, and there
might be limited mapping resources so you can't just statically map the
world with the intention that the source or destination will have a
permanent address on the bus the DMA engine sits on.

A generic DMA API might do something like:

dma_move(main_memory_device, virtual_address,
          serial_port_device, pci_address, length) ;

or

dma_move(bulk_memory_card, pci_address,
          serial_port, pci_address, length) ;

A generic DMA API could then pick the best DMA controller at it's
disposal to push data from one bus to another. Once it has picked the
right DMA engine it would know what bridges lie between the DMA engine
and the source and destination devices. At that point it could translate
each of the given addresses so that they can be programmed into the DMA
engine.

> Heck, let's make it simple.  Let's say I have a high-speed serial port,
> and I want to DMA data to it with a known DMA controller (not
> abstracted) with a standard "device" structure associated with it.  The
> serial driver has the physical address of the 1-byte transmit register
> of the serial port that it wants to DMA to.  How does he make this into
> a physical address the known DMA controller device can use?  There is no
> phys_to_bus() macro, and it would be deprecated if it existed.  There is
> no DMA/PCI API for taking a physical address and converting it to a
> dma_addr_t for a specific device (the DMA controller).  I can't
> ioremap() the device, and pass that virtual address to the DMA API, as
> it will produce a bad physical address and I have been told this is the
> desired way for the API to work.

On 2.4, at least, I believe you are supposed to pci_map_* the item if
it's on PCI, take the address, slam in the DMA engine, and when the
transfer is complete, pci_unamp_* the item. I think, though, that this
might even be some hackery since I think the address you get from
pci_map may or may not be appropriate for the DMA engine depending on
where it lives.

Good bus support is kind of lacking in Linux :( It would be nice if
Linux had something more like NetBSD's bus_space/bus_dma stuff, or
something even better.

If what you need is generic address translation, I don't think that
exists yet in Linux. If you need it, you may have to cook it up yourself.

--
----------------------------------------------
  Michael Zucca - [email-masked]
----------------------------------------------
  "I'm too old to use Emacs." -- Rod MacDonald
----------------------------------------------

** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/