summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/virtio/virtgpu_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_object.c')
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_object.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index ec9efacc6919..9bc0bd68c314 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -63,6 +63,15 @@ static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t
ida_free(&vgdev->resource_ida, id - 1);
}
+void virtio_gpu_remove_from_restore_list(struct virtio_gpu_object *bo)
+{
+ struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
+
+ mutex_lock(&vgdev->obj_restore_lock);
+ list_del_init(&bo->restore_node);
+ mutex_unlock(&vgdev->obj_restore_lock);
+}
+
void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
{
struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
@@ -94,7 +103,8 @@ static void virtio_gpu_free_object(struct drm_gem_object *obj)
struct virtio_gpu_device *vgdev = bo->base.base.dev->dev_private;
if (bo->created) {
- virtio_gpu_cmd_unref_resource(vgdev, bo);
+ virtio_gpu_remove_from_restore_list(bo);
+ virtio_gpu_cmd_unref_resource(vgdev, bo, false);
virtio_gpu_notify(vgdev);
/* completion handler calls virtio_gpu_cleanup_object() */
return;
@@ -220,6 +230,8 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
return PTR_ERR(shmem_obj);
bo = gem_to_virtio_gpu_obj(&shmem_obj->base);
+ INIT_LIST_HEAD(&bo->restore_node);
+
ret = virtio_gpu_resource_id_get(vgdev, &bo->hw_res_handle);
if (ret < 0)
goto err_free_gem;
@@ -258,6 +270,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
virtio_gpu_object_attach(vgdev, bo, ents, nents);
}
+ if (!params->virgl) {
+ /* store non-virgl object with its param to the restore list */
+ bo->params = *params;
+ virtio_gpu_add_object_to_restore_list(vgdev, bo);
+ }
+
*bo_ptr = bo;
return 0;
@@ -271,3 +289,73 @@ err_free_gem:
drm_gem_shmem_free(shmem_obj);
return ret;
}
+
+void virtio_gpu_add_object_to_restore_list(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_object *bo)
+{
+ mutex_lock(&vgdev->obj_restore_lock);
+ list_add_tail(&bo->restore_node, &vgdev->obj_restore_list);
+ mutex_unlock(&vgdev->obj_restore_lock);
+}
+
+int virtio_gpu_object_restore_all(struct virtio_gpu_device *vgdev)
+{
+ struct virtio_gpu_object *bo, *tmp;
+ struct virtio_gpu_mem_entry *ents;
+ unsigned int nents;
+ int ret = 0;
+
+ mutex_lock(&vgdev->obj_restore_lock);
+ list_for_each_entry_safe(bo, tmp, &vgdev->obj_restore_list,
+ restore_node) {
+ if (drm_gem_is_imported(&bo->base.base)) {
+ ret = virtgpu_dma_buf_obj_resubmit(vgdev, bo);
+ if (ret)
+ break;
+
+ continue;
+ }
+
+ if (bo->params.blob || bo->attached) {
+ ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents,
+ &nents);
+ if (ret)
+ break;
+ }
+
+ if (bo->params.blob) {
+ virtio_gpu_cmd_resource_create_blob(vgdev, bo,
+ &bo->params,
+ ents, nents);
+ } else {
+ virtio_gpu_cmd_create_resource(vgdev, bo, &bo->params,
+ NULL, NULL);
+ if (bo->attached) {
+ bo->attached = false;
+ virtio_gpu_object_attach(vgdev, bo, ents,
+ nents);
+ }
+ }
+ }
+ mutex_unlock(&vgdev->obj_restore_lock);
+
+ if (ret)
+ DRM_ERROR("failed to restore virtio-gpu objects: %d\n", ret);
+
+ return ret;
+}
+
+void virtio_gpu_object_unref_all(struct virtio_gpu_device *vgdev)
+{
+ struct virtio_gpu_object *bo, *tmp;
+
+ mutex_lock(&vgdev->obj_restore_lock);
+ list_for_each_entry_safe(bo, tmp, &vgdev->obj_restore_list,
+ restore_node)
+ if (bo->created) {
+ virtio_gpu_cmd_unref_resource(vgdev, bo, true);
+ virtio_gpu_notify(vgdev);
+ }
+
+ mutex_unlock(&vgdev->obj_restore_lock);
+}