diff options
Diffstat (limited to 'drivers/gpu/drm/drm_gem_vram_helper.c')
| -rw-r--r-- | drivers/gpu/drm/drm_gem_vram_helper.c | 263 |
1 files changed, 59 insertions, 204 deletions
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index b67eafa55715..5e5b70518dbe 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/export.h> #include <linux/iosys-map.h> #include <linux/module.h> @@ -16,7 +17,7 @@ #include <drm/drm_mode.h> #include <drm/drm_plane.h> #include <drm/drm_prime.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_print.h> #include <drm/ttm/ttm_range_manager.h> #include <drm/ttm/ttm_tt.h> @@ -89,11 +90,6 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; * drmm_vram_helper_init() is a managed interface that installs a * clean-up handler to run during the DRM device's release. * - * For drawing or scanout operations, rsp. buffer objects have to be pinned - * in video RAM. Call drm_gem_vram_pin() with &DRM_GEM_VRAM_PL_FLAG_VRAM or - * &DRM_GEM_VRAM_PL_FLAG_SYSTEM to pin a buffer object in video RAM or system - * memory. Call drm_gem_vram_unpin() to release the pinned object afterwards. - * * A buffer object that is pinned in video RAM has a fixed address within that * memory region. Call drm_gem_vram_offset() to retrieve this value. Typically * it's used to program the hardware's scanout engine for framebuffers, set @@ -112,7 +108,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo) { - /* We got here via ttm_bo_put(), which means that the + /* We got here via ttm_bo_fini(), which means that the * TTM buffer object in 'bo' has already been cleaned * up; only release the GEM object. */ @@ -147,7 +143,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, invariant_flags = TTM_PL_FLAG_TOPDOWN; gbo->placement.placement = gbo->placements; - gbo->placement.busy_placement = gbo->placements; if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) { gbo->placements[c].mem_type = TTM_PL_VRAM; @@ -160,7 +155,6 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, } gbo->placement.num_placement = c; - gbo->placement.num_busy_placement = c; for (i = 0; i < c; ++i) { gbo->placements[i].fpfn = 0; @@ -241,11 +235,11 @@ EXPORT_SYMBOL(drm_gem_vram_create); * drm_gem_vram_put() - Releases a reference to a VRAM-backed GEM object * @gbo: the GEM VRAM object * - * See ttm_bo_put() for more information. + * See ttm_bo_fini() for more information. */ void drm_gem_vram_put(struct drm_gem_vram_object *gbo) { - ttm_bo_put(&gbo->bo); + ttm_bo_fini(&gbo->bo); } EXPORT_SYMBOL(drm_gem_vram_put); @@ -260,8 +254,7 @@ static u64 drm_gem_vram_pg_offset(struct drm_gem_vram_object *gbo) } /** - * drm_gem_vram_offset() - \ - Returns a GEM VRAM object's offset in video memory + * drm_gem_vram_offset() - Returns a GEM VRAM object's offset in video memory * @gbo: the GEM VRAM object * * This function returns the buffer object's offset in the device's video @@ -285,6 +278,8 @@ static int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo, struct ttm_operation_ctx ctx = { false, false }; int ret; + dma_resv_assert_held(gbo->bo.base.resv); + if (gbo->bo.pin_count) goto out; @@ -301,30 +296,7 @@ out: return 0; } -/** - * drm_gem_vram_pin() - Pins a GEM VRAM object in a region. - * @gbo: the GEM VRAM object - * @pl_flag: a bitmask of possible memory regions - * - * Pinning a buffer object ensures that it is not evicted from - * a memory region. A pinned buffer object has to be unpinned before - * it can be pinned to another region. If the pl_flag argument is 0, - * the buffer is pinned at its current location (video RAM or system - * memory). - * - * Small buffer objects, such as cursor images, can lead to memory - * fragmentation if they are pinned in the middle of video RAM. This - * is especially a problem on devices with only a small amount of - * video RAM. Fragmentation can prevent the primary framebuffer from - * fitting in, even though there's enough memory overall. The modifier - * DRM_GEM_VRAM_PL_FLAG_TOPDOWN marks the buffer object to be pinned - * at the high end of the memory region to avoid fragmentation. - * - * Returns: - * 0 on success, or - * a negative error code otherwise. - */ -int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) +static int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) { int ret; @@ -336,22 +308,15 @@ int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) return ret; } -EXPORT_SYMBOL(drm_gem_vram_pin); static void drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo) { + dma_resv_assert_held(gbo->bo.base.resv); + ttm_bo_unpin(&gbo->bo); } -/** - * drm_gem_vram_unpin() - Unpins a GEM VRAM object - * @gbo: the GEM VRAM object - * - * Returns: - * 0 on success, or - * a negative error code otherwise. - */ -int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) +static int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) { int ret; @@ -364,13 +329,29 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) return 0; } -EXPORT_SYMBOL(drm_gem_vram_unpin); -static int drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo, - struct iosys_map *map) +/** + * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address + * space + * @gbo: The GEM VRAM object to map + * @map: Returns the kernel virtual address of the VRAM GEM object's backing + * store. + * + * 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 avoid pinning objects + * permanently. Call drm_gem_vram_vunmap() with the returned address to + * unmap and unpin the GEM VRAM object. + * + * Returns: + * 0 on success, or a negative error code otherwise. + */ +int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct iosys_map *map) { int ret; + dma_resv_assert_held(gbo->bo.base.resv); + if (gbo->vmap_use_count > 0) goto out; @@ -391,12 +372,23 @@ out: return 0; } +EXPORT_SYMBOL(drm_gem_vram_vmap); -static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo, - struct iosys_map *map) +/** + * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object + * @gbo: The GEM VRAM object to unmap + * @map: Kernel virtual address where the VRAM GEM object was mapped + * + * 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, + struct iosys_map *map) { struct drm_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; @@ -413,71 +405,18 @@ static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo, * from memory. See drm_gem_vram_bo_driver_move_notify(). */ } - -/** - * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address - * space - * @gbo: The GEM VRAM object to map - * @map: Returns the kernel virtual address of the VRAM GEM object's backing - * store. - * - * 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 avoid pinning objects - * permanently. Call drm_gem_vram_vunmap() with the returned address to - * unmap and unpin the GEM VRAM object. - * - * Returns: - * 0 on success, or a negative error code otherwise. - */ -int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct iosys_map *map) -{ - int ret; - - dma_resv_assert_held(gbo->bo.base.resv); - - ret = drm_gem_vram_pin_locked(gbo, 0); - if (ret) - return ret; - ret = drm_gem_vram_kmap_locked(gbo, map); - if (ret) - goto err_drm_gem_vram_unpin_locked; - - return 0; - -err_drm_gem_vram_unpin_locked: - drm_gem_vram_unpin_locked(gbo); - return ret; -} -EXPORT_SYMBOL(drm_gem_vram_vmap); - -/** - * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object - * @gbo: The GEM VRAM object to unmap - * @map: Kernel virtual address where the VRAM GEM object was mapped - * - * 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, - struct iosys_map *map) -{ - dma_resv_assert_held(gbo->bo.base.resv); - - drm_gem_vram_kunmap_locked(gbo, map); - drm_gem_vram_unpin_locked(gbo); -} EXPORT_SYMBOL(drm_gem_vram_vunmap); /** - * drm_gem_vram_fill_create_dumb() - \ - Helper for implementing &struct drm_driver.dumb_create + * drm_gem_vram_fill_create_dumb() - Helper for implementing + * &struct drm_driver.dumb_create + * * @file: the DRM file * @dev: the DRM device * @pg_align: the buffer's alignment in multiples of the page size * @pitch_align: the scanline's alignment in powers of 2 - * @args: the arguments as provided to \ - &struct drm_driver.dumb_create + * @args: the arguments as provided to + * &struct drm_driver.dumb_create * * This helper function fills &struct drm_mode_create_dumb, which is used * by &struct drm_driver.dumb_create. Implementations of this interface @@ -575,8 +514,7 @@ static int drm_gem_vram_bo_driver_move(struct drm_gem_vram_object *gbo, */ /** - * drm_gem_vram_object_free() - \ - Implements &struct drm_gem_object_funcs.free + * drm_gem_vram_object_free() - Implements &struct drm_gem_object_funcs.free * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem */ static void drm_gem_vram_object_free(struct drm_gem_object *gem) @@ -591,12 +529,11 @@ static void drm_gem_vram_object_free(struct drm_gem_object *gem) */ /** - * drm_gem_vram_driver_dumb_create() - \ - Implements &struct drm_driver.dumb_create + * drm_gem_vram_driver_dumb_create() - Implements &struct drm_driver.dumb_create * @file: the DRM file * @dev: the DRM device - * @args: the arguments as provided to \ - &struct drm_driver.dumb_create + * @args: the arguments as provided to + * &struct drm_driver.dumb_create * * This function requires the driver to use @drm_device.vram_mm for its * instance of VRAM MM. @@ -639,8 +576,8 @@ static void __drm_gem_vram_plane_helper_cleanup_fb(struct drm_plane *plane, } /** - * drm_gem_vram_plane_helper_prepare_fb() - \ - * Implements &struct drm_plane_helper_funcs.prepare_fb + * drm_gem_vram_plane_helper_prepare_fb() - Implements &struct + * drm_plane_helper_funcs.prepare_fb * @plane: a DRM plane * @new_state: the plane's new state * @@ -690,8 +627,8 @@ err_drm_gem_vram_unpin: EXPORT_SYMBOL(drm_gem_vram_plane_helper_prepare_fb); /** - * drm_gem_vram_plane_helper_cleanup_fb() - \ - * Implements &struct drm_plane_helper_funcs.cleanup_fb + * drm_gem_vram_plane_helper_cleanup_fb() - Implements &struct + * drm_plane_helper_funcs.cleanup_fb * @plane: a DRM plane * @old_state: the plane's old state * @@ -713,90 +650,10 @@ drm_gem_vram_plane_helper_cleanup_fb(struct drm_plane *plane, EXPORT_SYMBOL(drm_gem_vram_plane_helper_cleanup_fb); /* - * Helpers for struct drm_simple_display_pipe_funcs - */ - -/** - * drm_gem_vram_simple_display_pipe_prepare_fb() - \ - * Implements &struct drm_simple_display_pipe_funcs.prepare_fb - * @pipe: a simple display pipe - * @new_state: the plane's new state - * - * During plane updates, this function pins the GEM VRAM - * objects of the plane's new framebuffer to VRAM. Call - * drm_gem_vram_simple_display_pipe_cleanup_fb() to unpin them. - * - * Returns: - * 0 on success, or - * a negative errno code otherwise. - */ -int drm_gem_vram_simple_display_pipe_prepare_fb( - struct drm_simple_display_pipe *pipe, - struct drm_plane_state *new_state) -{ - return drm_gem_vram_plane_helper_prepare_fb(&pipe->plane, new_state); -} -EXPORT_SYMBOL(drm_gem_vram_simple_display_pipe_prepare_fb); - -/** - * drm_gem_vram_simple_display_pipe_cleanup_fb() - \ - * Implements &struct drm_simple_display_pipe_funcs.cleanup_fb - * @pipe: a simple display pipe - * @old_state: the plane's old state - * - * During plane updates, this function unpins the GEM VRAM - * objects of the plane's old framebuffer from VRAM. Complements - * drm_gem_vram_simple_display_pipe_prepare_fb(). - */ -void drm_gem_vram_simple_display_pipe_cleanup_fb( - struct drm_simple_display_pipe *pipe, - struct drm_plane_state *old_state) -{ - drm_gem_vram_plane_helper_cleanup_fb(&pipe->plane, old_state); -} -EXPORT_SYMBOL(drm_gem_vram_simple_display_pipe_cleanup_fb); - -/* * PRIME helpers */ /** - * drm_gem_vram_object_pin() - \ - Implements &struct drm_gem_object_funcs.pin - * @gem: The GEM object to pin - * - * Returns: - * 0 on success, or - * a negative errno code otherwise. - */ -static int drm_gem_vram_object_pin(struct drm_gem_object *gem) -{ - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); - - /* Fbdev console emulation is the use case of these PRIME - * helpers. This may involve updating a hardware buffer from - * a shadow FB. We pin the buffer to it's current location - * (either video RAM or system memory) to prevent it from - * being relocated during the update operation. If you require - * the buffer to be pinned to VRAM, implement a callback that - * sets the flags accordingly. - */ - return drm_gem_vram_pin(gbo, 0); -} - -/** - * drm_gem_vram_object_unpin() - \ - Implements &struct drm_gem_object_funcs.unpin - * @gem: The GEM object to unpin - */ -static void drm_gem_vram_object_unpin(struct drm_gem_object *gem) -{ - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); - - drm_gem_vram_unpin(gbo); -} - -/** * drm_gem_vram_object_vmap() - * Implements &struct drm_gem_object_funcs.vmap * @gem: The GEM object to map @@ -834,8 +691,6 @@ static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem, static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { .free = drm_gem_vram_object_free, - .pin = drm_gem_vram_object_pin, - .unpin = drm_gem_vram_object_unpin, .vmap = drm_gem_vram_object_vmap, .vunmap = drm_gem_vram_object_vunmap, .mmap = drm_gem_ttm_mmap, @@ -1005,7 +860,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, ret = ttm_device_init(&vmm->bdev, &bo_driver, dev->dev, dev->anon_inode->i_mapping, dev->vma_offset_manager, - false, true); + TTM_ALLOCATION_POOL_USE_DMA32); if (ret) return ret; @@ -1113,7 +968,7 @@ drm_vram_helper_mode_valid_internal(struct drm_device *dev, max_fbpages = (vmm->vram_size / 2) >> PAGE_SHIFT; - fbsize = mode->hdisplay * mode->vdisplay * max_bpp; + fbsize = (u32)mode->hdisplay * mode->vdisplay * max_bpp; fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE); if (fbpages > max_fbpages) |
