drm/vram-helper: Managed vram helpers
[linux-2.6-microblaze.git] / drivers / gpu / drm / drm_gem_vram_helper.c
index 8b2d5c9..c96d54f 100644 (file)
@@ -10,6 +10,7 @@
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_ttm_helper.h>
 #include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_plane.h>
 #include <drm/drm_prime.h>
@@ -40,12 +41,11 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
  * 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.
+ * To initialize the VRAM helper library call drmm_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
  *
@@ -69,7 +69,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
  *             // setup device, vram base and size
  *             // ...
  *
- *             ret = drm_vram_helper_alloc_mm(dev, vram_base, vram_size);
+ *             ret = drmm_vram_helper_alloc_mm(dev, vram_base, vram_size);
  *             if (ret)
  *                     return ret;
  *             return 0;
@@ -81,20 +81,12 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
  * 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.
+ * You don't have to clean up the instance of VRAM MM.
+ * drmm_vram_helper_alloc_mm() is a managed interface that installs a
+ * clean-up handler to run during the DRM device's release.
  *
- * .. 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
+ * For drawing or scanout operations, rsp. buffer objects have to be pinned
+ * in video RAM. Call drm_gem_vram_pin() with &DRM_GEM_VRAM_PL_FLAG_VRAM or
  * &DRM_GEM_VRAM_PL_FLAG_SYSTEM to pin a buffer object in video RAM or system
  * memory. Call drm_gem_vram_unpin() to release the pinned object afterwards.
  *
@@ -281,6 +273,15 @@ u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo)
 }
 EXPORT_SYMBOL(drm_gem_vram_mmap_offset);
 
+static u64 drm_gem_vram_pg_offset(struct drm_gem_vram_object *gbo)
+{
+       /* Keep TTM behavior for now, remove when drivers are audited */
+       if (WARN_ON_ONCE(!gbo->bo.mem.mm_node))
+               return 0;
+
+       return gbo->bo.mem.start;
+}
+
 /**
  * drm_gem_vram_offset() - \
        Returns a GEM VRAM object's offset in video memory
@@ -297,7 +298,7 @@ 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;
+       return drm_gem_vram_pg_offset(gbo) << PAGE_SHIFT;
 }
 EXPORT_SYMBOL(drm_gem_vram_offset);
 
@@ -618,9 +619,9 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
 
        ret = drm_gem_handle_create(file, &gbo->bo.base, &handle);
        if (ret)
-               goto err_drm_gem_object_put_unlocked;
+               goto err_drm_gem_object_put;
 
-       drm_gem_object_put_unlocked(&gbo->bo.base);
+       drm_gem_object_put(&gbo->bo.base);
 
        args->pitch = pitch;
        args->size = size;
@@ -628,8 +629,8 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
 
        return 0;
 
-err_drm_gem_object_put_unlocked:
-       drm_gem_object_put_unlocked(&gbo->bo.base);
+err_drm_gem_object_put:
+       drm_gem_object_put(&gbo->bo.base);
        return ret;
 }
 EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
@@ -737,7 +738,7 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
        gbo = drm_gem_vram_of_gem(gem);
        *offset = drm_gem_vram_mmap_offset(gbo);
 
-       drm_gem_object_put_unlocked(gem);
+       drm_gem_object_put(gem);
 
        return 0;
 }
@@ -1167,17 +1168,7 @@ static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
  * 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
- *
- * Returns:
- * The new instance of &struct drm_vram_mm on success, or
- * an ERR_PTR()-encoded errno code otherwise.
- */
+/* deprecated; use drmm_vram_mm_init() */
 struct drm_vram_mm *drm_vram_helper_alloc_mm(
        struct drm_device *dev, uint64_t vram_base, size_t vram_size)
 {
@@ -1203,11 +1194,6 @@ err_kfree:
 }
 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)
@@ -1219,6 +1205,41 @@ void drm_vram_helper_release_mm(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_vram_helper_release_mm);
 
+static void drm_vram_mm_release(struct drm_device *dev, void *ptr)
+{
+       drm_vram_helper_release_mm(dev);
+}
+
+/**
+ * drmm_vram_helper_init - Initializes 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
+ *
+ * Creates a new instance of &struct drm_vram_mm and stores it in
+ * struct &drm_device.vram_mm. The instance is auto-managed and cleaned
+ * up as part of device cleanup. Calling this function multiple times
+ * will generate an error message.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise.
+ */
+int drmm_vram_helper_init(struct drm_device *dev, uint64_t vram_base,
+                         size_t vram_size)
+{
+       struct drm_vram_mm *vram_mm;
+
+       if (drm_WARN_ON_ONCE(dev, dev->vram_mm))
+               return 0;
+
+       vram_mm = drm_vram_helper_alloc_mm(dev, vram_base, vram_size);
+       if (IS_ERR(vram_mm))
+               return PTR_ERR(vram_mm);
+       return drmm_add_action_or_reset(dev, drm_vram_mm_release, NULL);
+}
+EXPORT_SYMBOL(drmm_vram_helper_init);
+
 /*
  * Mode-config helpers
  */