[PATCH 2.6.39] V4L: videobuf-dma-contig: fix mmap_mapper broken on ARM

Mauro Carvalho Chehab mchehab at infradead.org
Sun Apr 10 20:42:13 EDT 2011


Em 10-04-2011 19:47, Janusz Krzysztofik escreveu:
> After switching from mem->dma_handle to virt_to_phys(mem->vaddr) used 
> for obtaining page frame number passed to remap_pfn_range()
> (commit 35d9f510b67b10338161aba6229d4f55b4000f5b), videobuf-dma-contig 
> stopped working on my ARM based board. The ARM architecture maintainer, 
> Russell King, confirmed that using something like 
> virt_to_phys(dma_alloc_coherent()) is not supported on ARM, and can be 
> broken on other architectures as well. The author of the change, Jiri 
> Slaby, also confirmed that his code may not work on all architectures.
> 
> The patch takes two different countermeasures against this regression:
> 
> 1. On architectures which provide dma_mmap_coherent() function (ARM for 
>    now), use it instead of just remap_pfn_range(). The code is stollen 
>    from sound/core/pcm_native.c:snd_pcm_default_mmap().
>    Set vma->vm_pgoff to 0 before calling dma_mmap_coherent(), or it 
>    fails.
> 
> 2. On other architectures, use virt_to_phys(bus_to_virt(mem->dma_handle)) 
>    instead of problematic virt_to_phys(mem->vaddr). This should work 
>    even if those translations would occure inaccurate for DMA addresses, 
>    since possible errors introduced by both calculations, performed in 
>    opposite directions, should compensate.
> 
> Both solutions tested on ARM OMAP1 based Amstrad Delta board.
> 
> Signed-off-by: Janusz Krzysztofik <jkrzyszt at tis.icnet.pl>
> ---
>  drivers/media/video/videobuf-dma-contig.c |   17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> --- linux-2.6.39-rc2/drivers/media/video/videobuf-dma-contig.c.orig	2011-04-09 00:38:45.000000000 +0200
> +++ linux-2.6.39-rc2/drivers/media/video/videobuf-dma-contig.c	2011-04-10 15:00:23.000000000 +0200
> @@ -295,13 +295,26 @@ static int __videobuf_mmap_mapper(struct
>  
>  	/* Try to remap memory */
>  
> +#ifndef ARCH_HAS_DMA_MMAP_COHERENT
> +/* This should be defined / handled globally! */
> +#ifdef CONFIG_ARM
> +#define ARCH_HAS_DMA_MMAP_COHERENT
> +#endif
> +#endif
> +
> +#ifdef ARCH_HAS_DMA_MMAP_COHERENT

Hmm... IMHO, this seems too confusing. Why not use just something like:

#if defined(CONFIG_ARM) || defined(ARCH_HAS_DMA_MMAP_COHERENT)

Better yet: why should CONFIG_ARM should explicitly be checked here? Is it the
only architecture where this would fail?dma_mmap_coherent

Hmm...

$ git grep ARCH_HAS_DMA_MMAP_COHERENT arch
arch/powerpc/include/asm/dma-mapping.h:#define ARCH_HAS_DMA_MMAP_COHERENT

The code is saying that dma_mmap_coherent should be used only on ARM and PPC architectures,
and remap_pfn_range should be used otherwise. Are you sure that this will work on the
other architectures? I really prefer to have one standard way for doing it, that
would be architecture-independent. Media drivers or core should not have arch-dependent
code inside.


> +	vma->vm_pgoff = 0;
> +	retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle,
> +			mem->size);
> +#else
>  	size = vma->vm_end - vma->vm_start;
>  	size = (size < mem->size) ? size : mem->size;
>  
>  	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
>  	retval = remap_pfn_range(vma, vma->vm_start,
> -				 PFN_DOWN(virt_to_phys(mem->vaddr)),
> -				 size, vma->vm_page_prot);
> +			PFN_DOWN(virt_to_phys(bus_to_virt(mem->dma_handle))),
> +			size, vma->vm_page_prot);
> +#endif
>  	if (retval) {
>  		dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
>  		dma_free_coherent(q->dev, mem->size,




More information about the linux-arm-kernel mailing list