Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 00/20] Share TTM code among DRM framebuffer drivers
Several simple framebuffer drivers copy most of the TTM code from each other. The implementation is always the same; except for the name of some data structures. As recently discussed, this patch set provides generic memory-management code for simple framebuffers with dedicated video memory. It further converts the respective drivers to the generic code. The shared code is basically the same implementation as the one copied among individual drivers. The patch set contains two major changes: first, it introduces |struct drm_gem_vram_object| and helpers (GEM VRAM). It's a GEM object that is backed by VRAM. The type's purpose is somewhat similar to |struct drm_gem_{cma, shmem}_object|: it provides an commom implementation that handles all the basic cases. Second, the patch set introduces |struct drm_vram_mm| and helpers (VRAM MM). It's an implementation of a basic memory manager for VRAM. Both, GEM VRAM and VRAM MM, support buffer placement in VRAM and system memory. Both can be used independedly from each other if desired by the DRM driver. Currently ast, bochs, mgag200, vboxvideo and hisilicon/hibmc can use these helpers. Future directions: with these changes, the respective drivers can also share some of their mode-setting or fbdev code. GEM VRAM's PRIME helpers allow for using the generic fbcon emulation. The patch set is against a recent drm-tip. v5: * move bochs PRIME functions to GEM VRAM helpers * always set struct file_operations.llseek to no_llseek() * add WARN_ON_ONCE for pin-count mismatches * only allocate 2 entries in placements array v4: * cleanups from checkpatch.pl * add more documentation for VRAM helpers * remove several fixed-size types from interfaces * don't make drivers depend on DRM_TTM; auto-selected if necessary * use single config optiom DRM_VRAM_HELPER v3: * share VRAM MM callback structure among drivers * move VRAM MM instances to drm_device and share rsp. code v2: * rename |struct drm_gem_ttm_object| to |struct drm_gem_vram_object| * rename |struct drm_simple_ttm| to |struct drm_vram_mm| * make drm_is_gem_ttm() an internal helper * add drm_gem_vram_kmap_at() * return is_iomem from kmap functions * redefine TTM placement flags for public interface * add drm_vram_mm_mmap() helper * replace almost all of driver's TTM code with these helpers * documentation fixes Thomas Zimmermann (20): drm: Add |struct drm_gem_vram_object| and helpers drm: Add |struct drm_gem_vram_object| callbacks for |struct ttm_bo_driver| drm: Add |struct drm_gem_vram_object| callbacks for |struct drm_driver| drm: Add drm_gem_vram_fill_create_dumb() to create dumb buffers drm: Add simple PRIME helpers for GEM VRAM drm: Add VRAM MM, a simple memory manager for dedicated VRAM drm: Add default instance for VRAM MM callback functions drm: Integrate VRAM MM into struct drm_device drm/ast: Convert AST driver to |struct drm_gem_vram_object| drm/ast: Convert AST driver to VRAM MM drm/ast: Replace mapping code with drm_gem_vram_{kmap/kunmap}() drm/bochs: Convert bochs driver to |struct drm_gem_vram_object| drm/bochs: Convert bochs driver to VRAM MM drm/mgag200: Convert mgag200 driver to |struct drm_gem_vram_object| drm/mgag200: Convert mgag200 driver to VRAM MM drm/mgag200: Replace mapping code with drm_gem_vram_{kmap/kunmap}() drm/vboxvideo: Convert vboxvideo driver to |struct drm_gem_vram_object| drm/vboxvideo: Convert vboxvideo driver to VRAM MM drm/hisilicon: Convert hibmc-drm driver to |struct drm_gem_vram_object| drm/hisilicon: Convert hibmc-drm driver to VRAM MM Documentation/gpu/drm-mm.rst | 34 +- drivers/gpu/drm/Kconfig | 7 + drivers/gpu/drm/Makefile | 5 + drivers/gpu/drm/ast/Kconfig | 3 +- drivers/gpu/drm/ast/ast_drv.c | 13 +- drivers/gpu/drm/ast/ast_drv.h | 71 +- drivers/gpu/drm/ast/ast_fb.c | 34 +- drivers/gpu/drm/ast/ast_main.c | 77 +- drivers/gpu/drm/ast/ast_mode.c | 124 +-- drivers/gpu/drm/ast/ast_ttm.c | 302 +------- drivers/gpu/drm/bochs/Kconfig | 2 +- drivers/gpu/drm/bochs/bochs.h | 54 +- drivers/gpu/drm/bochs/bochs_drv.c | 22 +- drivers/gpu/drm/bochs/bochs_kms.c | 18 +- drivers/gpu/drm/bochs/bochs_mm.c | 426 +---------- drivers/gpu/drm/drm_gem_vram_helper.c | 713 ++++++++++++++++++ drivers/gpu/drm/drm_vram_helper_common.c | 98 +++ drivers/gpu/drm/drm_vram_mm_helper.c | 295 ++++++++ drivers/gpu/drm/hisilicon/hibmc/Kconfig | 2 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 21 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 14 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 33 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 30 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 341 +-------- drivers/gpu/drm/mgag200/Kconfig | 2 +- drivers/gpu/drm/mgag200/mgag200_cursor.c | 88 ++- drivers/gpu/drm/mgag200/mgag200_drv.c | 13 +- drivers/gpu/drm/mgag200/mgag200_drv.h | 74 +- drivers/gpu/drm/mgag200/mgag200_fb.c | 34 +- drivers/gpu/drm/mgag200/mgag200_main.c | 87 +-- drivers/gpu/drm/mgag200/mgag200_mode.c | 53 +- drivers/gpu/drm/mgag200/mgag200_ttm.c | 301 +------- drivers/gpu/drm/vboxvideo/Kconfig | 2 +- drivers/gpu/drm/vboxvideo/vbox_drv.c | 12 +- drivers/gpu/drm/vboxvideo/vbox_drv.h | 75 +- drivers/gpu/drm/vboxvideo/vbox_fb.c | 22 +- drivers/gpu/drm/vboxvideo/vbox_main.c | 75 +- drivers/gpu/drm/vboxvideo/vbox_mode.c | 36 +- drivers/gpu/drm/vboxvideo/vbox_ttm.c | 355 +-------- include/drm/drm_device.h | 4 + include/drm/drm_gem_vram_helper.h | 160 ++++ include/drm/drm_vram_mm_helper.h | 102 +++ 42 files changed, 1797 insertions(+), 2437 deletions(-) create mode 100644 drivers/gpu/drm/drm_gem_vram_helper.c create mode 100644 drivers/gpu/drm/drm_vram_helper_common.c create mode 100644 drivers/gpu/drm/drm_vram_mm_helper.c create mode 100644 include/drm/drm_gem_vram_helper.h create mode 100644 include/drm/drm_vram_mm_helper.h -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 01/20] drm: Add |struct drm_gem_vram_object| and helpers
The type |struct drm_gem_vram_object| implements a GEM object for simple framebuffer devices with dedicated video memory. The BO is either located in VRAM or system memory. The implementation has been created from the respective code in ast, bochs and mgag200. These drivers copy their implementation from each other; except for the names of several data types. The helpers are currently build with TTM, but this is considered an implementation detail and may change in future updates. v5: * do WARN_ON_ONCE for pin-count mismatches * allocate only 2 entries in placements array v4: * cleanups from checkpatch.pl * removed several fixed-size types from interfaces * DRM_VRAM_HELPER now selects DRM_TTM * remove separate config option for GEM VRAM v2: * rename to |struct drm_gem_vram_object| * move drm_is_gem_ttm() to a later patch in the series * add drm_gem_vram_kmap_at() * return is_iomem from kmap functions * redefine TTM placement flags for public interface * documentation fixes Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- Documentation/gpu/drm-mm.rst | 15 + drivers/gpu/drm/Kconfig | 7 + drivers/gpu/drm/Makefile | 4 + drivers/gpu/drm/drm_gem_vram_helper.c | 412 +++++++++++++++++++++++ drivers/gpu/drm/drm_vram_helper_common.c | 6 + include/drm/drm_gem_vram_helper.h | 92 +++++ 6 files changed, 536 insertions(+) create mode 100644 drivers/gpu/drm/drm_gem_vram_helper.c create mode 100644 drivers/gpu/drm/drm_vram_helper_common.c create mode 100644 include/drm/drm_gem_vram_helper.h diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 54a696d961a7..a3b685089512 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -380,6 +380,21 @@ GEM CMA Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c :export: +VRAM Helper Function Reference +=============================+ +GEM VRAM Helper Functions Reference +----------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c + :doc: overview + +.. kernel-doc:: include/drm/drm_gem_vram_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c + :export: + VMA Offset Manager ================= diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 2267e84d5cb4..13d7b321db0d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -160,6 +160,13 @@ config DRM_TTM GPU memory types. Will be enabled automatically if a device driver uses it. +config DRM_VRAM_HELPER + tristate + depends on DRM + select DRM_TTM + help + Helpers for VRAM memory management + config DRM_GEM_CMA_HELPER bool depends on DRM diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 72f5036d9bfa..ed49b2480766 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -32,6 +32,10 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o +drm_vram_helper-y := drm_gem_vram_helper.o \ + drm_vram_helper_common.o +obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o + drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \ drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c new file mode 100644 index 000000000000..761a546412f8 --- /dev/null +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <drm/drm_gem_vram_helper.h> +#include <drm/ttm/ttm_page_alloc.h> + +/** + * DOC: overview + * + * This library provides a GEM buffer object that is backed by video RAM + * (VRAM). It can be used for framebuffer devices with dedicated memory. + */ + +/* + * Buffer-objects helpers + */ + +static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo) +{ + /* We got here via ttm_bo_put(), which means that the + * TTM buffer object in 'bo' has already been cleaned + * up; only release the GEM object. + */ + drm_gem_object_release(&gbo->gem); +} + +static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo) +{ + drm_gem_vram_cleanup(gbo); + kfree(gbo); +} + +static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo); + + drm_gem_vram_destroy(gbo); +} + +static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, + unsigned long pl_flag) +{ + unsigned int i; + unsigned int c = 0; + + gbo->placement.placement = gbo->placements; + gbo->placement.busy_placement = gbo->placements; + + if (pl_flag & TTM_PL_FLAG_VRAM) + gbo->placements[c++].flags = TTM_PL_FLAG_WC | + TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_VRAM; + + if (pl_flag & TTM_PL_FLAG_SYSTEM) + gbo->placements[c++].flags = TTM_PL_MASK_CACHING | + TTM_PL_FLAG_SYSTEM; + + if (!c) + gbo->placements[c++].flags = TTM_PL_MASK_CACHING | + TTM_PL_FLAG_SYSTEM; + + gbo->placement.num_placement = c; + gbo->placement.num_busy_placement = c; + + for (i = 0; i < c; ++i) { + gbo->placements[i].fpfn = 0; + gbo->placements[i].lpfn = 0; + } +} + +static int drm_gem_vram_init(struct drm_device *dev, + struct ttm_bo_device *bdev, + struct drm_gem_vram_object *gbo, + size_t size, unsigned long pg_align, + bool interruptible) +{ + int ret; + size_t acc_size; + + ret = drm_gem_object_init(dev, &gbo->gem, size); + if (ret) + return ret; + + acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); + + gbo->bo.bdev = bdev; + drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); + + ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, + &gbo->placement, pg_align, interruptible, acc_size, + NULL, NULL, ttm_buffer_object_destroy); + if (ret) + goto err_drm_gem_object_release; + + return 0; + +err_drm_gem_object_release: + drm_gem_object_release(&gbo->gem); + return ret; +} + +/** + * drm_gem_vram_create() - Creates a VRAM-backed GEM object + * @dev: the DRM device + * @bdev: the TTM BO device backing the object + * @size: the buffer size in bytes + * @pg_align: the buffer's alignment in multiples of the page size + * @interruptible: sleep interruptible if waiting for memory + * + * Returns: + * A new instance of &struct drm_gem_vram_object on success, or + * an ERR_PTR()-encoded error code otherwise. + */ +struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, + struct ttm_bo_device *bdev, + size_t size, + unsigned long pg_align, + bool interruptible) +{ + struct drm_gem_vram_object *gbo; + int ret; + + gbo = kzalloc(sizeof(*gbo), GFP_KERNEL); + if (!gbo) + return ERR_PTR(-ENOMEM); + + ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible); + if (ret < 0) + goto err_kfree; + + return gbo; + +err_kfree: + kfree(gbo); + return ERR_PTR(ret); +} +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. + */ +void drm_gem_vram_put(struct drm_gem_vram_object *gbo) +{ + ttm_bo_put(&gbo->bo); +} +EXPORT_SYMBOL(drm_gem_vram_put); + +/** + * drm_gem_vram_reserve() - Reserves a VRAM-backed GEM object + * @gbo: the GEM VRAM object + * @no_wait: don't wait for buffer object to become available + * + * See ttm_bo_reserve() for more information. + * + * Returns: + * 0 on success, or + * a negative error code otherwise + */ +int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait) +{ + return ttm_bo_reserve(&gbo->bo, true, no_wait, NULL); +} +EXPORT_SYMBOL(drm_gem_vram_reserve); + +/** + * drm_gem_vram_unreserve() - \ + Release a reservation acquired by drm_gem_vram_reserve() + * @gbo: the GEM VRAM object + * + * See ttm_bo_unreserve() for more information. + */ +void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo) +{ + ttm_bo_unreserve(&gbo->bo); +} +EXPORT_SYMBOL(drm_gem_vram_unreserve); + +/** + * drm_gem_vram_mmap_offset() - Returns a GEM VRAM object's mmap offset + * @gbo: the GEM VRAM object + * + * See drm_vma_node_offset_addr() for more information. + * + * Returns: + * The buffer object's offset for userspace mappings on success, or + * 0 if no offset is allocated. + */ +u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo) +{ + return drm_vma_node_offset_addr(&gbo->bo.vma_node); +} +EXPORT_SYMBOL(drm_gem_vram_mmap_offset); + +/** + * 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 + * memory. The buffer object has to be pinned to %TTM_PL_VRAM. + * + * Returns: + * The buffer object's offset in video memory on success, or + * a negative errno code otherwise. + */ +s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo) +{ + if (WARN_ON_ONCE(!gbo->pin_count)) + return (s64)-ENODEV; + return gbo->bo.offset; +} +EXPORT_SYMBOL(drm_gem_vram_offset); + +/** + * 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. + * + * 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) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (gbo->pin_count) { + ++gbo->pin_count; + return 0; + } + + drm_gem_vram_placement(gbo, pl_flag); + for (i = 0; i < gbo->placement.num_placement; ++i) + gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + gbo->pin_count = 1; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_pin); + +/** + * 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) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (WARN_ON_ONCE(!gbo->pin_count)) + return 0; + + --gbo->pin_count; + if (gbo->pin_count) + return 0; + + for (i = 0; i < gbo->placement.num_placement ; ++i) + gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_unpin); + +/** + * drm_gem_vram_push_to_system() - \ + Unpins a GEM VRAM object and moves it to system memory + * @gbo: the GEM VRAM object + * + * This operation only works if the caller holds the final pin on the + * buffer object. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo) +{ + int i, ret; + struct ttm_operation_ctx ctx = { false, false }; + + if (WARN_ON_ONCE(!gbo->pin_count)) + return 0; + + --gbo->pin_count; + if (gbo->pin_count) + return 0; + + if (gbo->kmap.virtual) + ttm_bo_kunmap(&gbo->kmap); + + drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); + for (i = 0; i < gbo->placement.num_placement ; ++i) + gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; + + ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_push_to_system); + +/** + * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space + * @gbo: the GEM VRAM object + * @map: establish a mapping if necessary + * @is_iomem: returns true if the mapped memory is I/O memory, or false \ + otherwise; can be NULL + * @kmap: the mapping's kmap object + * + * This function maps the buffer object into the kernel's address space + * or returns the current mapping. If the parameter map is false, the + * function only queries the current mapping, but does not establish a + * new one. + * + * Returns: + * The buffers virtual address if mapped, or + * NULL if not mapped, or + * an ERR_PTR()-encoded error code otherwise. + */ +void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem, struct ttm_bo_kmap_obj *kmap) +{ + int ret; + + if (kmap->virtual || !map) + goto out; + + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap); + if (ret) + return ERR_PTR(ret); + +out: + if (!is_iomem) + return kmap->virtual; + if (!kmap->virtual) { + *is_iomem = false; + return NULL; + } + return ttm_kmap_obj_virtual(kmap, is_iomem); +} +EXPORT_SYMBOL(drm_gem_vram_kmap_at); + +/** + * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space + * @gbo: the GEM VRAM object + * @map: establish a mapping if necessary + * @is_iomem: returns true if the mapped memory is I/O memory, or false \ + otherwise; can be NULL + * + * This function maps the buffer object into the kernel's address space + * or returns the current mapping. If the parameter map is false, the + * function only queries the current mapping, but does not establish a + * new one. + * + * Returns: + * The buffers virtual address if mapped, or + * NULL if not mapped, or + * an ERR_PTR()-encoded error code otherwise. + */ +void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem) +{ + return drm_gem_vram_kmap_at(gbo, map, is_iomem, &gbo->kmap); +} +EXPORT_SYMBOL(drm_gem_vram_kmap); + +/** + * drm_gem_vram_kunmap_at() - Unmaps a GEM VRAM object + * @gbo: the GEM VRAM object + * @kmap: the mapping's kmap object + */ +void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, + struct ttm_bo_kmap_obj *kmap) +{ + if (!kmap->virtual) + return; + + ttm_bo_kunmap(kmap); + kmap->virtual = NULL; +} +EXPORT_SYMBOL(drm_gem_vram_kunmap_at); + +/** + * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object + * @gbo: the GEM VRAM object + */ +void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) +{ + drm_gem_vram_kunmap_at(gbo, &gbo->kmap); +} +EXPORT_SYMBOL(drm_gem_vram_kunmap); diff --git a/drivers/gpu/drm/drm_vram_helper_common.c b/drivers/gpu/drm/drm_vram_helper_common.c new file mode 100644 index 000000000000..7c25daca18d0 --- /dev/null +++ b/drivers/gpu/drm/drm_vram_helper_common.c @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/module.h> + +MODULE_DESCRIPTION("DRM VRAM memory-management helpers"); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h new file mode 100644 index 000000000000..5802dd694939 --- /dev/null +++ b/include/drm/drm_gem_vram_helper.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef DRM_GEM_VRAM_HELPER_H +#define DRM_GEM_VRAM_HELPER_H + +#include <drm/drm_gem.h> +#include <drm/ttm/ttm_bo_api.h> +#include <drm/ttm/ttm_placement.h> +#include <linux/kernel.h> /* for container_of() */ + +struct filp; + +#define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM +#define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM + +/* + * Buffer-object helpers + */ + +/** + * struct drm_gem_vram_object - GEM object backed by VRAM + * @gem: GEM object + * @bo: TTM buffer object + * @kmap: Mapping information for @bo + * @placement: TTM placement information. Supported placements are \ + %TTM_PL_VRAM and %TTM_PL_SYSTEM + * @placements: TTM placement information. + * @pin_count: Pin counter + * + * The type struct drm_gem_vram_object represents a GEM object that is + * 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. + */ +struct drm_gem_vram_object { + struct drm_gem_object gem; + struct ttm_buffer_object bo; + struct ttm_bo_kmap_obj kmap; + + /* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */ + struct ttm_placement placement; + struct ttm_place placements[2]; + + int pin_count; +}; + +/** + * Returns the container of type &struct drm_gem_vram_object + * for field bo. + * @bo: the VRAM buffer object + * Returns: The containing GEM VRAM object + */ +static inline struct drm_gem_vram_object *drm_gem_vram_of_bo( + struct ttm_buffer_object *bo) +{ + return container_of(bo, struct drm_gem_vram_object, bo); +} + +/** + * Returns the container of type &struct drm_gem_vram_object + * for field gem. + * @gem: the GEM object + * Returns: The containing GEM VRAM object + */ +static inline struct drm_gem_vram_object *drm_gem_vram_of_gem( + struct drm_gem_object *gem) +{ + return container_of(gem, struct drm_gem_vram_object, gem); +} + +struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, + struct ttm_bo_device *bdev, + size_t size, + unsigned long pg_align, + bool interruptible); +void drm_gem_vram_put(struct drm_gem_vram_object *gbo); +int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait); +void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo); +u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); +s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); +int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); +int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); +int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo); +void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem, struct ttm_bo_kmap_obj *kmap); +void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, + bool *is_iomem); +void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, + struct ttm_bo_kmap_obj *kmap); +void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); + +#endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 02/20] drm: Add |struct drm_gem_vram_object| callbacks for |struct ttm_bo_driver|
The provided helpers can be used for the respective callback functions in |struct ttm_bo_driver|. v2: * drm_is_gem_vram() is now a private function * documentation fixes Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/drm_gem_vram_helper.c | 50 +++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 10 ++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 761a546412f8..d6c4e0d0a1c5 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -410,3 +410,53 @@ void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) drm_gem_vram_kunmap_at(gbo, &gbo->kmap); } EXPORT_SYMBOL(drm_gem_vram_kunmap); + +/* + * Helpers for struct ttm_bo_driver + */ + +static bool drm_is_gem_vram(struct ttm_buffer_object *bo) +{ + return (bo->destroy == ttm_buffer_object_destroy); +} + +/** + * drm_gem_vram_bo_driver_evict_flags() - \ + Implements &struct ttm_bo_driver.evict_flags + * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo + * @pl: TTM placement information. + */ +void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *pl) +{ + struct drm_gem_vram_object *gbo; + + /* TTM may pass BOs that are not GEM VRAM BOs. */ + if (!drm_is_gem_vram(bo)) + return; + + gbo = drm_gem_vram_of_bo(bo); + drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); + *pl = gbo->placement; +} +EXPORT_SYMBOL(drm_gem_vram_bo_driver_evict_flags); + +/** + * drm_gem_vram_bo_driver_verify_access() - \ + Implements &struct ttm_bo_driver.verify_access + * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo + * @filp: File pointer. + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo); + + return drm_vma_node_verify_access(&gbo->gem.vma_node, + filp->private_data); +} +EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 5802dd694939..1915d3958304 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -89,4 +89,14 @@ void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, struct ttm_bo_kmap_obj *kmap); void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); +/* + * Helpers for struct ttm_bo_driver + */ + +void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *pl); + +int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp); + #endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 03/20] drm: Add |struct drm_gem_vram_object| callbacks for |struct drm_driver|
The provided helpers can be used for the respective callback functions in |struct drm_driver|. v4: * cleanups from checkpatch.pl v2: * documentation fixes Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/drm_gem_vram_helper.c | 49 +++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 10 ++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index d6c4e0d0a1c5..264028374336 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -460,3 +460,52 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, filp->private_data); } EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); + +/* + * Helpers for struct drm_driver + */ + +/** + * drm_gem_vram_driver_gem_free_object_unlocked() - \ + Implements &struct drm_driver.gem_free_object_unlocked + * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem + */ +void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_put(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked); + +/** + * drm_gem_vram_driver_dumb_mmap_offset() - \ + Implements &struct drm_driver.dumb_mmap_offset + * @file: DRM file pointer. + * @dev: DRM device. + * @handle: GEM handle + * @offset: Returns the mapping's memory offset on success + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, + struct drm_device *dev, + uint32_t handle, uint64_t *offset) +{ + struct drm_gem_object *gem; + struct drm_gem_vram_object *gbo; + + gem = drm_gem_object_lookup(file, handle); + if (!gem) + return -ENOENT; + + gbo = drm_gem_vram_of_gem(gem); + *offset = drm_gem_vram_mmap_offset(gbo); + + drm_gem_object_put_unlocked(gem); + + return 0; +} +EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 1915d3958304..b87cb2e9d9da 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -99,4 +99,14 @@ void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, struct file *filp); +/* + * Helpers for struct drm_driver + */ + +void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); + +int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, + struct drm_device *dev, + uint32_t handle, uint64_t *offset); + #endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 04/20] drm: Add drm_gem_vram_fill_create_dumb() to create dumb buffers
The helper function drm_gem_vram_fill_create_dumb() implements most of struct drm_driver.dumb_create() for GEM-VRAM buffer objects. It's not a full implementation of the callback, as several driver-specific parameters are still required. v4: * cleanups from checkpatch.pl v2: * documentation fixes Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/drm_gem_vram_helper.c | 62 +++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 8 ++++ 2 files changed, 70 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 264028374336..aba073279ca2 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_mode.h> #include <drm/ttm/ttm_page_alloc.h> /** @@ -411,6 +412,67 @@ void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) } EXPORT_SYMBOL(drm_gem_vram_kunmap); +/** + * drm_gem_vram_fill_create_dumb() - \ + Helper for implementing &struct drm_driver.dumb_create + * @file: the DRM file + * @dev: the DRM device + * @bdev: the TTM BO device managing the buffer object + * @pg_align: the buffer's alignment in multiples of the page size + * @interruptible: sleep interruptible if waiting for memory + * @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 + * should forwards their arguments to this helper, plus the driver-specific + * parameters. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_fill_create_dumb(struct drm_file *file, + struct drm_device *dev, + struct ttm_bo_device *bdev, + unsigned long pg_align, + bool interruptible, + struct drm_mode_create_dumb *args) +{ + size_t pitch, size; + struct drm_gem_vram_object *gbo; + int ret; + u32 handle; + + pitch = args->width * ((args->bpp + 7) / 8); + size = pitch * args->height; + + size = roundup(size, PAGE_SIZE); + if (!size) + return -EINVAL; + + gbo = drm_gem_vram_create(dev, bdev, size, pg_align, interruptible); + if (IS_ERR(gbo)) + return PTR_ERR(gbo); + + ret = drm_gem_handle_create(file, &gbo->gem, &handle); + if (ret) + goto err_drm_gem_object_put_unlocked; + + drm_gem_object_put_unlocked(&gbo->gem); + + args->pitch = pitch; + args->size = size; + args->handle = handle; + + return 0; + +err_drm_gem_object_put_unlocked: + drm_gem_object_put_unlocked(&gbo->gem); + return ret; +} +EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb); + /* * Helpers for struct ttm_bo_driver */ diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index b87cb2e9d9da..8e54f721c9f8 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -8,6 +8,7 @@ #include <drm/ttm/ttm_placement.h> #include <linux/kernel.h> /* for container_of() */ +struct drm_mode_create_dumb; struct filp; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM @@ -89,6 +90,13 @@ void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo, struct ttm_bo_kmap_obj *kmap); void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); +int drm_gem_vram_fill_create_dumb(struct drm_file *file, + struct drm_device *dev, + struct ttm_bo_device *bdev, + unsigned long pg_align, + bool interruptible, + struct drm_mode_create_dumb *args); + /* * Helpers for struct ttm_bo_driver */ -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 05/20] drm: Add simple PRIME helpers for GEM VRAM
These basic helper functions for GEM VRAM allow for pinning and mapping GEM VRAM objects via the PRIME interfaces. It's not a full implementation, but complete enough for generic fbcon. Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/drm_gem_vram_helper.c | 98 +++++++++++++++++++++++++++ include/drm/drm_gem_vram_helper.h | 20 ++++++ 2 files changed, 118 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index aba073279ca2..15c6193e4985 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -2,6 +2,7 @@ #include <drm/drm_gem_vram_helper.h> #include <drm/drm_mode.h> +#include <drm/drm_prime.h> #include <drm/ttm/ttm_page_alloc.h> /** @@ -571,3 +572,100 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, return 0; } EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset); + +/* + * PRIME helpers for struct drm_driver + */ + +/** + * drm_gem_vram_driver_gem_prime_pin() - \ + Implements &struct drm_driver.gem_prime_pin + * @gem: The GEM object to pin + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_pin); + +/** + * drm_gem_vram_driver_gem_prime_unpin() - \ + Implements &struct drm_driver.gem_prime_unpin + * @gem: The GEM object to unpin + */ +void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *gem) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_unpin(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_unpin); + +/** + * drm_gem_vram_driver_gem_prime_vmap() - \ + Implements &struct drm_driver.gem_prime_vmap + * @gem: The GEM object to map + * + * Returns: + * The buffers virtual address on success, or + * NULL otherwise. + */ +void *drm_gem_vram_driver_gem_prime_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, DRM_GEM_VRAM_PL_FLAG_VRAM); + if (ret) + return NULL; + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + drm_gem_vram_unpin(gbo); + return NULL; + } + return base; +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vmap); + +/** + * drm_gem_vram_driver_gem_prime_vunmap() - \ + Implements &struct drm_driver.gem_prime_vunmap + * @gem: The GEM object to unmap + * @vaddr: The mapping's base address + */ +void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *gem, + void *vaddr) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vunmap); + +/** + * drm_gem_vram_driver_gem_prime_mmap() - \ + Implements &struct drm_driver.gem_prime_mmap + * @gem: The GEM object to map + * @vma: The VMA describing the mapping + * + * Returns: + * 0 on success, or + * a negative errno code otherwise. + */ +int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *gem, + struct vm_area_struct *vma) +{ + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); + + gbo->gem.vma_node.vm_node.start = gbo->bo.vma_node.vm_node.start; + return drm_gem_prime_mmap(gem, vma); +} +EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_mmap); diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 8e54f721c9f8..9a8bd98b623f 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -116,5 +116,25 @@ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); +/* + * PRIME helpers for struct drm_driver + */ + +int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *obj); +void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *obj); +void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *obj); +void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *obj, + void *vaddr); +int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma); + +#define DRM_GEM_VRAM_DRIVER_PRIME \ + .gem_prime_export = drm_gem_prime_export, \ + .gem_prime_import = drm_gem_prime_import, \ + .gem_prime_pin = drm_gem_vram_driver_gem_prime_pin, \ + .gem_prime_unpin = drm_gem_vram_driver_gem_prime_unpin, \ + .gem_prime_vmap = drm_gem_vram_driver_gem_prime_vmap, \ + .gem_prime_vunmap = drm_gem_vram_driver_gem_prime_vunmap, \ + .gem_prime_mmap = drm_gem_vram_driver_gem_prime_mmap #endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 06/20] drm: Add VRAM MM, a simple memory manager for dedicated VRAM
The VRAM MM memory manager is a helper library that manages dedicated video memory of simple framebuffer devices. It is supported to be used with struct drm_gem_vram_object, but does not depend on it. The implementation is based on the respective code from ast, bochs, and mgag200. These drivers share the exact same implementation except for type names. The helpers are currently build with TTM. This may change in future revisions. v4: * cleanups from checkpatch.pl v2: * renamed to struct drm_vram_mm * add drm_vram_mm_mmap() helper * documentation fixes Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- Documentation/gpu/drm-mm.rst | 13 +- drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_vram_mm_helper.c | 210 +++++++++++++++++++++++++++ include/drm/drm_vram_mm_helper.h | 69 +++++++++ 4 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/drm_vram_mm_helper.c create mode 100644 include/drm/drm_vram_mm_helper.h diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index a3b685089512..eba50afbda42 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -79,7 +79,6 @@ count for the TTM, which will call your initialization function. See the radeon_ttm.c file for an example of usage. - The Graphics Execution Manager (GEM) =================================== @@ -395,6 +394,18 @@ GEM VRAM Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c :export: +VRAM MM Helper Functions Reference +---------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c + :doc: overview + +.. kernel-doc:: include/drm/drm_vram_mm_helper.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c + :export: + VMA Offset Manager ================= diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index ed49b2480766..4c3dc4268b65 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -33,7 +33,8 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_vram_helper-y := drm_gem_vram_helper.o \ - drm_vram_helper_common.o + drm_vram_helper_common.o \ + drm_vram_mm_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper.o \ diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c new file mode 100644 index 000000000000..d17c5169b018 --- /dev/null +++ b/drivers/gpu/drm/drm_vram_mm_helper.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <drm/drm_vram_mm_helper.h> +#include <drm/drmP.h> +#include <drm/ttm/ttm_page_alloc.h> + +/** + * DOC: overview + * + * The data structure &struct drm_vram_mm and its helpers implement a memory + * manager for simple framebuffer devices with dedicated video memory. Buffer + * objects are either placed in video RAM or evicted to system memory. These + * helper functions work well with &struct drm_gem_vram_object. + */ + +/* + * TTM TT + */ + +static void backend_func_destroy(struct ttm_tt *tt) +{ + ttm_tt_fini(tt); + kfree(tt); +} + +static struct ttm_backend_func backend_func = { + .destroy = backend_func_destroy +}; + +/* + * TTM BO device + */ + +static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, + uint32_t page_flags) +{ + struct ttm_tt *tt; + int ret; + + tt = kzalloc(sizeof(*tt), GFP_KERNEL); + if (!tt) + return NULL; + + tt->func = &backend_func; + + ret = ttm_tt_init(tt, bo, page_flags); + if (ret < 0) + goto err_ttm_tt_init; + + return tt; + +err_ttm_tt_init: + kfree(tt); + return NULL; +} + +static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man) +{ + switch (type) { + case TTM_PL_SYSTEM: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + break; + case TTM_PL_VRAM: + man->func = &ttm_bo_manager_func; + man->flags = TTM_MEMTYPE_FLAG_FIXED | + TTM_MEMTYPE_FLAG_MAPPABLE; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + break; + default: + return -EINVAL; + } + return 0; +} + +static void bo_driver_evict_flags(struct ttm_buffer_object *bo, + struct ttm_placement *placement) +{ + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev); + + if (vmm->funcs && vmm->funcs->evict_flags) + vmm->funcs->evict_flags(bo, placement); +} + +static int bo_driver_verify_access(struct ttm_buffer_object *bo, + struct file *filp) +{ + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev); + + if (!vmm->funcs || !vmm->funcs->verify_access) + return 0; + return vmm->funcs->verify_access(bo, filp); +} + +static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = bdev->man + mem->mem_type; + struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev); + + if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) + return -EINVAL; + + mem->bus.addr = NULL; + mem->bus.size = mem->num_pages << PAGE_SHIFT; + + switch (mem->mem_type) { + case TTM_PL_SYSTEM: /* nothing to do */ + mem->bus.offset = 0; + mem->bus.base = 0; + mem->bus.is_iomem = false; + break; + case TTM_PL_VRAM: + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = vmm->vram_base; + mem->bus.is_iomem = true; + break; + default: + return -EINVAL; + } + + return 0; +} + +static void bo_driver_io_mem_free(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ } + +static struct ttm_bo_driver bo_driver = { + .ttm_tt_create = bo_driver_ttm_tt_create, + .ttm_tt_populate = ttm_pool_populate, + .ttm_tt_unpopulate = ttm_pool_unpopulate, + .init_mem_type = bo_driver_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, + .evict_flags = bo_driver_evict_flags, + .verify_access = bo_driver_verify_access, + .io_mem_reserve = bo_driver_io_mem_reserve, + .io_mem_free = bo_driver_io_mem_free, +}; + +/* + * struct drm_vram_mm + */ + +/** + * drm_vram_mm_init() - Initialize an instance of VRAM MM. + * @vmm: the VRAM MM instance to initialize + * @dev: the DRM device + * @vram_base: the base address of the video memory + * @vram_size: the size of the video memory in bytes + * @funcs: callback functions for buffer objects + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, + uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs) +{ + int ret; + + vmm->vram_base = vram_base; + vmm->vram_size = vram_size; + vmm->funcs = funcs; + + ret = ttm_bo_device_init(&vmm->bdev, &bo_driver, + dev->anon_inode->i_mapping, + true); + if (ret) + return ret; + + ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(drm_vram_mm_init); + +/** + * drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM. + * @vmm: the VRAM MM instance to clean up + */ +void drm_vram_mm_cleanup(struct drm_vram_mm *vmm) +{ + ttm_bo_device_release(&vmm->bdev); +} +EXPORT_SYMBOL(drm_vram_mm_cleanup); + +/** + * drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap() + * @filp: the mapping's file structure + * @vma: the mapping's memory area + * @vmm: the VRAM MM instance + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, + struct drm_vram_mm *vmm) +{ + return ttm_bo_mmap(filp, vma, &vmm->bdev); +} +EXPORT_SYMBOL(drm_vram_mm_mmap); diff --git a/include/drm/drm_vram_mm_helper.h b/include/drm/drm_vram_mm_helper.h new file mode 100644 index 000000000000..5d45c6447fa4 --- /dev/null +++ b/include/drm/drm_vram_mm_helper.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef DRM_VRAM_MM_HELPER_H +#define DRM_VRAM_MM_HELPER_H + +#include <drm/ttm/ttm_bo_driver.h> + +struct drm_device; + +/** + * struct drm_vram_mm_funcs - Callback functions for &struct drm_vram_mm + * @evict_flags: Provides an implementation for struct \ + &ttm_bo_driver.evict_flags + * @verify_access: Provides an implementation for \ + struct &ttm_bo_driver.verify_access + * + * These callback function integrate VRAM MM with TTM buffer objects. New + * functions can be added if necessary. + */ +struct drm_vram_mm_funcs { + void (*evict_flags)(struct ttm_buffer_object *bo, + struct ttm_placement *placement); + int (*verify_access)(struct ttm_buffer_object *bo, struct file *filp); +}; + +/** + * struct drm_vram_mm - An instance of VRAM MM + * @vram_base: Base address of the managed video memory + * @vram_size: Size of the managed video memory in bytes + * @bdev: The TTM BO device. + * @funcs: TTM BO functions + * + * The fields &struct drm_vram_mm.vram_base and + * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are + * available for public read access. Use the field + * &struct drm_vram_mm.bdev to access the TTM BO device. + */ +struct drm_vram_mm { + uint64_t vram_base; + size_t vram_size; + + struct ttm_bo_device bdev; + + const struct drm_vram_mm_funcs *funcs; +}; + +/** + * drm_vram_mm_of_bdev() - \ + Returns the container of type &struct ttm_bo_device for field bdev. + * @bdev: the TTM BO device + * + * Returns: + * The containing instance of &struct drm_vram_mm + */ +static inline struct drm_vram_mm *drm_vram_mm_of_bdev( + struct ttm_bo_device *bdev) +{ + return container_of(bdev, struct drm_vram_mm, bdev); +} + +int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, + uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs); +void drm_vram_mm_cleanup(struct drm_vram_mm *vmm); + +int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, + struct drm_vram_mm *vmm); + +#endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 07/20] drm: Add default instance for VRAM MM callback functions
VRAM MM is most likely be used with GEM VRAM. The latter now provides the required instance of struct drm_vram_mm_funcs for drivers to use. Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/drm_gem_vram_helper.c | 14 ++++++++++++++ include/drm/drm_gem_vram_helper.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 15c6193e4985..c21b1f920e0a 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -3,6 +3,7 @@ #include <drm/drm_gem_vram_helper.h> #include <drm/drm_mode.h> #include <drm/drm_prime.h> +#include <drm/drm_vram_mm_helper.h> #include <drm/ttm/ttm_page_alloc.h> /** @@ -524,6 +525,19 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); +/** + * drm_gem_vram_mm_funcs - Functions for &struct drm_vram_mm + * + * Most users of @struct drm_gem_vram_object will also use + * @struct drm_vram_mm. This instance of &struct drm_vram_mm_funcs + * can be used to connect both. + */ +const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = { + .evict_flags = drm_gem_vram_bo_driver_evict_flags, + .verify_access = drm_gem_vram_bo_driver_verify_access +}; +EXPORT_SYMBOL(drm_gem_vram_mm_funcs); + /* * Helpers for struct drm_driver */ diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 9a8bd98b623f..7971656afe87 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -9,6 +9,7 @@ #include <linux/kernel.h> /* for container_of() */ struct drm_mode_create_dumb; +struct drm_vram_mm_funcs; struct filp; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM @@ -107,6 +108,8 @@ void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo, int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, struct file *filp); +extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs; + /* * Helpers for struct drm_driver */ -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 08/20] drm: Integrate VRAM MM into struct drm_device
There's now a pointer to struct drm_vram_mm stored in struct drm_device. DRM drivers that use VRAM MM should use this field to refer to their instance of the data structure. Appropriate helpers are now provided as well. Adding struct drm_vram_mm to struct drm_device further avoids wrappers and boilerplate code in drivers. This patch implements default functions for callbacks in struct drm_driver and struct file_operations that use the struct drm_vram_mm stored in struct drm_device. Drivers that need to provide their own implementations can still do so. The patch also adds documentation for the VRAM helper library in general. v5: * set .llseek to no_llseek() from DRM_VRAM_MM_FILE_OPERATIONS v4: * cleanups from checkpatch.pl * document VRAM helper library Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- Documentation/gpu/drm-mm.rst | 6 ++ drivers/gpu/drm/drm_gem_vram_helper.c | 28 ++++++++ drivers/gpu/drm/drm_vram_helper_common.c | 92 ++++++++++++++++++++++++ drivers/gpu/drm/drm_vram_mm_helper.c | 85 ++++++++++++++++++++++ include/drm/drm_device.h | 4 ++ include/drm/drm_gem_vram_helper.h | 19 ++++- include/drm/drm_vram_mm_helper.h | 33 +++++++++ 7 files changed, 266 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index eba50afbda42..c8ebd4f66a6a 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -382,6 +382,12 @@ GEM CMA Helper Functions Reference VRAM Helper Function Reference ============================= +.. kernel-doc:: drivers/gpu/drm/drm_vram_helper_common.c + :doc: overview + +.. kernel-doc:: include/drm/drm_gem_vram_helper.h + :internal: + GEM VRAM Helper Functions Reference ----------------------------------- diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index c21b1f920e0a..8f142b810eb4 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_device.h> #include <drm/drm_mode.h> #include <drm/drm_prime.h> #include <drm/drm_vram_mm_helper.h> @@ -555,6 +556,33 @@ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem) } EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked); +/** + * drm_gem_vram_driver_create_dumb() - \ + 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 + * + * This function requires the driver to use @drm_device.vram_mm for its + * instance of VRAM MM. + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_gem_vram_driver_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) + return -EINVAL; + + return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev, 0, + false, args); +} +EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create); + /** * drm_gem_vram_driver_dumb_mmap_offset() - \ Implements &struct drm_driver.dumb_mmap_offset diff --git a/drivers/gpu/drm/drm_vram_helper_common.c b/drivers/gpu/drm/drm_vram_helper_common.c index 7c25daca18d0..3b47f7002115 100644 --- a/drivers/gpu/drm/drm_vram_helper_common.c +++ b/drivers/gpu/drm/drm_vram_helper_common.c @@ -2,5 +2,97 @@ #include <linux/module.h> +/** + * DOC: overview + * + * This library provides &struct drm_gem_vram_object (GEM VRAM), a GEM + * buffer object that is backed by video RAM. It can be used for + * framebuffer devices with dedicated memory. The video RAM can be + * managed with &struct drm_vram_mm (VRAM MM). Both data structures are + * supposed to be used together, but can also be used individually. + * + * With the GEM interface userspace applications create, manage and destroy + * graphics buffers, such as an on-screen framebuffer. GEM does not provide + * an implementation of these interfaces. It's up to the DRM driver to + * provide an implementation that suits the hardware. If the hardware device + * contains dedicated video memory, the DRM driver can use the VRAM helper + * library. Each active buffer object is stored in video RAM. Active + * buffer are used for drawing the current frame, typically something like + * the frame's scanout buffer or the cursor image. If there's no more space + * left in VRAM, inactive GEM objects can be moved to system memory. + * + * The easiest way to use the VRAM helper library is to call + * drm_vram_helper_alloc_mm(). The function allocates and initializes an + * instance of &struct drm_vram_mm in &struct drm_device.vram_mm . Use + * &DRM_GEM_VRAM_DRIVER to initialize &struct drm_driver and + * &DRM_VRAM_MM_FILE_OPERATIONS to initialize &struct file_operations; + * as illustrated below. + * + * .. code-block:: c + * + * struct file_operations fops ={ + * .owner = THIS_MODULE, + * DRM_VRAM_MM_FILE_OPERATION + * }; + * struct drm_driver drv = { + * .driver_feature = DRM_ ... , + * .fops = &fops, + * DRM_GEM_VRAM_DRIVER + * }; + * + * int init_drm_driver() + * { + * struct drm_device *dev; + * uint64_t vram_base; + * unsigned long vram_size; + * int ret; + * + * // setup device, vram base and size + * // ... + * + * ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size, + * &drm_gem_vram_mm_funcs); + * if (ret) + * return ret; + * return 0; + * } + * + * This creates an instance of &struct drm_vram_mm, exports DRM userspace + * interfaces for GEM buffer management and initializes file operations to + * allow for accessing created GEM buffers. With this setup, the DRM driver + * manages an area of video RAM with VRAM MM and provides GEM VRAM objects + * to userspace. + * + * To clean up the VRAM memory management, call drm_vram_helper_release_mm() + * in the driver's clean-up code. + * + * .. code-block:: c + * + * void fini_drm_driver() + * { + * struct drm_device *dev = ...; + * + * drm_vram_helper_release_mm(dev); + * } + * + * For drawing or scanout operations, buffer object 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. + * If you have to evict a buffer object from video RAM (e.g., for freeing up + * memory), unpin the buffer and call drm_gem_vram_push_to_system(). + * + * 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 + * the cursor overlay's image for a mouse cursor, or use it as input to the + * hardware's draing engine. + * + * To access a buffer object's memory from the DRM driver, call + * drm_gem_vram_kmap(). It (optionally) maps the buffer into kernel address + * space and returns the memory address. Use drm_gem_vram_kunmap() to + * release the mapping. + */ + MODULE_DESCRIPTION("DRM VRAM memory-management helpers"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/drm_vram_mm_helper.c b/drivers/gpu/drm/drm_vram_mm_helper.c index d17c5169b018..c94a6dc5ade7 100644 --- a/drivers/gpu/drm/drm_vram_mm_helper.c +++ b/drivers/gpu/drm/drm_vram_mm_helper.c @@ -208,3 +208,88 @@ int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, return ttm_bo_mmap(filp, vma, &vmm->bdev); } EXPORT_SYMBOL(drm_vram_mm_mmap); + +/* + * Helpers for integration with struct drm_device + */ + +/** + * drm_vram_helper_alloc_mm - Allocates a device's instance of \ + &struct drm_vram_mm + * @dev: the DRM device + * @vram_base: the base address of the video memory + * @vram_size: the size of the video memory in bytes + * @funcs: callback functions for buffer objects + * + * Returns: + * The new instance of &struct drm_vram_mm on success, or + * an ERR_PTR()-encoded errno code otherwise. + */ +struct drm_vram_mm *drm_vram_helper_alloc_mm( + struct drm_device *dev, uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs) +{ + int ret; + + if (WARN_ON(dev->vram_mm)) + return dev->vram_mm; + + dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL); + if (!dev->vram_mm) + return ERR_PTR(-ENOMEM); + + ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs); + if (ret) + goto err_kfree; + + return dev->vram_mm; + +err_kfree: + kfree(dev->vram_mm); + dev->vram_mm = NULL; + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_vram_helper_alloc_mm); + +/** + * drm_vram_helper_release_mm - Releases a device's instance of \ + &struct drm_vram_mm + * @dev: the DRM device + */ +void drm_vram_helper_release_mm(struct drm_device *dev) +{ + if (!dev->vram_mm) + return; + + drm_vram_mm_cleanup(dev->vram_mm); + kfree(dev->vram_mm); + dev->vram_mm = NULL; +} +EXPORT_SYMBOL(drm_vram_helper_release_mm); + +/* + * Helpers for &struct file_operations + */ + +/** + * drm_vram_mm_file_operations_mmap() - \ + Implements &struct file_operations.mmap() + * @filp: the mapping's file structure + * @vma: the mapping's memory area + * + * Returns: + * 0 on success, or + * a negative error code otherwise. + */ +int drm_vram_mm_file_operations_mmap( + struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *file_priv = filp->private_data; + struct drm_device *dev = file_priv->minor->dev; + + if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) + return -EINVAL; + + return drm_vram_mm_mmap(filp, vma, dev->vram_mm); +} +EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap); diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 7f9ef709b2b6..1acfc3bbd3fb 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -17,6 +17,7 @@ struct drm_vblank_crtc; struct drm_sg_mem; struct drm_local_map; struct drm_vma_offset_manager; +struct drm_vram_mm; struct drm_fb_helper; struct inode; @@ -286,6 +287,9 @@ struct drm_device { /** @vma_offset_manager: GEM information */ struct drm_vma_offset_manager *vma_offset_manager; + /** @vram_mm: VRAM MM memory manager */ + struct drm_vram_mm *vram_mm; + /** * @switch_power_state: * diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 7971656afe87..b056f189ba62 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -11,6 +11,7 @@ struct drm_mode_create_dumb; struct drm_vram_mm_funcs; struct filp; +struct vm_area_struct; #define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM #define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM @@ -115,10 +116,26 @@ extern const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs; */ void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem); - +int drm_gem_vram_driver_dumb_create(struct drm_file *file, + struct drm_device *dev, + struct drm_mode_create_dumb *args); int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); + +/** + * define DRM_GEM_VRAM_DRIVER - default callback functions for \ + &struct drm_driver + * + * Drivers that use VRAM MM and GEM VRAM can use this macro to initialize + * &struct drm_driver with default functions. + */ +#define DRM_GEM_VRAM_DRIVER \ + .gem_free_object_unlocked = \ + drm_gem_vram_driver_gem_free_object_unlocked, \ + .dumb_create = drm_gem_vram_driver_dumb_create, \ + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset + /* * PRIME helpers for struct drm_driver */ diff --git a/include/drm/drm_vram_mm_helper.h b/include/drm/drm_vram_mm_helper.h index 5d45c6447fa4..a8ffd8599b08 100644 --- a/include/drm/drm_vram_mm_helper.h +++ b/include/drm/drm_vram_mm_helper.h @@ -66,4 +66,37 @@ void drm_vram_mm_cleanup(struct drm_vram_mm *vmm); int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma, struct drm_vram_mm *vmm); +/* + * Helpers for integration with struct drm_device + */ + +struct drm_vram_mm *drm_vram_helper_alloc_mm( + struct drm_device *dev, uint64_t vram_base, size_t vram_size, + const struct drm_vram_mm_funcs *funcs); +void drm_vram_helper_release_mm(struct drm_device *dev); + +/* + * Helpers for &struct file_operations + */ + +int drm_vram_mm_file_operations_mmap( + struct file *filp, struct vm_area_struct *vma); + +/** + * define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \ + &struct file_operations + * + * Drivers that use VRAM MM can use this macro to initialize + * &struct file_operations with default functions. + */ +#define DRM_VRAM_MM_FILE_OPERATIONS \ + .llseek = no_llseek, \ + .read = drm_read, \ + .poll = drm_poll, \ + .unlocked_ioctl = drm_ioctl, \ + .compat_ioctl = drm_compat_ioctl, \ + .mmap = drm_vram_mm_file_operations_mmap, \ + .open = drm_open, \ + .release = drm_release \ + #endif -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 09/20] drm/ast: Convert AST driver to |struct drm_gem_vram_object|
The data structure |struct drm_gem_vram_object| and its helpers replace |struct ast_bo|. It's the same implementation; except for the type names. v4: * cleanups from checkpatch.pl Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/ast/Kconfig | 2 +- drivers/gpu/drm/ast/ast_drv.c | 5 +- drivers/gpu/drm/ast/ast_drv.h | 52 +--------- drivers/gpu/drm/ast/ast_fb.c | 23 +++-- drivers/gpu/drm/ast/ast_main.c | 74 ++------------ drivers/gpu/drm/ast/ast_mode.c | 78 +++++++++------ drivers/gpu/drm/ast/ast_ttm.c | 172 +-------------------------------- 7 files changed, 75 insertions(+), 331 deletions(-) diff --git a/drivers/gpu/drm/ast/Kconfig b/drivers/gpu/drm/ast/Kconfig index 9647e1f07088..f3737488630b 100644 --- a/drivers/gpu/drm/ast/Kconfig +++ b/drivers/gpu/drm/ast/Kconfig @@ -3,7 +3,7 @@ config DRM_AST depends on DRM && PCI && MMU select DRM_TTM select DRM_KMS_HELPER - select DRM_TTM + select DRM_VRAM_HELPER help Say yes for experimental AST GPU driver. Do not enable this driver without having a working -modesetting, diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 3871b39d4dea..7012b17b984f 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -228,9 +228,10 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .gem_free_object_unlocked = ast_gem_free_object, + .gem_free_object_unlocked + drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = ast_dumb_create, - .dumb_map_offset = ast_dumb_mmap_offset, + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, }; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 1cf0c75e411d..712838f725dc 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -38,6 +38,7 @@ #include <drm/ttm/ttm_module.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -321,25 +322,6 @@ void ast_fbdev_fini(struct drm_device *dev); void ast_fbdev_set_suspend(struct drm_device *dev, int state); void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr); -struct ast_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; - struct ttm_bo_kmap_obj kmap; - struct drm_gem_object gem; - struct ttm_place placements[3]; - int pin_count; -}; -#define gem_to_ast_bo(gobj) container_of((gobj), struct ast_bo, gem) - -static inline struct ast_bo * -ast_bo(struct ttm_buffer_object *bo) -{ - return container_of(bo, struct ast_bo, bo); -} - - -#define to_ast_obj(x) container_of(x, struct ast_gem_object, base) - #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) @@ -347,45 +329,13 @@ extern int ast_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -extern void ast_gem_free_object(struct drm_gem_object *obj); -extern int ast_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - uint32_t handle, - uint64_t *offset); - int ast_mm_init(struct ast_private *ast); void ast_mm_fini(struct ast_private *ast); -int ast_bo_create(struct drm_device *dev, int size, int align, - uint32_t flags, struct ast_bo **pastbo); - int ast_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj); -int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr); -int ast_bo_unpin(struct ast_bo *bo); - -static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait) -{ - int ret; - - ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL); - if (ret) { - if (ret != -ERESTARTSYS && ret != -EBUSY) - DRM_ERROR("reserve failed %p\n", bo); - return ret; - } - return 0; -} - -static inline void ast_bo_unreserve(struct ast_bo *bo) -{ - ttm_bo_unreserve(&bo->bo); -} - -void ast_ttm_placement(struct ast_bo *bo, int domain); -int ast_bo_push_sysram(struct ast_bo *bo); int ast_mmap(struct file *filp, struct vm_area_struct *vma); /* ast post */ diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index e718d0f60d6b..778423fcf352 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -49,7 +49,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, { int i; struct drm_gem_object *obj; - struct ast_bo *bo; + struct drm_gem_vram_object *gbo; int src_offset, dst_offset; int bpp = afbdev->afb.base.format->cpp[0]; int ret = -EBUSY; @@ -59,7 +59,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, unsigned long flags; obj = afbdev->afb.obj; - bo = gem_to_ast_bo(obj); + gbo = drm_gem_vram_of_gem(obj); /* * try and reserve the BO, if we fail with busy @@ -67,7 +67,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, * store up the damage until later. */ if (drm_can_sleep()) - ret = ast_bo_reserve(bo, true); + ret = drm_gem_vram_reserve(gbo, true); if (ret) { if (ret != -EBUSY) return; @@ -101,25 +101,28 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, afbdev->x2 = afbdev->y2 = 0; spin_unlock_irqrestore(&afbdev->dirty_lock, flags); - if (!bo->kmap.virtual) { - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + if (!gbo->kmap.virtual) { + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); if (ret) { DRM_ERROR("failed to kmap fb updates\n"); - ast_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); return; } unmap = true; } for (i = y; i <= y2; i++) { /* assume equal stride for now */ - src_offset = dst_offset = i * afbdev->afb.base.pitches[0] + (x * bpp); - memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp); + src_offset = dst_offset + i * afbdev->afb.base.pitches[0] + (x * bpp); + memcpy_toio(gbo->kmap.virtual + src_offset, + afbdev->sysram + dst_offset, + (x2 - x + 1) * bpp); } if (unmap) - ttm_bo_kunmap(&bo->kmap); + ttm_bo_kunmap(&gbo->kmap); - ast_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); } static void ast_fillrect(struct fb_info *info, diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 2854399856ba..61fc7b8ea470 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -593,7 +593,8 @@ int ast_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct ast_bo *astbo; + struct ast_private *ast = dev->dev_private; + struct drm_gem_vram_object *gbo; int ret; *obj = NULL; @@ -602,13 +603,14 @@ int ast_gem_create(struct drm_device *dev, if (size == 0) return -EINVAL; - ret = ast_bo_create(dev, size, 0, 0, &astbo); - if (ret) { + gbo = drm_gem_vram_create(dev, &ast->ttm.bdev, size, 0, false); + if (IS_ERR(gbo)) { + ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) DRM_ERROR("failed to allocate GEM object\n"); return ret; } - *obj = &astbo->gem; + *obj = &gbo->gem; return 0; } @@ -616,66 +618,8 @@ int ast_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - int ret; - struct drm_gem_object *gobj; - u32 handle; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - ret = ast_gem_create(dev, args->size, false, - &gobj); - if (ret) - return ret; - - ret = drm_gem_handle_create(file, gobj, &handle); - drm_gem_object_put_unlocked(gobj); - if (ret) - return ret; - - args->handle = handle; - return 0; -} - -static void ast_bo_unref(struct ast_bo **bo) -{ - if ((*bo) == NULL) - return; - ttm_bo_put(&((*bo)->bo)); - *bo = NULL; -} - -void ast_gem_free_object(struct drm_gem_object *obj) -{ - struct ast_bo *ast_bo = gem_to_ast_bo(obj); - - ast_bo_unref(&ast_bo); -} - - -static inline u64 ast_bo_mmap_offset(struct ast_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} -int -ast_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - uint32_t handle, - uint64_t *offset) -{ - struct drm_gem_object *obj; - struct ast_bo *bo; - - obj = drm_gem_object_lookup(file, handle); - if (obj == NULL) - return -ENOENT; - - bo = gem_to_ast_bo(obj); - *offset = ast_bo_mmap_offset(bo); - - drm_gem_object_put_unlocked(obj); - - return 0; + struct ast_private *ast = dev->dev_private; + return drm_gem_vram_fill_create_dumb(file, dev, &ast->ttm.bdev, 0, + false, args); } - diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 97fed0627d1c..b75ed3816642 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -529,50 +529,59 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, struct ast_private *ast = crtc->dev->dev_private; struct drm_gem_object *obj; struct ast_framebuffer *ast_fb; - struct ast_bo *bo; + struct drm_gem_vram_object *gbo; int ret; - u64 gpu_addr; + s64 gpu_addr; /* push the previous fb to system ram */ if (!atomic && fb) { ast_fb = to_ast_framebuffer(fb); obj = ast_fb->obj; - bo = gem_to_ast_bo(obj); - ret = ast_bo_reserve(bo, false); + gbo = drm_gem_vram_of_gem(obj); + ret = drm_gem_vram_reserve(gbo, false); if (ret) return ret; - ast_bo_push_sysram(bo); - ast_bo_unreserve(bo); + drm_gem_vram_push_to_system(gbo); + drm_gem_vram_unreserve(gbo); } ast_fb = to_ast_framebuffer(crtc->primary->fb); obj = ast_fb->obj; - bo = gem_to_ast_bo(obj); + gbo = drm_gem_vram_of_gem(obj); - ret = ast_bo_reserve(bo, false); + ret = drm_gem_vram_reserve(gbo, false); if (ret) return ret; - ret = ast_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - if (ret) { - ast_bo_unreserve(bo); - return ret; + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); + if (ret) + goto err_drm_gem_vram_unreserve; + gpu_addr = drm_gem_vram_offset(gbo); + if (gpu_addr < 0) { + ret = (int)gpu_addr; + goto err_drm_gem_vram_unpin; } if (&ast->fbdev->afb == ast_fb) { /* if pushing console in kmap it */ - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); if (ret) DRM_ERROR("failed to kmap fbcon\n"); else ast_fbdev_set_base(ast, gpu_addr); } - ast_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); ast_set_offset_reg(crtc); ast_set_start_address_crt1(crtc, (u32)gpu_addr); return 0; + +err_drm_gem_vram_unpin: + drm_gem_vram_unpin(gbo); +err_drm_gem_vram_unreserve: + drm_gem_vram_unreserve(gbo); + return ret; } static int ast_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, @@ -625,14 +634,13 @@ static void ast_crtc_disable(struct drm_crtc *crtc) if (crtc->primary->fb) { struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb); struct drm_gem_object *obj = ast_fb->obj; - struct ast_bo *bo = gem_to_ast_bo(obj); + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); - ret = ast_bo_reserve(bo, false); + ret = drm_gem_vram_reserve(gbo, false); if (ret) return; - - ast_bo_push_sysram(bo); - ast_bo_unreserve(bo); + drm_gem_vram_push_to_system(gbo); + drm_gem_vram_unreserve(gbo); } crtc->primary->fb = NULL; } @@ -918,26 +926,32 @@ static int ast_cursor_init(struct drm_device *dev) int size; int ret; struct drm_gem_object *obj; - struct ast_bo *bo; - uint64_t gpu_addr; + struct drm_gem_vram_object *gbo; + s64 gpu_addr; size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM; ret = ast_gem_create(dev, size, true, &obj); if (ret) return ret; - bo = gem_to_ast_bo(obj); - ret = ast_bo_reserve(bo, false); + gbo = drm_gem_vram_of_gem(obj); + ret = drm_gem_vram_reserve(gbo, false); if (unlikely(ret != 0)) goto fail; - ret = ast_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - ast_bo_unreserve(bo); + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); + drm_gem_vram_unreserve(gbo); if (ret) goto fail; + gpu_addr = drm_gem_vram_offset(gbo); + if (gpu_addr < 0) { + drm_gem_vram_unpin(gbo); + ret = (int)gpu_addr; + goto fail; + } /* kmap the object */ - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &ast->cache_kmap); + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &ast->cache_kmap); if (ret) goto fail; @@ -1173,8 +1187,8 @@ static int ast_cursor_set(struct drm_crtc *crtc, struct ast_private *ast = crtc->dev->dev_private; struct ast_crtc *ast_crtc = to_ast_crtc(crtc); struct drm_gem_object *obj; - struct ast_bo *bo; - uint64_t gpu_addr; + struct drm_gem_vram_object *gbo; + s64 gpu_addr; u32 csum; int ret; struct ttm_bo_kmap_obj uobj_map; @@ -1193,13 +1207,13 @@ static int ast_cursor_set(struct drm_crtc *crtc, DRM_ERROR("Cannot find cursor object %x for crtc\n", handle); return -ENOENT; } - bo = gem_to_ast_bo(obj); + gbo = drm_gem_vram_of_gem(obj); - ret = ast_bo_reserve(bo, false); + ret = drm_gem_vram_reserve(gbo, false); if (ret) goto fail; - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map); + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &uobj_map); src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem); dst = ttm_kmap_obj_virtual(&ast->cache_kmap, &dst_isiomem); @@ -1216,7 +1230,7 @@ static int ast_cursor_set(struct drm_crtc *crtc, /* write checksum + signature */ ttm_bo_kunmap(&uobj_map); - ast_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); { u8 *dst = (u8 *)ast->cache_kmap.virtual + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; writel(csum, dst); diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 75d477b37854..794ebb755a5d 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -36,23 +36,6 @@ ast_bdev(struct ttm_bo_device *bd) return container_of(bd, struct ast_private, ttm.bdev); } -static void ast_bo_ttm_destroy(struct ttm_buffer_object *tbo) -{ - struct ast_bo *bo; - - bo = container_of(tbo, struct ast_bo, bo); - - drm_gem_object_release(&bo->gem); - kfree(bo); -} - -static bool ast_ttm_bo_is_ast_bo(struct ttm_buffer_object *bo) -{ - if (bo->destroy == &ast_bo_ttm_destroy) - return true; - return false; -} - static int ast_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) @@ -78,26 +61,6 @@ ast_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, return 0; } -static void -ast_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) -{ - struct ast_bo *astbo = ast_bo(bo); - - if (!ast_ttm_bo_is_ast_bo(bo)) - return; - - ast_ttm_placement(astbo, TTM_PL_FLAG_SYSTEM); - *pl = astbo->placement; -} - -static int ast_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct ast_bo *astbo = ast_bo(bo); - - return drm_vma_node_verify_access(&astbo->gem.vma_node, - filp->private_data); -} - static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { @@ -162,9 +125,9 @@ struct ttm_bo_driver ast_bo_driver = { .ttm_tt_create = ast_ttm_tt_create, .init_mem_type = ast_bo_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = ast_bo_evict_flags, + .evict_flags = drm_gem_vram_bo_driver_evict_flags, .move = NULL, - .verify_access = ast_bo_verify_access, + .verify_access = drm_gem_vram_bo_driver_verify_access, .io_mem_reserve = &ast_ttm_io_mem_reserve, .io_mem_free = &ast_ttm_io_mem_free, }; @@ -210,137 +173,6 @@ void ast_mm_fini(struct ast_private *ast) pci_resource_len(dev->pdev, 0)); } -void ast_ttm_placement(struct ast_bo *bo, int domain) -{ - u32 c = 0; - unsigned i; - - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; - if (domain & TTM_PL_FLAG_VRAM) - bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; - if (domain & TTM_PL_FLAG_SYSTEM) - bo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; - if (!c) - bo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; - bo->placement.num_placement = c; - bo->placement.num_busy_placement = c; - for (i = 0; i < c; ++i) { - bo->placements[i].fpfn = 0; - bo->placements[i].lpfn = 0; - } -} - -int ast_bo_create(struct drm_device *dev, int size, int align, - uint32_t flags, struct ast_bo **pastbo) -{ - struct ast_private *ast = dev->dev_private; - struct ast_bo *astbo; - size_t acc_size; - int ret; - - astbo = kzalloc(sizeof(struct ast_bo), GFP_KERNEL); - if (!astbo) - return -ENOMEM; - - ret = drm_gem_object_init(dev, &astbo->gem, size); - if (ret) - goto error; - - astbo->bo.bdev = &ast->ttm.bdev; - - ast_ttm_placement(astbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); - - acc_size = ttm_bo_dma_acc_size(&ast->ttm.bdev, size, - sizeof(struct ast_bo)); - - ret = ttm_bo_init(&ast->ttm.bdev, &astbo->bo, size, - ttm_bo_type_device, &astbo->placement, - align >> PAGE_SHIFT, false, acc_size, - NULL, NULL, ast_bo_ttm_destroy); - if (ret) - goto error; - - *pastbo = astbo; - return 0; -error: - kfree(astbo); - return ret; -} - -static inline u64 ast_bo_gpu_offset(struct ast_bo *bo) -{ - return bo->bo.offset; -} - -int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (bo->pin_count) { - bo->pin_count++; - if (gpu_addr) - *gpu_addr = ast_bo_gpu_offset(bo); - } - - ast_ttm_placement(bo, pl_flag); - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) - return ret; - - bo->pin_count = 1; - if (gpu_addr) - *gpu_addr = ast_bo_gpu_offset(bo); - return 0; -} - -int ast_bo_unpin(struct ast_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i; - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - for (i = 0; i < bo->placement.num_placement ; i++) - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - return ttm_bo_validate(&bo->bo, &bo->placement, &ctx); -} - -int ast_bo_push_sysram(struct ast_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - if (bo->kmap.virtual) - ttm_bo_kunmap(&bo->kmap); - - ast_ttm_placement(bo, TTM_PL_FLAG_SYSTEM); - for (i = 0; i < bo->placement.num_placement ; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) { - DRM_ERROR("pushing to VRAM failed\n"); - return ret; - } - return 0; -} - int ast_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 10/20] drm/ast: Convert AST driver to VRAM MM
The data structure |struct drm_vram_mm| and its helpers replace ast's TTM-based memory manager. It's the same implementation; except for the type names. v4: * don't select DRM_TTM or DRM_VRAM_MM_HELPER v3: * use drm_gem_vram_mm_funcs * convert driver to drm_device-based instance v2: * implement ast_mmap() with drm_vram_mm_mmap() Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/ast/Kconfig | 1 - drivers/gpu/drm/ast/ast_drv.c | 14 +--- drivers/gpu/drm/ast/ast_drv.h | 18 +---- drivers/gpu/drm/ast/ast_main.c | 13 +--- drivers/gpu/drm/ast/ast_ttm.c | 134 ++------------------------------- 5 files changed, 13 insertions(+), 167 deletions(-) diff --git a/drivers/gpu/drm/ast/Kconfig b/drivers/gpu/drm/ast/Kconfig index f3737488630b..7c7e7c57911a 100644 --- a/drivers/gpu/drm/ast/Kconfig +++ b/drivers/gpu/drm/ast/Kconfig @@ -1,7 +1,6 @@ config DRM_AST tristate "AST server chips" depends on DRM && PCI && MMU - select DRM_TTM select DRM_KMS_HELPER select DRM_VRAM_HELPER help diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 7012b17b984f..3811997e78c4 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -205,13 +205,7 @@ static struct pci_driver ast_pci_driver = { static const struct file_operations ast_fops = { .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = ast_mmap, - .poll = drm_poll, - .compat_ioctl = drm_compat_ioctl, - .read = drm_read, + DRM_VRAM_MM_FILE_OPERATIONS }; static struct drm_driver driver = { @@ -228,11 +222,7 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .gem_free_object_unlocked - drm_gem_vram_driver_gem_free_object_unlocked, - .dumb_create = ast_dumb_create, - .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, - + DRM_GEM_VRAM_DRIVER }; static int __init ast_init(void) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 712838f725dc..32096a191aaf 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -31,15 +31,11 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> -#include <drm/ttm/ttm_bo_api.h> -#include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_memory.h> -#include <drm/ttm/ttm_module.h> - #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_vram_mm_helper.h> + #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -104,10 +100,6 @@ struct ast_private { int fb_mtrr; - struct { - struct ttm_bo_device bdev; - } ttm; - struct drm_gem_object *cursor_cache; uint64_t cursor_cache_gpu_addr; /* Acces to this cache is protected by the crtc->mutex of the only crtc @@ -325,10 +317,6 @@ void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr); #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) -extern int ast_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args); - int ast_mm_init(struct ast_private *ast); void ast_mm_fini(struct ast_private *ast); @@ -336,8 +324,6 @@ int ast_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj); -int ast_mmap(struct file *filp, struct vm_area_struct *vma); - /* ast post */ void ast_enable_vga(struct drm_device *dev); void ast_enable_mmio(struct drm_device *dev); diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 61fc7b8ea470..4c7e31cb45ff 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -593,7 +593,6 @@ int ast_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct ast_private *ast = dev->dev_private; struct drm_gem_vram_object *gbo; int ret; @@ -603,7 +602,7 @@ int ast_gem_create(struct drm_device *dev, if (size == 0) return -EINVAL; - gbo = drm_gem_vram_create(dev, &ast->ttm.bdev, size, 0, false); + gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) @@ -613,13 +612,3 @@ int ast_gem_create(struct drm_device *dev, *obj = &gbo->gem; return 0; } - -int ast_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct ast_private *ast = dev->dev_private; - - return drm_gem_vram_fill_create_dumb(file, dev, &ast->ttm.bdev, 0, - false, args); -} diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 794ebb755a5d..779c53efee8e 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -26,131 +26,21 @@ * Authors: Dave Airlie <airlied at redhat.com> */ #include <drm/drmP.h> -#include <drm/ttm/ttm_page_alloc.h> #include "ast_drv.h" -static inline struct ast_private * -ast_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct ast_private, ttm.bdev); -} - -static int -ast_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct ast_private *ast = ast_bdev(bdev); - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(ast->dev->pdev, 0); - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static void ast_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -{ -} - -static void ast_ttm_backend_destroy(struct ttm_tt *tt) -{ - ttm_tt_fini(tt); - kfree(tt); -} - -static struct ttm_backend_func ast_tt_backend_func = { - .destroy = &ast_ttm_backend_destroy, -}; - - -static struct ttm_tt *ast_ttm_tt_create(struct ttm_buffer_object *bo, - uint32_t page_flags) -{ - struct ttm_tt *tt; - - tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL); - if (tt == NULL) - return NULL; - tt->func = &ast_tt_backend_func; - if (ttm_tt_init(tt, bo, page_flags)) { - kfree(tt); - return NULL; - } - return tt; -} - -struct ttm_bo_driver ast_bo_driver = { - .ttm_tt_create = ast_ttm_tt_create, - .init_mem_type = ast_bo_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = drm_gem_vram_bo_driver_evict_flags, - .move = NULL, - .verify_access = drm_gem_vram_bo_driver_verify_access, - .io_mem_reserve = &ast_ttm_io_mem_reserve, - .io_mem_free = &ast_ttm_io_mem_free, -}; - int ast_mm_init(struct ast_private *ast) { + struct drm_vram_mm *vmm; int ret; struct drm_device *dev = ast->dev; - struct ttm_bo_device *bdev = &ast->ttm.bdev; - - ret = ttm_bo_device_init(&ast->ttm.bdev, - &ast_bo_driver, - dev->anon_inode->i_mapping, - true); - if (ret) { - DRM_ERROR("Error initialising bo driver; %d\n", ret); - return ret; - } - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, - ast->vram_size >> PAGE_SHIFT); - if (ret) { - DRM_ERROR("Failed ttm VRAM init: %d\n", ret); + vmm = drm_vram_helper_alloc_mm( + dev, pci_resource_start(dev->pdev, 0), + ast->vram_size, &drm_gem_vram_mm_funcs); + if (IS_ERR(vmm)) { + ret = PTR_ERR(vmm); + DRM_ERROR("Error initializing VRAM MM; %d\n", ret); return ret; } @@ -166,17 +56,9 @@ void ast_mm_fini(struct ast_private *ast) { struct drm_device *dev = ast->dev; - ttm_bo_device_release(&ast->ttm.bdev); + drm_vram_helper_release_mm(dev); arch_phys_wc_del(ast->fb_mtrr); arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), pci_resource_len(dev->pdev, 0)); } - -int ast_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct ast_private *ast = file_priv->minor->dev->dev_private; - - return ttm_bo_mmap(filp, vma, &ast->ttm.bdev); -} -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 11/20] drm/ast: Replace mapping code with drm_gem_vram_{kmap/kunmap}()
The AST driver establishes several memory mappings for frame buffers and cursors. This patch converts the driver to use the equivalent drm_gem_vram_kmap() functions. It removes the dependencies on TTM and cleans up the code. Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_fb.c | 23 +++++++++------ drivers/gpu/drm/ast/ast_mode.c | 54 ++++++++++++++++++++++++---------- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 32096a191aaf..b6cac9511796 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -256,7 +256,6 @@ struct ast_fbdev { struct ast_framebuffer afb; void *sysram; int size; - struct ttm_bo_kmap_obj mapping; int x1, y1, x2, y2; /* dirty rect */ spinlock_t dirty_lock; }; diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 778423fcf352..505e602855c0 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -53,6 +53,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, int src_offset, dst_offset; int bpp = afbdev->afb.base.format->cpp[0]; int ret = -EBUSY; + u8 *dst; bool unmap = false; bool store_for_later = false; int x2, y2; @@ -101,27 +102,31 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, afbdev->x2 = afbdev->y2 = 0; spin_unlock_irqrestore(&afbdev->dirty_lock, flags); - if (!gbo->kmap.virtual) { - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); - if (ret) { + dst = drm_gem_vram_kmap(gbo, false, NULL); + if (IS_ERR(dst)) { + DRM_ERROR("failed to kmap fb updates\n"); + goto out; + } else if (!dst) { + dst = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(dst)) { DRM_ERROR("failed to kmap fb updates\n"); - drm_gem_vram_unreserve(gbo); - return; + goto out; } unmap = true; } + for (i = y; i <= y2; i++) { /* assume equal stride for now */ src_offset = dst_offset i * afbdev->afb.base.pitches[0] + (x * bpp); - memcpy_toio(gbo->kmap.virtual + src_offset, - afbdev->sysram + dst_offset, + memcpy_toio(dst + dst_offset, afbdev->sysram + src_offset, (x2 - x + 1) * bpp); - } + if (unmap) - ttm_bo_kunmap(&gbo->kmap); + drm_gem_vram_kunmap(gbo); +out: drm_gem_vram_unreserve(gbo); } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index b75ed3816642..3475591a22c3 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -532,6 +532,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; + void *base; /* push the previous fb to system ram */ if (!atomic && fb) { @@ -564,11 +565,13 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, if (&ast->fbdev->afb == ast_fb) { /* if pushing console in kmap it */ - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); - if (ret) + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + ret = PTR_ERR(base); DRM_ERROR("failed to kmap fbcon\n"); - else + } else { ast_fbdev_set_base(ast, gpu_addr); + } } drm_gem_vram_unreserve(gbo); @@ -928,6 +931,7 @@ static int ast_cursor_init(struct drm_device *dev) struct drm_gem_object *obj; struct drm_gem_vram_object *gbo; s64 gpu_addr; + void *base; size = (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE) * AST_DEFAULT_HWC_NUM; @@ -951,9 +955,11 @@ static int ast_cursor_init(struct drm_device *dev) } /* kmap the object */ - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &ast->cache_kmap); - if (ret) + base = drm_gem_vram_kmap_at(gbo, true, NULL, &ast->cache_kmap); + if (IS_ERR(base)) { + ret = PTR_ERR(base); goto fail; + } ast->cursor_cache = obj; ast->cursor_cache_gpu_addr = gpu_addr; @@ -966,7 +972,9 @@ static int ast_cursor_init(struct drm_device *dev) static void ast_cursor_fini(struct drm_device *dev) { struct ast_private *ast = dev->dev_private; - ttm_bo_kunmap(&ast->cache_kmap); + struct drm_gem_vram_object *gbo + drm_gem_vram_of_gem(ast->cursor_cache); + drm_gem_vram_kunmap_at(gbo, &ast->cache_kmap); drm_gem_object_put_unlocked(ast->cursor_cache); } @@ -1213,13 +1221,21 @@ static int ast_cursor_set(struct drm_crtc *crtc, if (ret) goto fail; - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &uobj_map); - - src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem); - dst = ttm_kmap_obj_virtual(&ast->cache_kmap, &dst_isiomem); - + memset(&uobj_map, 0, sizeof(uobj_map)); + src = drm_gem_vram_kmap_at(gbo, true, &src_isiomem, &uobj_map); + if (IS_ERR(src)) { + ret = PTR_ERR(src); + goto fail_unreserve; + } if (src_isiomem == true) DRM_ERROR("src cursor bo should be in main memory\n"); + + dst = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache), + false, &dst_isiomem, &ast->cache_kmap); + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + goto fail_unreserve; + } if (dst_isiomem == false) DRM_ERROR("dst bo should be in VRAM\n"); @@ -1228,11 +1244,14 @@ static int ast_cursor_set(struct drm_crtc *crtc, /* do data transfer to cursor cache */ csum = copy_cursor_image(src, dst, width, height); - /* write checksum + signature */ - ttm_bo_kunmap(&uobj_map); + drm_gem_vram_kunmap_at(gbo, &uobj_map); drm_gem_vram_unreserve(gbo); + + /* write checksum + signature */ { - u8 *dst = (u8 *)ast->cache_kmap.virtual + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; + u8 *dst = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache), + false, NULL, &ast->cache_kmap); + dst += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; writel(csum, dst); writel(width, dst + AST_HWC_SIGNATURE_SizeX); writel(height, dst + AST_HWC_SIGNATURE_SizeY); @@ -1258,6 +1277,9 @@ static int ast_cursor_set(struct drm_crtc *crtc, drm_gem_object_put_unlocked(obj); return 0; + +fail_unreserve: + drm_gem_vram_unreserve(gbo); fail: drm_gem_object_put_unlocked(obj); return ret; @@ -1271,7 +1293,9 @@ static int ast_cursor_move(struct drm_crtc *crtc, int x_offset, y_offset; u8 *sig; - sig = (u8 *)ast->cache_kmap.virtual + (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; + sig = drm_gem_vram_kmap_at(drm_gem_vram_of_gem(ast->cursor_cache), + false, NULL, &ast->cache_kmap); + sig += (AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE)*ast->next_cursor + AST_HWC_SIZE; writel(x, sig + AST_HWC_SIGNATURE_X); writel(y, sig + AST_HWC_SIGNATURE_Y); -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 12/20] drm/bochs: Convert bochs driver to |struct drm_gem_vram_object|
The data structure |struct drm_gem_vram_object| and its helpers replace |struct bochs_bo|. It's the same implementation; except for the type names. v5: * use PRIME helpers from GEM VRAM v4: * cleanups from checkpatch.pl * select config option DRM_VRAM_HELPER Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/bochs/Kconfig | 1 + drivers/gpu/drm/bochs/bochs.h | 41 +---- drivers/gpu/drm/bochs/bochs_drv.c | 15 +- drivers/gpu/drm/bochs/bochs_kms.c | 18 +- drivers/gpu/drm/bochs/bochs_mm.c | 288 +----------------------------- 5 files changed, 21 insertions(+), 342 deletions(-) diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig index bd2718015cdb..4cbcff9e2eb8 100644 --- a/drivers/gpu/drm/bochs/Kconfig +++ b/drivers/gpu/drm/bochs/Kconfig @@ -3,6 +3,7 @@ config DRM_BOCHS depends on DRM && PCI && MMU select DRM_KMS_HELPER select DRM_TTM + select DRM_VRAM_HELPER help Choose this option for qemu. If M is selected the module will be called bochs-drm. diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 341cc9d1bab4..b0a4c3f90497 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -10,6 +10,7 @@ #include <drm/drm_simple_kms_helper.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_page_alloc.h> @@ -81,30 +82,6 @@ struct bochs_device { } ttm; }; -struct bochs_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; - struct ttm_bo_kmap_obj kmap; - struct drm_gem_object gem; - struct ttm_place placements[3]; - int pin_count; -}; - -static inline struct bochs_bo *bochs_bo(struct ttm_buffer_object *bo) -{ - return container_of(bo, struct bochs_bo, bo); -} - -static inline struct bochs_bo *gem_to_bochs_bo(struct drm_gem_object *gem) -{ - return container_of(gem, struct bochs_bo, gem); -} - -static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} - /* ---------------------------------------------------------------------- */ /* bochs_hw.c */ @@ -124,24 +101,8 @@ int bochs_mm_init(struct bochs_device *bochs); void bochs_mm_fini(struct bochs_device *bochs); int bochs_mmap(struct file *filp, struct vm_area_struct *vma); -int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel, - struct drm_gem_object **obj); -int bochs_gem_init_object(struct drm_gem_object *obj); -void bochs_gem_free_object(struct drm_gem_object *obj); int bochs_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset); - -int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag); -int bochs_bo_unpin(struct bochs_bo *bo); - -int bochs_gem_prime_pin(struct drm_gem_object *obj); -void bochs_gem_prime_unpin(struct drm_gem_object *obj); -void *bochs_gem_prime_vmap(struct drm_gem_object *obj); -void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); -int bochs_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma); /* bochs_kms.c */ int bochs_kms_init(struct bochs_device *bochs); diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 6b6e037258c3..1b1047ada130 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -82,17 +82,12 @@ static struct drm_driver bochs_driver = { .date = "20130925", .major = 1, .minor = 0, - .gem_free_object_unlocked = bochs_gem_free_object, + .gem_free_object_unlocked + drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = bochs_dumb_create, - .dumb_map_offset = bochs_dumb_mmap_offset, - - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_pin = bochs_gem_prime_pin, - .gem_prime_unpin = bochs_gem_prime_unpin, - .gem_prime_vmap = bochs_gem_prime_vmap, - .gem_prime_vunmap = bochs_gem_prime_vunmap, - .gem_prime_mmap = bochs_gem_prime_mmap, + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, + + DRM_GEM_VRAM_DRIVER_PRIME, }; /* ---------------------------------------------------------------------- */ diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 5e905f50449d..9e3ee7b511fb 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -30,16 +30,16 @@ static const uint32_t bochs_formats[] = { static void bochs_plane_update(struct bochs_device *bochs, struct drm_plane_state *state) { - struct bochs_bo *bo; + struct drm_gem_vram_object *gbo; if (!state->fb || !bochs->stride) return; - bo = gem_to_bochs_bo(state->fb->obj[0]); + gbo = drm_gem_vram_of_gem(state->fb->obj[0]); bochs_hw_setbase(bochs, state->crtc_x, state->crtc_y, - bo->bo.offset); + gbo->bo.offset); bochs_hw_setformat(bochs, state->fb->format); } @@ -72,23 +72,23 @@ static void bochs_pipe_update(struct drm_simple_display_pipe *pipe, static int bochs_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, struct drm_plane_state *new_state) { - struct bochs_bo *bo; + struct drm_gem_vram_object *gbo; if (!new_state->fb) return 0; - bo = gem_to_bochs_bo(new_state->fb->obj[0]); - return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); + gbo = drm_gem_vram_of_gem(new_state->fb->obj[0]); + return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); } static void bochs_pipe_cleanup_fb(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state) { - struct bochs_bo *bo; + struct drm_gem_vram_object *gbo; if (!old_state->fb) return; - bo = gem_to_bochs_bo(old_state->fb->obj[0]); - bochs_bo_unpin(bo); + gbo = drm_gem_vram_of_gem(old_state->fb->obj[0]); + drm_gem_vram_unpin(gbo); } static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = { diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 4a40308169c4..b19ff8094049 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -7,8 +7,6 @@ #include "bochs.h" -static void bochs_ttm_placement(struct bochs_bo *bo, int domain); - /* ---------------------------------------------------------------------- */ static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd) @@ -16,22 +14,6 @@ static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd) return container_of(bd, struct bochs_device, ttm.bdev); } -static void bochs_bo_ttm_destroy(struct ttm_buffer_object *tbo) -{ - struct bochs_bo *bo; - - bo = container_of(tbo, struct bochs_bo, bo); - drm_gem_object_release(&bo->gem); - kfree(bo); -} - -static bool bochs_ttm_bo_is_bochs_bo(struct ttm_buffer_object *bo) -{ - if (bo->destroy == &bochs_bo_ttm_destroy) - return true; - return false; -} - static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { @@ -56,27 +38,6 @@ static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, return 0; } -static void -bochs_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) -{ - struct bochs_bo *bochsbo = bochs_bo(bo); - - if (!bochs_ttm_bo_is_bochs_bo(bo)) - return; - - bochs_ttm_placement(bochsbo, TTM_PL_FLAG_SYSTEM); - *pl = bochsbo->placement; -} - -static int bochs_bo_verify_access(struct ttm_buffer_object *bo, - struct file *filp) -{ - struct bochs_bo *bochsbo = bochs_bo(bo); - - return drm_vma_node_verify_access(&bochsbo->gem.vma_node, - filp->private_data); -} - static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { @@ -141,9 +102,9 @@ static struct ttm_bo_driver bochs_bo_driver = { .ttm_tt_create = bochs_ttm_tt_create, .init_mem_type = bochs_bo_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = bochs_bo_evict_flags, + .evict_flags = drm_gem_vram_bo_driver_evict_flags, .move = NULL, - .verify_access = bochs_bo_verify_access, + .verify_access = drm_gem_vram_bo_driver_verify_access, .io_mem_reserve = &bochs_ttm_io_mem_reserve, .io_mem_free = &bochs_ttm_io_mem_free, }; @@ -182,85 +143,6 @@ void bochs_mm_fini(struct bochs_device *bochs) bochs->ttm.initialized = false; } -static void bochs_ttm_placement(struct bochs_bo *bo, int domain) -{ - unsigned i; - u32 c = 0; - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; - if (domain & TTM_PL_FLAG_VRAM) { - bo->placements[c++].flags = TTM_PL_FLAG_WC - | TTM_PL_FLAG_UNCACHED - | TTM_PL_FLAG_VRAM; - } - if (domain & TTM_PL_FLAG_SYSTEM) { - bo->placements[c++].flags = TTM_PL_MASK_CACHING - | TTM_PL_FLAG_SYSTEM; - } - if (!c) { - bo->placements[c++].flags = TTM_PL_MASK_CACHING - | TTM_PL_FLAG_SYSTEM; - } - for (i = 0; i < c; ++i) { - bo->placements[i].fpfn = 0; - bo->placements[i].lpfn = 0; - } - bo->placement.num_placement = c; - bo->placement.num_busy_placement = c; -} - -int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (bo->pin_count) { - bo->pin_count++; - return 0; - } - - bochs_ttm_placement(bo, pl_flag); - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); - if (ret) - return ret; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - ttm_bo_unreserve(&bo->bo); - if (ret) - return ret; - - bo->pin_count = 1; - return 0; -} - -int bochs_bo_unpin(struct bochs_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - - if (bo->pin_count) - return 0; - - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); - if (ret) - return ret; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - ttm_bo_unreserve(&bo->bo); - if (ret) - return ret; - - return 0; -} - int bochs_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; @@ -271,171 +153,11 @@ int bochs_mmap(struct file *filp, struct vm_area_struct *vma) /* ---------------------------------------------------------------------- */ -static int bochs_bo_create(struct drm_device *dev, int size, int align, - uint32_t flags, struct bochs_bo **pbochsbo) -{ - struct bochs_device *bochs = dev->dev_private; - struct bochs_bo *bochsbo; - size_t acc_size; - int ret; - - bochsbo = kzalloc(sizeof(struct bochs_bo), GFP_KERNEL); - if (!bochsbo) - return -ENOMEM; - - ret = drm_gem_object_init(dev, &bochsbo->gem, size); - if (ret) { - kfree(bochsbo); - return ret; - } - - bochsbo->bo.bdev = &bochs->ttm.bdev; - bochsbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping; - - bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); - - acc_size = ttm_bo_dma_acc_size(&bochs->ttm.bdev, size, - sizeof(struct bochs_bo)); - - ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size, - ttm_bo_type_device, &bochsbo->placement, - align >> PAGE_SHIFT, false, acc_size, - NULL, NULL, bochs_bo_ttm_destroy); - if (ret) - return ret; - - *pbochsbo = bochsbo; - return 0; -} - -int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel, - struct drm_gem_object **obj) -{ - struct bochs_bo *bochsbo; - int ret; - - *obj = NULL; - - size = PAGE_ALIGN(size); - if (size == 0) - return -EINVAL; - - ret = bochs_bo_create(dev, size, 0, 0, &bochsbo); - if (ret) { - if (ret != -ERESTARTSYS) - DRM_ERROR("failed to allocate GEM object\n"); - return ret; - } - *obj = &bochsbo->gem; - return 0; -} - int bochs_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - struct drm_gem_object *gobj; - u32 handle; - int ret; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - ret = bochs_gem_create(dev, args->size, false, - &gobj); - if (ret) - return ret; - - ret = drm_gem_handle_create(file, gobj, &handle); - drm_gem_object_put_unlocked(gobj); - if (ret) - return ret; - - args->handle = handle; - return 0; -} - -static void bochs_bo_unref(struct bochs_bo **bo) -{ - struct ttm_buffer_object *tbo; - - if ((*bo) == NULL) - return; - - tbo = &((*bo)->bo); - ttm_bo_put(tbo); - *bo = NULL; -} - -void bochs_gem_free_object(struct drm_gem_object *obj) -{ - struct bochs_bo *bochs_bo = gem_to_bochs_bo(obj); - - bochs_bo_unref(&bochs_bo); -} - -int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, - uint32_t handle, uint64_t *offset) -{ - struct drm_gem_object *obj; - struct bochs_bo *bo; - - obj = drm_gem_object_lookup(file, handle); - if (obj == NULL) - return -ENOENT; - - bo = gem_to_bochs_bo(obj); - *offset = bochs_bo_mmap_offset(bo); - - drm_gem_object_put_unlocked(obj); - return 0; -} - -/* ---------------------------------------------------------------------- */ - -int bochs_gem_prime_pin(struct drm_gem_object *obj) -{ - struct bochs_bo *bo = gem_to_bochs_bo(obj); - - return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); -} - -void bochs_gem_prime_unpin(struct drm_gem_object *obj) -{ - struct bochs_bo *bo = gem_to_bochs_bo(obj); - - bochs_bo_unpin(bo); -} - -void *bochs_gem_prime_vmap(struct drm_gem_object *obj) -{ - struct bochs_bo *bo = gem_to_bochs_bo(obj); - bool is_iomem; - int ret; - - ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM); - if (ret) - return NULL; - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); - if (ret) { - bochs_bo_unpin(bo); - return NULL; - } - return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem); -} - -void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) -{ - struct bochs_bo *bo = gem_to_bochs_bo(obj); - - ttm_bo_kunmap(&bo->kmap); - bochs_bo_unpin(bo); -} - -int bochs_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct bochs_bo *bo = gem_to_bochs_bo(obj); + struct bochs_device *bochs = dev->dev_private; - bo->gem.vma_node.vm_node.start = bo->bo.vma_node.vm_node.start; - return drm_gem_prime_mmap(obj, vma); + return drm_gem_vram_fill_create_dumb(file, dev, &bochs->ttm.bdev, 0, + false, args); } -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 13/20] drm/bochs: Convert bochs driver to VRAM MM
The data structure |struct drm_vram_mm| and its helpers replace bochs' TTM-based memory manager. It's the same implementation; except for the type names. v5: * set .llseek via DRM_VRAM_MM_FILE_OPERATIONS v4: * don't select DRM_TTM or DRM_VRAM_MM_HELPER v3: * use drm_gem_vram_mm_funcs * convert driver to drm_device-based instance v2: * implement bochs_mmap() with drm_vram_mm_mmap() Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/bochs/Kconfig | 1 - drivers/gpu/drm/bochs/bochs.h | 13 +-- drivers/gpu/drm/bochs/bochs_drv.c | 15 +-- drivers/gpu/drm/bochs/bochs_mm.c | 148 ++---------------------------- 4 files changed, 11 insertions(+), 166 deletions(-) diff --git a/drivers/gpu/drm/bochs/Kconfig b/drivers/gpu/drm/bochs/Kconfig index 4cbcff9e2eb8..e1f6ae9dd042 100644 --- a/drivers/gpu/drm/bochs/Kconfig +++ b/drivers/gpu/drm/bochs/Kconfig @@ -2,7 +2,6 @@ config DRM_BOCHS tristate "DRM Support for bochs dispi vga interface (qemu stdvga)" depends on DRM && PCI && MMU select DRM_KMS_HELPER - select DRM_TTM select DRM_VRAM_HELPER help Choose this option for qemu. diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index b0a4c3f90497..cc35d492142c 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -12,8 +12,7 @@ #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> -#include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_page_alloc.h> +#include <drm/drm_vram_mm_helper.h> /* ---------------------------------------------------------------------- */ @@ -74,12 +73,6 @@ struct bochs_device { struct drm_device *dev; struct drm_simple_display_pipe pipe; struct drm_connector connector; - - /* ttm */ - struct { - struct ttm_bo_device bdev; - bool initialized; - } ttm; }; /* ---------------------------------------------------------------------- */ @@ -99,10 +92,6 @@ int bochs_hw_load_edid(struct bochs_device *bochs); /* bochs_mm.c */ int bochs_mm_init(struct bochs_device *bochs); void bochs_mm_fini(struct bochs_device *bochs); -int bochs_mmap(struct file *filp, struct vm_area_struct *vma); - -int bochs_dumb_create(struct drm_file *file, struct drm_device *dev, - struct drm_mode_create_dumb *args); /* bochs_kms.c */ int bochs_kms_init(struct bochs_device *bochs); diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 1b1047ada130..4c425439c77d 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -63,14 +63,7 @@ static int bochs_load(struct drm_device *dev) static const struct file_operations bochs_fops = { .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .compat_ioctl = drm_compat_ioctl, - .poll = drm_poll, - .read = drm_read, - .llseek = no_llseek, - .mmap = bochs_mmap, + DRM_VRAM_MM_FILE_OPERATIONS }; static struct drm_driver bochs_driver = { @@ -82,11 +75,7 @@ static struct drm_driver bochs_driver = { .date = "20130925", .major = 1, .minor = 0, - .gem_free_object_unlocked - drm_gem_vram_driver_gem_free_object_unlocked, - .dumb_create = bochs_dumb_create, - .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, - + DRM_GEM_VRAM_DRIVER, DRM_GEM_VRAM_DRIVER_PRIME, }; diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index b19ff8094049..cfb497140f6f 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -9,155 +9,23 @@ /* ---------------------------------------------------------------------- */ -static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct bochs_device, ttm.bdev); -} - -static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct bochs_device *bochs = bochs_bdev(bdev); - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = bochs->fb_base; - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static void bochs_ttm_io_mem_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ -} - -static void bochs_ttm_backend_destroy(struct ttm_tt *tt) -{ - ttm_tt_fini(tt); - kfree(tt); -} - -static struct ttm_backend_func bochs_tt_backend_func = { - .destroy = &bochs_ttm_backend_destroy, -}; - -static struct ttm_tt *bochs_ttm_tt_create(struct ttm_buffer_object *bo, - uint32_t page_flags) -{ - struct ttm_tt *tt; - - tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL); - if (tt == NULL) - return NULL; - tt->func = &bochs_tt_backend_func; - if (ttm_tt_init(tt, bo, page_flags)) { - kfree(tt); - return NULL; - } - return tt; -} - -static struct ttm_bo_driver bochs_bo_driver = { - .ttm_tt_create = bochs_ttm_tt_create, - .init_mem_type = bochs_bo_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = drm_gem_vram_bo_driver_evict_flags, - .move = NULL, - .verify_access = drm_gem_vram_bo_driver_verify_access, - .io_mem_reserve = &bochs_ttm_io_mem_reserve, - .io_mem_free = &bochs_ttm_io_mem_free, -}; - int bochs_mm_init(struct bochs_device *bochs) { - struct ttm_bo_device *bdev = &bochs->ttm.bdev; - int ret; - - ret = ttm_bo_device_init(&bochs->ttm.bdev, - &bochs_bo_driver, - bochs->dev->anon_inode->i_mapping, - true); - if (ret) { - DRM_ERROR("Error initialising bo driver; %d\n", ret); - return ret; - } + struct drm_vram_mm *vmm; - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, - bochs->fb_size >> PAGE_SHIFT); - if (ret) { - DRM_ERROR("Failed ttm VRAM init: %d\n", ret); - return ret; - } + vmm = drm_vram_helper_alloc_mm(bochs->dev, bochs->fb_base, + bochs->fb_size, + &drm_gem_vram_mm_funcs); + if (IS_ERR(vmm)) + return PTR_ERR(vmm); - bochs->ttm.initialized = true; return 0; } void bochs_mm_fini(struct bochs_device *bochs) { - if (!bochs->ttm.initialized) + if (!bochs->dev->vram_mm) return; - ttm_bo_device_release(&bochs->ttm.bdev); - bochs->ttm.initialized = false; -} - -int bochs_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct bochs_device *bochs = file_priv->minor->dev->dev_private; - - return ttm_bo_mmap(filp, vma, &bochs->ttm.bdev); -} - -/* ---------------------------------------------------------------------- */ - -int bochs_dumb_create(struct drm_file *file, struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct bochs_device *bochs = dev->dev_private; - - return drm_gem_vram_fill_create_dumb(file, dev, &bochs->ttm.bdev, 0, - false, args); + drm_vram_helper_release_mm(bochs->dev); } -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 14/20] drm/mgag200: Convert mgag200 driver to |struct drm_gem_vram_object|
The data structure |struct drm_gem_vram_object| and its helpers replace |struct mgag200_bo|. It's the same implementation; except for the type names. v4: * cleanups from checkpatch.pl * select config option DRM_VRAM_HELPER Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/mgag200/Kconfig | 1 + drivers/gpu/drm/mgag200/mgag200_cursor.c | 63 +++++---- drivers/gpu/drm/mgag200/mgag200_drv.c | 5 +- drivers/gpu/drm/mgag200/mgag200_drv.h | 62 ++------ drivers/gpu/drm/mgag200/mgag200_fb.c | 22 +-- drivers/gpu/drm/mgag200/mgag200_main.c | 84 +++-------- drivers/gpu/drm/mgag200/mgag200_mode.c | 46 +++--- drivers/gpu/drm/mgag200/mgag200_ttm.c | 172 +---------------------- 8 files changed, 107 insertions(+), 348 deletions(-) diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index db58578719d2..907bb2162228 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -3,6 +3,7 @@ config DRM_MGAG200 depends on DRM && PCI && MMU select DRM_KMS_HELPER select DRM_TTM + select DRM_VRAM_HELPER help This is a KMS driver for the MGA G200 server chips, it does not support the original MGA G200 or any of the desktop diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index 968e20379d54..cca3922f9f67 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -23,9 +23,9 @@ static void mga_hide_cursor(struct mga_device *mdev) WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); if (mdev->cursor.pixels_1->pin_count) - mgag200_bo_unpin(mdev->cursor.pixels_1); + drm_gem_vram_unpin(mdev->cursor.pixels_1); if (mdev->cursor.pixels_2->pin_count) - mgag200_bo_unpin(mdev->cursor.pixels_2); + drm_gem_vram_unpin(mdev->cursor.pixels_2); } int mga_crtc_cursor_set(struct drm_crtc *crtc, @@ -36,12 +36,12 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct mga_device *mdev = (struct mga_device *)dev->dev_private; - struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1; - struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2; - struct mgag200_bo *pixels_current = mdev->cursor.pixels_current; - struct mgag200_bo *pixels_prev = mdev->cursor.pixels_prev; + struct drm_gem_vram_object *pixels_1 = mdev->cursor.pixels_1; + struct drm_gem_vram_object *pixels_2 = mdev->cursor.pixels_2; + struct drm_gem_vram_object *pixels_current = mdev->cursor.pixels_current; + struct drm_gem_vram_object *pixels_prev = mdev->cursor.pixels_prev; struct drm_gem_object *obj; - struct mgag200_bo *bo = NULL; + struct drm_gem_vram_object *gbo = NULL; int ret = 0; unsigned int i, row, col; uint32_t colour_set[16]; @@ -50,7 +50,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, uint32_t this_colour; bool found = false; int colour_count = 0; - u64 gpu_addr; + s64 gpu_addr; u8 reg_index; u8 this_row[48]; @@ -79,44 +79,55 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, if (!obj) return -ENOENT; - ret = mgag200_bo_reserve(pixels_1, true); + ret = drm_gem_vram_reserve(pixels_1, true); if (ret) { WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); goto out_unref; } - ret = mgag200_bo_reserve(pixels_2, true); + ret = drm_gem_vram_reserve(pixels_2, true); if (ret) { WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXH, 0); - mgag200_bo_unreserve(pixels_1); + drm_gem_vram_unreserve(pixels_1); goto out_unreserve1; } /* Move cursor buffers into VRAM if they aren't already */ if (!pixels_1->pin_count) { - ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM, - &mdev->cursor.pixels_1_gpu_addr); + ret = drm_gem_vram_pin(pixels_1, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) goto out1; + gpu_addr = drm_gem_vram_offset(pixels_1); + if (gpu_addr < 0) { + drm_gem_vram_unpin(pixels_1); + goto out1; + } + mdev->cursor.pixels_1_gpu_addr = gpu_addr; } if (!pixels_2->pin_count) { - ret = mgag200_bo_pin(pixels_2, TTM_PL_FLAG_VRAM, - &mdev->cursor.pixels_2_gpu_addr); + ret = drm_gem_vram_pin(pixels_2, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) { - mgag200_bo_unpin(pixels_1); + drm_gem_vram_unpin(pixels_1); + goto out1; + } + gpu_addr = drm_gem_vram_offset(pixels_2); + if (gpu_addr < 0) { + drm_gem_vram_unpin(pixels_1); + drm_gem_vram_unpin(pixels_2); goto out1; } + mdev->cursor.pixels_2_gpu_addr = gpu_addr; } - bo = gem_to_mga_bo(obj); - ret = mgag200_bo_reserve(bo, true); + gbo = drm_gem_vram_of_gem(obj); + ret = drm_gem_vram_reserve(gbo, true); if (ret) { dev_err(&dev->pdev->dev, "failed to reserve user bo\n"); goto out1; } - if (!bo->kmap.virtual) { - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + if (!gbo->kmap.virtual) { + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); if (ret) { dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n"); goto out2; @@ -126,7 +137,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, memset(&colour_set[0], 0, sizeof(uint32_t)*16); /* width*height*4 = 16384 */ for (i = 0; i < 16384; i += 4) { - this_colour = ioread32(bo->kmap.virtual + i); + this_colour = ioread32(gbo->kmap.virtual + i); /* No transparency */ if (this_colour>>24 != 0xff && this_colour>>24 != 0x0) { @@ -192,7 +203,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, for (row = 0; row < 64; row++) { memset(&this_row[0], 0, 48); for (col = 0; col < 64; col++) { - this_colour = ioread32(bo->kmap.virtual + 4*(col + 64*row)); + this_colour = ioread32(gbo->kmap.virtual + 4*(col + 64*row)); /* write transparent pixels */ if (this_colour>>24 == 0x0) { this_row[47 - col/8] |= 0x80>>(col%8); @@ -238,15 +249,15 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, ttm_bo_kunmap(&pixels_prev->kmap); out3: - ttm_bo_kunmap(&bo->kmap); + ttm_bo_kunmap(&gbo->kmap); out2: - mgag200_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); out1: if (ret) mga_hide_cursor(mdev); - mgag200_bo_unreserve(pixels_1); + drm_gem_vram_unreserve(pixels_1); out_unreserve1: - mgag200_bo_unreserve(pixels_2); + drm_gem_vram_unreserve(pixels_2); out_unref: drm_gem_object_put_unlocked(obj); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ac6af4bd9df6..1f2a034d5a9b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -80,9 +80,10 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .gem_free_object_unlocked = mgag200_gem_free_object, + .gem_free_object_unlocked + drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = mgag200_dumb_create, - .dumb_map_offset = mgag200_dumb_mmap_offset, + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, }; static struct pci_driver mgag200_pci_driver = { diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 8c31e4422cae..86b33e23ab7f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -1,6 +1,6 @@ /* * Copyright 2010 Matt Turner. - * Copyright 2012 Red Hat + * Copyright 2012 Red Hat * * This file is subject to the terms and conditions of the GNU General * Public License version 2. See the file COPYING in the main @@ -24,6 +24,7 @@ #include <drm/ttm/ttm_module.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -159,13 +160,13 @@ struct mga_cursor { If either of these is NULL, then don't do hardware cursors, and fall back to software. */ - struct mgag200_bo *pixels_1; - struct mgag200_bo *pixels_2; + struct drm_gem_vram_object *pixels_1; + struct drm_gem_vram_object *pixels_2; u64 pixels_1_gpu_addr, pixels_2_gpu_addr; /* The currently displayed icon, this points to one of pixels_1, or pixels_2 */ - struct mgag200_bo *pixels_current; + struct drm_gem_vram_object *pixels_current; /* The previously displayed icon */ - struct mgag200_bo *pixels_prev; + struct drm_gem_vram_object *pixels_prev; }; struct mga_mc { @@ -219,23 +220,6 @@ struct mga_device { u32 unique_rev_id; }; - -struct mgag200_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; - struct ttm_bo_kmap_obj kmap; - struct drm_gem_object gem; - struct ttm_place placements[3]; - int pin_count; -}; -#define gem_to_mga_bo(gobj) container_of((gobj), struct mgag200_bo, gem) - -static inline struct mgag200_bo * -mgag200_bo(struct ttm_buffer_object *bo) -{ - return container_of(bo, struct mgag200_bo, bo); -} - /* mgag200_mode.c */ int mgag200_modeset_init(struct mga_device *mdev); void mgag200_modeset_fini(struct mga_device *mdev); @@ -259,45 +243,15 @@ int mgag200_gem_create(struct drm_device *dev, int mgag200_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -void mgag200_gem_free_object(struct drm_gem_object *obj); -int -mgag200_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - uint32_t handle, - uint64_t *offset); + /* mgag200_i2c.c */ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev); void mgag200_i2c_destroy(struct mga_i2c_chan *i2c); -void mgag200_ttm_placement(struct mgag200_bo *bo, int domain); - -static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait) -{ - int ret; - - ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL); - if (ret) { - if (ret != -ERESTARTSYS && ret != -EBUSY) - DRM_ERROR("reserve failed %p\n", bo); - return ret; - } - return 0; -} - -static inline void mgag200_bo_unreserve(struct mgag200_bo *bo) -{ - ttm_bo_unreserve(&bo->bo); -} - -int mgag200_bo_create(struct drm_device *dev, int size, int align, - uint32_t flags, struct mgag200_bo **pastbo); int mgag200_mm_init(struct mga_device *mdev); void mgag200_mm_fini(struct mga_device *mdev); int mgag200_mmap(struct file *filp, struct vm_area_struct *vma); -int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr); -int mgag200_bo_unpin(struct mgag200_bo *bo); -int mgag200_bo_push_sysram(struct mgag200_bo *bo); - /* mgag200_cursor.c */ + int mga_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height); int mga_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 5b7e64cac004..1bcf0d65868d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -23,7 +23,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, { int i; struct drm_gem_object *obj; - struct mgag200_bo *bo; + struct drm_gem_vram_object *gbo; int src_offset, dst_offset; int bpp = mfbdev->mfb.base.format->cpp[0]; int ret = -EBUSY; @@ -33,7 +33,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, unsigned long flags; obj = mfbdev->mfb.obj; - bo = gem_to_mga_bo(obj); + gbo = drm_gem_vram_of_gem(obj); /* * try and reserve the BO, if we fail with busy @@ -41,7 +41,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, * store up the damage until later. */ if (drm_can_sleep()) - ret = mgag200_bo_reserve(bo, true); + ret = drm_gem_vram_reserve(gbo, true); if (ret) { if (ret != -EBUSY) return; @@ -75,25 +75,27 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, mfbdev->x2 = mfbdev->y2 = 0; spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); - if (!bo->kmap.virtual) { - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + if (!gbo->kmap.virtual) { + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); if (ret) { DRM_ERROR("failed to kmap fb updates\n"); - mgag200_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); return; } unmap = true; } for (i = y; i <= y2; i++) { /* assume equal stride for now */ - src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp); - memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, (x2 - x + 1) * bpp); + src_offset = dst_offset + i * mfbdev->mfb.base.pitches[0] + (x * bpp); + memcpy_toio(gbo->kmap.virtual + src_offset, + mfbdev->sysram + dst_offset, (x2 - x + 1) * bpp); } if (unmap) - ttm_bo_kunmap(&bo->kmap); + ttm_bo_kunmap(&gbo->kmap); - mgag200_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); } static void mga_fillrect(struct fb_info *info, diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index 163255099779..59a4028a5c6c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -230,11 +230,13 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) } /* Make small buffers to store a hardware cursor (double buffered icon updates) */ - mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, - &mdev->cursor.pixels_1); - mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0, - &mdev->cursor.pixels_2); - if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) { + mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &mdev->ttm.bdev, + roundup(48*64, PAGE_SIZE), + 0, 0); + mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &mdev->ttm.bdev, + roundup(48*64, PAGE_SIZE), + 0, 0); + if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) { mdev->cursor.pixels_1 = NULL; mdev->cursor.pixels_2 = NULL; dev_warn(&dev->pdev->dev, @@ -272,7 +274,8 @@ int mgag200_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct mgag200_bo *astbo; + struct mga_device *mdev = dev->dev_private; + struct drm_gem_vram_object *gbo; int ret; *obj = NULL; @@ -281,13 +284,14 @@ int mgag200_gem_create(struct drm_device *dev, if (size == 0) return -EINVAL; - ret = mgag200_bo_create(dev, size, 0, 0, &astbo); - if (ret) { + gbo = drm_gem_vram_create(dev, &mdev->ttm.bdev, size, 0, false); + if (IS_ERR(gbo)) { + ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) DRM_ERROR("failed to allocate GEM object\n"); return ret; } - *obj = &astbo->gem; + *obj = &gbo->gem; return 0; } @@ -295,64 +299,8 @@ int mgag200_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - int ret; - struct drm_gem_object *gobj; - u32 handle; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - ret = mgag200_gem_create(dev, args->size, false, - &gobj); - if (ret) - return ret; - - ret = drm_gem_handle_create(file, gobj, &handle); - drm_gem_object_put_unlocked(gobj); - if (ret) - return ret; - - args->handle = handle; - return 0; -} - -static void mgag200_bo_unref(struct mgag200_bo **bo) -{ - if ((*bo) == NULL) - return; - ttm_bo_put(&((*bo)->bo)); - *bo = NULL; -} - -void mgag200_gem_free_object(struct drm_gem_object *obj) -{ - struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj); - - mgag200_bo_unref(&mgag200_bo); -} - - -static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} - -int -mgag200_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - uint32_t handle, - uint64_t *offset) -{ - struct drm_gem_object *obj; - struct mgag200_bo *bo; - - obj = drm_gem_object_lookup(file, handle); - if (obj == NULL) - return -ENOENT; - - bo = gem_to_mga_bo(obj); - *offset = mgag200_bo_mmap_offset(bo); + struct mga_device *mdev = dev->dev_private; - drm_gem_object_put_unlocked(obj); - return 0; + return drm_gem_vram_fill_create_dumb(file, dev, &mdev->ttm.bdev, 0, + false, args); } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 7481a3d556ad..26baae5eeb9b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -867,48 +867,57 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, struct mga_device *mdev = crtc->dev->dev_private; struct drm_gem_object *obj; struct mga_framebuffer *mga_fb; - struct mgag200_bo *bo; + struct drm_gem_vram_object *gbo; int ret; - u64 gpu_addr; + s64 gpu_addr; /* push the previous fb to system ram */ if (!atomic && fb) { mga_fb = to_mga_framebuffer(fb); obj = mga_fb->obj; - bo = gem_to_mga_bo(obj); - ret = mgag200_bo_reserve(bo, false); + gbo = drm_gem_vram_of_gem(obj); + ret = drm_gem_vram_reserve(gbo, false); if (ret) return ret; - mgag200_bo_push_sysram(bo); - mgag200_bo_unreserve(bo); + drm_gem_vram_push_to_system(gbo); + drm_gem_vram_unreserve(gbo); } mga_fb = to_mga_framebuffer(crtc->primary->fb); obj = mga_fb->obj; - bo = gem_to_mga_bo(obj); + gbo = drm_gem_vram_of_gem(obj); - ret = mgag200_bo_reserve(bo, false); + ret = drm_gem_vram_reserve(gbo, false); if (ret) return ret; - ret = mgag200_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - if (ret) { - mgag200_bo_unreserve(bo); - return ret; + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); + if (ret) + goto err_drm_gem_vram_unreserve; + gpu_addr = drm_gem_vram_offset(gbo); + if (gpu_addr < 0) { + ret = (int)gpu_addr; + goto err_drm_gem_vram_unpin; } if (&mdev->mfbdev->mfb == mga_fb) { /* if pushing console in kmap it */ - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); + ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); if (ret) DRM_ERROR("failed to kmap fbcon\n"); } - mgag200_bo_unreserve(bo); + drm_gem_vram_unreserve(gbo); mga_set_start_address(crtc, (u32)gpu_addr); return 0; + +err_drm_gem_vram_unpin: + drm_gem_vram_unpin(gbo); +err_drm_gem_vram_unreserve: + drm_gem_vram_unreserve(gbo); + return ret; } static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, @@ -1428,12 +1437,13 @@ static void mga_crtc_disable(struct drm_crtc *crtc) if (crtc->primary->fb) { struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb); struct drm_gem_object *obj = mga_fb->obj; - struct mgag200_bo *bo = gem_to_mga_bo(obj); - ret = mgag200_bo_reserve(bo, false); + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); + + ret = drm_gem_vram_reserve(gbo, false); if (ret) return; - mgag200_bo_push_sysram(bo); - mgag200_bo_unreserve(bo); + drm_gem_vram_push_to_system(gbo); + drm_gem_vram_unreserve(gbo); } crtc->primary->fb = NULL; } diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index bd42365a8aa8..2c0249086bf9 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -36,23 +36,6 @@ mgag200_bdev(struct ttm_bo_device *bd) return container_of(bd, struct mga_device, ttm.bdev); } -static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo) -{ - struct mgag200_bo *bo; - - bo = container_of(tbo, struct mgag200_bo, bo); - - drm_gem_object_release(&bo->gem); - kfree(bo); -} - -static bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo) -{ - if (bo->destroy == &mgag200_bo_ttm_destroy) - return true; - return false; -} - static int mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) @@ -78,26 +61,6 @@ mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, return 0; } -static void -mgag200_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) -{ - struct mgag200_bo *mgabo = mgag200_bo(bo); - - if (!mgag200_ttm_bo_is_mgag200_bo(bo)) - return; - - mgag200_ttm_placement(mgabo, TTM_PL_FLAG_SYSTEM); - *pl = mgabo->placement; -} - -static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) -{ - struct mgag200_bo *mgabo = mgag200_bo(bo); - - return drm_vma_node_verify_access(&mgabo->gem.vma_node, - filp->private_data); -} - static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { @@ -162,9 +125,9 @@ struct ttm_bo_driver mgag200_bo_driver = { .ttm_tt_create = mgag200_ttm_tt_create, .init_mem_type = mgag200_bo_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = mgag200_bo_evict_flags, + .evict_flags = drm_gem_vram_bo_driver_evict_flags, .move = NULL, - .verify_access = mgag200_bo_verify_access, + .verify_access = drm_gem_vram_bo_driver_verify_access, .io_mem_reserve = &mgag200_ttm_io_mem_reserve, .io_mem_free = &mgag200_ttm_io_mem_free, }; @@ -211,137 +174,6 @@ void mgag200_mm_fini(struct mga_device *mdev) mdev->fb_mtrr = 0; } -void mgag200_ttm_placement(struct mgag200_bo *bo, int domain) -{ - u32 c = 0; - unsigned i; - - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; - if (domain & TTM_PL_FLAG_VRAM) - bo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; - if (domain & TTM_PL_FLAG_SYSTEM) - bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; - if (!c) - bo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; - bo->placement.num_placement = c; - bo->placement.num_busy_placement = c; - for (i = 0; i < c; ++i) { - bo->placements[i].fpfn = 0; - bo->placements[i].lpfn = 0; - } -} - -int mgag200_bo_create(struct drm_device *dev, int size, int align, - uint32_t flags, struct mgag200_bo **pmgabo) -{ - struct mga_device *mdev = dev->dev_private; - struct mgag200_bo *mgabo; - size_t acc_size; - int ret; - - mgabo = kzalloc(sizeof(struct mgag200_bo), GFP_KERNEL); - if (!mgabo) - return -ENOMEM; - - ret = drm_gem_object_init(dev, &mgabo->gem, size); - if (ret) { - kfree(mgabo); - return ret; - } - - mgabo->bo.bdev = &mdev->ttm.bdev; - - mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); - - acc_size = ttm_bo_dma_acc_size(&mdev->ttm.bdev, size, - sizeof(struct mgag200_bo)); - - ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size, - ttm_bo_type_device, &mgabo->placement, - align >> PAGE_SHIFT, false, acc_size, - NULL, NULL, mgag200_bo_ttm_destroy); - if (ret) - return ret; - - *pmgabo = mgabo; - return 0; -} - -static inline u64 mgag200_bo_gpu_offset(struct mgag200_bo *bo) -{ - return bo->bo.offset; -} - -int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (bo->pin_count) { - bo->pin_count++; - if (gpu_addr) - *gpu_addr = mgag200_bo_gpu_offset(bo); - return 0; - } - - mgag200_ttm_placement(bo, pl_flag); - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) - return ret; - - bo->pin_count = 1; - if (gpu_addr) - *gpu_addr = mgag200_bo_gpu_offset(bo); - return 0; -} - -int mgag200_bo_unpin(struct mgag200_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i; - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - for (i = 0; i < bo->placement.num_placement ; i++) - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - return ttm_bo_validate(&bo->bo, &bo->placement, &ctx); -} - -int mgag200_bo_push_sysram(struct mgag200_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - if (bo->kmap.virtual) - ttm_bo_kunmap(&bo->kmap); - - mgag200_ttm_placement(bo, TTM_PL_FLAG_SYSTEM); - for (i = 0; i < bo->placement.num_placement ; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) { - DRM_ERROR("pushing to VRAM failed\n"); - return ret; - } - return 0; -} - int mgag200_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 15/20] drm/mgag200: Convert mgag200 driver to VRAM MM
The data structure |struct drm_vram_mm| and its helpers replace mgag200's TTM-based memory manager. It's the same implementation; except for the type names. v4: * don't select DRM_TTM or DRM_VRAM_MM_HELPER v3: * use drm_gem_vram_mm_funcs * convert driver to drm_device-based instance v2: * implement mgag200_mmap() with drm_vram_mm_mmap() Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/mgag200/Kconfig | 1 - drivers/gpu/drm/mgag200/mgag200_drv.c | 14 +-- drivers/gpu/drm/mgag200/mgag200_drv.h | 11 +- drivers/gpu/drm/mgag200/mgag200_main.c | 17 +--- drivers/gpu/drm/mgag200/mgag200_ttm.c | 133 ++----------------------- 5 files changed, 15 insertions(+), 161 deletions(-) diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index 907bb2162228..738ed20163c7 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -2,7 +2,6 @@ config DRM_MGAG200 tristate "Kernel modesetting driver for MGA G200 server engines" depends on DRM && PCI && MMU select DRM_KMS_HELPER - select DRM_TTM select DRM_VRAM_HELPER help This is a KMS driver for the MGA G200 server chips, it diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 1f2a034d5a9b..93bd1589e50e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -59,13 +59,7 @@ static void mga_pci_remove(struct pci_dev *pdev) static const struct file_operations mgag200_driver_fops = { .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = mgag200_mmap, - .poll = drm_poll, - .compat_ioctl = drm_compat_ioctl, - .read = drm_read, + DRM_VRAM_MM_FILE_OPERATIONS }; static struct drm_driver driver = { @@ -79,11 +73,7 @@ static struct drm_driver driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - - .gem_free_object_unlocked - drm_gem_vram_driver_gem_free_object_unlocked, - .dumb_create = mgag200_dumb_create, - .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, + DRM_GEM_VRAM_DRIVER }; static struct pci_driver mgag200_pci_driver = { diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 86b33e23ab7f..16ce6b338dce 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -17,15 +17,12 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> -#include <drm/ttm/ttm_bo_api.h> -#include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_memory.h> -#include <drm/ttm/ttm_module.h> #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_vram_mm_helper.h> + #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -212,10 +209,6 @@ struct mga_device { int fb_mtrr; - struct { - struct ttm_bo_device bdev; - } ttm; - /* SE model number stored in reg 0x1e24 */ u32 unique_rev_id; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index 59a4028a5c6c..f3687fed4075 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -230,10 +230,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) } /* Make small buffers to store a hardware cursor (double buffered icon updates) */ - mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &mdev->ttm.bdev, + mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, roundup(48*64, PAGE_SIZE), 0, 0); - mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &mdev->ttm.bdev, + mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, roundup(48*64, PAGE_SIZE), 0, 0); if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) { @@ -274,7 +274,6 @@ int mgag200_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct mga_device *mdev = dev->dev_private; struct drm_gem_vram_object *gbo; int ret; @@ -284,7 +283,7 @@ int mgag200_gem_create(struct drm_device *dev, if (size == 0) return -EINVAL; - gbo = drm_gem_vram_create(dev, &mdev->ttm.bdev, size, 0, false); + gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) @@ -294,13 +293,3 @@ int mgag200_gem_create(struct drm_device *dev, *obj = &gbo->gem; return 0; } - -int mgag200_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct mga_device *mdev = dev->dev_private; - - return drm_gem_vram_fill_create_dumb(file, dev, &mdev->ttm.bdev, 0, - false, args); -} diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 2c0249086bf9..59294c0fd24a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -26,130 +26,21 @@ * Authors: Dave Airlie <airlied at redhat.com> */ #include <drm/drmP.h> -#include <drm/ttm/ttm_page_alloc.h> #include "mgag200_drv.h" -static inline struct mga_device * -mgag200_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct mga_device, ttm.bdev); -} - -static int -mgag200_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; -} - -static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct mga_device *mdev = mgag200_bdev(bdev); - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(mdev->dev->pdev, 0); - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static void mgag200_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) -{ -} - -static void mgag200_ttm_backend_destroy(struct ttm_tt *tt) -{ - ttm_tt_fini(tt); - kfree(tt); -} - -static struct ttm_backend_func mgag200_tt_backend_func = { - .destroy = &mgag200_ttm_backend_destroy, -}; - - -static struct ttm_tt *mgag200_ttm_tt_create(struct ttm_buffer_object *bo, - uint32_t page_flags) -{ - struct ttm_tt *tt; - - tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL); - if (tt == NULL) - return NULL; - tt->func = &mgag200_tt_backend_func; - if (ttm_tt_init(tt, bo, page_flags)) { - kfree(tt); - return NULL; - } - return tt; -} - -struct ttm_bo_driver mgag200_bo_driver = { - .ttm_tt_create = mgag200_ttm_tt_create, - .init_mem_type = mgag200_bo_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = drm_gem_vram_bo_driver_evict_flags, - .move = NULL, - .verify_access = drm_gem_vram_bo_driver_verify_access, - .io_mem_reserve = &mgag200_ttm_io_mem_reserve, - .io_mem_free = &mgag200_ttm_io_mem_free, -}; - int mgag200_mm_init(struct mga_device *mdev) { + struct drm_vram_mm *vmm; int ret; struct drm_device *dev = mdev->dev; - struct ttm_bo_device *bdev = &mdev->ttm.bdev; - - ret = ttm_bo_device_init(&mdev->ttm.bdev, - &mgag200_bo_driver, - dev->anon_inode->i_mapping, - true); - if (ret) { - DRM_ERROR("Error initialising bo driver; %d\n", ret); - return ret; - } - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, mdev->mc.vram_size >> PAGE_SHIFT); - if (ret) { - DRM_ERROR("Failed ttm VRAM init: %d\n", ret); + vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0), + mdev->mc.vram_size, + &drm_gem_vram_mm_funcs); + if (IS_ERR(vmm)) { + ret = PTR_ERR(vmm); + DRM_ERROR("Error initializing VRAM MM; %d\n", ret); return ret; } @@ -166,18 +57,10 @@ void mgag200_mm_fini(struct mga_device *mdev) { struct drm_device *dev = mdev->dev; - ttm_bo_device_release(&mdev->ttm.bdev); + drm_vram_helper_release_mm(dev); arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0), pci_resource_len(dev->pdev, 0)); arch_phys_wc_del(mdev->fb_mtrr); mdev->fb_mtrr = 0; } - -int mgag200_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct mga_device *mdev = file_priv->minor->dev->dev_private; - - return ttm_bo_mmap(filp, vma, &mdev->ttm.bdev); -} -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 16/20] drm/mgag200: Replace mapping code with drm_gem_vram_{kmap/kunmap}()
The mgag200 driver establishes several memory mappings for frame buffers and cursors. This patch converts the driver to use the equivalent drm_gem_vram_kmap() functions. It removes the dependencies on TTM and cleans up the code. v4: * cleanups from checkpatch.pl Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/mgag200/mgag200_cursor.c | 35 +++++++++++------------- drivers/gpu/drm/mgag200/mgag200_drv.h | 1 - drivers/gpu/drm/mgag200/mgag200_fb.c | 24 ++++++++++------ drivers/gpu/drm/mgag200/mgag200_mode.c | 9 ++++-- 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index cca3922f9f67..6c1a9d724d85 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -43,6 +43,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, struct drm_gem_object *obj; struct drm_gem_vram_object *gbo = NULL; int ret = 0; + u8 *src, *dst; unsigned int i, row, col; uint32_t colour_set[16]; uint32_t *next_space = &colour_set[0]; @@ -126,18 +127,17 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, dev_err(&dev->pdev->dev, "failed to reserve user bo\n"); goto out1; } - if (!gbo->kmap.virtual) { - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); - if (ret) { - dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n"); - goto out2; - } + src = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(src)) { + ret = PTR_ERR(src); + dev_err(&dev->pdev->dev, "failed to kmap user buffer updates\n"); + goto out2; } memset(&colour_set[0], 0, sizeof(uint32_t)*16); /* width*height*4 = 16384 */ for (i = 0; i < 16384; i += 4) { - this_colour = ioread32(gbo->kmap.virtual + i); + this_colour = ioread32(src + i); /* No transparency */ if (this_colour>>24 != 0xff && this_colour>>24 != 0x0) { @@ -189,21 +189,18 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, } /* Map up-coming buffer to write colour indices */ - if (!pixels_prev->kmap.virtual) { - ret = ttm_bo_kmap(&pixels_prev->bo, 0, - pixels_prev->bo.num_pages, - &pixels_prev->kmap); - if (ret) { - dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n"); - goto out3; - } + dst = drm_gem_vram_kmap(pixels_prev, true, NULL); + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + dev_err(&dev->pdev->dev, "failed to kmap cursor updates\n"); + goto out3; } /* now write colour indices into hardware cursor buffer */ for (row = 0; row < 64; row++) { memset(&this_row[0], 0, 48); for (col = 0; col < 64; col++) { - this_colour = ioread32(gbo->kmap.virtual + 4*(col + 64*row)); + this_colour = ioread32(src + 4*(col + 64*row)); /* write transparent pixels */ if (this_colour>>24 == 0x0) { this_row[47 - col/8] |= 0x80>>(col%8); @@ -221,7 +218,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, } } } - memcpy_toio(pixels_prev->kmap.virtual + row*48, &this_row[0], 48); + memcpy_toio(dst + row*48, &this_row[0], 48); } /* Program gpu address of cursor buffer */ @@ -247,9 +244,9 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, } ret = 0; - ttm_bo_kunmap(&pixels_prev->kmap); + drm_gem_vram_kunmap(pixels_prev); out3: - ttm_bo_kunmap(&gbo->kmap); + drm_gem_vram_kunmap(gbo); out2: drm_gem_vram_unreserve(gbo); out1: diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 16ce6b338dce..6180acbca7ca 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -115,7 +115,6 @@ struct mga_fbdev { struct mga_framebuffer mfb; void *sysram; int size; - struct ttm_bo_kmap_obj mapping; int x1, y1, x2, y2; /* dirty rect */ spinlock_t dirty_lock; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 1bcf0d65868d..87217bdce9f8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -27,6 +27,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, int src_offset, dst_offset; int bpp = mfbdev->mfb.base.format->cpp[0]; int ret = -EBUSY; + u8 *dst; bool unmap = false; bool store_for_later = false; int x2, y2; @@ -75,26 +76,31 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, mfbdev->x2 = mfbdev->y2 = 0; spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); - if (!gbo->kmap.virtual) { - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); - if (ret) { + dst = drm_gem_vram_kmap(gbo, false, NULL); + if (IS_ERR(dst)) { + DRM_ERROR("failed to kmap fb updates\n"); + goto out; + } else if (!dst) { + dst = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(dst)) { DRM_ERROR("failed to kmap fb updates\n"); - drm_gem_vram_unreserve(gbo); - return; + goto out; } unmap = true; } + for (i = y; i <= y2; i++) { /* assume equal stride for now */ src_offset = dst_offset i * mfbdev->mfb.base.pitches[0] + (x * bpp); - memcpy_toio(gbo->kmap.virtual + src_offset, - mfbdev->sysram + dst_offset, (x2 - x + 1) * bpp); - + memcpy_toio(dst + dst_offset, mfbdev->sysram + src_offset, + (x2 - x + 1) * bpp); } + if (unmap) - ttm_bo_kunmap(&gbo->kmap); + drm_gem_vram_kunmap(gbo); +out: drm_gem_vram_unreserve(gbo); } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 26baae5eeb9b..3098bf5c1744 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -870,6 +870,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; + void *base; /* push the previous fb to system ram */ if (!atomic && fb) { @@ -902,11 +903,13 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, if (&mdev->mfbdev->mfb == mga_fb) { /* if pushing console in kmap it */ - ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, &gbo->kmap); - if (ret) + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + ret = PTR_ERR(base); DRM_ERROR("failed to kmap fbcon\n"); - + } } + drm_gem_vram_unreserve(gbo); mga_set_start_address(crtc, (u32)gpu_addr); -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 17/20] drm/vboxvideo: Convert vboxvideo driver to |struct drm_gem_vram_object|
This patch replaces |struct vbox_bo| and its helpers with the generic implementation of |struct drm_gem_vram_object|. The only change in semantics is that &ttm_bo_driver.verify_access() now does the actual verification. v4: * select config option DRM_VRAM_HELPER v3: * remove forward declaration of struct vbox_gem_object v2: nothing Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> Reviewed-by: Hans de Goede <hdegoede at redhat.com> --- drivers/gpu/drm/vboxvideo/Kconfig | 1 + drivers/gpu/drm/vboxvideo/vbox_drv.c | 5 +- drivers/gpu/drm/vboxvideo/vbox_drv.h | 60 +------ drivers/gpu/drm/vboxvideo/vbox_fb.c | 22 +-- drivers/gpu/drm/vboxvideo/vbox_main.c | 70 +------- drivers/gpu/drm/vboxvideo/vbox_mode.c | 36 +++-- drivers/gpu/drm/vboxvideo/vbox_ttm.c | 223 +------------------------- 7 files changed, 45 insertions(+), 372 deletions(-) diff --git a/drivers/gpu/drm/vboxvideo/Kconfig b/drivers/gpu/drm/vboxvideo/Kconfig index 1f4182e2e980..f8f689c55e94 100644 --- a/drivers/gpu/drm/vboxvideo/Kconfig +++ b/drivers/gpu/drm/vboxvideo/Kconfig @@ -3,6 +3,7 @@ config DRM_VBOXVIDEO depends on DRM && X86 && PCI select DRM_KMS_HELPER select DRM_TTM + select DRM_VRAM_HELPER select GENERIC_ALLOCATOR help This is a KMS driver for the virtual Graphics Card used in diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c index fb6a0f0b8167..336a8e03e151 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c @@ -215,9 +215,10 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .gem_free_object_unlocked = vbox_gem_free_object, + .gem_free_object_unlocked + drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = vbox_dumb_create, - .dumb_map_offset = vbox_dumb_mmap_offset, + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h b/drivers/gpu/drm/vboxvideo/vbox_drv.h index ece31f395540..12e47392b2f9 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.h +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h @@ -18,6 +18,7 @@ #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> @@ -96,8 +97,6 @@ struct vbox_private { #undef CURSOR_PIXEL_COUNT #undef CURSOR_DATA_SIZE -struct vbox_gem_object; - struct vbox_connector { struct drm_connector base; char name[32]; @@ -170,73 +169,16 @@ int vboxfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); void vbox_fbdev_fini(struct vbox_private *vbox); -struct vbox_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; - struct ttm_bo_kmap_obj kmap; - struct drm_gem_object gem; - struct ttm_place placements[3]; - int pin_count; -}; - -#define gem_to_vbox_bo(gobj) container_of((gobj), struct vbox_bo, gem) - -static inline struct vbox_bo *vbox_bo(struct ttm_buffer_object *bo) -{ - return container_of(bo, struct vbox_bo, bo); -} - -#define to_vbox_obj(x) container_of(x, struct vbox_gem_object, base) - -static inline u64 vbox_bo_gpu_offset(struct vbox_bo *bo) -{ - return bo->bo.offset; -} - int vbox_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -void vbox_gem_free_object(struct drm_gem_object *obj); -int vbox_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - u32 handle, u64 *offset); - int vbox_mm_init(struct vbox_private *vbox); void vbox_mm_fini(struct vbox_private *vbox); -int vbox_bo_create(struct vbox_private *vbox, int size, int align, - u32 flags, struct vbox_bo **pvboxbo); - int vbox_gem_create(struct vbox_private *vbox, u32 size, bool iskernel, struct drm_gem_object **obj); - -int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag); -int vbox_bo_unpin(struct vbox_bo *bo); - -static inline int vbox_bo_reserve(struct vbox_bo *bo, bool no_wait) -{ - int ret; - - ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL); - if (ret) { - if (ret != -ERESTARTSYS && ret != -EBUSY) - DRM_ERROR("reserve failed %p\n", bo); - return ret; - } - return 0; -} - -static inline void vbox_bo_unreserve(struct vbox_bo *bo) -{ - ttm_bo_unreserve(&bo->bo); -} - -void vbox_ttm_placement(struct vbox_bo *bo, int domain); -int vbox_bo_push_sysram(struct vbox_bo *bo); int vbox_mmap(struct file *filp, struct vm_area_struct *vma); -void *vbox_bo_kmap(struct vbox_bo *bo); -void vbox_bo_kunmap(struct vbox_bo *bo); /* vbox_prime.c */ int vbox_gem_prime_pin(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/vboxvideo/vbox_fb.c b/drivers/gpu/drm/vboxvideo/vbox_fb.c index b724fe7c0c30..8f74bcffc034 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_fb.c +++ b/drivers/gpu/drm/vboxvideo/vbox_fb.c @@ -51,9 +51,9 @@ int vboxfb_create(struct drm_fb_helper *helper, struct drm_framebuffer *fb; struct fb_info *info; struct drm_gem_object *gobj; - struct vbox_bo *bo; + struct drm_gem_vram_object *gbo; int size, ret; - u64 gpu_addr; + s64 gpu_addr; u32 pitch; mode_cmd.width = sizes->surface_width; @@ -75,9 +75,9 @@ int vboxfb_create(struct drm_fb_helper *helper, if (ret) return ret; - bo = gem_to_vbox_bo(gobj); + gbo = drm_gem_vram_of_gem(gobj); - ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM); + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) return ret; @@ -86,7 +86,7 @@ int vboxfb_create(struct drm_fb_helper *helper, return PTR_ERR(info); info->screen_size = size; - info->screen_base = (char __iomem *)vbox_bo_kmap(bo); + info->screen_base = (char __iomem *)drm_gem_vram_kmap(gbo, true, NULL); if (IS_ERR(info->screen_base)) return PTR_ERR(info->screen_base); @@ -104,7 +104,9 @@ int vboxfb_create(struct drm_fb_helper *helper, drm_fb_helper_fill_info(info, helper, sizes); - gpu_addr = vbox_bo_gpu_offset(bo); + gpu_addr = drm_gem_vram_offset(gbo); + if (gpu_addr < 0) + return (int)gpu_addr; info->fix.smem_start = info->apertures->ranges[0].base + gpu_addr; info->fix.smem_len = vbox->available_vram_size - gpu_addr; @@ -132,12 +134,10 @@ void vbox_fbdev_fini(struct vbox_private *vbox) drm_fb_helper_unregister_fbi(&vbox->fb_helper); if (afb->obj) { - struct vbox_bo *bo = gem_to_vbox_bo(afb->obj); + struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(afb->obj); - vbox_bo_kunmap(bo); - - if (bo->pin_count) - vbox_bo_unpin(bo); + drm_gem_vram_kunmap(gbo); + drm_gem_vram_unpin(gbo); drm_gem_object_put_unlocked(afb->obj); afb->obj = NULL; diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index f4d02de5518a..525e9fd63f4d 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -274,7 +274,7 @@ void vbox_hw_fini(struct vbox_private *vbox) int vbox_gem_create(struct vbox_private *vbox, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct vbox_bo *vboxbo; + struct drm_gem_vram_object *gbo; int ret; *obj = NULL; @@ -283,14 +283,15 @@ int vbox_gem_create(struct vbox_private *vbox, if (size == 0) return -EINVAL; - ret = vbox_bo_create(vbox, size, 0, 0, &vboxbo); - if (ret) { + gbo = drm_gem_vram_create(&vbox->ddev, &vbox->ttm.bdev, size, 0, false); + if (IS_ERR(gbo)) { + ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) DRM_ERROR("failed to allocate GEM object\n"); return ret; } - *obj = &vboxbo->gem; + *obj = &gbo->gem; return 0; } @@ -298,64 +299,9 @@ int vbox_gem_create(struct vbox_private *vbox, int vbox_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args) { - struct vbox_private *vbox - container_of(dev, struct vbox_private, ddev); - struct drm_gem_object *gobj; - u32 handle; - int ret; - - args->pitch = args->width * ((args->bpp + 7) / 8); - args->size = args->pitch * args->height; - - ret = vbox_gem_create(vbox, args->size, false, &gobj); - if (ret) - return ret; - - ret = drm_gem_handle_create(file, gobj, &handle); - drm_gem_object_put_unlocked(gobj); - if (ret) - return ret; + struct vbox_private *vbox = dev->dev_private; - args->handle = handle; - - return 0; -} - -void vbox_gem_free_object(struct drm_gem_object *obj) -{ - struct vbox_bo *vbox_bo = gem_to_vbox_bo(obj); + return drm_gem_vram_fill_create_dumb(file, dev, &vbox->ttm.bdev, 0, + false, args); - ttm_bo_put(&vbox_bo->bo); -} - -static inline u64 vbox_bo_mmap_offset(struct vbox_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} - -int -vbox_dumb_mmap_offset(struct drm_file *file, - struct drm_device *dev, - u32 handle, u64 *offset) -{ - struct drm_gem_object *obj; - int ret; - struct vbox_bo *bo; - - mutex_lock(&dev->struct_mutex); - obj = drm_gem_object_lookup(file, handle); - if (!obj) { - ret = -ENOENT; - goto out_unlock; - } - - bo = gem_to_vbox_bo(obj); - *offset = vbox_bo_mmap_offset(bo); - - drm_gem_object_put(obj); - ret = 0; - -out_unlock: - mutex_unlock(&dev->struct_mutex); - return ret; } diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index 620a6e38f71f..9432c3ceec7c 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -173,7 +173,8 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y) { - struct vbox_bo *bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj); + struct drm_gem_vram_object *gbo + drm_gem_vram_of_gem(to_vbox_framebuffer(fb)->obj); struct vbox_private *vbox = crtc->dev->dev_private; struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); bool needs_modeset = drm_atomic_crtc_needs_modeset(crtc->state); @@ -187,7 +188,7 @@ static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc, vbox_crtc->x = x; vbox_crtc->y = y; - vbox_crtc->fb_offset = vbox_bo_gpu_offset(bo); + vbox_crtc->fb_offset = drm_gem_vram_offset(gbo); /* vbox_do_modeset() checks vbox->single_framebuffer so update it now */ if (needs_modeset && vbox_set_up_input_mapping(vbox)) { @@ -303,14 +304,14 @@ static void vbox_primary_atomic_disable(struct drm_plane *plane, static int vbox_primary_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { - struct vbox_bo *bo; + struct drm_gem_vram_object *gbo; int ret; if (!new_state->fb) return 0; - bo = gem_to_vbox_bo(to_vbox_framebuffer(new_state->fb)->obj); - ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM); + gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(new_state->fb)->obj); + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) DRM_WARN("Error %d pinning new fb, out of video mem?\n", ret); @@ -320,13 +321,13 @@ static int vbox_primary_prepare_fb(struct drm_plane *plane, static void vbox_primary_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct vbox_bo *bo; + struct drm_gem_vram_object *gbo; if (!old_state->fb) return; - bo = gem_to_vbox_bo(to_vbox_framebuffer(old_state->fb)->obj); - vbox_bo_unpin(bo); + gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(old_state->fb)->obj); + drm_gem_vram_unpin(gbo); } static int vbox_cursor_atomic_check(struct drm_plane *plane, @@ -386,7 +387,8 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, container_of(plane->dev, struct vbox_private, ddev); struct vbox_crtc *vbox_crtc = to_vbox_crtc(plane->state->crtc); struct drm_framebuffer *fb = plane->state->fb; - struct vbox_bo *bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj); + struct drm_gem_vram_object *gbo + drm_gem_vram_of_gem(to_vbox_framebuffer(fb)->obj); u32 width = plane->state->crtc_w; u32 height = plane->state->crtc_h; size_t data_size, mask_size; @@ -405,7 +407,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, vbox_crtc->cursor_enabled = true; /* pinning is done in prepare/cleanup framebuffer */ - src = vbox_bo_kmap(bo); + src = drm_gem_vram_kmap(gbo, true, NULL); if (IS_ERR(src)) { mutex_unlock(&vbox->hw_mutex); DRM_WARN("Could not kmap cursor bo, skipping update\n"); @@ -421,7 +423,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, data_size = width * height * 4 + mask_size; copy_cursor_image(src, vbox->cursor_data, width, height, mask_size); - vbox_bo_kunmap(bo); + drm_gem_vram_kunmap(gbo); flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE | VBOX_MOUSE_POINTER_ALPHA; @@ -461,25 +463,25 @@ static void vbox_cursor_atomic_disable(struct drm_plane *plane, static int vbox_cursor_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { - struct vbox_bo *bo; + struct drm_gem_vram_object *gbo; if (!new_state->fb) return 0; - bo = gem_to_vbox_bo(to_vbox_framebuffer(new_state->fb)->obj); - return vbox_bo_pin(bo, TTM_PL_FLAG_SYSTEM); + gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(new_state->fb)->obj); + return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM); } static void vbox_cursor_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct vbox_bo *bo; + struct drm_gem_vram_object *gbo; if (!plane->state->fb) return; - bo = gem_to_vbox_bo(to_vbox_framebuffer(plane->state->fb)->obj); - vbox_bo_unpin(bo); + gbo = drm_gem_vram_of_gem(to_vbox_framebuffer(plane->state->fb)->obj); + drm_gem_vram_unpin(gbo); } static const u32 vbox_cursor_plane_formats[] = { diff --git a/drivers/gpu/drm/vboxvideo/vbox_ttm.c b/drivers/gpu/drm/vboxvideo/vbox_ttm.c index 9d78438c2877..0989d656eed6 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_ttm.c +++ b/drivers/gpu/drm/vboxvideo/vbox_ttm.c @@ -16,24 +16,6 @@ static inline struct vbox_private *vbox_bdev(struct ttm_bo_device *bd) return container_of(bd, struct vbox_private, ttm.bdev); } -static void vbox_bo_ttm_destroy(struct ttm_buffer_object *tbo) -{ - struct vbox_bo *bo; - - bo = container_of(tbo, struct vbox_bo, bo); - - drm_gem_object_release(&bo->gem); - kfree(bo); -} - -static bool vbox_ttm_bo_is_vbox_bo(struct ttm_buffer_object *bo) -{ - if (bo->destroy == &vbox_bo_ttm_destroy) - return true; - - return false; -} - static int vbox_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, struct ttm_mem_type_manager *man) @@ -58,24 +40,6 @@ vbox_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, return 0; } -static void -vbox_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) -{ - struct vbox_bo *vboxbo = vbox_bo(bo); - - if (!vbox_ttm_bo_is_vbox_bo(bo)) - return; - - vbox_ttm_placement(vboxbo, TTM_PL_FLAG_SYSTEM); - *pl = vboxbo->placement; -} - -static int vbox_bo_verify_access(struct ttm_buffer_object *bo, - struct file *filp) -{ - return 0; -} - static int vbox_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { @@ -141,8 +105,8 @@ static struct ttm_bo_driver vbox_bo_driver = { .ttm_tt_create = vbox_ttm_tt_create, .init_mem_type = vbox_bo_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = vbox_bo_evict_flags, - .verify_access = vbox_bo_verify_access, + .evict_flags = drm_gem_vram_bo_driver_evict_flags, + .verify_access = drm_gem_vram_bo_driver_verify_access, .io_mem_reserve = &vbox_ttm_io_mem_reserve, .io_mem_free = &vbox_ttm_io_mem_free, }; @@ -196,165 +160,6 @@ void vbox_mm_fini(struct vbox_private *vbox) ttm_bo_device_release(&vbox->ttm.bdev); } -void vbox_ttm_placement(struct vbox_bo *bo, int domain) -{ - unsigned int i; - u32 c = 0; - - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; - - if (domain & TTM_PL_FLAG_VRAM) - bo->placements[c++].flags - TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; - if (domain & TTM_PL_FLAG_SYSTEM) - bo->placements[c++].flags - TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; - if (!c) - bo->placements[c++].flags - TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; - - bo->placement.num_placement = c; - bo->placement.num_busy_placement = c; - - for (i = 0; i < c; ++i) { - bo->placements[i].fpfn = 0; - bo->placements[i].lpfn = 0; - } -} - -int vbox_bo_create(struct vbox_private *vbox, int size, int align, - u32 flags, struct vbox_bo **pvboxbo) -{ - struct vbox_bo *vboxbo; - size_t acc_size; - int ret; - - vboxbo = kzalloc(sizeof(*vboxbo), GFP_KERNEL); - if (!vboxbo) - return -ENOMEM; - - ret = drm_gem_object_init(&vbox->ddev, &vboxbo->gem, size); - if (ret) - goto err_free_vboxbo; - - vboxbo->bo.bdev = &vbox->ttm.bdev; - - vbox_ttm_placement(vboxbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); - - acc_size = ttm_bo_dma_acc_size(&vbox->ttm.bdev, size, - sizeof(struct vbox_bo)); - - ret = ttm_bo_init(&vbox->ttm.bdev, &vboxbo->bo, size, - ttm_bo_type_device, &vboxbo->placement, - align >> PAGE_SHIFT, false, acc_size, - NULL, NULL, vbox_bo_ttm_destroy); - if (ret) - goto err_free_vboxbo; - - *pvboxbo = vboxbo; - - return 0; - -err_free_vboxbo: - kfree(vboxbo); - return ret; -} - -int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (bo->pin_count) { - bo->pin_count++; - return 0; - } - - ret = vbox_bo_reserve(bo, false); - if (ret) - return ret; - - vbox_ttm_placement(bo, pl_flag); - - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret == 0) - bo->pin_count = 1; - - vbox_bo_unreserve(bo); - - return ret; -} - -int vbox_bo_unpin(struct vbox_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - ret = vbox_bo_reserve(bo, false); - if (ret) { - DRM_ERROR("Error %d reserving bo, leaving it pinned\n", ret); - return ret; - } - - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - - vbox_bo_unreserve(bo); - - return ret; -} - -/* - * Move a vbox-owned buffer object to system memory if no one else has it - * pinned. The caller must have pinned it previously, and this call will - * release the caller's pin. - */ -int vbox_bo_push_sysram(struct vbox_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - if (bo->kmap.virtual) { - ttm_bo_kunmap(&bo->kmap); - bo->kmap.virtual = NULL; - } - - vbox_ttm_placement(bo, TTM_PL_FLAG_SYSTEM); - - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) { - DRM_ERROR("pushing to VRAM failed\n"); - return ret; - } - - return 0; -} - int vbox_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; @@ -362,27 +167,3 @@ int vbox_mmap(struct file *filp, struct vm_area_struct *vma) return ttm_bo_mmap(filp, vma, &vbox->ttm.bdev); } - -void *vbox_bo_kmap(struct vbox_bo *bo) -{ - int ret; - - if (bo->kmap.virtual) - return bo->kmap.virtual; - - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); - if (ret) { - DRM_ERROR("Error kmapping bo: %d\n", ret); - return NULL; - } - - return bo->kmap.virtual; -} - -void vbox_bo_kunmap(struct vbox_bo *bo) -{ - if (bo->kmap.virtual) { - ttm_bo_kunmap(&bo->kmap); - bo->kmap.virtual = NULL; - } -} -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 18/20] drm/vboxvideo: Convert vboxvideo driver to VRAM MM
The data structure |struct drm_vram_mm| and its helpers replace vboxvideo's TTM-based memory manager. It's the same implementation; except for the type names. v4: * don't select DRM_TTM or DRM_VRAM_MM_HELPER v3: * use drm_gem_vram_mm_funcs * convert driver to drm_device-based instance v2: * implement vbox_mmap() with drm_vram_mm_mmap() Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> Reviewed-by: Hans de Goede <hdegoede at redhat.com> --- drivers/gpu/drm/vboxvideo/Kconfig | 1 - drivers/gpu/drm/vboxvideo/vbox_drv.c | 13 +-- drivers/gpu/drm/vboxvideo/vbox_drv.h | 15 +-- drivers/gpu/drm/vboxvideo/vbox_main.c | 13 +-- drivers/gpu/drm/vboxvideo/vbox_ttm.c | 136 ++------------------------ 5 files changed, 13 insertions(+), 165 deletions(-) diff --git a/drivers/gpu/drm/vboxvideo/Kconfig b/drivers/gpu/drm/vboxvideo/Kconfig index f8f689c55e94..fc16a5589379 100644 --- a/drivers/gpu/drm/vboxvideo/Kconfig +++ b/drivers/gpu/drm/vboxvideo/Kconfig @@ -2,7 +2,6 @@ config DRM_VBOXVIDEO tristate "Virtual Box Graphics Card" depends on DRM && X86 && PCI select DRM_KMS_HELPER - select DRM_TTM select DRM_VRAM_HELPER select GENERIC_ALLOCATOR help diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c index 336a8e03e151..02537ab9cc08 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c @@ -191,13 +191,7 @@ static struct pci_driver vbox_pci_driver = { static const struct file_operations vbox_fops = { .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .compat_ioctl = drm_compat_ioctl, - .mmap = vbox_mmap, - .poll = drm_poll, - .read = drm_read, + DRM_VRAM_MM_FILE_OPERATIONS }; static struct drm_driver driver = { @@ -215,10 +209,7 @@ static struct drm_driver driver = { .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .gem_free_object_unlocked - drm_gem_vram_driver_gem_free_object_unlocked, - .dumb_create = vbox_dumb_create, - .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, + DRM_GEM_VRAM_DRIVER, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h b/drivers/gpu/drm/vboxvideo/vbox_drv.h index 12e47392b2f9..9028f946bc06 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.h +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h @@ -20,11 +20,7 @@ #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> -#include <drm/ttm/ttm_bo_api.h> -#include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_memory.h> -#include <drm/ttm/ttm_module.h> +#include <drm/drm_vram_mm_helper.h> #include "vboxvideo_guest.h" #include "vboxvideo_vbe.h" @@ -78,10 +74,6 @@ struct vbox_private { int fb_mtrr; - struct { - struct ttm_bo_device bdev; - } ttm; - struct mutex hw_mutex; /* protects modeset and accel/vbva accesses */ struct work_struct hotplug_work; u32 input_mapping_width; @@ -169,16 +161,11 @@ int vboxfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); void vbox_fbdev_fini(struct vbox_private *vbox); -int vbox_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args); - int vbox_mm_init(struct vbox_private *vbox); void vbox_mm_fini(struct vbox_private *vbox); int vbox_gem_create(struct vbox_private *vbox, u32 size, bool iskernel, struct drm_gem_object **obj); -int vbox_mmap(struct file *filp, struct vm_area_struct *vma); /* vbox_prime.c */ int vbox_gem_prime_pin(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index 525e9fd63f4d..18693e2bf72a 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -283,7 +283,8 @@ int vbox_gem_create(struct vbox_private *vbox, if (size == 0) return -EINVAL; - gbo = drm_gem_vram_create(&vbox->ddev, &vbox->ttm.bdev, size, 0, false); + gbo = drm_gem_vram_create(&vbox->ddev, &vbox->ddev.vram_mm->bdev, + size, 0, false); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) @@ -295,13 +296,3 @@ int vbox_gem_create(struct vbox_private *vbox, return 0; } - -int vbox_dumb_create(struct drm_file *file, - struct drm_device *dev, struct drm_mode_create_dumb *args) -{ - struct vbox_private *vbox = dev->dev_private; - - return drm_gem_vram_fill_create_dumb(file, dev, &vbox->ttm.bdev, 0, - false, args); - -} diff --git a/drivers/gpu/drm/vboxvideo/vbox_ttm.c b/drivers/gpu/drm/vboxvideo/vbox_ttm.c index 0989d656eed6..b82595a9ed0f 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_ttm.c +++ b/drivers/gpu/drm/vboxvideo/vbox_ttm.c @@ -8,131 +8,23 @@ */ #include <linux/pci.h> #include <drm/drm_file.h> -#include <drm/ttm/ttm_page_alloc.h> #include "vbox_drv.h" -static inline struct vbox_private *vbox_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct vbox_private, ttm.bdev); -} - -static int -vbox_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type); - return -EINVAL; - } - - return 0; -} - -static int vbox_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct vbox_private *vbox = vbox_bdev(bdev); - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(vbox->ddev.pdev, 0); - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - } - return 0; -} - -static void vbox_ttm_io_mem_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ -} - -static void vbox_ttm_backend_destroy(struct ttm_tt *tt) -{ - ttm_tt_fini(tt); - kfree(tt); -} - -static struct ttm_backend_func vbox_tt_backend_func = { - .destroy = &vbox_ttm_backend_destroy, -}; - -static struct ttm_tt *vbox_ttm_tt_create(struct ttm_buffer_object *bo, - u32 page_flags) -{ - struct ttm_tt *tt; - - tt = kzalloc(sizeof(*tt), GFP_KERNEL); - if (!tt) - return NULL; - - tt->func = &vbox_tt_backend_func; - if (ttm_tt_init(tt, bo, page_flags)) { - kfree(tt); - return NULL; - } - - return tt; -} - -static struct ttm_bo_driver vbox_bo_driver = { - .ttm_tt_create = vbox_ttm_tt_create, - .init_mem_type = vbox_bo_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, - .evict_flags = drm_gem_vram_bo_driver_evict_flags, - .verify_access = drm_gem_vram_bo_driver_verify_access, - .io_mem_reserve = &vbox_ttm_io_mem_reserve, - .io_mem_free = &vbox_ttm_io_mem_free, -}; - int vbox_mm_init(struct vbox_private *vbox) { + struct drm_vram_mm *vmm; int ret; struct drm_device *dev = &vbox->ddev; - struct ttm_bo_device *bdev = &vbox->ttm.bdev; - ret = ttm_bo_device_init(&vbox->ttm.bdev, - &vbox_bo_driver, - dev->anon_inode->i_mapping, - true); - if (ret) { - DRM_ERROR("Error initialising bo driver; %d\n", ret); + vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0), + vbox->available_vram_size, + &drm_gem_vram_mm_funcs); + if (IS_ERR(vmm)) { + ret = PTR_ERR(vmm); + DRM_ERROR("Error initializing VRAM MM; %d\n", ret); return ret; } - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, - vbox->available_vram_size >> PAGE_SHIFT); - if (ret) { - DRM_ERROR("Failed ttm VRAM init: %d\n", ret); - goto err_device_release; - } - #ifdef DRM_MTRR_WC vbox->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0), pci_resource_len(dev->pdev, 0), @@ -142,10 +34,6 @@ int vbox_mm_init(struct vbox_private *vbox) pci_resource_len(dev->pdev, 0)); #endif return 0; - -err_device_release: - ttm_bo_device_release(&vbox->ttm.bdev); - return ret; } void vbox_mm_fini(struct vbox_private *vbox) @@ -157,13 +45,5 @@ void vbox_mm_fini(struct vbox_private *vbox) #else arch_phys_wc_del(vbox->fb_mtrr); #endif - ttm_bo_device_release(&vbox->ttm.bdev); -} - -int vbox_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct vbox_private *vbox = file_priv->minor->dev->dev_private; - - return ttm_bo_mmap(filp, vma, &vbox->ttm.bdev); + drm_vram_helper_release_mm(&vbox->ddev); } -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 19/20] drm/hisilicon: Convert hibmc-drm driver to |struct drm_gem_vram_object|
The data structure |struct drm_gem_vram_object| and its helpers replace |struct hibmc_bo|. It's the same implementation; except for the type names. v4: * select config option DRM_VRAM_HELPER Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 + .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 21 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 5 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 25 +-- .../gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 30 +-- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 210 +----------------- 6 files changed, 44 insertions(+), 248 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig index c7129dc3bdfc..04d0bc685560 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig @@ -3,6 +3,7 @@ config DRM_HISI_HIBMC depends on DRM && PCI && MMU select DRM_KMS_HELPER select DRM_TTM + select DRM_VRAM_HELPER help Choose this option if you have a Hisilicon Hibmc soc chipset. diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 9316b724e7a2..db0dfa57844e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -96,27 +96,32 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *state = plane->state; u32 reg; int ret; - u64 gpu_addr = 0; + s64 gpu_addr = 0; unsigned int line_l; struct hibmc_drm_private *priv = plane->dev->dev_private; struct hibmc_framebuffer *hibmc_fb; - struct hibmc_bo *bo; + struct drm_gem_vram_object *gbo; if (!state->fb) return; hibmc_fb = to_hibmc_framebuffer(state->fb); - bo = gem_to_hibmc_bo(hibmc_fb->obj); - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); + gbo = drm_gem_vram_of_gem(hibmc_fb->obj); + ret = drm_gem_vram_reserve(gbo, false); if (ret) { - DRM_ERROR("failed to reserve ttm_bo: %d", ret); + DRM_ERROR("failed to reserve BO: %d", ret); return; } - ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr); - ttm_bo_unreserve(&bo->bo); + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); + drm_gem_vram_unreserve(gbo); if (ret) { - DRM_ERROR("failed to pin hibmc_bo: %d", ret); + DRM_ERROR("failed to pin bo: %d", ret); + return; + } + gpu_addr = drm_gem_vram_offset(gbo); + if (gpu_addr < 0) { + drm_gem_vram_unpin(gbo); return; } diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 8ed94fcd42a7..7027a1a05768 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -63,9 +63,10 @@ static struct drm_driver hibmc_driver = { .desc = "hibmc drm driver", .major = 1, .minor = 0, - .gem_free_object_unlocked = hibmc_gem_free_object, + .gem_free_object_unlocked + drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = hibmc_dumb_create, - .dumb_map_offset = hibmc_dumb_mmap_offset, + .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, .irq_handler = hibmc_drm_interrupt, }; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 0a381c22de26..6b3430fc5148 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -23,6 +23,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/ttm/ttm_bo_driver.h> struct hibmc_framebuffer { @@ -59,25 +60,6 @@ struct hibmc_drm_private { #define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb) -struct hibmc_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; - struct ttm_bo_kmap_obj kmap; - struct drm_gem_object gem; - struct ttm_place placements[3]; - int pin_count; -}; - -static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo) -{ - return container_of(bo, struct hibmc_bo, bo); -} - -static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem) -{ - return container_of(gem, struct hibmc_bo, gem); -} - void hibmc_set_power_mode(struct hibmc_drm_private *priv, unsigned int power_mode); void hibmc_set_current_gate(struct hibmc_drm_private *priv, @@ -97,13 +79,8 @@ hibmc_framebuffer_init(struct drm_device *dev, int hibmc_mm_init(struct hibmc_drm_private *hibmc); void hibmc_mm_fini(struct hibmc_drm_private *hibmc); -int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr); -int hibmc_bo_unpin(struct hibmc_bo *bo); -void hibmc_gem_free_object(struct drm_gem_object *obj); int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, - u32 handle, u64 *offset); int hibmc_mmap(struct file *filp, struct vm_area_struct *vma); extern const struct drm_mode_config_funcs hibmc_mode_funcs; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c index 8026859aa07d..9d2025fa16f8 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c @@ -66,7 +66,8 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, int ret1; size_t size; unsigned int bytes_per_pixel; - struct hibmc_bo *bo = NULL; + struct drm_gem_vram_object *gbo = NULL; + void *base; DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n", sizes->surface_width, sizes->surface_height, @@ -88,26 +89,27 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, return -ENOMEM; } - bo = gem_to_hibmc_bo(gobj); + gbo = drm_gem_vram_of_gem(gobj); - ret = ttm_bo_reserve(&bo->bo, true, false, NULL); + ret = drm_gem_vram_reserve(gbo, false); if (ret) { - DRM_ERROR("failed to reserve ttm_bo: %d\n", ret); + DRM_ERROR("failed to reserve bo: %d\n", ret); goto out_unref_gem; } - ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); + ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) { DRM_ERROR("failed to pin fbcon: %d\n", ret); goto out_unreserve_ttm_bo; } - ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); - if (ret) { + base = drm_gem_vram_kmap(gbo, true, NULL); + if (IS_ERR(base)) { + ret = PTR_ERR(base); DRM_ERROR("failed to kmap fbcon: %d\n", ret); goto out_unpin_bo; } - ttm_bo_unreserve(&bo->bo); + drm_gem_vram_unreserve(gbo); info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { @@ -131,24 +133,24 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, drm_fb_helper_fill_info(info, &priv->fbdev->helper, sizes); - info->screen_base = bo->kmap.virtual; + info->screen_base = base; info->screen_size = size; - info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base; + info->fix.smem_start = gbo->bo.mem.bus.offset + gbo->bo.mem.bus.base; info->fix.smem_len = size; return 0; out_release_fbi: - ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL); + ret1 = drm_gem_vram_reserve(gbo, false); if (ret1) { DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1); goto out_unref_gem; } - ttm_bo_kunmap(&bo->kmap); + drm_gem_vram_kunmap(gbo); out_unpin_bo: - hibmc_bo_unpin(bo); + drm_gem_vram_unpin(gbo); out_unreserve_ttm_bo: - ttm_bo_unreserve(&bo->bo); + drm_gem_vram_unreserve(gbo); out_unref_gem: drm_gem_object_put_unlocked(gobj); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 6093c421daff..fbf8eb048ebc 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -27,19 +27,6 @@ hibmc_bdev(struct ttm_bo_device *bd) return container_of(bd, struct hibmc_drm_private, bdev); } -static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo) -{ - struct hibmc_bo *bo = container_of(tbo, struct hibmc_bo, bo); - - drm_gem_object_release(&bo->gem); - kfree(bo); -} - -static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo) -{ - return bo->destroy == &hibmc_bo_ttm_destroy; -} - static int hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, struct ttm_mem_type_manager *man) @@ -65,52 +52,6 @@ hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, return 0; } -void hibmc_ttm_placement(struct hibmc_bo *bo, int domain) -{ - u32 count = 0; - u32 i; - - bo->placement.placement = bo->placements; - bo->placement.busy_placement = bo->placements; - if (domain & TTM_PL_FLAG_VRAM) - bo->placements[count++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; - if (domain & TTM_PL_FLAG_SYSTEM) - bo->placements[count++].flags = TTM_PL_MASK_CACHING | - TTM_PL_FLAG_SYSTEM; - if (!count) - bo->placements[count++].flags = TTM_PL_MASK_CACHING | - TTM_PL_FLAG_SYSTEM; - - bo->placement.num_placement = count; - bo->placement.num_busy_placement = count; - for (i = 0; i < count; i++) { - bo->placements[i].fpfn = 0; - bo->placements[i].lpfn = 0; - } -} - -static void -hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) -{ - struct hibmc_bo *hibmcbo = hibmc_bo(bo); - - if (!hibmc_ttm_bo_is_hibmc_bo(bo)) - return; - - hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM); - *pl = hibmcbo->placement; -} - -static int hibmc_bo_verify_access(struct ttm_buffer_object *bo, - struct file *filp) -{ - struct hibmc_bo *hibmcbo = hibmc_bo(bo); - - return drm_vma_node_verify_access(&hibmcbo->gem.vma_node, - filp->private_data); -} - static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { @@ -173,9 +114,9 @@ static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_buffer_object *bo, struct ttm_bo_driver hibmc_bo_driver = { .ttm_tt_create = hibmc_ttm_tt_create, .init_mem_type = hibmc_bo_init_mem_type, - .evict_flags = hibmc_bo_evict_flags, + .evict_flags = drm_gem_vram_bo_driver_evict_flags, .move = NULL, - .verify_access = hibmc_bo_verify_access, + .verify_access = drm_gem_vram_bo_driver_verify_access, .io_mem_reserve = &hibmc_ttm_io_mem_reserve, .io_mem_free = NULL, }; @@ -215,108 +156,6 @@ void hibmc_mm_fini(struct hibmc_drm_private *hibmc) hibmc->mm_inited = false; } -static void hibmc_bo_unref(struct hibmc_bo **bo) -{ - struct ttm_buffer_object *tbo; - - if ((*bo) == NULL) - return; - - tbo = &((*bo)->bo); - ttm_bo_put(tbo); - *bo = NULL; -} - -int hibmc_bo_create(struct drm_device *dev, int size, int align, - u32 flags, struct hibmc_bo **phibmcbo) -{ - struct hibmc_drm_private *hibmc = dev->dev_private; - struct hibmc_bo *hibmcbo; - size_t acc_size; - int ret; - - hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL); - if (!hibmcbo) { - DRM_ERROR("failed to allocate hibmcbo\n"); - return -ENOMEM; - } - ret = drm_gem_object_init(dev, &hibmcbo->gem, size); - if (ret) { - DRM_ERROR("failed to initialize drm gem object: %d\n", ret); - kfree(hibmcbo); - return ret; - } - - hibmcbo->bo.bdev = &hibmc->bdev; - - hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); - - acc_size = ttm_bo_dma_acc_size(&hibmc->bdev, size, - sizeof(struct hibmc_bo)); - - ret = ttm_bo_init(&hibmc->bdev, &hibmcbo->bo, size, - ttm_bo_type_device, &hibmcbo->placement, - align >> PAGE_SHIFT, false, acc_size, - NULL, NULL, hibmc_bo_ttm_destroy); - if (ret) { - hibmc_bo_unref(&hibmcbo); - DRM_ERROR("failed to initialize ttm_bo: %d\n", ret); - return ret; - } - - *phibmcbo = hibmcbo; - return 0; -} - -int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (bo->pin_count) { - bo->pin_count++; - if (gpu_addr) - *gpu_addr = bo->bo.offset; - return 0; - } - - hibmc_ttm_placement(bo, pl_flag); - for (i = 0; i < bo->placement.num_placement; i++) - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) - return ret; - - bo->pin_count = 1; - if (gpu_addr) - *gpu_addr = bo->bo.offset; - return 0; -} - -int hibmc_bo_unpin(struct hibmc_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - int i, ret; - - if (!bo->pin_count) { - DRM_ERROR("unpin bad %p\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; - - for (i = 0; i < bo->placement.num_placement ; i++) - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx); - if (ret) { - DRM_ERROR("validate failed for unpin: %d\n", ret); - return ret; - } - - return 0; -} - int hibmc_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; @@ -328,24 +167,24 @@ int hibmc_mmap(struct file *filp, struct vm_area_struct *vma) int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct hibmc_bo *hibmcbo; + struct hibmc_drm_private *hibmc = dev->dev_private; + struct drm_gem_vram_object *gbo; int ret; *obj = NULL; - size = PAGE_ALIGN(size); - if (size == 0) { - DRM_ERROR("error: zero size\n"); + size = roundup(size, PAGE_SIZE); + if (size == 0) return -EINVAL; - } - ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo); - if (ret) { + gbo = drm_gem_vram_create(dev, &hibmc->bdev, size, 0, false); + if (IS_ERR(gbo)) { + ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) DRM_ERROR("failed to allocate GEM object: %d\n", ret); return ret; } - *obj = &hibmcbo->gem; + *obj = &gbo->gem; return 0; } @@ -377,35 +216,6 @@ int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, return 0; } -void hibmc_gem_free_object(struct drm_gem_object *obj) -{ - struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj); - - hibmc_bo_unref(&hibmcbo); -} - -static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo) -{ - return drm_vma_node_offset_addr(&bo->bo.vma_node); -} - -int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, - u32 handle, u64 *offset) -{ - struct drm_gem_object *obj; - struct hibmc_bo *bo; - - obj = drm_gem_object_lookup(file, handle); - if (!obj) - return -ENOENT; - - bo = gem_to_hibmc_bo(obj); - *offset = hibmc_bo_mmap_offset(bo); - - drm_gem_object_put_unlocked(obj); - return 0; -} - static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb); -- 2.21.0
Thomas Zimmermann
2019-May-08 08:26 UTC
[PATCH v5 20/20] drm/hisilicon: Convert hibmc-drm driver to VRAM MM
The data structure |struct drm_vram_mm| and its helpers replace hibmc's TTM-based memory manager. It's the same implementation; except for the type names. v5: * set .llseek via DRM_VRAM_MM_FILE_OPERATIONS v4: * don't select DRM_TTM or DRM_VRAM_MM_HELPER v3: * use drm_gem_vram_mm_funcs * convert driver to drm_device-based instance v2: * implement hibmc_mmap() with drm_vram_mm_mmap() Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de> --- drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 - .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 9 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 8 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 139 ++---------------- 4 files changed, 12 insertions(+), 145 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig index 04d0bc685560..c36ec03f3d92 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig @@ -2,7 +2,6 @@ config DRM_HISI_HIBMC tristate "DRM Support for Hisilicon Hibmc" depends on DRM && PCI && MMU select DRM_KMS_HELPER - select DRM_TTM select DRM_VRAM_HELPER help diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 7027a1a05768..725c0f53ed93 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -27,14 +27,7 @@ static const struct file_operations hibmc_fops = { .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .compat_ioctl = drm_compat_ioctl, - .mmap = hibmc_mmap, - .poll = drm_poll, - .read = drm_read, - .llseek = no_llseek, + DRM_VRAM_MM_FILE_OPERATIONS }; static irqreturn_t hibmc_drm_interrupt(int irq, void *arg) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 6b3430fc5148..3967693ecbdc 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -24,7 +24,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> -#include <drm/ttm/ttm_bo_driver.h> +#include <drm/drm_vram_mm_helper.h> struct hibmc_framebuffer { struct drm_framebuffer fb; @@ -49,13 +49,8 @@ struct hibmc_drm_private { struct drm_device *dev; bool mode_config_initialized; - /* ttm */ - struct ttm_bo_device bdev; - bool initialized; - /* fbdev */ struct hibmc_fbdev *fbdev; - bool mm_inited; }; #define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb) @@ -81,7 +76,6 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc); void hibmc_mm_fini(struct hibmc_drm_private *hibmc); int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -int hibmc_mmap(struct file *filp, struct vm_area_struct *vma); extern const struct drm_mode_config_funcs hibmc_mode_funcs; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index fbf8eb048ebc..52fba8cb8ddd 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -17,157 +17,38 @@ */ #include <drm/drm_atomic_helper.h> -#include <drm/ttm/ttm_page_alloc.h> #include "hibmc_drm_drv.h" -static inline struct hibmc_drm_private * -hibmc_bdev(struct ttm_bo_device *bd) -{ - return container_of(bd, struct hibmc_drm_private, bdev); -} - -static int -hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type, - struct ttm_mem_type_manager *man) -{ - switch (type) { - case TTM_PL_SYSTEM: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("unsupported memory type %u\n", type); - return -EINVAL; - } - return 0; -} - -static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) -{ - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; - struct hibmc_drm_private *hibmc = hibmc_bdev(bdev); - - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; - switch (mem->mem_type) { - case TTM_PL_SYSTEM: - /* system memory */ - return 0; - case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0); - mem->bus.is_iomem = true; - break; - default: - return -EINVAL; - } - return 0; -} - -static void hibmc_ttm_backend_destroy(struct ttm_tt *tt) -{ - ttm_tt_fini(tt); - kfree(tt); -} - -static struct ttm_backend_func hibmc_tt_backend_func = { - .destroy = &hibmc_ttm_backend_destroy, -}; - -static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_buffer_object *bo, - u32 page_flags) -{ - struct ttm_tt *tt; - int ret; - - tt = kzalloc(sizeof(*tt), GFP_KERNEL); - if (!tt) { - DRM_ERROR("failed to allocate ttm_tt\n"); - return NULL; - } - tt->func = &hibmc_tt_backend_func; - ret = ttm_tt_init(tt, bo, page_flags); - if (ret) { - DRM_ERROR("failed to initialize ttm_tt: %d\n", ret); - kfree(tt); - return NULL; - } - return tt; -} - -struct ttm_bo_driver hibmc_bo_driver = { - .ttm_tt_create = hibmc_ttm_tt_create, - .init_mem_type = hibmc_bo_init_mem_type, - .evict_flags = drm_gem_vram_bo_driver_evict_flags, - .move = NULL, - .verify_access = drm_gem_vram_bo_driver_verify_access, - .io_mem_reserve = &hibmc_ttm_io_mem_reserve, - .io_mem_free = NULL, -}; - int hibmc_mm_init(struct hibmc_drm_private *hibmc) { + struct drm_vram_mm *vmm; int ret; struct drm_device *dev = hibmc->dev; - struct ttm_bo_device *bdev = &hibmc->bdev; - - ret = ttm_bo_device_init(&hibmc->bdev, - &hibmc_bo_driver, - dev->anon_inode->i_mapping, - true); - if (ret) { - DRM_ERROR("error initializing bo driver: %d\n", ret); - return ret; - } - ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM, - hibmc->fb_size >> PAGE_SHIFT); - if (ret) { - DRM_ERROR("failed ttm VRAM init: %d\n", ret); + vmm = drm_vram_helper_alloc_mm(dev, + pci_resource_start(dev->pdev, 0), + hibmc->fb_size, &drm_gem_vram_mm_funcs); + if (IS_ERR(vmm)) { + ret = PTR_ERR(vmm); + DRM_ERROR("Error initializing VRAM MM; %d\n", ret); return ret; } - hibmc->mm_inited = true; return 0; } void hibmc_mm_fini(struct hibmc_drm_private *hibmc) { - if (!hibmc->mm_inited) + if (!hibmc->dev->vram_mm) return; - ttm_bo_device_release(&hibmc->bdev); - hibmc->mm_inited = false; -} - -int hibmc_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *file_priv = filp->private_data; - struct hibmc_drm_private *hibmc = file_priv->minor->dev->dev_private; - - return ttm_bo_mmap(filp, vma, &hibmc->bdev); + drm_vram_helper_release_mm(hibmc->dev); } int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel, struct drm_gem_object **obj) { - struct hibmc_drm_private *hibmc = dev->dev_private; struct drm_gem_vram_object *gbo; int ret; @@ -177,7 +58,7 @@ int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel, if (size == 0) return -EINVAL; - gbo = drm_gem_vram_create(dev, &hibmc->bdev, size, 0, false); + gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false); if (IS_ERR(gbo)) { ret = PTR_ERR(gbo); if (ret != -ERESTARTSYS) -- 2.21.0
Thomas Zimmermann
2019-May-15 07:05 UTC
[PATCH v5 00/20] Share TTM code among DRM framebuffer drivers
Hi, most of this patch set still needs reviews. If it's too large for merging or reviewing at once, I could move the driver changes into separate patch sets. The vbox driver's changes have been accepted by Hans already. So only keeping the core changes plus vbox would be an option. Best regards Thomas Am 08.05.19 um 10:26 schrieb Thomas Zimmermann:> Several simple framebuffer drivers copy most of the TTM code from each > other. The implementation is always the same; except for the name of > some data structures. > > As recently discussed, this patch set provides generic memory-management > code for simple framebuffers with dedicated video memory. It further > converts the respective drivers to the generic code. The shared code > is basically the same implementation as the one copied among individual > drivers. > > The patch set contains two major changes: first, it introduces > |struct drm_gem_vram_object| and helpers (GEM VRAM). It's a GEM object > that is backed by VRAM. The type's purpose is somewhat similar to > |struct drm_gem_{cma, shmem}_object|: it provides an commom implementation > that handles all the basic cases. Second, the patch set introduces > |struct drm_vram_mm| and helpers (VRAM MM). It's an implementation of a > basic memory manager for VRAM. > > Both, GEM VRAM and VRAM MM, support buffer placement in VRAM and system > memory. Both can be used independedly from each other if desired by the > DRM driver. > > Currently ast, bochs, mgag200, vboxvideo and hisilicon/hibmc can use > these helpers. > > Future directions: with these changes, the respective drivers can also > share some of their mode-setting or fbdev code. GEM VRAM's PRIME helpers > allow for using the generic fbcon emulation. > > The patch set is against a recent drm-tip. > > v5: > * move bochs PRIME functions to GEM VRAM helpers > * always set struct file_operations.llseek to no_llseek() > * add WARN_ON_ONCE for pin-count mismatches > * only allocate 2 entries in placements array > v4: > * cleanups from checkpatch.pl > * add more documentation for VRAM helpers > * remove several fixed-size types from interfaces > * don't make drivers depend on DRM_TTM; auto-selected if necessary > * use single config optiom DRM_VRAM_HELPER > v3: > * share VRAM MM callback structure among drivers > * move VRAM MM instances to drm_device and share rsp. code > v2: > * rename |struct drm_gem_ttm_object| to |struct drm_gem_vram_object| > * rename |struct drm_simple_ttm| to |struct drm_vram_mm| > * make drm_is_gem_ttm() an internal helper > * add drm_gem_vram_kmap_at() > * return is_iomem from kmap functions > * redefine TTM placement flags for public interface > * add drm_vram_mm_mmap() helper > * replace almost all of driver's TTM code with these helpers > * documentation fixes > > Thomas Zimmermann (20): > drm: Add |struct drm_gem_vram_object| and helpers > drm: Add |struct drm_gem_vram_object| callbacks for |struct > ttm_bo_driver| > drm: Add |struct drm_gem_vram_object| callbacks for |struct > drm_driver| > drm: Add drm_gem_vram_fill_create_dumb() to create dumb buffers > drm: Add simple PRIME helpers for GEM VRAM > drm: Add VRAM MM, a simple memory manager for dedicated VRAM > drm: Add default instance for VRAM MM callback functions > drm: Integrate VRAM MM into struct drm_device > drm/ast: Convert AST driver to |struct drm_gem_vram_object| > drm/ast: Convert AST driver to VRAM MM > drm/ast: Replace mapping code with drm_gem_vram_{kmap/kunmap}() > drm/bochs: Convert bochs driver to |struct drm_gem_vram_object| > drm/bochs: Convert bochs driver to VRAM MM > drm/mgag200: Convert mgag200 driver to |struct drm_gem_vram_object| > drm/mgag200: Convert mgag200 driver to VRAM MM > drm/mgag200: Replace mapping code with drm_gem_vram_{kmap/kunmap}() > drm/vboxvideo: Convert vboxvideo driver to |struct > drm_gem_vram_object| > drm/vboxvideo: Convert vboxvideo driver to VRAM MM > drm/hisilicon: Convert hibmc-drm driver to |struct > drm_gem_vram_object| > drm/hisilicon: Convert hibmc-drm driver to VRAM MM > > Documentation/gpu/drm-mm.rst | 34 +- > drivers/gpu/drm/Kconfig | 7 + > drivers/gpu/drm/Makefile | 5 + > drivers/gpu/drm/ast/Kconfig | 3 +- > drivers/gpu/drm/ast/ast_drv.c | 13 +- > drivers/gpu/drm/ast/ast_drv.h | 71 +- > drivers/gpu/drm/ast/ast_fb.c | 34 +- > drivers/gpu/drm/ast/ast_main.c | 77 +- > drivers/gpu/drm/ast/ast_mode.c | 124 +-- > drivers/gpu/drm/ast/ast_ttm.c | 302 +------- > drivers/gpu/drm/bochs/Kconfig | 2 +- > drivers/gpu/drm/bochs/bochs.h | 54 +- > drivers/gpu/drm/bochs/bochs_drv.c | 22 +- > drivers/gpu/drm/bochs/bochs_kms.c | 18 +- > drivers/gpu/drm/bochs/bochs_mm.c | 426 +---------- > drivers/gpu/drm/drm_gem_vram_helper.c | 713 ++++++++++++++++++ > drivers/gpu/drm/drm_vram_helper_common.c | 98 +++ > drivers/gpu/drm/drm_vram_mm_helper.c | 295 ++++++++ > drivers/gpu/drm/hisilicon/hibmc/Kconfig | 2 +- > .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 21 +- > .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 14 +- > .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 33 +- > .../gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 30 +- > drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 341 +-------- > drivers/gpu/drm/mgag200/Kconfig | 2 +- > drivers/gpu/drm/mgag200/mgag200_cursor.c | 88 ++- > drivers/gpu/drm/mgag200/mgag200_drv.c | 13 +- > drivers/gpu/drm/mgag200/mgag200_drv.h | 74 +- > drivers/gpu/drm/mgag200/mgag200_fb.c | 34 +- > drivers/gpu/drm/mgag200/mgag200_main.c | 87 +-- > drivers/gpu/drm/mgag200/mgag200_mode.c | 53 +- > drivers/gpu/drm/mgag200/mgag200_ttm.c | 301 +------- > drivers/gpu/drm/vboxvideo/Kconfig | 2 +- > drivers/gpu/drm/vboxvideo/vbox_drv.c | 12 +- > drivers/gpu/drm/vboxvideo/vbox_drv.h | 75 +- > drivers/gpu/drm/vboxvideo/vbox_fb.c | 22 +- > drivers/gpu/drm/vboxvideo/vbox_main.c | 75 +- > drivers/gpu/drm/vboxvideo/vbox_mode.c | 36 +- > drivers/gpu/drm/vboxvideo/vbox_ttm.c | 355 +-------- > include/drm/drm_device.h | 4 + > include/drm/drm_gem_vram_helper.h | 160 ++++ > include/drm/drm_vram_mm_helper.h | 102 +++ > 42 files changed, 1797 insertions(+), 2437 deletions(-) > create mode 100644 drivers/gpu/drm/drm_gem_vram_helper.c > create mode 100644 drivers/gpu/drm/drm_vram_helper_common.c > create mode 100644 drivers/gpu/drm/drm_vram_mm_helper.c > create mode 100644 include/drm/drm_gem_vram_helper.h > create mode 100644 include/drm/drm_vram_mm_helper.h > > -- > 2.21.0 >-- Thomas Zimmermann Graphics Driver Developer SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany GF: Felix Imend?rffer, Mary Higgins, Sri Rasiah HRB 21284 (AG N?rnberg) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20190515/d0e924b3/attachment-0001.sig>
Gerd Hoffmann
2019-May-15 14:22 UTC
[PATCH v5 00/20] Share TTM code among DRM framebuffer drivers
On Wed, May 15, 2019 at 09:05:54AM +0200, Thomas Zimmermann wrote:> Hi, > > most of this patch set still needs reviews. > > If it's too large for merging or reviewing at once, I could move the > driver changes into separate patch sets. The vbox driver's changes have > been accepted by Hans already. So only keeping the core changes plus > vbox would be an option.Looks all good to me. bochs survived my testing, vbox is reviewed and IIRC you've tested two of the other three drivers. So all but one driver is covered. I'll go push this to drm-misc-next in a moment.> > Future directions: with these changes, the respective drivers can also > > share some of their mode-setting or fbdev code. GEM VRAM's PRIME helpers > > allow for using the generic fbcon emulation.Using generic fbcon should be easy now. cheers, Gerd
Reasonably Related Threads
- [PATCH v2 00/17] Share TTM code among DRM framebuffer drivers
- [PATCH v3 00/19] Share TTM code among DRM framebuffer drivers
- [PATCH v5 00/20] Share TTM code among DRM framebuffer drivers
- [PATCH v4 00/19] Share TTM code among DRM framebuffer drivers
- [PATCH v4 00/19] Share TTM code among DRM framebuffer drivers