Re: Howto use PPC4xx memory to memory DMA

2 messages, 2 authors, 2007-01-21 · open the first message on its own page

Re: Howto use PPC4xx memory to memory DMA

From: Alexis Berlemont <hidden>
Date: 2007-01-19 23:01:36

Hi,

I would like to add some comments on this topic, I am very interested by more 
details.
Here are a few things to check:

1. Your memory destination and source addresses are contiguous. You can get
this using something like:

mem = (void*)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(size));

2. Your source and dest addresses are _bus_ addresses. You can get these
by:

source = virt_to_bus((u32 *)mem);
But you must check that your src and dst addresses does not point to 
a "vmallocated" buffer (unless you allocated less than PAGE_SIZE and you know 
how to convert a virtual kernel address into a physical address, for example 
thanks to the function iopa() ). 
Consequently, with a 2.6 kernel, the function virt_to_bus() will not work 
properly on a virtual address.

Consequently, if the dst or the src address belongs to a buffer allocated with 
vmalloc() or ioremap(), you will have to use the function iopa() to perform 
the translation.

Besides, I have a question : I do not understand why the 2.6 implementation of 
the function virt_to_bus() is different from the 2.4 version; 
->on 2.4, virt_to_bus() calls iopa() (if CONFIG_PPC4xx is defined),therefore 
it works with virtual addresses (vmallocated or ioremapped);
->on 2.6, virt_to_bus works with logical address (kmallocated or 
get_free_pages);

Do you know why ?
Ooh - and the 3d thing - cache coherence. I.e.:

      dma_cache_inv((u32)mem, (u32)nBytes);
I just add a little precision:

With PPC405 (no cache coherency integrated), you have to invalidate the cache 
of the destination buffer (with dma_cache_inv() )and you have to write back 
the cache of the source buffer (with dma_cache_wback() ). But if you do not 
want to care about the direction point, you can use dma_cache_inv_wback() 
which does both operations.

Of course, if you work with an "ioremapped" area (either as source or 
destination buffer), this functions are useless for this buffer (ioremap() 
maps the address range with the flag "PAGE_NO_CACHE").

Also, we had some trouble with the ppc4xx_ functions using 440 - it seems
these functions are specific to the PLB4. So if you are trying to do DMA on
say the PLB peripheral bus on a memory mapped device, you definitely have
some trouble.
I do not understand, I would be very interested by what kind of trouble you 
had to cope with.

Alexis.

Re: Howto use PPC4xx memory to memory DMA

From: Eugene Surovegin <hidden>
Date: 2007-01-21 19:54:23

On Fri, Jan 19, 2007 at 11:32:04PM +0100, Alexis Berlemont wrote:
Hi,

I would like to add some comments on this topic, I am very interested by more 
details.
quoted
Here are a few things to check:

1. Your memory destination and source addresses are contiguous. You can get
this using something like:

mem = (void*)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(size));

2. Your source and dest addresses are _bus_ addresses. You can get these
by:

source = virt_to_bus((u32 *)mem);
But you must check that your src and dst addresses does not point to 
a "vmallocated" buffer (unless you allocated less than PAGE_SIZE and you know 
how to convert a virtual kernel address into a physical address, for example 
thanks to the function iopa() ). 
Consequently, with a 2.6 kernel, the function virt_to_bus() will not work 
properly on a virtual address.

Consequently, if the dst or the src address belongs to a buffer allocated with 
vmalloc() or ioremap(), you will have to use the function iopa() to perform 
the translation.

Besides, I have a question : I do not understand why the 2.6 implementation of 
the function virt_to_bus() is different from the 2.4 version; 
->on 2.4, virt_to_bus() calls iopa() (if CONFIG_PPC4xx is defined),therefore 
it works with virtual addresses (vmallocated or ioremapped);
->on 2.6, virt_to_bus works with logical address (kmallocated or 
get_free_pages);

Do you know why ?
virt_to_bus was never supposed to work on anything else except for 
directly mapped kernel address. 2.6 version just fixes this for 4xx. 
And yes, virt_to_bus is deprecated.

quoted
Ooh - and the 3d thing - cache coherence. I.e.:

      dma_cache_inv((u32)mem, (u32)nBytes);
I just add a little precision:

With PPC405 (no cache coherency integrated), you have to invalidate the cache 
of the destination buffer (with dma_cache_inv() )and you have to write back 
the cache of the source buffer (with dma_cache_wback() ). But if you do not 
want to care about the direction point, you can use dma_cache_inv_wback() 
which does both operations.

Of course, if you work with an "ioremapped" area (either as source or 
destination buffer), this functions are useless for this buffer (ioremap() 
maps the address range with the flag "PAGE_NO_CACHE").
Guys, please stop reinventing the wheel. There is a documented kernel 
API which takes care of coherency issues and it should be used for any 
sort of DMA (be it general purpose DMA controller or external 
DMA-capable device).

PLEASE, read Documentation/DMA-API.txt and use it to obtain DMA-able 
address for your buffer.

-- 
Eugene
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help