On Wed, Dec 09, 2020 at 03:25:22PM +0100, Thomas Zimmermann wrote:
> The existing dma-buf calls dma_buf_vmap() and dma_buf_vunmap() are
> allowed to pin the buffer or acquire the buffer's reservation object
> lock.
>
> This is a problem for callers that only require a short-term mapping
> of the buffer without the pinning, or callers that have special locking
> requirements. These may suffer from unnecessary overhead or interfere
> with regular pin operations.
>
> The new interfaces dma_buf_vmap_local(), dma_buf_vunmapo_local(), and
> their rsp callbacks in struct dma_buf_ops provide an alternative without
> pinning or reservation locking. Callers are responsible for these
> operations.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
> ---
> drivers/dma-buf/dma-buf.c | 80 +++++++++++++++++++++++++++++++++++++++
> include/linux/dma-buf.h | 34 +++++++++++++++++
> 2 files changed, 114 insertions(+)
>
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index e63684d4cd90..be9f80190a66 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -1265,6 +1265,86 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map)
> }
> EXPORT_SYMBOL_GPL(dma_buf_vunmap);
>
> +/**
> + * dma_buf_vmap_local - Create virtual mapping for the buffer object into kernel
> + * address space.
> + * @dmabuf: [in] buffer to vmap
> + * @map: [out] returns the vmap pointer
> + *
> + * This call may fail due to lack of virtual mapping address space.
> + * These calls are optional in drivers. The intended use for them
> + * is for mapping objects linear in kernel space for high use objects.
> + * Please attempt to use kmap/kunmap before thinking about these interfaces.
Kmap is gone, so the entire 2 sentences here are no longer needed. Maybe
mention something like "Unlike dma_buf_vmap() this is a short term mapping
and will not pin the buffer. The struct dma_resv for the @dmabuf must be
locked until dma_buf_vunmap_local() is called."
> + *
> + * Returns:
> + * 0 on success, or a negative errno code otherwise.
> + */
> +int dma_buf_vmap_local(struct dma_buf *dmabuf, struct dma_buf_map *map)
> +{
> + struct dma_buf_map ptr;
> + int ret = 0;
> +
> + dma_buf_map_clear(map);
> +
> + if (WARN_ON(!dmabuf))
> + return -EINVAL;
> +
> + dma_resv_assert_held(dmabuf->resv);
> +
> + if (!dmabuf->ops->vmap_local)
> + return -EINVAL;
> +
> + mutex_lock(&dmabuf->lock);
> + if (dmabuf->vmapping_counter) {
> + dmabuf->vmapping_counter++;
> + BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
> + *map = dmabuf->vmap_ptr;
> + goto out_unlock;
> + }
> +
> + BUG_ON(dma_buf_map_is_set(&dmabuf->vmap_ptr));
> +
> + ret = dmabuf->ops->vmap_local(dmabuf, &ptr);
> + if (WARN_ON_ONCE(ret))
> + goto out_unlock;
> +
> + dmabuf->vmap_ptr = ptr;
> + dmabuf->vmapping_counter = 1;
> +
> + *map = dmabuf->vmap_ptr;
> +
> +out_unlock:
> + mutex_unlock(&dmabuf->lock);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(dma_buf_vmap_local);
> +
> +/**
> + * dma_buf_vunmap_local - Unmap a vmap obtained by dma_buf_vmap_local.
> + * @dmabuf: [in] buffer to vunmap
> + * @map: [in] vmap pointer to vunmap
Maybe for hyperlinking add "Release a mapping established with
dma_buf_vmap_local()."
> + */
> +void dma_buf_vunmap_local(struct dma_buf *dmabuf, struct dma_buf_map *map)
> +{
> + if (WARN_ON(!dmabuf))
> + return;
> +
> + dma_resv_assert_held(dmabuf->resv);
> +
> + BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr));
> + BUG_ON(dmabuf->vmapping_counter == 0);
> + BUG_ON(!dma_buf_map_is_equal(&dmabuf->vmap_ptr, map));
> +
> + mutex_lock(&dmabuf->lock);
> + if (--dmabuf->vmapping_counter == 0) {
> + if (dmabuf->ops->vunmap_local)
> + dmabuf->ops->vunmap_local(dmabuf, map);
> + dma_buf_map_clear(&dmabuf->vmap_ptr);
> + }
> + mutex_unlock(&dmabuf->lock);
> +}
> +EXPORT_SYMBOL_GPL(dma_buf_vunmap_local);
> +
> #ifdef CONFIG_DEBUG_FS
> static int dma_buf_debug_show(struct seq_file *s, void *unused)
> {
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index cf72699cb2bc..f66580d23a9b 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -269,6 +269,38 @@ struct dma_buf_ops {
>
> int (*vmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> void (*vunmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> +
> + /**
> + * @vmap_local:
> + *
> + * Creates a virtual mapping for the buffer into kernel address space.
> + *
> + * This callback establishes short-term mappings for situations where
> + * callers only use the buffer for a bounded amount of time; such as
> + * updates to the framebuffer or reading back contained information.
> + * In contrast to the regular @vmap callback, vmap_local does never pin
> + * the buffer to a specific domain or acquire the buffer's reservation
> + * lock.
> + *
> + * This is called with the dmabuf->resv object locked. Callers must hold
^^Not the right kerneldoc, I think it
should be &dma_buf.resv to get the
hyperlink.
> + * the lock until after removing the mapping with @vunmap_local.
> + *
> + * This callback is optional.
> + *
> + * Returns:
> + *
> + * 0 on success or a negative error code on failure.
> + */
> + int (*vmap_local)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> +
> + /**
> + * @vunmap_local:
> + *
> + * Removes a virtual mapping that wa sestablished by @vmap_local.
^^established
> + *
> + * This callback is optional.
> + */
> + void (*vunmap_local)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> };
>
> /**
> @@ -506,4 +538,6 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
> unsigned long);
> int dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map);
> void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map);
> +int dma_buf_vmap_local(struct dma_buf *dmabuf, struct dma_buf_map *map);
> +void dma_buf_vunmap_local(struct dma_buf *dmabuf, struct dma_buf_map *map);
> #endif /* __DMA_BUF_H__ */
With the doc nits addressed:
Reviewed-by: Daniel Vetter <daniel.vetter(a)ffwll.ch>
> --
> 2.29.2
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
This patchset introduces a new dma heap, chunk heap that makes it
easy to perform the bulk allocation of high order pages.
It has been created to help optimize the 4K/8K HDR video playback
with secure DRM HW to protect contents on memory. The HW needs
physically contiguous memory chunks up to several hundred MB memory.
The chunk heap is registered by device tree with alignment and memory
node of Contiguous Memory Allocator(CMA). Alignment defines chunk page size.
For example, alignment 0x1_0000 means chunk page size is 64KB.
The phandle to memory node indicates contiguous memory allocator(CMA).
If device node doesn't have cma, the registration of chunk heap fails.
This patchset is against on next-20201110.
The patchset includes the following:
- cma_alloc_bulk API
- export dma-heap API to register kernel module dma heap.
- add chunk heap implementation.
- devicetree
Hyesoo Yu (3):
dma-buf: add export symbol for dma-heap
dma-buf: heaps: add chunk heap to dmabuf heaps
dma-heap: Devicetree binding for chunk heap
Minchan Kim (1):
mm: introduce cma_alloc_bulk API
.../bindings/dma-buf/chunk_heap.yaml | 52 ++
drivers/dma-buf/dma-heap.c | 2 +
drivers/dma-buf/heaps/Kconfig | 9 +
drivers/dma-buf/heaps/Makefile | 1 +
drivers/dma-buf/heaps/chunk_heap.c | 458 ++++++++++++++++++
include/linux/cma.h | 5 +
include/linux/page-isolation.h | 1 +
mm/cma.c | 129 ++++-
mm/page_alloc.c | 19 +-
mm/page_isolation.c | 3 +-
10 files changed, 666 insertions(+), 13 deletions(-)
create mode 100644 Documentation/devicetree/bindings/dma-buf/chunk_heap.yaml
create mode 100644 drivers/dma-buf/heaps/chunk_heap.c
--
2.29.2.299.gdc1121823c-goog
On Wed, Dec 9, 2020 at 10:32 AM Thomas Zimmermann <tzimmermann(a)suse.de> wrote:
>
> Hi
>
> Am 09.12.20 um 01:13 schrieb Daniel Vetter:
> > On Fri, Dec 04, 2020 at 09:47:08AM +0100, Christian König wrote:
> >> Am 04.12.20 um 09:32 schrieb Thomas Zimmermann:
> >>> Hi
> >>>
> >>> Am 03.12.20 um 21:41 schrieb Daniel Vetter:
> >>>> On Thu, Dec 03, 2020 at 07:59:04PM +0100, Thomas Zimmermann wrote:
> >>>>> Hi
> >>>>>
> >>>>> Am 03.12.20 um 16:26 schrieb Daniel Vetter:
> >>>>>> On Thu, Dec 03, 2020 at 03:02:59PM +0100, Thomas Zimmermann wrote:
> >>>>>>> Dma-buf's vmap and vunmap callbacks are undocumented and various
> >>>>>>> exporters currently have slightly different semantics for them. Add
> >>>>>>> documentation on how to implement and use these interfaces correctly.
> >>>>>>>
> >>>>>>> v2:
> >>>>>>> * document vmap semantics in struct dma_buf_ops
> >>>>>>> * add TODO item for reviewing and maybe fixing dma-buf exporters
> >>>>>>>
> >>>>>>> Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
> >>>>>>
> >>>>>> I still don't think this works, we're breaking dma_buf_vmap
> >>>>>> for everyone
> >>>>>> else here.
> >>>>>
> >>>>> I removed the text on the importer. These notes for callers in
> >>>>> the docs are
> >>>>> more or less a consequence of the exporter semantics.
> >>>>
> >>>> Callers are importers, so I'm not seeing how that fixes anything.
> >>>>
> >>>>> I thought we at least agreed on the exporter semantics in the
> >>>>> other thread,
> >>>>> didn't we?
> >>>>>
> >>>>> What I'm trying to do is to write dome some rules for exporters,
> >>>>> even if not
> >>>>> all exporters follow them.
> >>>>
> >>>> This is a standard interface, everyone needs to follow the same
> >>>> rules. And
> >>>> if they change, we need to make sure nothing breaks and we're not
> >>>> creating
> >>>> issues.
> >>>>
> >>>> In the past the rule was the dma_buf_vmap was allowed to take the
> >>>> dma_resv_lock, and that the buffer should be pinned. Now some ttm
> >>>> drivers
> >>>> didn't ever bother with the pinning, and mostly got away with that
> >>>> because
> >>>> drm_prime helpers do the pinning by default at attach time, and most
> >>>> users
> >>>> do call dma_buf_attach.
> >>>>
> >>>> But if you look through dma-buf docs nothing ever said you have to do a
> >>>> dummy attachment before you call dma_buf_vmap, that's just slightly
> >>>> crappy
> >>>> implementations that didn't blow up yet.
> >>>
> >>> I had a patch for adding pin to radeon's implementation of vmap. [1]
> >>> Christian told me to not do this; instead just get the lock in the fbdev
> >>> code. His advise almost seems the opposite of what you're telling me
> >>> here.
> >>
> >> I think what Daniel suggests here is that we need to smoothly transition the
> >> code from making assumptions to having a straight interface where importers
> >> explicitly say when stuff is locked and when stuff is pinned.
> >>
> >> I've started this with the attach interface by adding a new dynamic approach
> >> to that, but you probably need to carry on here with that for vmap as well.
> >>
> >> When that is done we can migrate every exporter over to the new dynamic
> >> approach.
> >>
> >>>
> >>> For the GEM VRAM helpers, that implicit pin in vmap gave me headaches.
> >>> Because scanouts can only be done from VRAM, which is badly suited for
> >>> exporting. So I ended up with an implicit pin that pins the buffer to
> >>> whatever domain it currently is. I got away with it because GEM VRAM BOs
> >>> are not sharable among devices; fbdev is the only user of that
> >>> functionality and only pins for short periods of time.
> >>>
> >>> I suspect that fixing TTM-based drivers by adding an implicit pin would
> >>> result in a similar situation. Whatever domain it ends up pinning, some
> >>> functionality might not be compatible with that.
> >>
> >> Correct, exactly that's the problem.
> >>
> >>>
> >>>>
> >>>>> Given the circumstances, we should leave out this patch from the
> >>>>> patchset.
> >>>>
> >>>> So the defacto rules are already a big mess, but that's not a good
> >>>> excuse
> >>>> to make it worse.
> >>>>
> >>>> What I had in mind is that we split dma_buf_vmap up into two variants:
> >>>>
> >>>> - The current one, which should guarantee that the buffer is pinned.
> >>>> Because that's what all current callers wanted, before the fbdev code
> >>>> started allowing non-pinned buffers.
> >>>
> >>> Can we add an explicit pin operation to dma_buf_vmap() to enforce the
> >>> semantics?
> >>
> >> At least I would be fine with that. For now amdgpu is the only exporter who
> >> implements the explicit pin/unpin semantics anyway.
> >
> > Yup, I think that makes sense (if it works). Maybe we could use something
> > like:
> >
> > a) dma_buf pin exists, driver is dynamic. This means dma_buf_vmap needs to
> > first pin, then call ->vmap. dma_buf_vmap_local otoh can directly call
> > ->vmap since the exporter relies on either a pin or dma_resv_lock.
> >
> > b) dma_buf pin not implement, driver is a legacy pile. dma_buf_vmap will
> > pin (somewhere at least, or rely on some implicit pin), dma_buf_vmap_local
> > doesn't work and should fail.
>
> I think I read in the dma-buf documentation that pin is supposed to put
> the BO in a domain that is suitable for scanout. Now I don't really
> trust this to work. Amdgpu, radeon and nouveau put it into the GTT
> region. Qxl appears to put it wherever it is.
Uh that sounds wrong, or at least not the full complexity. ->pin's
main use right now is to freeze the dma-buf into system memory when
there's a non-dynamic attachement for a dynamic exporter. There's also
a dma_buf_pin call in amdgpu, and I think that only works for scanout
on integrated gpu. Pinning to vram would break sharing for all
existing dma-buf users.
Christian can you perhaps explain when amdgpu uses dma_buf_pin()?
My take is the ->pin callback should clarify that it should pin into
system memory, for legacy (non-dynamic) dma-buf users. And
dma_buf_pin() should gain some kerneldoc which then states that "This
should only be used in limited use cases like scanout and not for
temporary pin operations." I think the problem with this kerneldoc is
simply that it tries to document the exporter and importer side of the
contract in one place and makes a mess of it, plus leaves the actual
importer side function undocumented. I think the kerneldoc also
predates the final patch version, and we didn't update it fully.
> > I think for less transition work fbdev helpers could first try
> > dma_resv_lock + dma_buf_vmap_local, if that fails, drop the dma_resv_lock
> > and do the pinning dma_buf_vmap. That way we don't have to convert shmem
> > helpers over to dma_resv locking, which should help.
>
> I have meanwhile made a patchset that updates helpers for cma, shmem and
> vram with vmap_local; and converts fbdev emulation as well. It needs a
> bit more testing before being posted.
Nice, even better!
-Daniel
> Best regards
> Thomas
>
> >
> > And ttm drivers would do the new clean interface, so at least everyone
> > using dma_resv today is all fine. Intel's conversion to dma_resv lock is
> > in-flight, but that needs a conversion to the dynamic interface anyway,
> > the current code splats. And dynamic brings means explicit pin/unpin
> > callbacks, so should be good too.
> > -Daniel
> >
> >>
> >> Regards,
> >> Christian.
> >>
> >>>
> >>> Best regards
> >>> Thomas
> >>>
> >>> [1] https://patchwork.freedesktop.org/patch/400054/?series=83765&rev=1
> >>>
> >>>>
> >>>> - The new one, which allows vmapping with just dma_resv locked, and
> >>>> should
> >>>> have some caching in exporters.
> >>>>
> >>>> Breaking code and then adding todos about that is kinda not so cool
> >>>> approach here imo.
> >>>>
> >>>> Also I guess ttm_bo_vmap should have a check that either the buffer is
> >>>> pinned, or dma_resv_lock is held.
> >>>>
> >>>> Cheers, Daniel
> >>>>
> >>>>
> >>>>
> >>>>>
> >>>>> Best regards
> >>>>> Thomas
> >>>>>
> >>>>>>
> >>>>>>> ---
> >>>>>>> Documentation/gpu/todo.rst | 15 +++++++++++++
> >>>>>>> include/drm/drm_gem.h | 4 ++++
> >>>>>>> include/linux/dma-buf.h | 45
> >>>>>>> ++++++++++++++++++++++++++++++++++++++
> >>>>>>> 3 files changed, 64 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> >>>>>>> index 009d8e6c7e3c..32bb797a84fc 100644
> >>>>>>> --- a/Documentation/gpu/todo.rst
> >>>>>>> +++ b/Documentation/gpu/todo.rst
> >>>>>>> @@ -505,6 +505,21 @@ Contact: Thomas Zimmermann
> >>>>>>> <tzimmermann(a)suse.de>, Christian König, Daniel Vette
> >>>>>>> Level: Intermediate
> >>>>>>> +Enforce rules for dma-buf vmap and pin ops
> >>>>>>> +------------------------------------------
> >>>>>>> +
> >>>>>>> +Exporter implementations of vmap and pin in struct
> >>>>>>> dma_buf_ops (and consequently
> >>>>>>> +struct drm_gem_object_funcs) use a variety of locking
> >>>>>>> semantics. Some rely on
> >>>>>>> +the caller holding the dma-buf's reservation lock, some
> >>>>>>> do their own locking,
> >>>>>>> +some don't require any locking. VRAM helpers even used
> >>>>>>> to pin as part of vmap.
> >>>>>>> +
> >>>>>>> +We need to review each exporter and enforce the documented rules.
> >>>>>>> +
> >>>>>>> +Contact: Christian König, Daniel Vetter, Thomas
> >>>>>>> Zimmermann <tzimmermann(a)suse.de>
> >>>>>>> +
> >>>>>>> +Level: Advanced
> >>>>>>> +
> >>>>>>> +
> >>>>>>> Core refactorings
> >>>>>>> =================
> >>>>>>> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> >>>>>>> index 5e6daa1c982f..1864c6a721b1 100644
> >>>>>>> --- a/include/drm/drm_gem.h
> >>>>>>> +++ b/include/drm/drm_gem.h
> >>>>>>> @@ -138,6 +138,8 @@ struct drm_gem_object_funcs {
> >>>>>>> * drm_gem_dmabuf_vmap() helper.
> >>>>>>> *
> >>>>>>> * This callback is optional.
> >>>>>>> + *
> >>>>>>> + * See also struct dma_buf_ops.vmap
> >>>>>>> */
> >>>>>>> int (*vmap)(struct drm_gem_object *obj, struct
> >>>>>>> dma_buf_map *map);
> >>>>>>> @@ -148,6 +150,8 @@ struct drm_gem_object_funcs {
> >>>>>>> * drm_gem_dmabuf_vunmap() helper.
> >>>>>>> *
> >>>>>>> * This callback is optional.
> >>>>>>> + *
> >>>>>>> + * See also struct dma_buf_ops.vunmap
> >>>>>>> */
> >>>>>>> void (*vunmap)(struct drm_gem_object *obj, struct
> >>>>>>> dma_buf_map *map);
> >>>>>>> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> >>>>>>> index cf72699cb2bc..dc81fdc01dda 100644
> >>>>>>> --- a/include/linux/dma-buf.h
> >>>>>>> +++ b/include/linux/dma-buf.h
> >>>>>>> @@ -267,7 +267,52 @@ struct dma_buf_ops {
> >>>>>>> */
> >>>>>>> int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
> >>>>>>> + /**
> >>>>>>> + * @vmap:
> >>>>>>
> >>>>>> There's already a @vmap and @vunamp kerneldoc at the top comment, that
> >>>>>> needs to be removed.
> >>>>>> -Daniel
> >>>>>>
> >>>>>>> + *
> >>>>>>> + * Returns a virtual address for the buffer.
> >>>>>>> + *
> >>>>>>> + * Notes to callers:
> >>>>>>> + *
> >>>>>>> + * - Callers must hold the struct dma_buf.resv lock
> >>>>>>> before calling
> >>>>>>> + * this interface.
> >>>>>>> + *
> >>>>>>> + * - Callers must provide means to prevent the
> >>>>>>> mappings from going
> >>>>>>> + * stale, such as holding the reservation lock or providing a
> >>>>>>> + * move-notify callback to the exporter.
> >>>>>>> + *
> >>>>>>> + * Notes to implementors:
> >>>>>>> + *
> >>>>>>> + * - Implementations must expect pairs of @vmap and
> >>>>>>> @vunmap to be
> >>>>>>> + * called frequently and should optimize for this case.
> >>>>>>> + *
> >>>>>>> + * - Implementations should avoid additional operations, such as
> >>>>>>> + * pinning.
> >>>>>>> + *
> >>>>>>> + * - Implementations may expect the caller to hold the dma-buf's
> >>>>>>> + * reservation lock to protect against concurrent calls and
> >>>>>>> + * relocation.
> >>>>>>> + *
> >>>>>>> + * - Implementations may provide additional
> >>>>>>> guarantees, such as working
> >>>>>>> + * without holding the reservation lock.
> >>>>>>> + *
> >>>>>>> + * This callback is optional.
> >>>>>>> + *
> >>>>>>> + * Returns:
> >>>>>>> + *
> >>>>>>> + * 0 on success or a negative error code on failure.
> >>>>>>> + */
> >>>>>>> int (*vmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> >>>>>>> +
> >>>>>>> + /**
> >>>>>>> + * @vunmap:
> >>>>>>> + *
> >>>>>>> + * Releases the address previously returned by @vmap.
> >>>>>>> + *
> >>>>>>> + * This callback is optional.
> >>>>>>> + *
> >>>>>>> + * See also @vmap()
> >>>>>>> + */
> >>>>>>> void (*vunmap)(struct dma_buf *dmabuf, struct
> >>>>>>> dma_buf_map *map);
> >>>>>>> };
> >>>>>>> --
> >>>>>>> 2.29.2
> >>>>>>>
> >>>>>>
> >>>>>
> >>>>> --
> >>>>> Thomas Zimmermann
> >>>>> Graphics Driver Developer
> >>>>> SUSE Software Solutions Germany GmbH
> >>>>> Maxfeldstr. 5, 90409 Nürnberg, Germany
> >>>>> (HRB 36809, AG Nürnberg)
> >>>>> Geschäftsführer: Felix Imendörffer
> >>>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>
> >>
> >
>
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> (HRB 36809, AG Nürnberg)
> Geschäftsführer: Felix Imendörffer
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
Am 04.12.20 um 09:32 schrieb Thomas Zimmermann:
> Hi
>
> Am 03.12.20 um 21:41 schrieb Daniel Vetter:
>> On Thu, Dec 03, 2020 at 07:59:04PM +0100, Thomas Zimmermann wrote:
>>> Hi
>>>
>>> Am 03.12.20 um 16:26 schrieb Daniel Vetter:
>>>> On Thu, Dec 03, 2020 at 03:02:59PM +0100, Thomas Zimmermann wrote:
>>>>> Dma-buf's vmap and vunmap callbacks are undocumented and various
>>>>> exporters currently have slightly different semantics for them. Add
>>>>> documentation on how to implement and use these interfaces correctly.
>>>>>
>>>>> v2:
>>>>> * document vmap semantics in struct dma_buf_ops
>>>>> * add TODO item for reviewing and maybe fixing dma-buf exporters
>>>>>
>>>>> Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
>>>>
>>>> I still don't think this works, we're breaking dma_buf_vmap for
>>>> everyone
>>>> else here.
>>>
>>> I removed the text on the importer. These notes for callers in the
>>> docs are
>>> more or less a consequence of the exporter semantics.
>>
>> Callers are importers, so I'm not seeing how that fixes anything.
>>
>>> I thought we at least agreed on the exporter semantics in the other
>>> thread,
>>> didn't we?
>>>
>>> What I'm trying to do is to write dome some rules for exporters,
>>> even if not
>>> all exporters follow them.
>>
>> This is a standard interface, everyone needs to follow the same
>> rules. And
>> if they change, we need to make sure nothing breaks and we're not
>> creating
>> issues.
>>
>> In the past the rule was the dma_buf_vmap was allowed to take the
>> dma_resv_lock, and that the buffer should be pinned. Now some ttm
>> drivers
>> didn't ever bother with the pinning, and mostly got away with that
>> because
>> drm_prime helpers do the pinning by default at attach time, and most
>> users
>> do call dma_buf_attach.
>>
>> But if you look through dma-buf docs nothing ever said you have to do a
>> dummy attachment before you call dma_buf_vmap, that's just slightly
>> crappy
>> implementations that didn't blow up yet.
>
> I had a patch for adding pin to radeon's implementation of vmap. [1]
> Christian told me to not do this; instead just get the lock in the
> fbdev code. His advise almost seems the opposite of what you're
> telling me here.
I think what Daniel suggests here is that we need to smoothly transition
the code from making assumptions to having a straight interface where
importers explicitly say when stuff is locked and when stuff is pinned.
I've started this with the attach interface by adding a new dynamic
approach to that, but you probably need to carry on here with that for
vmap as well.
When that is done we can migrate every exporter over to the new dynamic
approach.
>
> For the GEM VRAM helpers, that implicit pin in vmap gave me headaches.
> Because scanouts can only be done from VRAM, which is badly suited for
> exporting. So I ended up with an implicit pin that pins the buffer to
> whatever domain it currently is. I got away with it because GEM VRAM
> BOs are not sharable among devices; fbdev is the only user of that
> functionality and only pins for short periods of time.
>
> I suspect that fixing TTM-based drivers by adding an implicit pin
> would result in a similar situation. Whatever domain it ends up
> pinning, some functionality might not be compatible with that.
Correct, exactly that's the problem.
>
>>
>>> Given the circumstances, we should leave out this patch from the
>>> patchset.
>>
>> So the defacto rules are already a big mess, but that's not a good
>> excuse
>> to make it worse.
>>
>> What I had in mind is that we split dma_buf_vmap up into two variants:
>>
>> - The current one, which should guarantee that the buffer is pinned.
>> Because that's what all current callers wanted, before the fbdev code
>> started allowing non-pinned buffers.
>
> Can we add an explicit pin operation to dma_buf_vmap() to enforce the
> semantics?
At least I would be fine with that. For now amdgpu is the only exporter
who implements the explicit pin/unpin semantics anyway.
Regards,
Christian.
>
> Best regards
> Thomas
>
> [1] https://patchwork.freedesktop.org/patch/400054/?series=83765&rev=1
>
>>
>> - The new one, which allows vmapping with just dma_resv locked, and
>> should
>> have some caching in exporters.
>>
>> Breaking code and then adding todos about that is kinda not so cool
>> approach here imo.
>>
>> Also I guess ttm_bo_vmap should have a check that either the buffer is
>> pinned, or dma_resv_lock is held.
>>
>> Cheers, Daniel
>>
>>
>>
>>>
>>> Best regards
>>> Thomas
>>>
>>>>
>>>>> ---
>>>>> Documentation/gpu/todo.rst | 15 +++++++++++++
>>>>> include/drm/drm_gem.h | 4 ++++
>>>>> include/linux/dma-buf.h | 45
>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>> 3 files changed, 64 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
>>>>> index 009d8e6c7e3c..32bb797a84fc 100644
>>>>> --- a/Documentation/gpu/todo.rst
>>>>> +++ b/Documentation/gpu/todo.rst
>>>>> @@ -505,6 +505,21 @@ Contact: Thomas Zimmermann
>>>>> <tzimmermann(a)suse.de>, Christian König, Daniel Vette
>>>>> Level: Intermediate
>>>>> +Enforce rules for dma-buf vmap and pin ops
>>>>> +------------------------------------------
>>>>> +
>>>>> +Exporter implementations of vmap and pin in struct dma_buf_ops
>>>>> (and consequently
>>>>> +struct drm_gem_object_funcs) use a variety of locking semantics.
>>>>> Some rely on
>>>>> +the caller holding the dma-buf's reservation lock, some do their
>>>>> own locking,
>>>>> +some don't require any locking. VRAM helpers even used to pin as
>>>>> part of vmap.
>>>>> +
>>>>> +We need to review each exporter and enforce the documented rules.
>>>>> +
>>>>> +Contact: Christian König, Daniel Vetter, Thomas Zimmermann
>>>>> <tzimmermann(a)suse.de>
>>>>> +
>>>>> +Level: Advanced
>>>>> +
>>>>> +
>>>>> Core refactorings
>>>>> =================
>>>>> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
>>>>> index 5e6daa1c982f..1864c6a721b1 100644
>>>>> --- a/include/drm/drm_gem.h
>>>>> +++ b/include/drm/drm_gem.h
>>>>> @@ -138,6 +138,8 @@ struct drm_gem_object_funcs {
>>>>> * drm_gem_dmabuf_vmap() helper.
>>>>> *
>>>>> * This callback is optional.
>>>>> + *
>>>>> + * See also struct dma_buf_ops.vmap
>>>>> */
>>>>> int (*vmap)(struct drm_gem_object *obj, struct dma_buf_map
>>>>> *map);
>>>>> @@ -148,6 +150,8 @@ struct drm_gem_object_funcs {
>>>>> * drm_gem_dmabuf_vunmap() helper.
>>>>> *
>>>>> * This callback is optional.
>>>>> + *
>>>>> + * See also struct dma_buf_ops.vunmap
>>>>> */
>>>>> void (*vunmap)(struct drm_gem_object *obj, struct
>>>>> dma_buf_map *map);
>>>>> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
>>>>> index cf72699cb2bc..dc81fdc01dda 100644
>>>>> --- a/include/linux/dma-buf.h
>>>>> +++ b/include/linux/dma-buf.h
>>>>> @@ -267,7 +267,52 @@ struct dma_buf_ops {
>>>>> */
>>>>> int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
>>>>> + /**
>>>>> + * @vmap:
>>>>
>>>> There's already a @vmap and @vunamp kerneldoc at the top comment, that
>>>> needs to be removed.
>>>> -Daniel
>>>>
>>>>> + *
>>>>> + * Returns a virtual address for the buffer.
>>>>> + *
>>>>> + * Notes to callers:
>>>>> + *
>>>>> + * - Callers must hold the struct dma_buf.resv lock before
>>>>> calling
>>>>> + * this interface.
>>>>> + *
>>>>> + * - Callers must provide means to prevent the mappings from
>>>>> going
>>>>> + * stale, such as holding the reservation lock or providing a
>>>>> + * move-notify callback to the exporter.
>>>>> + *
>>>>> + * Notes to implementors:
>>>>> + *
>>>>> + * - Implementations must expect pairs of @vmap and @vunmap
>>>>> to be
>>>>> + * called frequently and should optimize for this case.
>>>>> + *
>>>>> + * - Implementations should avoid additional operations, such as
>>>>> + * pinning.
>>>>> + *
>>>>> + * - Implementations may expect the caller to hold the dma-buf's
>>>>> + * reservation lock to protect against concurrent calls and
>>>>> + * relocation.
>>>>> + *
>>>>> + * - Implementations may provide additional guarantees, such
>>>>> as working
>>>>> + * without holding the reservation lock.
>>>>> + *
>>>>> + * This callback is optional.
>>>>> + *
>>>>> + * Returns:
>>>>> + *
>>>>> + * 0 on success or a negative error code on failure.
>>>>> + */
>>>>> int (*vmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
>>>>> +
>>>>> + /**
>>>>> + * @vunmap:
>>>>> + *
>>>>> + * Releases the address previously returned by @vmap.
>>>>> + *
>>>>> + * This callback is optional.
>>>>> + *
>>>>> + * See also @vmap()
>>>>> + */
>>>>> void (*vunmap)(struct dma_buf *dmabuf, struct dma_buf_map
>>>>> *map);
>>>>> };
>>>>> --
>>>>> 2.29.2
>>>>>
>>>>
>>>
>>> --
>>> Thomas Zimmermann
>>> Graphics Driver Developer
>>> SUSE Software Solutions Germany GmbH
>>> Maxfeldstr. 5, 90409 Nürnberg, Germany
>>> (HRB 36809, AG Nürnberg)
>>> Geschäftsführer: Felix Imendörffer
>>>
>>
>>
>>
>>
>
On Thu, Dec 03, 2020 at 07:59:04PM +0100, Thomas Zimmermann wrote:
> Hi
>
> Am 03.12.20 um 16:26 schrieb Daniel Vetter:
> > On Thu, Dec 03, 2020 at 03:02:59PM +0100, Thomas Zimmermann wrote:
> > > Dma-buf's vmap and vunmap callbacks are undocumented and various
> > > exporters currently have slightly different semantics for them. Add
> > > documentation on how to implement and use these interfaces correctly.
> > >
> > > v2:
> > > * document vmap semantics in struct dma_buf_ops
> > > * add TODO item for reviewing and maybe fixing dma-buf exporters
> > >
> > > Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
> >
> > I still don't think this works, we're breaking dma_buf_vmap for everyone
> > else here.
>
> I removed the text on the importer. These notes for callers in the docs are
> more or less a consequence of the exporter semantics.
Callers are importers, so I'm not seeing how that fixes anything.
> I thought we at least agreed on the exporter semantics in the other thread,
> didn't we?
>
> What I'm trying to do is to write dome some rules for exporters, even if not
> all exporters follow them.
This is a standard interface, everyone needs to follow the same rules. And
if they change, we need to make sure nothing breaks and we're not creating
issues.
In the past the rule was the dma_buf_vmap was allowed to take the
dma_resv_lock, and that the buffer should be pinned. Now some ttm drivers
didn't ever bother with the pinning, and mostly got away with that because
drm_prime helpers do the pinning by default at attach time, and most users
do call dma_buf_attach.
But if you look through dma-buf docs nothing ever said you have to do a
dummy attachment before you call dma_buf_vmap, that's just slightly crappy
implementations that didn't blow up yet.
> Given the circumstances, we should leave out this patch from the patchset.
So the defacto rules are already a big mess, but that's not a good excuse
to make it worse.
What I had in mind is that we split dma_buf_vmap up into two variants:
- The current one, which should guarantee that the buffer is pinned.
Because that's what all current callers wanted, before the fbdev code
started allowing non-pinned buffers.
- The new one, which allows vmapping with just dma_resv locked, and should
have some caching in exporters.
Breaking code and then adding todos about that is kinda not so cool
approach here imo.
Also I guess ttm_bo_vmap should have a check that either the buffer is
pinned, or dma_resv_lock is held.
Cheers, Daniel
>
> Best regards
> Thomas
>
> >
> > > ---
> > > Documentation/gpu/todo.rst | 15 +++++++++++++
> > > include/drm/drm_gem.h | 4 ++++
> > > include/linux/dma-buf.h | 45 ++++++++++++++++++++++++++++++++++++++
> > > 3 files changed, 64 insertions(+)
> > >
> > > diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> > > index 009d8e6c7e3c..32bb797a84fc 100644
> > > --- a/Documentation/gpu/todo.rst
> > > +++ b/Documentation/gpu/todo.rst
> > > @@ -505,6 +505,21 @@ Contact: Thomas Zimmermann <tzimmermann(a)suse.de>, Christian König, Daniel Vette
> > > Level: Intermediate
> > > +Enforce rules for dma-buf vmap and pin ops
> > > +------------------------------------------
> > > +
> > > +Exporter implementations of vmap and pin in struct dma_buf_ops (and consequently
> > > +struct drm_gem_object_funcs) use a variety of locking semantics. Some rely on
> > > +the caller holding the dma-buf's reservation lock, some do their own locking,
> > > +some don't require any locking. VRAM helpers even used to pin as part of vmap.
> > > +
> > > +We need to review each exporter and enforce the documented rules.
> > > +
> > > +Contact: Christian König, Daniel Vetter, Thomas Zimmermann <tzimmermann(a)suse.de>
> > > +
> > > +Level: Advanced
> > > +
> > > +
> > > Core refactorings
> > > =================
> > > diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> > > index 5e6daa1c982f..1864c6a721b1 100644
> > > --- a/include/drm/drm_gem.h
> > > +++ b/include/drm/drm_gem.h
> > > @@ -138,6 +138,8 @@ struct drm_gem_object_funcs {
> > > * drm_gem_dmabuf_vmap() helper.
> > > *
> > > * This callback is optional.
> > > + *
> > > + * See also struct dma_buf_ops.vmap
> > > */
> > > int (*vmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
> > > @@ -148,6 +150,8 @@ struct drm_gem_object_funcs {
> > > * drm_gem_dmabuf_vunmap() helper.
> > > *
> > > * This callback is optional.
> > > + *
> > > + * See also struct dma_buf_ops.vunmap
> > > */
> > > void (*vunmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
> > > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> > > index cf72699cb2bc..dc81fdc01dda 100644
> > > --- a/include/linux/dma-buf.h
> > > +++ b/include/linux/dma-buf.h
> > > @@ -267,7 +267,52 @@ struct dma_buf_ops {
> > > */
> > > int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
> > > + /**
> > > + * @vmap:
> >
> > There's already a @vmap and @vunamp kerneldoc at the top comment, that
> > needs to be removed.
> > -Daniel
> >
> > > + *
> > > + * Returns a virtual address for the buffer.
> > > + *
> > > + * Notes to callers:
> > > + *
> > > + * - Callers must hold the struct dma_buf.resv lock before calling
> > > + * this interface.
> > > + *
> > > + * - Callers must provide means to prevent the mappings from going
> > > + * stale, such as holding the reservation lock or providing a
> > > + * move-notify callback to the exporter.
> > > + *
> > > + * Notes to implementors:
> > > + *
> > > + * - Implementations must expect pairs of @vmap and @vunmap to be
> > > + * called frequently and should optimize for this case.
> > > + *
> > > + * - Implementations should avoid additional operations, such as
> > > + * pinning.
> > > + *
> > > + * - Implementations may expect the caller to hold the dma-buf's
> > > + * reservation lock to protect against concurrent calls and
> > > + * relocation.
> > > + *
> > > + * - Implementations may provide additional guarantees, such as working
> > > + * without holding the reservation lock.
> > > + *
> > > + * This callback is optional.
> > > + *
> > > + * Returns:
> > > + *
> > > + * 0 on success or a negative error code on failure.
> > > + */
> > > int (*vmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> > > +
> > > + /**
> > > + * @vunmap:
> > > + *
> > > + * Releases the address previously returned by @vmap.
> > > + *
> > > + * This callback is optional.
> > > + *
> > > + * See also @vmap()
> > > + */
> > > void (*vunmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> > > };
> > > --
> > > 2.29.2
> > >
> >
>
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> (HRB 36809, AG Nürnberg)
> Geschäftsführer: Felix Imendörffer
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
On Thu, Dec 03, 2020 at 03:02:59PM +0100, Thomas Zimmermann wrote:
> Dma-buf's vmap and vunmap callbacks are undocumented and various
> exporters currently have slightly different semantics for them. Add
> documentation on how to implement and use these interfaces correctly.
>
> v2:
> * document vmap semantics in struct dma_buf_ops
> * add TODO item for reviewing and maybe fixing dma-buf exporters
>
> Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
I still don't think this works, we're breaking dma_buf_vmap for everyone
else here.
> ---
> Documentation/gpu/todo.rst | 15 +++++++++++++
> include/drm/drm_gem.h | 4 ++++
> include/linux/dma-buf.h | 45 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 64 insertions(+)
>
> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> index 009d8e6c7e3c..32bb797a84fc 100644
> --- a/Documentation/gpu/todo.rst
> +++ b/Documentation/gpu/todo.rst
> @@ -505,6 +505,21 @@ Contact: Thomas Zimmermann <tzimmermann(a)suse.de>, Christian König, Daniel Vette
> Level: Intermediate
>
>
> +Enforce rules for dma-buf vmap and pin ops
> +------------------------------------------
> +
> +Exporter implementations of vmap and pin in struct dma_buf_ops (and consequently
> +struct drm_gem_object_funcs) use a variety of locking semantics. Some rely on
> +the caller holding the dma-buf's reservation lock, some do their own locking,
> +some don't require any locking. VRAM helpers even used to pin as part of vmap.
> +
> +We need to review each exporter and enforce the documented rules.
> +
> +Contact: Christian König, Daniel Vetter, Thomas Zimmermann <tzimmermann(a)suse.de>
> +
> +Level: Advanced
> +
> +
> Core refactorings
> =================
>
> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> index 5e6daa1c982f..1864c6a721b1 100644
> --- a/include/drm/drm_gem.h
> +++ b/include/drm/drm_gem.h
> @@ -138,6 +138,8 @@ struct drm_gem_object_funcs {
> * drm_gem_dmabuf_vmap() helper.
> *
> * This callback is optional.
> + *
> + * See also struct dma_buf_ops.vmap
> */
> int (*vmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
>
> @@ -148,6 +150,8 @@ struct drm_gem_object_funcs {
> * drm_gem_dmabuf_vunmap() helper.
> *
> * This callback is optional.
> + *
> + * See also struct dma_buf_ops.vunmap
> */
> void (*vunmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
>
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index cf72699cb2bc..dc81fdc01dda 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -267,7 +267,52 @@ struct dma_buf_ops {
> */
> int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
>
> + /**
> + * @vmap:
There's already a @vmap and @vunamp kerneldoc at the top comment, that
needs to be removed.
-Daniel
> + *
> + * Returns a virtual address for the buffer.
> + *
> + * Notes to callers:
> + *
> + * - Callers must hold the struct dma_buf.resv lock before calling
> + * this interface.
> + *
> + * - Callers must provide means to prevent the mappings from going
> + * stale, such as holding the reservation lock or providing a
> + * move-notify callback to the exporter.
> + *
> + * Notes to implementors:
> + *
> + * - Implementations must expect pairs of @vmap and @vunmap to be
> + * called frequently and should optimize for this case.
> + *
> + * - Implementations should avoid additional operations, such as
> + * pinning.
> + *
> + * - Implementations may expect the caller to hold the dma-buf's
> + * reservation lock to protect against concurrent calls and
> + * relocation.
> + *
> + * - Implementations may provide additional guarantees, such as working
> + * without holding the reservation lock.
> + *
> + * This callback is optional.
> + *
> + * Returns:
> + *
> + * 0 on success or a negative error code on failure.
> + */
> int (*vmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> +
> + /**
> + * @vunmap:
> + *
> + * Releases the address previously returned by @vmap.
> + *
> + * This callback is optional.
> + *
> + * See also @vmap()
> + */
> void (*vunmap)(struct dma_buf *dmabuf, struct dma_buf_map *map);
> };
>
> --
> 2.29.2
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch