VIGS: Dirty flag support in vigs_surface
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 6 May 2013 14:48:07 +0000 (18:48 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 9 Apr 2014 05:42:21 +0000 (14:42 +0900)
Dirty flag in vigs_surface is need in order to tell the kernel
that we want contents of VRAM to be uploaded into GPU when the surface
is evicted from VRAM. The flag is automatically cleared whenever
update_gpu command is found in execbuffer

Change-Id: I78e20f541d56ba958c5ac15d00b2ed7a2c841f2d

drivers/gpu/drm/vigs/vigs_comm.c
drivers/gpu/drm/vigs/vigs_comm.h
drivers/gpu/drm/vigs/vigs_device.c
drivers/gpu/drm/vigs/vigs_driver.c
drivers/gpu/drm/vigs/vigs_mman.c
drivers/gpu/drm/vigs/vigs_mman.h
drivers/gpu/drm/vigs/vigs_protocol.h
drivers/gpu/drm/vigs/vigs_surface.c
drivers/gpu/drm/vigs/vigs_surface.h
include/drm/vigs_drm.h

index c5bed18fc753ae175fd8fc2f09df173eb90e82fb..5d478b4748953b350d4aa19247d86a43828a3ecc 100644 (file)
@@ -329,6 +329,66 @@ int vigs_comm_set_root_surface(struct vigs_comm *comm,
     return ret;
 }
 
+int vigs_comm_update_vram(struct vigs_comm *comm,
+                          vigsp_surface_id id,
+                          vigsp_offset offset)
+{
+    int ret;
+    struct vigsp_cmd_update_vram_request *request;
+
+    DRM_DEBUG_DRIVER("id = %u, offset = %u\n", id, offset);
+
+    mutex_lock(&comm->mutex);
+
+    ret = vigs_comm_prepare(comm,
+                            vigsp_cmd_update_vram,
+                            sizeof(*request),
+                            0,
+                            (void**)&request,
+                            NULL);
+
+    if (ret == 0) {
+        request->sfc_id = id;
+        request->offset = offset;
+
+        ret = vigs_comm_exec_internal(comm);
+    }
+
+    mutex_unlock(&comm->mutex);
+
+    return ret;
+}
+
+int vigs_comm_update_gpu(struct vigs_comm *comm,
+                         vigsp_surface_id id,
+                         vigsp_offset offset)
+{
+    int ret;
+    struct vigsp_cmd_update_gpu_request *request;
+
+    DRM_DEBUG_DRIVER("id = %u, offset = %u\n", id, offset);
+
+    mutex_lock(&comm->mutex);
+
+    ret = vigs_comm_prepare(comm,
+                            vigsp_cmd_update_gpu,
+                            sizeof(*request),
+                            0,
+                            (void**)&request,
+                            NULL);
+
+    if (ret == 0) {
+        request->sfc_id = id;
+        request->offset = offset;
+
+        ret = vigs_comm_exec_internal(comm);
+    }
+
+    mutex_unlock(&comm->mutex);
+
+    return ret;
+}
+
 int vigs_comm_get_protocol_version_ioctl(struct drm_device *drm_dev,
                                          void *data,
                                          struct drm_file *file_priv)
index 5283da883914dba79555e7a9f7b3e29864f47922..d5c0cfd2bd9d97cff73d50572a57d3294cf24978 100644 (file)
@@ -53,6 +53,14 @@ int vigs_comm_set_root_surface(struct vigs_comm *comm,
                                vigsp_surface_id id,
                                vigsp_offset offset);
 
+int vigs_comm_update_vram(struct vigs_comm *comm,
+                          vigsp_surface_id id,
+                          vigsp_offset offset);
+
+int vigs_comm_update_gpu(struct vigs_comm *comm,
+                         vigsp_surface_id id,
+                         vigsp_offset offset);
+
 /*
  * IOCTLs
  * @{
index c1a027fecfbd34938067453727b080d2d865ebae..039339035961171640cbb822d7f5f82a7a039157 100644 (file)
@@ -9,6 +9,67 @@
 #include "vigs_surface.h"
 #include <drm/vigs_drm.h>
 
+static int vigs_device_mman_map(void *user_data, struct ttm_buffer_object *bo)
+{
+    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
+    int ret;
+
+    vigs_gem_reserve(vigs_gem);
+
+    ret = vigs_gem_pin(vigs_gem);
+
+    vigs_gem_unreserve(vigs_gem);
+
+    return ret;
+}
+
+static void vigs_device_mman_unmap(void *user_data, struct ttm_buffer_object *bo)
+{
+    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
+
+    vigs_gem_reserve(vigs_gem);
+
+    vigs_gem_unpin(vigs_gem);
+
+    vigs_gem_unreserve(vigs_gem);
+}
+
+static void vigs_device_mman_vram_to_gpu(void *user_data,
+                                         struct ttm_buffer_object *bo)
+{
+    struct vigs_device *vigs_dev = user_data;
+    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
+    struct vigs_surface *vigs_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    if (vigs_sfc->is_dirty) {
+        vigs_comm_update_gpu(vigs_dev->comm,
+                             vigs_sfc->id,
+                             vigs_gem_offset(vigs_gem));
+        vigs_sfc->is_dirty = false;
+    }
+}
+
+static void vigs_device_mman_gpu_to_vram(void *user_data,
+                                         struct ttm_buffer_object *bo,
+                                         unsigned long new_offset)
+{
+    struct vigs_device *vigs_dev = user_data;
+    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
+    struct vigs_surface *vigs_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_comm_update_vram(vigs_dev->comm,
+                          vigs_sfc->id,
+                          new_offset);
+}
+
+static struct vigs_mman_ops mman_ops =
+{
+    .map = &vigs_device_mman_map,
+    .unmap = &vigs_device_mman_unmap,
+    .vram_to_gpu = &vigs_device_mman_vram_to_gpu,
+    .gpu_to_vram = &vigs_device_mman_gpu_to_vram
+};
+
 static struct vigs_surface
     *vigs_device_reference_surface_unlocked(struct vigs_device *vigs_dev,
                                             vigsp_surface_id sfc_id)
@@ -80,6 +141,8 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
             if (vigs_gem_in_vram(&sfc->gem)) {
                 update_vram_request->offset = vigs_gem_offset(&sfc->gem);
             } else {
+                DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_vram\n",
+                                 update_vram_request->sfc_id);
                 update_vram_request->sfc_id = 0;
             }
             list_add_tail(&sfc->gem.list, gem_list);
@@ -96,7 +159,10 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
             vigs_gem_reserve(&sfc->gem);
             if (vigs_gem_in_vram(&sfc->gem)) {
                 update_gpu_request->offset = vigs_gem_offset(&sfc->gem);
+                sfc->is_dirty = false;
             } else {
+                DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_gpu\n",
+                                 update_gpu_request->sfc_id);
                 update_gpu_request->sfc_id = 0;
             }
             list_add_tail(&sfc->gem.list, gem_list);
@@ -174,6 +240,8 @@ int vigs_device_init(struct vigs_device *vigs_dev,
 
     ret = vigs_mman_create(vigs_dev->vram_base, vigs_dev->vram_size,
                            vigs_dev->ram_base, vigs_dev->ram_size,
+                           &mman_ops,
+                           vigs_dev,
                            &vigs_dev->mman);
 
     if (ret != 0) {
index 74062874027ea6110fc1230150adf6b3705c127e..7caa8372423128d648866e1d45a1ebc6ad6c18f5 100644 (file)
@@ -43,6 +43,8 @@ static struct drm_ioctl_desc vigs_drm_ioctls[] =
                                          DRM_UNLOCKED | DRM_AUTH),
     DRM_IOCTL_DEF_DRV(VIGS_EXEC, vigs_device_exec_ioctl,
                                  DRM_UNLOCKED | DRM_AUTH),
+    DRM_IOCTL_DEF_DRV(VIGS_SURFACE_SET_DIRTY, vigs_surface_set_dirty_ioctl,
+                                              DRM_UNLOCKED | DRM_AUTH),
 };
 
 static const struct file_operations vigs_drm_driver_fops =
index 43e142fb8ea8483d9a194d5335977a7613d01de0..5feb6b07f4c297d70bf039dad78c527844693b1c 100644 (file)
@@ -1,5 +1,4 @@
 #include "vigs_mman.h"
-#include "vigs_gem.h"
 #include <ttm/ttm_placement.h>
 
 /*
@@ -230,12 +229,15 @@ static int vigs_ttm_move(struct ttm_buffer_object *bo,
                          bool no_wait_gpu,
                          struct ttm_mem_reg *new_mem)
 {
+    struct vigs_mman *mman = bo_dev_to_vigs_mman(bo->bdev);
     struct ttm_mem_reg *old_mem = &bo->mem;
 
     if ((old_mem->mem_type == TTM_PL_VRAM) &&
         (new_mem->mem_type == TTM_PL_TT)) {
         DRM_DEBUG_DRIVER("ttm_move: 0x%llX vram -> gpu\n", bo->addr_space_offset);
 
+        mman->ops->vram_to_gpu(mman->user_data, bo);
+
         ttm_bo_mem_put(bo, old_mem);
 
         *old_mem = *new_mem;
@@ -246,6 +248,10 @@ static int vigs_ttm_move(struct ttm_buffer_object *bo,
                (new_mem->mem_type == TTM_PL_VRAM)) {
         DRM_DEBUG_DRIVER("ttm_move: 0x%llX gpu -> vram\n", bo->addr_space_offset);
 
+        mman->ops->gpu_to_vram(mman->user_data, bo,
+                               (new_mem->start << PAGE_SHIFT) +
+                               bo->bdev->man[new_mem->mem_type].gpu_offset);
+
         ttm_bo_mem_put(bo, old_mem);
 
         *old_mem = *new_mem;
@@ -323,6 +329,8 @@ int vigs_mman_create(resource_size_t vram_base,
                      resource_size_t vram_size,
                      resource_size_t ram_base,
                      resource_size_t ram_size,
+                     struct vigs_mman_ops *ops,
+                     void *user_data,
                      struct vigs_mman **mman)
 {
     int ret = 0;
@@ -345,6 +353,8 @@ int vigs_mman_create(resource_size_t vram_base,
 
     (*mman)->vram_base = vram_base;
     (*mman)->ram_base = ram_base;
+    (*mman)->ops = ops;
+    (*mman)->user_data = user_data;
 
     ret = ttm_bo_device_init(&(*mman)->bo_dev,
                              (*mman)->bo_global_ref.ref.object,
@@ -452,13 +462,9 @@ static const struct vm_operations_struct *ttm_vm_ops = NULL;
 static void vigs_ttm_open(struct vm_area_struct *vma)
 {
     struct ttm_buffer_object *bo = vma->vm_private_data;
-    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
-
-    vigs_gem_reserve(vigs_gem);
+    struct vigs_mman *mman = bo_dev_to_vigs_mman(bo->bdev);
 
-    vigs_gem_pin(vigs_gem);
-
-    vigs_gem_unreserve(vigs_gem);
+    mman->ops->map(mman->user_data, bo);
 
     ttm_vm_ops->open(vma);
 }
@@ -466,13 +472,9 @@ static void vigs_ttm_open(struct vm_area_struct *vma)
 static void vigs_ttm_close(struct vm_area_struct *vma)
 {
     struct ttm_buffer_object *bo = vma->vm_private_data;
-    struct vigs_gem_object *vigs_gem = bo_to_vigs_gem(bo);
-
-    vigs_gem_reserve(vigs_gem);
+    struct vigs_mman *mman = bo_dev_to_vigs_mman(bo->bdev);
 
-    vigs_gem_unpin(vigs_gem);
-
-    vigs_gem_unreserve(vigs_gem);
+    mman->ops->unmap(mman->user_data, bo);
 
     ttm_vm_ops->close(vma);
 }
@@ -493,7 +495,6 @@ int vigs_mman_mmap(struct vigs_mman *mman,
                    struct vm_area_struct *vma)
 {
     struct ttm_buffer_object *bo;
-    struct vigs_gem_object *vigs_gem;
     int ret;
 
     if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) {
@@ -518,13 +519,7 @@ int vigs_mman_mmap(struct vigs_mman *mman,
 
     bo = vma->vm_private_data;
 
-    vigs_gem = bo_to_vigs_gem(bo);
-
-    vigs_gem_reserve(vigs_gem);
-
-    ret = vigs_gem_pin(vigs_gem);
-
-    vigs_gem_unreserve(vigs_gem);
+    ret = mman->ops->map(mman->user_data, bo);
 
     if (ret != 0) {
         ttm_vm_ops->close(vma);
index 0233146331770fb4fdb085955c8a8db6c6d2c044..9bef3802b1583a3db2f536ed77774e07dc851b5e 100644 (file)
@@ -6,9 +6,25 @@
 
 struct vigs_mman_ops
 {
+    /*
+     * 'bo' is unreserved while calling these.
+     */
+    int (*map)(void *user_data, struct ttm_buffer_object *bo);
+    void (*unmap)(void *user_data, struct ttm_buffer_object *bo);
+    /*
+     * @}
+     */
+
+    /*
+     * 'bo' is reserved while calling these.
+     * @{
+     */
     void (*vram_to_gpu)(void *user_data, struct ttm_buffer_object *bo);
-
-    void (*gpu_to_vram)(void *user_data, struct ttm_buffer_object *bo);
+    void (*gpu_to_vram)(void *user_data, struct ttm_buffer_object *bo,
+                        unsigned long new_offset);
+    /*
+     * @}
+     */
 };
 
 struct vigs_mman
