[PATCH] Use Normal uncached memory rather than Strongly Ordered on ARMv6+

adharmap at codeaurora.org adharmap at codeaurora.org
Fri Oct 23 17:48:31 EDT 2009


In addition we would need to change mb() rmb() wmb() to expand to dmb() for
arch = v7


Abhijeet Dharmapurikar

> On Fri, Oct 23, 2009 at 06:12:27PM +0100, Russell King - ARM Linux wrote:
>> As far as I'm concerned, we've spent far too long discussing this issue
>> -
>> there's nothing really to discuss.  We need dma_alloc_coherent() to use
>> its own page protection modifier, which causes it to behave the same as
>> dma_alloc_writecombine() on ARMv7, and with the existing behaviour (for
>> the time being) on ARMv6 and below.  We should leave pgprot_noncached()
>> well alone until we know that its other places need to be changed.
>
> And here is the patch which does this.  Note that it also ensures that
> NX is set for these pages on both ARMv6 and later.
>
> diff --git a/arch/arm/include/asm/pgtable.h
> b/arch/arm/include/asm/pgtable.h
> index 201ccaa..1139768 100644
> --- a/arch/arm/include/asm/pgtable.h
> +++ b/arch/arm/include/asm/pgtable.h
> @@ -304,13 +304,23 @@ PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
>
>  static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
>
> +#define __pgprot_modify(prot,mask,bits)		\
> +	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
> +
>  /*
>   * Mark the prot value as uncacheable and unbufferable.
>   */
>  #define pgprot_noncached(prot) \
> -	__pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_UNCACHED)
> +	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
>  #define pgprot_writecombine(prot) \
> -	__pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_BUFFERABLE)
> +	__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
> +#if __LINUX_ARM_ARCH__ >= 7
> +#define pgprot_dmacoherent(prot) \
> +	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
> +#else
> +#define pgprot_dmacoherent(prot) \
> +	__pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
> +#endif
>
>  #define pmd_none(pmd)		(!pmd_val(pmd))
>  #define pmd_present(pmd)	(pmd_val(pmd))
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index b30925f..7a976bb 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -328,7 +328,7 @@ dma_alloc_coherent(struct device *dev, size_t size,
> dma_addr_t *handle, gfp_t gf
>  	}
>
>  	return __dma_alloc(dev, size, handle, gfp,
> -			   pgprot_noncached(pgprot_kernel));
> +			   pgprot_dmacoherent(pgprot_kernel));
>  }
>  EXPORT_SYMBOL(dma_alloc_coherent);
>
> @@ -379,7 +379,7 @@ static int dma_mmap(struct device *dev, struct
> vm_area_struct *vma,
>  int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
>  		      void *cpu_addr, dma_addr_t dma_addr, size_t size)
>  {
> -	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> +	vma->vm_page_prot = pgprot_dmacoherent(vma->vm_page_prot);
>  	return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
>  }
>  EXPORT_SYMBOL(dma_mmap_coherent);
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>





More information about the linux-arm-kernel mailing list