From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:44:29
GEM VRAM helpers used to pin the BO in their implementation of vmap, so
that they could not be relocated. In recent discussions, [1][2] it became
clear that this is incorrect for in-kernel use cases, such as fbdev
emulation; which should rather depend on the reservation lock to prevent
relocation.
This patchset addresses the issue by introducing the new interfaces
vmap_local and vunmap_local throughout dma-buf and GEM. It further adds
support to DRM's CMA, SHMEM and VRAM helpers and finally converts fbdev
emulation to the new interface.
Patches 1 and 2 add the vmap_local infrastructure throughout dma-buf,
GEM and PRIME.
Patches 3 to 11 add implementations of vmap_local to DRM's various GEM
helper libraries. Due to the simple nature of these libraries, existing
vmap code can be reused easily. Several drivers are updated as well to
use the new interfaces.
Patch 12 converts generic fbdev emulation to use vmap_local. Only DRM
drivers that use GEM helpers currently use fbdev emulation, so patches
3 to 11 covered all necessary instances.
Finally patch 13 removes drm_gem_vram_vmap() functionality, which is now
unused.
I smoke-tested the patchset with ast (VRAM helpers), mgag200 (SHMEM) and
vc4 (CMA). I also tested with a version of radeon (raw TTM) that had been
converted to generic fbdev emulation.
v4:
* move driver changes out of SHMEM and VRAM patches (Daniel)
* call dma_buf_vmap_local() in SHMEM implementation (Daniel)
* remove unused drm_gem_vram_vmap() functionality
* update documentation (Daniel)
v3:
* rewrite patchset around vmap_local
v2:
* make importers acquire resv locks by themselves
* document dma-buf vmap/vunmap ops
[1] https://patchwork.freedesktop.org/patch/400054/?series=83765&rev=1
[2] https://patchwork.freedesktop.org/patch/405407/?series=84401&rev=2
Thomas Zimmermann (13):
dma-buf: Add vmap_local and vnumap_local operations
drm/gem: Create infrastructure for GEM vmap_local
drm/cma-helper: Provide a vmap function for short-term mappings
drm/shmem-helper: Provide a vmap function for short-term mappings
drm/mgag200: Use drm_gem_shmem_vmap_local() in damage handling
drm/cirrus: Use drm_gem_shmem_vmap_local() in damage handling
drm/gm12u320: Use drm_gem_shmem_vmap_local() in damage handling
drm/udl: Use drm_gem_shmem_vmap_local() in damage handling
drm/vram-helper: Provide a vmap function for short-term mappings
drm/ast: Use drm_gem_vram_vmap_local() in cursor update
drm/vboxvideo: Use drm_gem_vram_vmap_local() in cursor update
drm/fb-helper: Move BO locking from DRM client to fbdev damage worker
drm/vram-helper: Remove unused drm_gem_vram_{vmap,vunmap}()
drivers/dma-buf/dma-buf.c | 81 ++++++++++++++
drivers/gpu/drm/ast/ast_cursor.c | 37 +++++--
drivers/gpu/drm/drm_client.c | 94 +++++++++++++++++
drivers/gpu/drm/drm_fb_helper.c | 41 ++++----
drivers/gpu/drm/drm_gem.c | 28 +++++
drivers/gpu/drm/drm_gem_cma_helper.c | 27 +++++
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 ++++++++++++++--
drivers/gpu/drm/drm_gem_vram_helper.c | 139 ++++++++-----------------
drivers/gpu/drm/drm_internal.h | 2 +
drivers/gpu/drm/drm_prime.c | 39 +++++++
drivers/gpu/drm/mgag200/mgag200_mode.c | 16 ++-
drivers/gpu/drm/tiny/cirrus.c | 10 +-
drivers/gpu/drm/tiny/gm12u320.c | 14 ++-
drivers/gpu/drm/udl/udl_modeset.c | 18 ++--
drivers/gpu/drm/vboxvideo/vbox_mode.c | 15 +--
drivers/gpu/drm/vc4/vc4_bo.c | 1 +
drivers/gpu/drm/virtio/virtgpu_prime.c | 2 +
include/drm/drm_client.h | 4 +
include/drm/drm_gem.h | 21 ++++
include/drm/drm_gem_cma_helper.h | 1 +
include/drm/drm_gem_shmem_helper.h | 2 +
include/drm/drm_gem_vram_helper.h | 4 +-
include/drm/drm_prime.h | 2 +
include/linux/dma-buf.h | 34 ++++++
24 files changed, 566 insertions(+), 156 deletions(-)
--
2.29.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:44:29
This patch adds vmap_local and vunmap_local to struct drm_gem_object_funcs;
including the PRIME helpers to connect with dma-buf's related interfaces.
Besides the generic DRM core, this will become relevant for fbdev emulation
with virtio, so we update it as well.
v4:
* update documentation (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
---
drivers/gpu/drm/drm_gem.c | 28 ++++++++++++++++++
drivers/gpu/drm/drm_internal.h | 2 ++
drivers/gpu/drm/drm_prime.c | 39 ++++++++++++++++++++++++++
drivers/gpu/drm/virtio/virtgpu_prime.c | 2 ++
include/drm/drm_gem.h | 21 ++++++++++++++
include/drm/drm_prime.h | 2 ++
6 files changed, 94 insertions(+)
@@ -1234,6 +1234,34 @@ void drm_gem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)dma_buf_map_clear(map);}+intdrm_gem_vmap_local(structdrm_gem_object*obj,structdma_buf_map*map)+{+intret;++if(!obj->funcs->vmap_local)+return-EOPNOTSUPP;++ret=obj->funcs->vmap_local(obj,map);+if(ret)+returnret;+elseif(dma_buf_map_is_null(map))+return-ENOMEM;++return0;+}++voiddrm_gem_vunmap_local(structdrm_gem_object*obj,structdma_buf_map*map)+{+if(dma_buf_map_is_null(map))+return;++if(obj->funcs->vunmap_local)+obj->funcs->vunmap_local(obj,map);++/* Always set the mapping to NULL. Callers may rely on this. */+dma_buf_map_clear(map);+}+/***drm_gem_lock_reservations-Setsupthewwcontextandacquires*thelockonanarrayofGEMobjects.
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:44:30
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.
v4:
* update documentation (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
Suggested-by: Daniel Vetter <redacted>
---
drivers/dma-buf/dma-buf.c | 81 +++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 34 ++++++++++++++++
2 files changed, 115 insertions(+)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:44:31
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private CMA buffers, but may happen
with imported ones.
Therefore provide the new interface drm_gem_cma_vmap_local(), which only
performs the vmap operations. Callers have to hold the reservation lock
while the mapping persists.
This patch also connects GEM CMA helpers to the GEM object function with
equivalent functionality.
v4:
* vc4: don't wrap drm_gem_cma_vmap_local() in BO funcs (Daniel)
* remove the TODO comment (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
---
drivers/gpu/drm/drm_gem_cma_helper.c | 27 +++++++++++++++++++++++++++
drivers/gpu/drm/vc4/vc4_bo.c | 1 +
include/drm/drm_gem_cma_helper.h | 1 +
3 files changed, 29 insertions(+)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:44:31
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Damage handling in cirrus requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/tiny/cirrus.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Damage handling in mgag200 requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/mgag200/mgag200_mode.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
@@ -1552,22 +1552,32 @@ mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,structdrm_rect*clip){structdrm_device*dev=&mdev->base;+structdrm_gem_object*obj=fb->obj[0];structdma_buf_mapmap;void*vmap;intret;-ret=drm_gem_shmem_vmap(fb->obj[0],&map);+ret=dma_resv_lock(obj->resv,NULL);if(drm_WARN_ON(dev,ret))-return;/* BUG: SHMEM BO should always be vmapped */+return;+ret=drm_gem_shmem_vmap_local(obj,&map);+if(drm_WARN_ON(dev,ret))+gotoerr_dma_resv_unlock;/* BUG: SHMEM BO should always be vmapped */vmap=map.vaddr;/* TODO: Use mapping abstraction properly */drm_fb_memcpy_dstclip(mdev->vram,vmap,fb,clip);-drm_gem_shmem_vunmap(fb->obj[0],&map);+drm_gem_shmem_vunmap_local(obj,&map);+dma_resv_unlock(obj->resv);/* Always scanout image at VRAM offset 0 */mgag200_set_startadd(mdev,(u32)0);mgag200_set_offset(mdev,fb);++return;++err_dma_resv_unlock:+dma_resv_unlock(obj->resv);}staticvoid
--
2.29.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Damage handling in udl requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/udl/udl_modeset.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
@@ -290,14 +290,18 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,elseif((clip.x2>fb->width)||(clip.y2>fb->height))return-EINVAL;+ret=dma_resv_lock(fb->obj[0]->resv,NULL);+if(ret)+returnret;+if(import_attach){ret=dma_buf_begin_cpu_access(import_attach->dmabuf,DMA_FROM_DEVICE);if(ret)-returnret;+gotoout_dma_resv_unlock;}-ret=drm_gem_shmem_vmap(fb->obj[0],&map);+ret=drm_gem_shmem_vmap_local(fb->obj[0],&map);if(ret){DRM_ERROR("failed to vmap fb\n");gotoout_dma_buf_end_cpu_access;
@@ -307,7 +311,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,urb=udl_get_urb(dev);if(!urb){ret=-ENOMEM;-gotoout_drm_gem_shmem_vunmap;+gotoout_drm_gem_shmem_vunmap_local;}cmd=urb->transfer_buffer;
@@ -320,7 +324,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,&cmd,byte_offset,dev_byte_offset,byte_width);if(ret)-gotoout_drm_gem_shmem_vunmap;+gotoout_drm_gem_shmem_vunmap_local;}if(cmd>(char*)urb->transfer_buffer){
@@ -336,8 +340,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,ret=0;-out_drm_gem_shmem_vunmap:-drm_gem_shmem_vunmap(fb->obj[0],&map);+out_drm_gem_shmem_vunmap_local:+drm_gem_shmem_vunmap_local(fb->obj[0],&map);out_dma_buf_end_cpu_access:if(import_attach){tmp_ret=dma_buf_end_cpu_access(import_attach->dmabuf,
@@ -345,6 +349,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, int x, int y,if(tmp_ret&&!ret)ret=tmp_ret;/* only update ret if not set yet */}+out_dma_resv_unlock:+dma_resv_unlock(fb->obj[0]->resv);returnret;}
--
2.29.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
VRAM-helper BO's cannot be exported, so calls for vmap and vunmap
can only come from the BO's drivers or a kernel client. These are
supposed use vmap_local functionality.
The vmap and vunmap operations in VRAM helpers are therefore unused
and can be removed.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_vram_helper.c | 98 ---------------------------
include/drm/drm_gem_vram_helper.h | 2 -
2 files changed, 100 deletions(-)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Cursor updates in ast require a short-term mapping of the source and
destination BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/ast/ast_cursor.c | 37 +++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 10 deletions(-)
@@ -168,26 +170,34 @@ int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb)drm_WARN_ON_ONCE(dev,fb->height>AST_MAX_HWC_HEIGHT))return-EINVAL;-ret=drm_gem_vram_vmap(src_gbo,&src_map);+ret=drm_gem_lock_reservations(objs,ARRAY_SIZE(objs),&ctx);if(ret)returnret;++ret=drm_gem_vram_vmap_local(src_gbo,&src_map);+if(ret)+gotoerr_drm_gem_unlock_reservations;src=src_map.vaddr;/* TODO: Use mapping abstraction properly */-ret=drm_gem_vram_vmap(dst_gbo,&dst_map);+ret=drm_gem_vram_vmap_local(dst_gbo,&dst_map);if(ret)-gotoerr_drm_gem_vram_vunmap;+gotoerr_drm_gem_vram_vunmap_local;dst=dst_map.vaddr_iomem;/* TODO: Use mapping abstraction properly *//* do data transfer to cursor BO */update_cursor_image(dst,src,fb->width,fb->height);-drm_gem_vram_vunmap(dst_gbo,&dst_map);-drm_gem_vram_vunmap(src_gbo,&src_map);+drm_gem_vram_vunmap_local(dst_gbo,&dst_map);+drm_gem_vram_vunmap_local(src_gbo,&src_map);++drm_gem_unlock_reservations(objs,ARRAY_SIZE(objs),&ctx);return0;-err_drm_gem_vram_vunmap:-drm_gem_vram_vunmap(src_gbo,&src_map);+err_drm_gem_vram_vunmap_local:+drm_gem_vram_vunmap_local(src_gbo,&src_map);+err_drm_gem_unlock_reservations:+drm_gem_unlock_reservations(objs,ARRAY_SIZE(objs),&ctx);returnret;}
@@ -241,6 +251,7 @@ void ast_cursor_show(struct ast_private *ast, int x, int y,{structdrm_device*dev=&ast->base;structdrm_gem_vram_object*gbo=ast->cursor.gbo[ast->cursor.next_index];+structdrm_gem_object*obj=&gbo->bo.base;structdma_buf_mapmap;u8x_offset,y_offset;u8__iomem*dst;
@@ -248,16 +259,22 @@ void ast_cursor_show(struct ast_private *ast, int x, int y,u8jreg;intret;-ret=drm_gem_vram_vmap(gbo,&map);-if(drm_WARN_ONCE(dev,ret,"drm_gem_vram_vmap() failed, ret=%d\n",ret))+ret=dma_resv_lock(obj->resv,NULL);+if(ret)+return;+ret=drm_gem_vram_vmap_local(gbo,&map);+if(drm_WARN_ONCE(dev,ret,"drm_gem_vram_vmap_local() failed, ret=%d\n",ret)){+dma_resv_unlock(obj->resv);return;+}dst=map.vaddr_iomem;/* TODO: Use mapping abstraction properly */sig=dst+AST_HWC_SIZE;writel(x,sig+AST_HWC_SIGNATURE_X);writel(y,sig+AST_HWC_SIGNATURE_Y);-drm_gem_vram_vunmap(gbo,&map);+drm_gem_vram_vunmap_local(gbo,&map);+dma_resv_unlock(obj->resv);if(x<0){x_offset=(-x)+offset_x;
--
2.29.2
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
It's somewhat inconvenient to callers that simply require a mapping of
the contained memory; and also ipmplies a certain overhead.
Therefore provide drm_gem_vram_vmap_local() drm_gem_vram_vunmap_local(),
which only perform the vmap/vunmap operations. Callers have to hold the
reservation lock while the mapping persists; or have to pin the BO by
themselves.
This patch connects GEM VRAM helpers to GEM object functions with
equivalent functionality.
v4:
* move driver changes into separate patches (Daniel)
* update documentation (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
---
drivers/gpu/drm/drm_gem_vram_helper.c | 141 +++++++++++++++++---------
include/drm/drm_gem_vram_helper.h | 2 +
2 files changed, 95 insertions(+), 48 deletions(-)
@@ -379,47 +379,6 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)}EXPORT_SYMBOL(drm_gem_vram_unpin);-staticintdrm_gem_vram_kmap_locked(structdrm_gem_vram_object*gbo,-structdma_buf_map*map)-{-intret;--if(gbo->vmap_use_count>0)-gotoout;--ret=ttm_bo_vmap(&gbo->bo,&gbo->map);-if(ret)-returnret;--out:-++gbo->vmap_use_count;-*map=gbo->map;--return0;-}--staticvoiddrm_gem_vram_kunmap_locked(structdrm_gem_vram_object*gbo,-structdma_buf_map*map)-{-structdrm_device*dev=gbo->bo.base.dev;--if(drm_WARN_ON_ONCE(dev,!gbo->vmap_use_count))-return;--if(drm_WARN_ON_ONCE(dev,!dma_buf_map_is_equal(&gbo->map,map)))-return;/* BUG: map not mapped from this BO */--if(--gbo->vmap_use_count>0)-return;--/*-*Permanentlymappingandunmappingbuffersaddsoverheadfrom-*updatingthepagetablesandcreatesdebuggingoutput.Therefore,-*wedelaytheactualunmapoperationuntiltheBOgetsevicted-*frommemory.Seedrm_gem_vram_bo_driver_move_notify().-*/-}-/***drm_gem_vram_vmap()-PinsandmapsaGEMVRAMobjectintokerneladdress*space
@@ -479,13 +438,83 @@ void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, struct dma_buf_map *maif(WARN_ONCE(ret,"ttm_bo_reserve_failed(): ret=%d\n",ret))return;-drm_gem_vram_kunmap_locked(gbo,map);+drm_gem_vram_vunmap_local(gbo,map);drm_gem_vram_unpin_locked(gbo);ttm_bo_unreserve(&gbo->bo);}EXPORT_SYMBOL(drm_gem_vram_vunmap);+/**+*drm_gem_vram_vmap_local()-MapsaGEMVRAMobjectintokerneladdressspace+*@gbo:TheGEMVRAMobjecttomap+*@map:ReturnsthekernelvirtualaddressoftheVRAMGEMobject'sbacking+*store.+*+*Thevmap_localfunctionmapsthebufferofaGEMVRAMobjectintokerneladdress+*space.Calldrm_gem_vram_vunmap_local()withthereturnedaddresstounmapand+*unpintheGEMVRAMobject.+*+*ThefunctioniscalledwiththeBO'sreservationobjectlocked.Forshort-term+*mappings,callersmustholdtheBO'sreservationlockuntilafterunmappingthe+*buffer.+*+*Returns:+*0onsuccess,oranegativeerrorcodeotherwise.+*/+intdrm_gem_vram_vmap_local(structdrm_gem_vram_object*gbo,structdma_buf_map*map)+{+intret;++dma_resv_assert_held(gbo->bo.base.resv);++if(gbo->vmap_use_count>0)+gotoout;++ret=ttm_bo_vmap(&gbo->bo,&gbo->map);+if(ret)+returnret;++out:+++gbo->vmap_use_count;+*map=gbo->map;++return0;+}+EXPORT_SYMBOL(drm_gem_vram_vmap_local);++/**+*drm_gem_vram_vunmap_local()-UnmapsaGEMVRAMobject+*@gbo:TheGEMVRAMobjecttounmap+*@map:KernelvirtualaddresswheretheVRAMGEMobjectwasmapped+*+*Acalltodrm_gem_vram_vunmap_local()unmapsaGEMVRAMobject'sbuffer.See+*thedocumentationfordrm_gem_vram_vmap_local()formoreinformation.+*/+voiddrm_gem_vram_vunmap_local(structdrm_gem_vram_object*gbo,structdma_buf_map*map)+{+structdrm_device*dev=gbo->bo.base.dev;++dma_resv_assert_held(gbo->bo.base.resv);++if(drm_WARN_ON_ONCE(dev,!gbo->vmap_use_count))+return;++if(drm_WARN_ON_ONCE(dev,!dma_buf_map_is_equal(&gbo->map,map)))+return;/* BUG: map not mapped from this BO */++if(--gbo->vmap_use_count>0)+return;++/*+*Permanentlymappingandunmappingbuffersaddsoverheadfrom+*updatingthepagetablesandcreatesdebuggingoutput.Therefore,+*wedelaytheactualunmapoperationuntiltheBOgetsevicted+*frommemory.Seedrm_gem_vram_bo_driver_move_notify().+*/+}+EXPORT_SYMBOL(drm_gem_vram_vunmap_local);+/***drm_gem_vram_fill_create_dumb()-\Helperforimplementing&structdrm_driver.dumb_create
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:26
Fbdev emulation has to lock the BO into place while flushing the shadow
buffer into the BO's memory. Remove any interference with pinning by
using vmap_local functionality (instead of full vmap). This requires
BO reservation locking in fbdev's damage worker.
The new DRM client functions for locking and vmap_local functionality
are added for consistency with the existing style.
v4:
* update documentation (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
---
drivers/gpu/drm/drm_client.c | 94 +++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_fb_helper.c | 41 +++++++-------
include/drm/drm_client.h | 4 ++
3 files changed, 119 insertions(+), 20 deletions(-)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:27
Cursor updates in vboxvideo require a short-term mapping of the
source BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/vboxvideo/vbox_mode.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-08 09:45:29
Damage handling in gm12u320 requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/tiny/gm12u320.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
From: Daniel Vetter <hidden> Date: 2021-01-11 16:51:32
On Fri, Jan 08, 2021 at 10:43:31AM +0100, Thomas Zimmermann wrote:
quoted hunk
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
This is a bit spaghetti and also has the problem that we're not changing
shmem->vmap_use_count under different locks, depending upon which path
we're taking.
I think the cleanest would be if we pull the if (import_attach) case out
of the _locked() version completely, for all cases, and also outside of
the shmem->vmap_lock. This means no caching of vmaps in the shmem layer
anymore for imported buffers, but this is no longer a problem: We cache
them in the exporters instead (I think at least, if not maybe need to fix
that where it's expensive).
Other option would be to unly pull it out for the _vmap_local case, but
that's a bit ugly because no longer symmetrical in the various paths.
quoted hunk
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -272,7 +275,10 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct } if (obj->import_attach) {- ret = dma_buf_vmap(obj->import_attach->dmabuf, map);+ if (local)+ ret = dma_buf_vmap_local(obj->import_attach->dmabuf, map);+ else+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); if (!ret) { if (WARN_ON(map->is_iomem)) { ret = -EIO;
@@ -313,7 +319,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct return ret; }-/*+/** * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object * @shmem: shmem GEM object * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
@@ -339,15 +345,53 @@ int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ret = mutex_lock_interruptible(&shmem->vmap_lock); if (ret) return ret;- ret = drm_gem_shmem_vmap_locked(shmem, map);+ ret = drm_gem_shmem_vmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); return ret; } EXPORT_SYMBOL(drm_gem_shmem_vmap);+/**+ * drm_gem_shmem_vmap_local - Create a virtual mapping for a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing+ * store.+ *+ * This function makes sure that a contiguous kernel virtual address mapping+ * exists for the buffer backing the shmem GEM object.+ *+ * The function is called with the BO's reservation object locked. Callers must+ * hold the lock until after unmapping the buffer.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local. But+ * it can also be called by drivers directly, in which case it will hide the+ * differences between dma-buf imported and natively allocated objects.
So for the other callbacks I tried to make sure we have different entry
points for this, since it's not really the same thing and because of the
locking mess we have with dma_resv_lock vs various pre-existing local
locking scheme, it's easy to get a mess.
I think the super clean version here would be to also export just the
internal stuff for the ->v(un)map_local hooks, but that's maybe a bit too
much boilerplate for no real gain.
-Daniel
quoted hunk
+ *
+ * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_local().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ dma_resv_assert_held(obj->resv);
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ret;
+ ret = drm_gem_shmem_vmap_locked(shmem, map, true);
+ mutex_unlock(&shmem->vmap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap_local);
+
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
- struct dma_buf_map *map)
+ struct dma_buf_map *map, bool local)
{
struct drm_gem_object *obj = &shmem->base;
@@ -366,7 +413,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, drm_gem_shmem_put_pages(shmem); }-/*+/** * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object * @shmem: shmem GEM object * @map: Kernel virtual address where the SHMEM GEM object was mapped
@@ -384,11 +431,38 @@ void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); mutex_lock(&shmem->vmap_lock);- drm_gem_shmem_vunmap_locked(shmem, map);+ drm_gem_shmem_vunmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); } EXPORT_SYMBOL(drm_gem_shmem_vunmap);+/**+ * drm_gem_shmem_vunmap_local - Unmap a virtual mapping fo a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Kernel virtual address where the SHMEM GEM object was mapped+ *+ * This function cleans up a kernel virtual address mapping acquired by+ * drm_gem_shmem_vmap_local(). The mapping is only removed when the use count+ * drops to zero.+ *+ * The function is called with the BO's reservation object locked.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local.+ * But it can also be called by drivers directly, in which case it will hide+ * the differences between dma-buf imported and natively allocated objects.+ */+void drm_gem_shmem_vunmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)+{+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);++ dma_resv_assert_held(obj->resv);++ mutex_lock(&shmem->vmap_lock);+ drm_gem_shmem_vunmap_locked(shmem, map, true);+ mutex_unlock(&shmem->vmap_lock);+}+EXPORT_SYMBOL(drm_gem_shmem_vunmap_local);+ struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size,
From: Daniel Vetter <hidden> Date: 2021-01-11 16:53:18
On Fri, Jan 08, 2021 at 10:43:40AM +0100, Thomas Zimmermann wrote:
VRAM-helper BO's cannot be exported, so calls for vmap and vunmap
can only come from the BO's drivers or a kernel client. These are
supposed use vmap_local functionality.
^to
The vmap and vunmap operations in VRAM helpers are therefore unused
and can be removed.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
From: Daniel Vetter <hidden> Date: 2021-01-11 16:54:39
On Fri, Jan 08, 2021 at 10:43:32AM +0100, Thomas Zimmermann wrote:
Damage handling in mgag200 requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
@@ -1552,22 +1552,32 @@ mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,structdrm_rect*clip){structdrm_device*dev=&mdev->base;+structdrm_gem_object*obj=fb->obj[0];structdma_buf_mapmap;void*vmap;intret;-ret=drm_gem_shmem_vmap(fb->obj[0],&map);+ret=dma_resv_lock(obj->resv,NULL);if(drm_WARN_ON(dev,ret))-return;/* BUG: SHMEM BO should always be vmapped */+return;+ret=drm_gem_shmem_vmap_local(obj,&map);+if(drm_WARN_ON(dev,ret))+gotoerr_dma_resv_unlock;/* BUG: SHMEM BO should always be vmapped */vmap=map.vaddr;/* TODO: Use mapping abstraction properly */drm_fb_memcpy_dstclip(mdev->vram,vmap,fb,clip);-drm_gem_shmem_vunmap(fb->obj[0],&map);+drm_gem_shmem_vunmap_local(obj,&map);+dma_resv_unlock(obj->resv);/* Always scanout image at VRAM offset 0 */mgag200_set_startadd(mdev,(u32)0);mgag200_set_offset(mdev,fb);++return;++err_dma_resv_unlock:+dma_resv_unlock(obj->resv);}staticvoid
From: Daniel Vetter <hidden> Date: 2021-01-11 16:58:59
On Mon, Jan 11, 2021 at 05:53:41PM +0100, Daniel Vetter wrote:
On Fri, Jan 08, 2021 at 10:43:32AM +0100, Thomas Zimmermann wrote:
quoted
Damage handling in mgag200 requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Daniel Vetter <redacted>
On second thought, strike that r-b, I have a confused question.
@@ -1552,22 +1552,32 @@ mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,structdrm_rect*clip){structdrm_device*dev=&mdev->base;+structdrm_gem_object*obj=fb->obj[0];structdma_buf_mapmap;void*vmap;intret;-ret=drm_gem_shmem_vmap(fb->obj[0],&map);+ret=dma_resv_lock(obj->resv,NULL);if(drm_WARN_ON(dev,ret))-return;/* BUG: SHMEM BO should always be vmapped */+return;+ret=drm_gem_shmem_vmap_local(obj,&map);+if(drm_WARN_ON(dev,ret))+gotoerr_dma_resv_unlock;/* BUG: SHMEM BO should always be vmapped */
Why is this guaranteed? I tried to hunt for a vmap in mga200g code, and
dind't find any. I'd ahve expected something in prepare/finish_fb.
Also since this is not a vram-helper using driver, why convert it over to
vmap_local? I guess that should also be explained in the commit message a
bit better.
-Daniel
From: Daniel Vetter <hidden> Date: 2021-01-11 17:01:29
On Fri, Jan 08, 2021 at 10:43:33AM +0100, Thomas Zimmermann wrote:
Damage handling in cirrus requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Hm more possible errors that we don't report to userspace ... Why don't we
vmap/vunmap these in prepare/cleanup_fb? Generally we'd want a long-term
vmap here to make sure this all works nicely.
Since it's nothing new, on this patch:
Reviewed-by: Daniel Vetter <redacted>
From: Daniel Vetter <hidden> Date: 2021-01-11 17:01:49
On Fri, Jan 08, 2021 at 10:43:34AM +0100, Thomas Zimmermann wrote:
quoted hunk
Damage handling in gm12u320 requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/tiny/gm12u320.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
From: Daniel Vetter <hidden> Date: 2021-01-11 17:04:23
On Mon, Jan 11, 2021 at 06:00:42PM +0100, Daniel Vetter wrote:
On Fri, Jan 08, 2021 at 10:43:33AM +0100, Thomas Zimmermann wrote:
quoted
Damage handling in cirrus requires a short-term mapping of the source
BO. Use drm_gem_shmem_vmap_local().
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Hm more possible errors that we don't report to userspace ... Why don't we
vmap/vunmap these in prepare/cleanup_fb? Generally we'd want a long-term
vmap here to make sure this all works nicely.
Since it's nothing new, on this patch:
Reviewed-by: Daniel Vetter <redacted>
Ok, also strike this r-b here. This is called from that atomic commit
paths, and we cannot call dma_resv_lock here. This should splat with
lockdep enabled against the dma-fence annotations I've merged, I'm kinda
surprised it doesn't?
-Daniel
From: Daniel Vetter <hidden> Date: 2021-01-11 17:07:09
On Fri, Jan 08, 2021 at 10:43:38AM +0100, Thomas Zimmermann wrote:
Cursor updates in vboxvideo require a short-term mapping of the
source BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
All these drivers patches break the dma_resv_lock vs
dma_fence_begin/end_signalling nesting rules, so this doesn't work.
Generally this is what the prepare/cleanup_fb hooks are for, that's where
mappings (including vmaps) are meant to be set up, permanently.
I'm kinda not clear on why we need all these changes, I thought the
locking problem is just in the fb helper paths, because it's outside of
the atomic path and could conflict with an atomic update at the same time?
So only that one should get the vmap_local treatment, everything else
should keep the normal vmap treatment.
-Daniel
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-12 07:55:02
Hi
Am 11.01.21 um 18:06 schrieb Daniel Vetter:
On Fri, Jan 08, 2021 at 10:43:38AM +0100, Thomas Zimmermann wrote:
quoted
Cursor updates in vboxvideo require a short-term mapping of the
source BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
All these drivers patches break the dma_resv_lock vs
dma_fence_begin/end_signalling nesting rules, so this doesn't work.
Generally this is what the prepare/cleanup_fb hooks are for, that's where
mappings (including vmaps) are meant to be set up, permanently.
I'm kinda not clear on why we need all these changes, I thought the
locking problem is just in the fb helper paths, because it's outside of
the atomic path and could conflict with an atomic update at the same time?
So only that one should get the vmap_local treatment, everything else
should keep the normal vmap treatment.
Kind of responding to all your comment on the driver changes:
These drivers only require short-term mappings, so using vmap_local
would be the natural choice. For SHMEM helpers, it's mostly a cosmetic
thing. For VRAM helpers, I was hoping to remove the vmap/vunmap helpers
entirely. One cannot really map the BOs for the long-term, so not having
the helpers at all would make sense.
But reading all your comments on the driver patches, I'd rather not
update the drivers here but later convert them to use
prepare_fb/cleanup_fb in the correct way.
Best regards
Thomas
From: Daniel Vetter <hidden> Date: 2021-01-12 09:18:02
On Tue, Jan 12, 2021 at 08:54:02AM +0100, Thomas Zimmermann wrote:
Hi
Am 11.01.21 um 18:06 schrieb Daniel Vetter:
quoted
On Fri, Jan 08, 2021 at 10:43:38AM +0100, Thomas Zimmermann wrote:
quoted
Cursor updates in vboxvideo require a short-term mapping of the
source BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
All these drivers patches break the dma_resv_lock vs
dma_fence_begin/end_signalling nesting rules, so this doesn't work.
Generally this is what the prepare/cleanup_fb hooks are for, that's where
mappings (including vmaps) are meant to be set up, permanently.
I'm kinda not clear on why we need all these changes, I thought the
locking problem is just in the fb helper paths, because it's outside of
the atomic path and could conflict with an atomic update at the same time?
So only that one should get the vmap_local treatment, everything else
should keep the normal vmap treatment.
Kind of responding to all your comment on the driver changes:
These drivers only require short-term mappings, so using vmap_local would be
the natural choice. For SHMEM helpers, it's mostly a cosmetic thing. For
VRAM helpers, I was hoping to remove the vmap/vunmap helpers entirely. One
cannot really map the BOs for the long-term, so not having the helpers at
all would make sense.
But reading all your comments on the driver patches, I'd rather not update
the drivers here but later convert them to use prepare_fb/cleanup_fb in the
correct way.
Ack from me on this plan. I think I got all the other patches with an r-b
or ack?
-Daniel
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-12 09:54:27
Hi
Am 12.01.21 um 10:17 schrieb Daniel Vetter:
On Tue, Jan 12, 2021 at 08:54:02AM +0100, Thomas Zimmermann wrote:
quoted
Hi
Am 11.01.21 um 18:06 schrieb Daniel Vetter:
quoted
On Fri, Jan 08, 2021 at 10:43:38AM +0100, Thomas Zimmermann wrote:
quoted
Cursor updates in vboxvideo require a short-term mapping of the
source BO. Use drm_gem_vram_vmap_local() and avoid the pinning
operations.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
All these drivers patches break the dma_resv_lock vs
dma_fence_begin/end_signalling nesting rules, so this doesn't work.
Generally this is what the prepare/cleanup_fb hooks are for, that's where
mappings (including vmaps) are meant to be set up, permanently.
I'm kinda not clear on why we need all these changes, I thought the
locking problem is just in the fb helper paths, because it's outside of
the atomic path and could conflict with an atomic update at the same time?
So only that one should get the vmap_local treatment, everything else
should keep the normal vmap treatment.
Kind of responding to all your comment on the driver changes:
These drivers only require short-term mappings, so using vmap_local would be
the natural choice. For SHMEM helpers, it's mostly a cosmetic thing. For
VRAM helpers, I was hoping to remove the vmap/vunmap helpers entirely. One
cannot really map the BOs for the long-term, so not having the helpers at
all would make sense.
But reading all your comments on the driver patches, I'd rather not update
the drivers here but later convert them to use prepare_fb/cleanup_fb in the
correct way.
Ack from me on this plan. I think I got all the other patches with an r-b
or ack?
The shmem patch needs an update from my side.
Best regards
Thomas
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-12 13:12:45
Hi
Am 11.01.21 um 17:50 schrieb Daniel Vetter:
On Fri, Jan 08, 2021 at 10:43:31AM +0100, Thomas Zimmermann wrote:
quoted
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
This is a bit spaghetti and also has the problem that we're not changing
shmem->vmap_use_count under different locks, depending upon which path
we're taking.
I think the cleanest would be if we pull the if (import_attach) case out
of the _locked() version completely, for all cases, and also outside of
the shmem->vmap_lock. This means no caching of vmaps in the shmem layer
anymore for imported buffers, but this is no longer a problem: We cache
them in the exporters instead (I think at least, if not maybe need to fix
that where it's expensive).
If we do that, what protects shmem->vaddr from concurrent access near
line 281? would it be kept NULL then?
Also, we have some stats in debugfs (see drm_gem_shmem_print_info) which
would be incorrect (or misleading at least).
Given all that, would it be possible to remove vmap_lock in favor of
taking the resv lock in vmap/vunmap?
Best regards
Thomas
Other option would be to unly pull it out for the _vmap_local case, but
that's a bit ugly because no longer symmetrical in the various paths.
quoted
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -272,7 +275,10 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct } if (obj->import_attach) {- ret = dma_buf_vmap(obj->import_attach->dmabuf, map);+ if (local)+ ret = dma_buf_vmap_local(obj->import_attach->dmabuf, map);+ else+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); if (!ret) { if (WARN_ON(map->is_iomem)) { ret = -EIO;
@@ -313,7 +319,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct return ret; }-/*+/** * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object * @shmem: shmem GEM object * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
@@ -339,15 +345,53 @@ int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ret = mutex_lock_interruptible(&shmem->vmap_lock); if (ret) return ret;- ret = drm_gem_shmem_vmap_locked(shmem, map);+ ret = drm_gem_shmem_vmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); return ret; } EXPORT_SYMBOL(drm_gem_shmem_vmap);+/**+ * drm_gem_shmem_vmap_local - Create a virtual mapping for a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing+ * store.+ *+ * This function makes sure that a contiguous kernel virtual address mapping+ * exists for the buffer backing the shmem GEM object.+ *+ * The function is called with the BO's reservation object locked. Callers must+ * hold the lock until after unmapping the buffer.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local. But+ * it can also be called by drivers directly, in which case it will hide the+ * differences between dma-buf imported and natively allocated objects.
So for the other callbacks I tried to make sure we have different entry
points for this, since it's not really the same thing and because of the
locking mess we have with dma_resv_lock vs various pre-existing local
locking scheme, it's easy to get a mess.
I think the super clean version here would be to also export just the
internal stuff for the ->v(un)map_local hooks, but that's maybe a bit too
much boilerplate for no real gain.
-Daniel
quoted
+ *
+ * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_local().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ dma_resv_assert_held(obj->resv);
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ret;
+ ret = drm_gem_shmem_vmap_locked(shmem, map, true);
+ mutex_unlock(&shmem->vmap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap_local);
+
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
- struct dma_buf_map *map)
+ struct dma_buf_map *map, bool local)
{
struct drm_gem_object *obj = &shmem->base;
@@ -366,7 +413,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, drm_gem_shmem_put_pages(shmem); }-/*+/** * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object * @shmem: shmem GEM object * @map: Kernel virtual address where the SHMEM GEM object was mapped
@@ -384,11 +431,38 @@ void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); mutex_lock(&shmem->vmap_lock);- drm_gem_shmem_vunmap_locked(shmem, map);+ drm_gem_shmem_vunmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); } EXPORT_SYMBOL(drm_gem_shmem_vunmap);+/**+ * drm_gem_shmem_vunmap_local - Unmap a virtual mapping fo a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Kernel virtual address where the SHMEM GEM object was mapped+ *+ * This function cleans up a kernel virtual address mapping acquired by+ * drm_gem_shmem_vmap_local(). The mapping is only removed when the use count+ * drops to zero.+ *+ * The function is called with the BO's reservation object locked.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local.+ * But it can also be called by drivers directly, in which case it will hide+ * the differences between dma-buf imported and natively allocated objects.+ */+void drm_gem_shmem_vunmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)+{+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);++ dma_resv_assert_held(obj->resv);++ mutex_lock(&shmem->vmap_lock);+ drm_gem_shmem_vunmap_locked(shmem, map, true);+ mutex_unlock(&shmem->vmap_lock);+}+EXPORT_SYMBOL(drm_gem_shmem_vunmap_local);+ struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size,
From: Daniel Vetter <hidden> Date: 2021-01-12 14:17:07
On Tue, Jan 12, 2021 at 02:11:24PM +0100, Thomas Zimmermann wrote:
Hi
Am 11.01.21 um 17:50 schrieb Daniel Vetter:
quoted
On Fri, Jan 08, 2021 at 10:43:31AM +0100, Thomas Zimmermann wrote:
quoted
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
This is a bit spaghetti and also has the problem that we're not changing
shmem->vmap_use_count under different locks, depending upon which path
we're taking.
I think the cleanest would be if we pull the if (import_attach) case out
of the _locked() version completely, for all cases, and also outside of
the shmem->vmap_lock. This means no caching of vmaps in the shmem layer
anymore for imported buffers, but this is no longer a problem: We cache
them in the exporters instead (I think at least, if not maybe need to fix
that where it's expensive).
If we do that, what protects shmem->vaddr from concurrent access near line
281? would it be kept NULL then?
Also, we have some stats in debugfs (see drm_gem_shmem_print_info) which
would be incorrect (or misleading at least).
We'd need to disable all that for pass-through vmap of imported objects.
Given all that, would it be possible to remove vmap_lock in favor of taking
the resv lock in vmap/vunmap?
All possible (and imo long-term desirable), the trouble is in rolling it
out. I've looked at rolling out dma_resv as the one and only lock for
shmem helpers before, and gave up. Exynos is the worst (but not the only)
offender:
- it has it's own per-object lock
- that per-object lock is taken most often before calling into various
vfuncs, which means for a gradual transition the dma_resv lock would
nest within that existing per-object lock (until we've completely
replaced it)
- but exynos also uses dma_resv already as an outermost lock in its
command submission path
iow as soon as you add dma_resv_lock anywhere in shmem helpers, we've
angered lockdep with a deadlock.
That means the only path I think is feasible is adding dma_resv lock to
all drivers paths first, _outside_ of any existing driver specific
per-object locks. Then remove the driver-specific object locks, and only
then can we sprinkle dma_resv_assert_locked all over shmem helpers.
Ofc any driver without per-driver locks of their own could directly switch
over to dma_resv lock, but until we've converted over all the drivers with
their own locking shmem helpers would be stuck where they are right now.
I gave up :-/ But maybe if you only try to tackle vmap it might be
feasible, since a lot fewer callers.
Cheers, Daniel
Best regards
Thomas
quoted
Other option would be to unly pull it out for the _vmap_local case, but
that's a bit ugly because no longer symmetrical in the various paths.
quoted
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -272,7 +275,10 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct } if (obj->import_attach) {- ret = dma_buf_vmap(obj->import_attach->dmabuf, map);+ if (local)+ ret = dma_buf_vmap_local(obj->import_attach->dmabuf, map);+ else+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); if (!ret) { if (WARN_ON(map->is_iomem)) { ret = -EIO;
@@ -313,7 +319,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct return ret; }-/*+/** * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object * @shmem: shmem GEM object * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
@@ -339,15 +345,53 @@ int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ret = mutex_lock_interruptible(&shmem->vmap_lock); if (ret) return ret;- ret = drm_gem_shmem_vmap_locked(shmem, map);+ ret = drm_gem_shmem_vmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); return ret; } EXPORT_SYMBOL(drm_gem_shmem_vmap);+/**+ * drm_gem_shmem_vmap_local - Create a virtual mapping for a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing+ * store.+ *+ * This function makes sure that a contiguous kernel virtual address mapping+ * exists for the buffer backing the shmem GEM object.+ *+ * The function is called with the BO's reservation object locked. Callers must+ * hold the lock until after unmapping the buffer.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local. But+ * it can also be called by drivers directly, in which case it will hide the+ * differences between dma-buf imported and natively allocated objects.
So for the other callbacks I tried to make sure we have different entry
points for this, since it's not really the same thing and because of the
locking mess we have with dma_resv_lock vs various pre-existing local
locking scheme, it's easy to get a mess.
I think the super clean version here would be to also export just the
internal stuff for the ->v(un)map_local hooks, but that's maybe a bit too
much boilerplate for no real gain.
-Daniel
quoted
+ *
+ * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_local().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ dma_resv_assert_held(obj->resv);
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ret;
+ ret = drm_gem_shmem_vmap_locked(shmem, map, true);
+ mutex_unlock(&shmem->vmap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap_local);
+
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
- struct dma_buf_map *map)
+ struct dma_buf_map *map, bool local)
{
struct drm_gem_object *obj = &shmem->base;
@@ -366,7 +413,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, drm_gem_shmem_put_pages(shmem); }-/*+/** * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object * @shmem: shmem GEM object * @map: Kernel virtual address where the SHMEM GEM object was mapped
@@ -384,11 +431,38 @@ void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); mutex_lock(&shmem->vmap_lock);- drm_gem_shmem_vunmap_locked(shmem, map);+ drm_gem_shmem_vunmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); } EXPORT_SYMBOL(drm_gem_shmem_vunmap);+/**+ * drm_gem_shmem_vunmap_local - Unmap a virtual mapping fo a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Kernel virtual address where the SHMEM GEM object was mapped+ *+ * This function cleans up a kernel virtual address mapping acquired by+ * drm_gem_shmem_vmap_local(). The mapping is only removed when the use count+ * drops to zero.+ *+ * The function is called with the BO's reservation object locked.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local.+ * But it can also be called by drivers directly, in which case it will hide+ * the differences between dma-buf imported and natively allocated objects.+ */+void drm_gem_shmem_vunmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)+{+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);++ dma_resv_assert_held(obj->resv);++ mutex_lock(&shmem->vmap_lock);+ drm_gem_shmem_vunmap_locked(shmem, map, true);+ mutex_unlock(&shmem->vmap_lock);+}+EXPORT_SYMBOL(drm_gem_shmem_vunmap_local);+ struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size,
From: Thomas Zimmermann <tzimmermann@suse.de> Date: 2021-01-27 12:12:21
Hi
Am 11.01.21 um 17:50 schrieb Daniel Vetter:
On Fri, Jan 08, 2021 at 10:43:31AM +0100, Thomas Zimmermann wrote:
quoted
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
This is a bit spaghetti and also has the problem that we're not changing
shmem->vmap_use_count under different locks, depending upon which path
we're taking.
I think the cleanest would be if we pull the if (import_attach) case out
of the _locked() version completely, for all cases, and also outside of
the shmem->vmap_lock. This means no caching of vmaps in the shmem layer
anymore for imported buffers, but this is no longer a problem: We cache
them in the exporters instead (I think at least, if not maybe need to fix
that where it's expensive).
There's no vmap refcounting in amdgpu AFAICT. So importing pages from
there into an SHMEM object has the potential of breaking. IIRC same fro
radeon and nouveau.
So I'm somewhat reluctant to making this change. I guess I'll look
elsewhere first to fix some of the locking issues (e.g., my recent ast
cursor patches).
Best regards
Thomas
Other option would be to unly pull it out for the _vmap_local case, but
that's a bit ugly because no longer symmetrical in the various paths.
quoted
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -272,7 +275,10 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct } if (obj->import_attach) {- ret = dma_buf_vmap(obj->import_attach->dmabuf, map);+ if (local)+ ret = dma_buf_vmap_local(obj->import_attach->dmabuf, map);+ else+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); if (!ret) { if (WARN_ON(map->is_iomem)) { ret = -EIO;
@@ -313,7 +319,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct return ret; }-/*+/** * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object * @shmem: shmem GEM object * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
@@ -339,15 +345,53 @@ int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ret = mutex_lock_interruptible(&shmem->vmap_lock); if (ret) return ret;- ret = drm_gem_shmem_vmap_locked(shmem, map);+ ret = drm_gem_shmem_vmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); return ret; } EXPORT_SYMBOL(drm_gem_shmem_vmap);+/**+ * drm_gem_shmem_vmap_local - Create a virtual mapping for a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing+ * store.+ *+ * This function makes sure that a contiguous kernel virtual address mapping+ * exists for the buffer backing the shmem GEM object.+ *+ * The function is called with the BO's reservation object locked. Callers must+ * hold the lock until after unmapping the buffer.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local. But+ * it can also be called by drivers directly, in which case it will hide the+ * differences between dma-buf imported and natively allocated objects.
So for the other callbacks I tried to make sure we have different entry
points for this, since it's not really the same thing and because of the
locking mess we have with dma_resv_lock vs various pre-existing local
locking scheme, it's easy to get a mess.
I think the super clean version here would be to also export just the
internal stuff for the ->v(un)map_local hooks, but that's maybe a bit too
much boilerplate for no real gain.
-Daniel
quoted
+ *
+ * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_local().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ dma_resv_assert_held(obj->resv);
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ret;
+ ret = drm_gem_shmem_vmap_locked(shmem, map, true);
+ mutex_unlock(&shmem->vmap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap_local);
+
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
- struct dma_buf_map *map)
+ struct dma_buf_map *map, bool local)
{
struct drm_gem_object *obj = &shmem->base;
@@ -366,7 +413,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, drm_gem_shmem_put_pages(shmem); }-/*+/** * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object * @shmem: shmem GEM object * @map: Kernel virtual address where the SHMEM GEM object was mapped
@@ -384,11 +431,38 @@ void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); mutex_lock(&shmem->vmap_lock);- drm_gem_shmem_vunmap_locked(shmem, map);+ drm_gem_shmem_vunmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); } EXPORT_SYMBOL(drm_gem_shmem_vunmap);+/**+ * drm_gem_shmem_vunmap_local - Unmap a virtual mapping fo a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Kernel virtual address where the SHMEM GEM object was mapped+ *+ * This function cleans up a kernel virtual address mapping acquired by+ * drm_gem_shmem_vmap_local(). The mapping is only removed when the use count+ * drops to zero.+ *+ * The function is called with the BO's reservation object locked.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local.+ * But it can also be called by drivers directly, in which case it will hide+ * the differences between dma-buf imported and natively allocated objects.+ */+void drm_gem_shmem_vunmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)+{+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);++ dma_resv_assert_held(obj->resv);++ mutex_lock(&shmem->vmap_lock);+ drm_gem_shmem_vunmap_locked(shmem, map, true);+ mutex_unlock(&shmem->vmap_lock);+}+EXPORT_SYMBOL(drm_gem_shmem_vunmap_local);+ struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size,
From: Daniel Vetter <hidden> Date: 2021-02-02 17:43:20
On Wed, Jan 27, 2021 at 01:08:05PM +0100, Thomas Zimmermann wrote:
Hi
Am 11.01.21 um 17:50 schrieb Daniel Vetter:
quoted
On Fri, Jan 08, 2021 at 10:43:31AM +0100, Thomas Zimmermann wrote:
quoted
Implementations of the vmap/vunmap GEM callbacks may perform pinning
of the BO and may acquire the associated reservation object's lock.
Callers that only require a mapping of the contained memory can thus
interfere with other tasks that require exact pinning, such as scanout.
This is less of an issue with private SHMEM buffers, but may happen
with imported ones.
Therefore provide the new interfaces drm_gem_shmem_vmap_local() and
drm_gem_shmem_vunmap_local(), which only perform the vmap/vunmap
operations. Callers have to hold the reservation lock while the mapping
persists.
This patch also connects GEM SHMEM helpers to GEM object functions with
equivalent functionality.
v4:
* call dma_buf_{vmap,vunmap}_local() where necessary (Daniel)
* move driver changes into separate patches (Daniel)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_gem_shmem_helper.c | 90 +++++++++++++++++++++++---
include/drm/drm_gem_shmem_helper.h | 2 +
2 files changed, 84 insertions(+), 8 deletions(-)
This is a bit spaghetti and also has the problem that we're not changing
shmem->vmap_use_count under different locks, depending upon which path
we're taking.
I think the cleanest would be if we pull the if (import_attach) case out
of the _locked() version completely, for all cases, and also outside of
the shmem->vmap_lock. This means no caching of vmaps in the shmem layer
anymore for imported buffers, but this is no longer a problem: We cache
them in the exporters instead (I think at least, if not maybe need to fix
that where it's expensive).
There's no vmap refcounting in amdgpu AFAICT. So importing pages from there
into an SHMEM object has the potential of breaking. IIRC same fro radeon and
nouveau.
As long as the pinning is refcounted I think it should be fine, it's just
that if you have multiple vmaps (e.g. 2 udl devices plugged in) we'll set
up 2 vmaps. Which is a point pointless, but not really harmful. At least
on 64bit where there's enough virtual address space.
So I'm somewhat reluctant to making this change. I guess I'll look elsewhere
first to fix some of the locking issues (e.g., my recent ast cursor
patches).
If this would break for amdgpu/radeon/nouveau then we already have a bug,
since 2 udl devices can provoke this issue already as-is. So I don't think
this should be a blocker.
-Daniel
Best regards
Thomas
quoted
Other option would be to unly pull it out for the _vmap_local case, but
that's a bit ugly because no longer symmetrical in the various paths.
quoted
{
struct drm_gem_object *obj = &shmem->base;
int ret = 0;
@@ -272,7 +275,10 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct } if (obj->import_attach) {- ret = dma_buf_vmap(obj->import_attach->dmabuf, map);+ if (local)+ ret = dma_buf_vmap_local(obj->import_attach->dmabuf, map);+ else+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); if (!ret) { if (WARN_ON(map->is_iomem)) { ret = -EIO;
@@ -313,7 +319,7 @@ static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct return ret; }-/*+/** * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object * @shmem: shmem GEM object * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
@@ -339,15 +345,53 @@ int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map) ret = mutex_lock_interruptible(&shmem->vmap_lock); if (ret) return ret;- ret = drm_gem_shmem_vmap_locked(shmem, map);+ ret = drm_gem_shmem_vmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); return ret; } EXPORT_SYMBOL(drm_gem_shmem_vmap);+/**+ * drm_gem_shmem_vmap_local - Create a virtual mapping for a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing+ * store.+ *+ * This function makes sure that a contiguous kernel virtual address mapping+ * exists for the buffer backing the shmem GEM object.+ *+ * The function is called with the BO's reservation object locked. Callers must+ * hold the lock until after unmapping the buffer.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local. But+ * it can also be called by drivers directly, in which case it will hide the+ * differences between dma-buf imported and natively allocated objects.
So for the other callbacks I tried to make sure we have different entry
points for this, since it's not really the same thing and because of the
locking mess we have with dma_resv_lock vs various pre-existing local
locking scheme, it's easy to get a mess.
I think the super clean version here would be to also export just the
internal stuff for the ->v(un)map_local hooks, but that's maybe a bit too
much boilerplate for no real gain.
-Daniel
quoted
+ *
+ * Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap_local().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_shmem_vmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)
+{
+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+ int ret;
+
+ dma_resv_assert_held(obj->resv);
+
+ ret = mutex_lock_interruptible(&shmem->vmap_lock);
+ if (ret)
+ return ret;
+ ret = drm_gem_shmem_vmap_locked(shmem, map, true);
+ mutex_unlock(&shmem->vmap_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_shmem_vmap_local);
+
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
- struct dma_buf_map *map)
+ struct dma_buf_map *map, bool local)
{
struct drm_gem_object *obj = &shmem->base;
@@ -366,7 +413,7 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, drm_gem_shmem_put_pages(shmem); }-/*+/** * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object * @shmem: shmem GEM object * @map: Kernel virtual address where the SHMEM GEM object was mapped
@@ -384,11 +431,38 @@ void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map) struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); mutex_lock(&shmem->vmap_lock);- drm_gem_shmem_vunmap_locked(shmem, map);+ drm_gem_shmem_vunmap_locked(shmem, map, false); mutex_unlock(&shmem->vmap_lock); } EXPORT_SYMBOL(drm_gem_shmem_vunmap);+/**+ * drm_gem_shmem_vunmap_local - Unmap a virtual mapping fo a shmem GEM object+ * @shmem: shmem GEM object+ * @map: Kernel virtual address where the SHMEM GEM object was mapped+ *+ * This function cleans up a kernel virtual address mapping acquired by+ * drm_gem_shmem_vmap_local(). The mapping is only removed when the use count+ * drops to zero.+ *+ * The function is called with the BO's reservation object locked.+ *+ * This function can be used to implement &drm_gem_object_funcs.vmap_local.+ * But it can also be called by drivers directly, in which case it will hide+ * the differences between dma-buf imported and natively allocated objects.+ */+void drm_gem_shmem_vunmap_local(struct drm_gem_object *obj, struct dma_buf_map *map)+{+ struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);++ dma_resv_assert_held(obj->resv);++ mutex_lock(&shmem->vmap_lock);+ drm_gem_shmem_vunmap_locked(shmem, map, true);+ mutex_unlock(&shmem->vmap_lock);+}+EXPORT_SYMBOL(drm_gem_shmem_vunmap_local);+ struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size,