diff options
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_object.c')
| -rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_object.c | 90 |
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); +} |