@@ -33,6 +49,8 @@ int vigs_mman_create(resource_size_t vram_base,
                      resource_size_t vram_size,
                      resource_size_t ram_base,
                      resource_size_t ram_size,
+                     struct vigs_mman_ops *ops,
+                     void *user_data,
                      struct vigs_mman **mman);
 
 void vigs_mman_destroy(struct vigs_mman *mman);
index 9eaf2f287719257b216b02e5bb09c42f9c9a0db3..03a78e04e30957a60f8c3aefc53e734dfed5db79 100644 (file)
@@ -14,7 +14,7 @@
 /*
  * Bump this whenever protocol changes.
  */
-#define VIGS_PROTOCOL_VERSION 11
+#define VIGS_PROTOCOL_VERSION 12
 
 typedef signed char vigsp_s8;
 typedef signed short vigsp_s16;
@@ -228,7 +228,6 @@ struct vigsp_cmd_update_vram_request
 {
     vigsp_surface_id sfc_id;
     vigsp_offset offset;
-    struct vigsp_rect rect;
 };
 
 /*
@@ -247,7 +246,6 @@ struct vigsp_cmd_update_gpu_request
 {
     vigsp_surface_id sfc_id;
     vigsp_offset offset;
-    struct vigsp_rect rect;
 };
 
 /*
index 99c2367b0bd5cb6a7c847eaea6a674261a97f752..b03e3b7d0ae6cc846d832c2f9170047477ceb80a 100644 (file)
@@ -149,3 +149,40 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
 
     return 0;
 }
+
+int vigs_surface_set_dirty_ioctl(struct drm_device *drm_dev,
+                                 void *data,
+                                 struct drm_file *file_priv)
+{
+    struct drm_vigs_surface_set_dirty *args = data;
+    struct drm_gem_object *gem;
+    struct vigs_gem_object *vigs_gem;
+    struct vigs_surface *sfc;
+
+    gem = drm_gem_object_lookup(drm_dev, file_priv, args->handle);
+
+    if (gem == NULL) {
+        return -ENOENT;
+    }
+
+    vigs_gem = gem_to_vigs_gem(gem);
+
+    if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+        drm_gem_object_unreference_unlocked(gem);
+        return -ENOENT;
+    }
+
+    sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+    vigs_gem_reserve(&sfc->gem);
+
+    if (vigs_gem_in_vram(&sfc->gem)) {
+        sfc->is_dirty = true;
+    }
+
+    vigs_gem_unreserve(&sfc->gem);
+
+    drm_gem_object_unreference_unlocked(gem);
+
+    return 0;
+}
index 8b904f82b7ff011c94d1fc0d66072b33e883f7fa..6a81fdc57da7822a7399f05e12a2f968229ac5ac 100644 (file)
@@ -17,6 +17,18 @@ struct vigs_surface
     u32 stride;
     vigsp_surface_format format;
     vigsp_surface_id id;
+
+    /*
+     * Members below MUST be accessed between
+     * vigs_gem_reserve/vigs_gem_unreserve.
+     * @{
+     */
+
+    bool is_dirty;
+
+    /*
+     * @}
+     */
 };
 
 static inline struct vigs_surface *vigs_gem_to_vigs_surface(struct vigs_gem_object *vigs_gem)
