VIGS: VRAM <-> GPU movements are now handled via page faults
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Fri, 7 Jun 2013 14:40:28 +0000 (18:40 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Fri, 7 Jun 2013 14:40:28 +0000 (18:40 +0400)
VIGS: Fixed update_gpu command

VRAM <-> GPU movements are now handled via page faults, thus, user space
can mmap as many GEMs as it likes, they'll all be in GPU placement by
default and moved to VRAM as needed on page faults. Page fault handler will
also take care of eviction in case of there's no free space in VRAM

update_gpu command wasn't updated for last protocol change, fixed it

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_gem.h
drivers/gpu/drm/vigs/vigs_mman.c
drivers/gpu/drm/vigs/vigs_mman.h
drivers/gpu/drm/vigs/vigs_surface.c
drivers/gpu/drm/vigs/vigs_surface.h
include/drm/vigs_drm.h

index 5d478b4748953b350d4aa19247d86a43828a3ecc..cf94c090ec1465c4dc07b956b1890b877250bbc1 100644 (file)
@@ -361,6 +361,8 @@ int vigs_comm_update_vram(struct vigs_comm *comm,
 
 int vigs_comm_update_gpu(struct vigs_comm *comm,
                          vigsp_surface_id id,
+                         u32 width,
+                         u32 height,
                          vigsp_offset offset)
 {
     int ret;
@@ -372,7 +374,7 @@ int vigs_comm_update_gpu(struct vigs_comm *comm,
 
     ret = vigs_comm_prepare(comm,
                             vigsp_cmd_update_gpu,
-                            sizeof(*request),
+                            sizeof(*request) + sizeof(struct vigsp_rect),
                             0,
                             (void**)&request,
                             NULL);
@@ -380,6 +382,11 @@ int vigs_comm_update_gpu(struct vigs_comm *comm,
     if (ret == 0) {
         request->sfc_id = id;
         request->offset = offset;
+        request->num_entries = 1;
+        request->entries[0].pos.x = 0;
+        request->entries[0].pos.y = 0;
+        request->entries[0].size.w = width;
+        request->entries[0].size.h = height;
 
         ret = vigs_comm_exec_internal(comm);
     }
index d5c0cfd2bd9d97cff73d50572a57d3294cf24978..5372696fb3e0f78fcb5b6d79885477216a1fa0e9 100644 (file)
@@ -59,6 +59,8 @@ int vigs_comm_update_vram(struct vigs_comm *comm,
 
 int vigs_comm_update_gpu(struct vigs_comm *comm,
                          vigsp_surface_id id,
+                         u32 width,
+                         u32 height,
                          vigsp_offset offset);
 
 /*
index 4489ccc511e81fe8555e303b66c8b5d70408e094..5bc96867f66f51bcd35093e13f9738f48638787c 100644 (file)
@@ -9,31 +9,6 @@
 #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)
 {
@@ -41,12 +16,15 @@ static void vigs_device_mman_vram_to_gpu(void *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->dirty_flag == vigs_dirty_vram) {
+    if (!vigs_sfc->is_gpu_dirty) {
         vigs_comm_update_gpu(vigs_dev->comm,
                              vigs_sfc->id,
+                             vigs_sfc->width,
+                             vigs_sfc->height,
                              vigs_gem_offset(vigs_gem));
     }
-    vigs_sfc->dirty_flag = vigs_dirty_none;
+
+    vigs_sfc->is_gpu_dirty = false;
 }
 
 static void vigs_device_mman_gpu_to_vram(void *user_data,
@@ -64,8 +42,6 @@ static void vigs_device_mman_gpu_to_vram(void *user_data,
 
 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
 };
@@ -164,7 +140,7 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
                 request.update_vram->offset = vigs_gem_offset(&sfc->gem);
-                sfc->dirty_flag = vigs_dirty_none;
+                sfc->is_gpu_dirty = false;
             } else {
                 DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_vram\n",
                                  request.update_vram->sfc_id);
@@ -188,7 +164,7 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
                 request.update_gpu->offset = vigs_gem_offset(&sfc->gem);
-                sfc->dirty_flag = vigs_dirty_none;
+                sfc->is_gpu_dirty = false;
             } else {
                 DRM_DEBUG_DRIVER("Surface %u not in VRAM, ignoring update_gpu\n",
                                  request.update_gpu->sfc_id);
@@ -211,7 +187,7 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 list_add_tail(&sfc->gem.list, gem_list);
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
-                sfc->dirty_flag = vigs_dirty_gpu;
+                sfc->is_gpu_dirty = true;
             }
             break;
         case vigsp_cmd_solid_fill:
@@ -230,7 +206,7 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 list_add_tail(&sfc->gem.list, gem_list);
             }
             if (vigs_gem_in_vram(&sfc->gem)) {
-                sfc->dirty_flag = vigs_dirty_gpu;
+                sfc->is_gpu_dirty = true;
             }
             break;
         default:
index c36abaf4ea1120f162fea30f02695eb8727585bf..f5d3fd746e9db65393cfc34549640e898651c57e 100644 (file)
@@ -43,8 +43,6 @@ 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_VRAM_DIRTY, vigs_surface_set_vram_dirty_ioctl,
-                                                   DRM_UNLOCKED | DRM_AUTH),
     DRM_IOCTL_DEF_DRV(VIGS_SURFACE_SET_GPU_DIRTY, vigs_surface_set_gpu_dirty_ioctl,
                                                   DRM_UNLOCKED | DRM_AUTH),
     DRM_IOCTL_DEF_DRV(VIGS_SURFACE_UPDATE_VRAM, vigs_surface_update_vram_ioctl,
index c3d4c7135c5fbc512c4bc2b8ace26b2bbac51234..25280d5c3f17c648d2b88d9c29b82fba1eb53046 100644 (file)
@@ -77,7 +77,7 @@ static inline unsigned long vigs_gem_size(struct vigs_gem_object *vigs_gem)
 
 /*
  * GEM offset in a placement. In case of execbuffer always the same.
- * In case of surface only valid when GEM is pinned.
+ * In case of surface only valid when GEM is in VRAM.
  */
 static inline unsigned long vigs_gem_offset(struct vigs_gem_object *vigs_gem)
 {
index 5feb6b07f4c297d70bf039dad78c527844693b1c..19c63b5eba56291d9f94d86e43a02568a158460c 100644 (file)
@@ -85,11 +85,24 @@ static int vigs_mman_global_init(struct vigs_mman *mman)
         return ret;
     }
 
+    /*
+     * Hack. Assign 'shrink' to NULL in order to prevent
+     * swapping out BOs, we don't need this because
+     * we don't occupy any system RAM at all, our GPU
+     * placement is entirely on host.
+     */
+
+    mman->old_shrink = mman->bo_global_ref.mem_glob->shrink;
+    mman->bo_global_ref.mem_glob->shrink = NULL;
+
     return 0;
 }
 
 static void vigs_mman_global_cleanup(struct vigs_mman *mman)
 {
+    mman->bo_global_ref.mem_glob->shrink = mman->old_shrink;
+    mman->old_shrink = NULL;
+
     drm_global_item_unref(&mman->bo_global_ref.ref);
     drm_global_item_unref(&mman->mem_global_ref);
 }
@@ -234,7 +247,7 @@ static int vigs_ttm_move(struct ttm_buffer_object *bo,
 
     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);
+        DRM_INFO("ttm_move: 0x%llX vram -> gpu\n", bo->addr_space_offset);
 
         mman->ops->vram_to_gpu(mman->user_data, bo);
 
@@ -269,6 +282,43 @@ static int vigs_ttm_verify_access(struct ttm_buffer_object *bo,
     return 0;
 }
 
+int vigs_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
+{
+    u32 placements[1];
+    struct ttm_placement placement;
+    int ret;
+
+    if (bo->mem.mem_type != TTM_PL_TT) {
+        /*
+         * We're only interested in GPU memory page faults.
+         */
+
+        return 0;
+    }
+
+    /*
+     * It's GPU memory page fault. Move this buffer into VRAM.
+     */
+
+    placements[0] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM;
+
+    memset(&placement, 0, sizeof(placement));
+
+    placement.placement = placements;
+    placement.busy_placement = placements;
+    placement.num_placement = 1;
+    placement.num_busy_placement = 1;
+
+    ret = ttm_bo_validate(bo, &placement, false, true, false);
+
+    if (ret != 0) {
+        DRM_ERROR("movement failed for 0x%llX\n", bo->addr_space_offset);
+        return ret;
+    }
+
+    return 0;
+}
+
 static int vigs_ttm_io_mem_reserve(struct ttm_bo_device *bo_dev,
                                    struct ttm_mem_reg *mem)
 {
@@ -321,6 +371,7 @@ static struct ttm_bo_driver vigs_ttm_bo_driver =
     .evict_flags = &vigs_ttm_evict_flags,
     .move = &vigs_ttm_move,
     .verify_access = &vigs_ttm_verify_access,
+    .fault_reserve_notify = &vigs_ttm_fault_reserve_notify,
     .io_mem_reserve = &vigs_ttm_io_mem_reserve,
     .io_mem_free = &vigs_ttm_io_mem_free,
 };
@@ -459,26 +510,6 @@ void vigs_mman_destroy(struct vigs_mman *mman)
 static struct vm_operations_struct vigs_ttm_vm_ops;
 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_mman *mman = bo_dev_to_vigs_mman(bo->bdev);
-
-    mman->ops->map(mman->user_data, bo);
-
-    ttm_vm_ops->open(vma);
-}
-
-static void vigs_ttm_close(struct vm_area_struct *vma)
-{
-    struct ttm_buffer_object *bo = vma->vm_private_data;
-    struct vigs_mman *mman = bo_dev_to_vigs_mman(bo->bdev);
-
-    mman->ops->unmap(mman->user_data, bo);
-
-    ttm_vm_ops->close(vma);
-}
-
 static int vigs_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
     struct ttm_buffer_object *bo = vma->vm_private_data;
@@ -494,7 +525,6 @@ int vigs_mman_mmap(struct vigs_mman *mman,
                    struct file *filp,
                    struct vm_area_struct *vma)
 {
-    struct ttm_buffer_object *bo;
     int ret;
 
     if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) {
@@ -510,21 +540,10 @@ int vigs_mman_mmap(struct vigs_mman *mman,
     if (unlikely(ttm_vm_ops == NULL)) {
         ttm_vm_ops = vma->vm_ops;
         vigs_ttm_vm_ops = *ttm_vm_ops;
-        vigs_ttm_vm_ops.open = &vigs_ttm_open;
-        vigs_ttm_vm_ops.close = &vigs_ttm_close;
         vigs_ttm_vm_ops.fault = &vigs_ttm_fault;
     }
 
     vma->vm_ops = &vigs_ttm_vm_ops;
 
-    bo = vma->vm_private_data;
-
-    ret = mman->ops->map(mman->user_data, bo);
-
-    if (ret != 0) {
-        ttm_vm_ops->close(vma);
-        return ret;
-    }
-
     return 0;
 }
index 9bef3802b1583a3db2f536ed77774e07dc851b5e..0c1d8608b8b8e5da44687f4b5785803d2043bd75 100644 (file)
@@ -6,19 +6,11 @@
 
 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,
                         unsigned long new_offset);
@@ -31,6 +23,7 @@ struct vigs_mman
 {
     struct drm_global_reference mem_global_ref;
     struct ttm_bo_global_ref bo_global_ref;
+    struct ttm_mem_shrink *old_shrink;
     struct ttm_bo_device bo_dev;
 
     resource_size_t vram_base;
index b3634bb623b059e56f6c86f5ee58070a19554981..a106835d059180fbd0fe7e3f80b2a5ee18becb99 100644 (file)
@@ -35,7 +35,6 @@ int vigs_surface_create(struct vigs_device *vigs_dev,
     (*sfc)->height = height;
     (*sfc)->stride = stride;
     (*sfc)->format = format;
-    (*sfc)->dirty_flag = vigs_dirty_none;
 
     ret = vigs_gem_init(&(*sfc)->gem,
                         vigs_dev,
@@ -151,43 +150,6 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
     return 0;
 }
 
-int vigs_surface_set_vram_dirty_ioctl(struct drm_device *drm_dev,
-                                      void *data,
-                                      struct drm_file *file_priv)
-{
-    struct drm_vigs_surface_set_vram_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->dirty_flag = vigs_dirty_vram;
-    }
-
-    vigs_gem_unreserve(&sfc->gem);
-
-    drm_gem_object_unreference_unlocked(gem);
-
-    return 0;
-}
-
 int vigs_surface_set_gpu_dirty_ioctl(struct drm_device *drm_dev,
                                      void *data,
                                      struct drm_file *file_priv)
@@ -215,7 +177,7 @@ int vigs_surface_set_gpu_dirty_ioctl(struct drm_device *drm_dev,
     vigs_gem_reserve(&sfc->gem);
 
     if (vigs_gem_in_vram(&sfc->gem)) {
-        sfc->dirty_flag = vigs_dirty_gpu;
+        sfc->is_gpu_dirty = true;
     }
 
     vigs_gem_unreserve(&sfc->gem);
@@ -252,11 +214,11 @@ int vigs_surface_update_vram_ioctl(struct drm_device *drm_dev,
 
     vigs_gem_reserve(&sfc->gem);
 
-    if (vigs_gem_in_vram(&sfc->gem) && (sfc->dirty_flag == vigs_dirty_gpu)) {
+    if (vigs_gem_in_vram(&sfc->gem) && sfc->is_gpu_dirty) {
         vigs_comm_update_vram(vigs_dev->comm,
                               sfc->id,
                               vigs_gem_offset(vigs_gem));
-        sfc->dirty_flag = vigs_dirty_none;
+        sfc->is_gpu_dirty = false;
     }
 
     vigs_gem_unreserve(&sfc->gem);
@@ -296,8 +258,10 @@ int vigs_surface_update_gpu_ioctl(struct drm_device *drm_dev,
     if (vigs_gem_in_vram(&sfc->gem)) {
         vigs_comm_update_gpu(vigs_dev->comm,
                              sfc->id,
+                             sfc->width,
+                             sfc->height,
                              vigs_gem_offset(vigs_gem));
-        sfc->dirty_flag = vigs_dirty_none;
+        sfc->is_gpu_dirty = false;
     }
 
     vigs_gem_unreserve(&sfc->gem);
index 25ad8dac464ad6830b4ef42ce5a07cbc5fc4a142..9ddfb4d77405d586facffcb58cbb6e80998c9940 100644 (file)
@@ -5,13 +5,6 @@
 #include "vigs_protocol.h"
 #include "vigs_gem.h"
 
-typedef enum
-{
-    vigs_dirty_none = 0,
-    vigs_dirty_vram = 1,
-    vigs_dirty_gpu = 2
-} vigs_dirty_flag;
-
 struct vigs_surface
 {
     /*
@@ -31,7 +24,7 @@ struct vigs_surface
      * @{
      */
 
-    vigs_dirty_flag dirty_flag;
+    bool is_gpu_dirty;
 
     /*
      * @}
@@ -63,10 +56,6 @@ int vigs_surface_info_ioctl(struct drm_device *drm_dev,
                             void *data,
                             struct drm_file *file_priv);
 
-int vigs_surface_set_vram_dirty_ioctl(struct drm_device *drm_dev,
-                                      void *data,
-                                      struct drm_file *file_priv);
-
 int vigs_surface_set_gpu_dirty_ioctl(struct drm_device *drm_dev,
                                      void *data,
                                      struct drm_file *file_priv);
index 878384149a9dfb87cab36faff9dc4b720129e247..687b7b67b31e83822a5a223c9da18cad037660a8 100644 (file)
@@ -8,7 +8,7 @@
 /*
  * Bump this whenever driver interface changes.
  */
-#define DRM_VIGS_DRIVER_VERSION 6
+#define DRM_VIGS_DRIVER_VERSION 7
 
 struct drm_vigs_get_protocol_version
 {
@@ -51,11 +51,6 @@ struct drm_vigs_exec
     uint32_t handle;
 };
 
-struct drm_vigs_surface_set_vram_dirty
-{
-    uint32_t handle;
-};
-
 struct drm_vigs_surface_set_gpu_dirty
 {
     uint32_t handle;
@@ -76,10 +71,9 @@ struct drm_vigs_surface_update_gpu
 #define DRM_VIGS_CREATE_EXECBUFFER 0x02
 #define DRM_VIGS_SURFACE_INFO 0x03
 #define DRM_VIGS_EXEC 0x04
-#define DRM_VIGS_SURFACE_SET_VRAM_DIRTY 0x05
-#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x06
-#define DRM_VIGS_SURFACE_UPDATE_VRAM 0x07
-#define DRM_VIGS_SURFACE_UPDATE_GPU 0x08
+#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x05
+#define DRM_VIGS_SURFACE_UPDATE_VRAM 0x06
+#define DRM_VIGS_SURFACE_UPDATE_GPU 0x07
 
 #define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
             DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
@@ -91,8 +85,6 @@ struct drm_vigs_surface_update_gpu
             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_VRAM_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
-            DRM_VIGS_SURFACE_SET_VRAM_DIRTY, struct drm_vigs_surface_set_vram_dirty)
 #define DRM_IOCTL_VIGS_SURFACE_SET_GPU_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
             DRM_VIGS_SURFACE_SET_GPU_DIRTY, struct drm_vigs_surface_set_gpu_dirty)
 #define DRM_IOCTL_VIGS_SURFACE_UPDATE_VRAM DRM_IOW(DRM_COMMAND_BASE + \