From 16e267a1d28e9a1e9a44286230f138d0f8dbdece Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Mon, 6 May 2013 18:48:07 +0400 Subject: [PATCH] VIGS: Dirty flag support in vigs_surface 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 | 60 ++++++++++++++++++++++++ drivers/gpu/drm/vigs/vigs_comm.h | 8 ++++ drivers/gpu/drm/vigs/vigs_device.c | 68 ++++++++++++++++++++++++++++ drivers/gpu/drm/vigs/vigs_driver.c | 2 + drivers/gpu/drm/vigs/vigs_mman.c | 37 +++++++-------- drivers/gpu/drm/vigs/vigs_mman.h | 22 ++++++++- drivers/gpu/drm/vigs/vigs_protocol.h | 4 +- drivers/gpu/drm/vigs/vigs_surface.c | 37 +++++++++++++++ drivers/gpu/drm/vigs/vigs_surface.h | 16 +++++++ include/drm/vigs_drm.h | 10 +++- 10 files changed, 237 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/vigs/vigs_comm.c b/drivers/gpu/drm/vigs/vigs_comm.c index c5bed18fc753..5d478b474895 100644 --- a/drivers/gpu/drm/vigs/vigs_comm.c +++ b/drivers/gpu/drm/vigs/vigs_comm.c @@ -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) diff --git a/drivers/gpu/drm/vigs/vigs_comm.h b/drivers/gpu/drm/vigs/vigs_comm.h index 5283da883914..d5c0cfd2bd9d 100644 --- a/drivers/gpu/drm/vigs/vigs_comm.h +++ b/drivers/gpu/drm/vigs/vigs_comm.h @@ -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 * @{ diff --git a/drivers/gpu/drm/vigs/vigs_device.c b/drivers/gpu/drm/vigs/vigs_device.c index c1a027fecfbd..039339035961 100644 --- a/drivers/gpu/drm/vigs/vigs_device.c +++ b/drivers/gpu/drm/vigs/vigs_device.c @@ -9,6 +9,67 @@ #include "vigs_surface.h" #include +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) { diff --git a/drivers/gpu/drm/vigs/vigs_driver.c b/drivers/gpu/drm/vigs/vigs_driver.c index 74062874027e..7caa83724231 100644 --- a/drivers/gpu/drm/vigs/vigs_driver.c +++ b/drivers/gpu/drm/vigs/vigs_driver.c @@ -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 = diff --git a/drivers/gpu/drm/vigs/vigs_mman.c b/drivers/gpu/drm/vigs/vigs_mman.c index 43e142fb8ea8..5feb6b07f4c2 100644 --- a/drivers/gpu/drm/vigs/vigs_mman.c +++ b/drivers/gpu/drm/vigs/vigs_mman.c @@ -1,5 +1,4 @@ #include "vigs_mman.h" -#include "vigs_gem.h" #include /* @@ -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); diff --git a/drivers/gpu/drm/vigs/vigs_mman.h b/drivers/gpu/drm/vigs/vigs_mman.h index 023314633177..9bef3802b158 100644 --- a/drivers/gpu/drm/vigs/vigs_mman.h +++ b/drivers/gpu/drm/vigs/vigs_mman.h @@ -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); diff --git a/drivers/gpu/drm/vigs/vigs_protocol.h b/drivers/gpu/drm/vigs/vigs_protocol.h index 9eaf2f287719..03a78e04e309 100644 --- a/drivers/gpu/drm/vigs/vigs_protocol.h +++ b/drivers/gpu/drm/vigs/vigs_protocol.h @@ -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; }; /* diff --git a/drivers/gpu/drm/vigs/vigs_surface.c b/drivers/gpu/drm/vigs/vigs_surface.c index 99c2367b0bd5..b03e3b7d0ae6 100644 --- a/drivers/gpu/drm/vigs/vigs_surface.c +++ b/drivers/gpu/drm/vigs/vigs_surface.c @@ -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; +} diff --git a/drivers/gpu/drm/vigs/vigs_surface.h b/drivers/gpu/drm/vigs/vigs_surface.h index 8b904f82b7ff..6a81fdc57da7 100644 --- a/drivers/gpu/drm/vigs/vigs_surface.h +++ b/drivers/gpu/drm/vigs/vigs_surface.h @@ -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); + /* * @} */ diff --git a/include/drm/vigs_drm.h b/include/drm/vigs_drm.h index 2e9daf2b5471..10427f34eb86 100644 --- a/include/drm/vigs_drm.h +++ b/include/drm/vigs_drm.h @@ -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 -- 2.34.1