int vigs_comm_update_gpu(struct vigs_comm *comm,
vigsp_surface_id id,
+ u32 width,
+ u32 height,
vigsp_offset offset)
{
int ret;
ret = vigs_comm_prepare(comm,
vigsp_cmd_update_gpu,
- sizeof(*request),
+ sizeof(*request) + sizeof(struct vigsp_rect),
0,
(void**)&request,
NULL);
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);
}
int vigs_comm_update_gpu(struct vigs_comm *comm,
vigsp_surface_id id,
+ u32 width,
+ u32 height,
vigsp_offset offset);
/*
#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_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,
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
};
}
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);
}
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);
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:
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:
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,
/*
* 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)
{
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);
}
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);
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)
{
.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,
};
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;
struct file *filp,
struct vm_area_struct *vma)
{
- struct ttm_buffer_object *bo;
int ret;
if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) {
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;
}
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);
{
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;
(*sfc)->height = height;
(*sfc)->stride = stride;
(*sfc)->format = format;
- (*sfc)->dirty_flag = vigs_dirty_none;
ret = vigs_gem_init(&(*sfc)->gem,
vigs_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)
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);
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);
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);
#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
{
/*
* @{
*/
- vigs_dirty_flag dirty_flag;
+ bool is_gpu_dirty;
/*
* @}
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);
/*
* Bump this whenever driver interface changes.
*/
-#define DRM_VIGS_DRIVER_VERSION 6
+#define DRM_VIGS_DRIVER_VERSION 7
struct drm_vigs_get_protocol_version
{
uint32_t handle;
};
-struct drm_vigs_surface_set_vram_dirty
-{
- uint32_t handle;
-};
-
struct drm_vigs_surface_set_gpu_dirty
{
uint32_t handle;
#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)
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 + \