[PATCH] ARM: dma-mapping: Fix dma_get_sgtable() for regions without struct page

Shuah Khan shuahkhan at gmail.com
Wed Mar 29 09:51:05 PDT 2017


Hi Russell,

On Wed, Mar 29, 2017 at 10:33 AM, Russell King - ARM Linux
<linux at armlinux.org.uk> wrote:
> Okay, I'm about to merge the following patch for -rc, since refusing
> to create a scattertable for non-page backed memory is the only valid
> solution for that case.  I'm intending to queue this for -rc this
> evening.

I was bit sidetracked and getting back to this today. I am just about
to test this change on my system. I will test your patch and send you
results.

This might not help my use-case - I suspect it will trip this check.
That said I will send you results very soon.

>
> 8<====
> ARM: dma-mapping: disallow dma_get_sgtable() for non-kernel managed memory
>
> dma_get_sgtable() tries to create a scatterlist table containing valid
> struct page pointers for the coherent memory allocation passed in to it.
>
> However, memory can be declared via dma_declare_coherent_memory(), or
> via other reservation schemes which means that coherent memory is not
> guaranteed to be backed by struct pages.  This means it is not possible
> to create a valid scatterlist via this mechanism.

I have been thinking about this some. I would like to see if we can
provide a way forward to address the cases where coherent memory is
not guaranteed to be backed by struct pages. We know the memory isn't
backed at alloc time in dma_alloc_coherent(). Can we key off of that
maybe add a new attr flag to avoid page lookups. I am willing to work
on the fixing it.

Let me first send you the results after testing your patch. Maybe we
can explore ways to fix the problem.

thanks,
-- Shuah

>
> This patch adds detection of such memory, and refuses to create a
> scatterlist table for such memory.
>
> Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
> ---
>  arch/arm/mm/dma-mapping.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 63eabb06f9f1..475811f5383a 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -935,13 +935,31 @@ static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_add
>         __arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
>  }
>
> +/*
> + * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems
> + * that the intention is to allow exporting memory allocated via the
> + * coherent DMA APIs through the dma_buf API, which only accepts a
> + * scattertable.  This presents a couple of problems:
> + * 1. Not all memory allocated via the coherent DMA APIs is backed by
> + *    a struct page
> + * 2. Passing coherent DMA memory into the streaming APIs is not allowed
> + *    as we will try to flush the memory through a different alias to that
> + *    actually being used (and the flushes are redundant.)
> + */
>  int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
>                  void *cpu_addr, dma_addr_t handle, size_t size,
>                  unsigned long attrs)
>  {
> -       struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
> +       unsigned long pfn = dma_to_pfn(dev, handle);
> +       struct page *page;
>         int ret;
>
> +       /* If the PFN is not valid, we do not have a struct page */
> +       if (!pfn_valid(pfn))
> +               return -ENXIO;
> +
> +       page = pfn_to_page(pfn);
> +
>         ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
>         if (unlikely(ret))
>                 return ret;
> --
> 2.7.4
>
> --
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.



More information about the linux-arm-kernel mailing list