From: Michal Simek <monstr@monstr.eu>
To: Lars-Peter Clausen <lars@metafoo.de>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] microblaze: Fix mmap for cache coherent memory
Date: Wed, 10 Dec 2014 10:27:52 +0100 [thread overview]
Message-ID: <54881218.6010107@monstr.eu> (raw)
In-Reply-To: <1417619248-20365-1-git-send-email-lars@metafoo.de>
[-- Attachment #1: Type: text/plain, Size: 4673 bytes --]
On 12/03/2014 04:07 PM, Lars-Peter Clausen wrote:
> When running in non-cache coherent configuration the memory that was
> allocated with dma_alloc_coherent() has a custom mapping and so there is no
> 1-to-1 relationship between the kernel virtual address and the PFN. This
> means that virt_to_pfn() will not work correctly for those addresses and the
> default mmap implementation in the form of dma_common_mmap() will map some
> random, but not the requested, memory area.
>
> Fix this by providing a custom mmap implementation that looks up the PFN
> from the page table rather than using virt_to_pfn.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> arch/microblaze/include/asm/pgtable.h | 1 +
> arch/microblaze/kernel/dma.c | 26 ++++++++++++++++++++++++++
> arch/microblaze/mm/consistent.c | 23 ++++++++++++++++++-----
> 3 files changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
> index 95cef0b..df19d0c 100644
> --- a/arch/microblaze/include/asm/pgtable.h
> +++ b/arch/microblaze/include/asm/pgtable.h
> @@ -565,6 +565,7 @@ void consistent_free(size_t size, void *vaddr);
> void consistent_sync(void *vaddr, size_t size, int direction);
> void consistent_sync_page(struct page *page, unsigned long offset,
> size_t size, int direction);
> +unsigned long consistent_virt_to_pfn(void *vaddr);
>
> void setup_memory(void);
> #endif /* __ASSEMBLY__ */
> diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
> index 4633c36..4822367 100644
> --- a/arch/microblaze/kernel/dma.c
> +++ b/arch/microblaze/kernel/dma.c
> @@ -154,9 +154,35 @@ dma_direct_sync_sg_for_device(struct device *dev,
> __dma_sync(sg->dma_address, sg->length, direction);
> }
>
> +int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
> + void *cpu_addr, dma_addr_t handle, size_t size,
> + struct dma_attrs *attrs)
> +{
> + unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
> + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> + unsigned long off = vma->vm_pgoff;
> + unsigned long pfn;
> +
> + if (!IS_ENABLED(CONFIG_MMU))
> + return -ENXIO;
> +
> + if (off >= count || user_count > (count - off))
> + return -ENXIO;
> +
> +#ifdef NOT_COHERENT_CACHE
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> + pfn = consistent_virt_to_pfn(cpu_addr);
> +#else
> + pfn = virt_to_pfn(cpu_addr);
> +#endif
> + return remap_pfn_range(vma, vma->vm_start, pfn + off,
> + vma->vm_end - vma->vm_start, vma->vm_page_prot);
> +}
> +
> struct dma_map_ops dma_direct_ops = {
> .alloc = dma_direct_alloc_coherent,
> .free = dma_direct_free_coherent,
> + .mmap = dma_direct_mmap_coherent,
> .map_sg = dma_direct_map_sg,
> .dma_supported = dma_direct_dma_supported,
> .map_page = dma_direct_map_page,
> diff --git a/arch/microblaze/mm/consistent.c b/arch/microblaze/mm/consistent.c
> index e10ad93..f358cd2 100644
> --- a/arch/microblaze/mm/consistent.c
> +++ b/arch/microblaze/mm/consistent.c
> @@ -156,6 +156,23 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
> }
> EXPORT_SYMBOL(consistent_alloc);
>
> +static pte_t *consistent_virt_to_pte(void *vaddr)
> +{
> + unsigned long addr = (unsigned long)vaddr;
> +
> + return pte_offset_kernel(pmd_offset(pgd_offset_k(addr), addr), addr);
> +}
> +
> +unsigned long consistent_virt_to_pfn(void *vaddr)
> +{
> + pte_t *ptep = consistent_virt_to_pte(vaddr);
> +
> + if (pte_none(*ptep) || !pte_present(*ptep))
> + return 0;
> +
> + return pte_pfn(*ptep);
> +}
> +
> /*
> * free page(s) as defined by the above mapping.
> */
> @@ -181,13 +198,9 @@ void consistent_free(size_t size, void *vaddr)
> } while (size -= PAGE_SIZE);
> #else
> do {
> - pte_t *ptep;
> + pte_t *ptep = consistent_virt_to_pte(vaddr);
> unsigned long pfn;
>
> - ptep = pte_offset_kernel(pmd_offset(pgd_offset_k(
> - (unsigned int)vaddr),
> - (unsigned int)vaddr),
> - (unsigned int)vaddr);
> if (!pte_none(*ptep) && pte_present(*ptep)) {
> pfn = pte_pfn(*ptep);
> pte_clear(&init_mm, (unsigned int)vaddr, ptep);
>
Applied.
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
prev parent reply other threads:[~2014-12-10 9:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-03 15:07 [PATCH] microblaze: Fix mmap for cache coherent memory Lars-Peter Clausen
2014-12-10 9:27 ` Michal Simek [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54881218.6010107@monstr.eu \
--to=monstr@monstr.eu \
--cc=lars@metafoo.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.