drm: Integrate VRAM MM into struct drm_device
authorThomas Zimmermann <tzimmermann@suse.de>
Wed, 8 May 2019 08:26:18 +0000 (10:26 +0200)
committerGerd Hoffmann <kraxel@redhat.com>
Wed, 15 May 2019 14:17:06 +0000 (16:17 +0200)
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@suse.de>
Link: http://patchwork.freedesktop.org/patch/msgid/20190508082630.15116-9-tzimmermann@suse.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Documentation/gpu/drm-mm.rst
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_vram_helper_common.c
drivers/gpu/drm/drm_vram_mm_helper.c
include/drm/drm_device.h
include/drm/drm_gem_vram_helper.h
include/drm/drm_vram_mm_helper.h

index eba50afbda424a1f240c9b9bff33ecdb4688c7c3..c8ebd4f66a6a6369ecffd937762adb158f42af8b 100644 (file)
@@ -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
 -----------------------------------
 
index c21b1f920e0af2626564b48b36ee01016dd5a598..8f142b810eb4d7a4e749462b4702782f851cc408 100644 (file)
@@ -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
index 7c25daca18d074ef80db82de8a87da788031ba76..3b47f7002115b7eb44c18906ffc4144a20384af9 100644 (file)
@@ -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");
index d17c5169b018ae9a14aed68b01cfedab39e89d94..c94a6dc5ade784e51c91226e141b6e9f68d2818c 100644 (file)
@@ -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);
index 7f9ef709b2b619360caac5dd08f321dd316ee382..1acfc3bbd3fb2e29c3fe3f2139076b09152708ff 100644 (file)
@@ -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:
         *
index 7971656afe8766d977a88aba5d4ecb9a8cddb601..b056f189ba620cc38ab7edac8b50aada5c1f8e4a 100644 (file)
@@ -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
  */
index 5d45c6447fa4ec13557bee68c34a7f491898fb87..a8ffd8599b08579fbf485082d7b2cbd544daa61e 100644 (file)
@@ -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