Re: noveau vs arm dma ops
From: Christoph Hellwig
Date: Thu Apr 26 2018 - 05:10:00 EST
On Wed, Apr 25, 2018 at 11:35:13PM +0200, Daniel Vetter wrote:
> > get_required_mask() is supposed to tell you if you are safe. However
> > we are missing lots of implementations of it for iommus so you might get
> > some false negatives, improvements welcome. It's been on my list of
> > things to fix in the DMA API, but it is nowhere near the top.
>
> I hasn't come up in a while in some fireworks, so I honestly don't
> remember exactly what the issues have been. But
>
> commit d766ef53006c2c38a7fe2bef0904105a793383f2
> Author: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
> Date: Mon Dec 19 12:43:45 2016 +0000
>
> drm/i915: Fallback to single PAGE_SIZE segments for DMA remapping
>
> and the various bits of code that a
>
> $ git grep SWIOTLB -- drivers/gpu
>
> turns up is what we're doing to hack around that stuff. And in general
> (there's some exceptions) gpus should be able to address everything,
> so I never fully understood where that's even coming from.
I'm pretty sure I've seen some oddly low dma masks in GPU drivers. E.g.
duplicated in various AMD files:
adev->need_dma32 = false;
dma_bits = adev->need_dma32 ? 32 : 40;
r = pci_set_dma_mask(adev->pdev, DMA_BIT_MASK(dma_bits));
if (r) {
adev->need_dma32 = true;
dma_bits = 32;
dev_warn(adev->dev, "amdgpu: No suitable DMA available.\n");
}
synopsis:
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c: pdevinfo.dma_mask = DMA_BIT_MASK(32);
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c: pdevinfo.dma_mask = DMA_BIT_MASK(32);
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c: pdevinfo.dma_mask = DMA_BIT_MASK(32);
etnaviv gets it right:
drivers/gpu/drm/etnaviv/etnaviv_gpu.c: u32 dma_mask = (u32)dma_get_required_mask(gpu->dev);
But yes, the swiotlb hackery really irks me. I just have some more
important and bigger fires to fight first, but I plan to get back to the
root cause of that eventually.
>
> >> - dma api hides the cache flushing requirements from us. GPUs love
> >> non-snooped access, and worse give userspace control over that. We want
> >> a strict separation between mapping stuff and flushing stuff. With the
> >> IOMMU api we mostly have the former, but for the later arch maintainers
> >> regularly tells they won't allow that. So we have drm_clflush.c.
> >
> > The problem is that a cache flushing API entirely separate is hard. That
> > being said if you look at my generic dma-noncoherent API series it tries
> > to move that way. So far it is in early stages and apparently rather
> > buggy unfortunately.
>
> I'm assuming this stuff here?
>
> https://lkml.org/lkml/2018/4/20/146
>
> Anyway got lost in all that work a bit, looks really nice.
That url doesn't seem to work currently. But I am talking about the
thread titled '[RFC] common non-cache coherent direct dma mapping ops'
> Yeah the above is pretty much what we do on x86. dma-api believes
> everything is coherent, so dma_map_sg does the mapping we want and
> nothing else (minus swiotlb fun). Cache flushing, allocations, all
> done by the driver.
Which sounds like the right thing to do to me.
> On arm that doesn't work. The iommu api seems like a good fit, except
> the dma-api tends to get in the way a bit (drm/msm apparently has
> similar problems like tegra), and if you need contiguous memory
> dma_alloc_coherent is the only way to get at contiguous memory. There
> was a huge discussion years ago about that, and direct cma access was
> shot down because it would have exposed too much of the caching
> attribute mangling required (most arm platforms need wc-pages to not
> be in the kernel's linear map apparently).
Simple cma_alloc() doesn't do anything about cache handling, it
just is a very dumb allocator for large contiguous regions inside
a big pool.
I'm not the CMA maintainer, but in general I'd love to see an
EXPORT_SYMBOL_GPL slapped onto cma_alloc/release and drivers use
that were needed. Using that plus dma_map*/dma_unmap* sounds like
a much saner interface than dma_alloc_attrs + DMA_ATTR_NON_CONSISTENT
or DMA_ATTR_NO_KERNEL_MAPPING.
You don't happen to have a pointer to that previous discussion?
> Anything that separate these 3 things more (allocation pools, mapping
> through IOMMUs and flushing cpu caches) sounds like the right
> direction to me. Even if that throws some portability across platforms
> away - drivers who want to control things in this much detail aren't
> really portable (without some serious work) anyway.
As long as we stay away from the dma coherent allocations separating
them is fine, and I'm working towards it. dma coherent allocations on
the other hand are very hairy beasts, and provide by very different
implementations depending on the architecture, or often even depending
on the specifics of individual implementations inside the architecture.
So for your GPU/media case it seems like you'd better stay away from
them as much as you can.