@@ -44,6 +56,10 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
                             void *data,
                             struct drm_file *file_priv);
 
+int vigs_surface_set_dirty_ioctl(struct drm_device *drm_dev,
+                                 void *data,
+                                 struct drm_file *file_priv);
+
 /*
  * @}
  */
index 2e9daf2b54713f4ebf09d572def22dd76e0cf800..10427f34eb8689a255e89c4c4dc76cccae6f59ee 100644 (file)
@@ -8,7 +8,7 @@
 /*
  * Bump this whenever driver interface changes.
  */
-#define DRM_VIGS_DRIVER_VERSION 4
+#define DRM_VIGS_DRIVER_VERSION 5
 
 struct drm_vigs_get_protocol_version
 {
@@ -51,11 +51,17 @@ struct drm_vigs_exec
     uint32_t handle;
 };
 
+struct drm_vigs_surface_set_dirty
+{
+    uint32_t handle;
+};
+
 #define DRM_VIGS_GET_PROTOCOL_VERSION 0x00
 #define DRM_VIGS_CREATE_SURFACE 0x01
 #define DRM_VIGS_CREATE_EXECBUFFER 0x02
 #define DRM_VIGS_SURFACE_INFO 0x03
 #define DRM_VIGS_EXEC 0x04
+#define DRM_VIGS_SURFACE_SET_DIRTY 0x05
 
 #define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
             DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
@@ -67,5 +73,7 @@ struct drm_vigs_exec
             DRM_VIGS_SURFACE_INFO, struct drm_vigs_surface_info)
 #define DRM_IOCTL_VIGS_EXEC DRM_IOW(DRM_COMMAND_BASE + \
             DRM_VIGS_EXEC, struct drm_vigs_exec)
+#define DRM_IOCTL_VIGS_SURFACE_SET_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_SET_DIRTY, struct drm_vigs_surface_set_dirty)
 
 #endif