The pattern of temporarily pinning and kmap-ing the BO's memory is common enough to justify helper functions that do and undo these operations. The implementation of vmap and vunmap for GEM VRAM helpers is already in PRIME helpers. The patch moves the operations to separate functions and exports them for general use. The patch also adds a note about possible kmap counting. So far this isn't required by drivers, but more complex use cases might make it necessary. v2: * fix documentation * add cross references to function documentation * document (the lack of) ref-counting for GEM VRAM BO mappings Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/gpu/drm/drm_gem_vram_helper.c | 63 ++++++++++++++++++++++----- include/drm/drm_gem_vram_helper.h | 13 ++++++ 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index e0fbfb6570cf..f9b2b8e12b49 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -340,6 +340,56 @@ void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) } EXPORT_SYMBOL(drm_gem_vram_kunmap); +/** + * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address + space + * @gbo: The GEM VRAM object to map + * + * The vmap function pins a GEM VRAM object to its current location, either + * system or video memory, and maps its buffer into kernel address space. As + * pinned object cannot be relocated, you should not permanently pin objects. + * Call drm_gem_vram_vunmap() with the returned address to unmap and unpin + * the GEM VRAM object. + * + * If you have special requirements for the pinning or mapping operations, + * call drm_gem_vram_pin() and drm_gem_vram_kmap() directly. + * + * Returns: + * The buffer's virtual address on success, or + * an ERR_PTR()-encoded error code otherwise. + */ +void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo) +{ + int ret; + void *base; + + ret = drm_gem_vram_pin(gbo, 0); + if (ret) + return ERR_PTR(ret); + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + drm_gem_vram_unpin(gbo); + return base; + } + return base; +} +EXPORT_SYMBOL(drm_gem_vram_vmap); + +/** + * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object + * @gbo: The GEM VRAM object to unmap + * @vaddr: The mapping's base address as returned by drm_gem_vram_vmap() + * + * A call to drm_gem_vram_vunmap() unmaps and unpins a GEM VRAM buffer. See + * the documentation for drm_gem_vram_vmap() for more information. + */ +void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr) +{ + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_vunmap); + /** * drm_gem_vram_fill_create_dumb() - \ Helper for implementing &struct drm_driver.dumb_create @@ -595,17 +645,11 @@ static void drm_gem_vram_object_unpin(struct drm_gem_object *gem) static void *drm_gem_vram_object_vmap(struct drm_gem_object *gem) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); - int ret; void *base; - ret = drm_gem_vram_pin(gbo, 0); - if (ret) + base = drm_gem_vram_vmap(gbo); + if (IS_ERR(base)) return NULL; - base = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(base)) { - drm_gem_vram_unpin(gbo); - return NULL; - } return base; } @@ -620,8 +664,7 @@ static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem, { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); - drm_gem_vram_kunmap(gbo); - drm_gem_vram_unpin(gbo); + drm_gem_vram_vunmap(gbo, vaddr); } /* diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index b41d932eb53a..88da46552d07 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -34,6 +34,17 @@ struct vm_area_struct; * backed by VRAM. It can be used for simple framebuffer devices with * dedicated memory. The buffer object can be evicted to system memory if * video memory becomes scarce. + * + * GEM VRAM objects perform a reference counting for pin operations. So a + * buffer object that has been pinned N times with drm_gem_vram_pin() must + * be unpinned N times with drm_gem_vram_unpin(). + * + * So far, drivers based on VRAM helpers don't have overlapping + * mapping operations. A driver temporarily maps an object with + * drm_gem_vram_kmap()and unmaps it ASAP with drm_gem_vram_kunmap(). This + * works well for fbdev emulation or cursor images. If we ever have a + * driver with buffer objects that are mapped by multiple code fragments + * concurrently, we may need a map counter to get the mapping right. */ struct drm_gem_vram_object { struct drm_gem_object gem; @@ -84,6 +95,8 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, bool *is_iomem); void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); +void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo); +void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr); int drm_gem_vram_fill_create_dumb(struct drm_file *file, struct drm_device *dev, -- 2.22.0 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel