drm/virtio: rework resource creation workflow.
This patch moves the virtio_gpu_cmd_create_resource() call (which notifies the host about the new resource created) into the virtio_gpu_object_create() function. That way we can call virtio_gpu_cmd_create_resource() before ttm_bo_init(), so the host already knows about the object when ttm initializes the object and calls our driver callbacks. Specifically the object is already created when the virtio_gpu_ttm_tt_bind() callback invokes virtio_gpu_object_attach(), so the extra virtio_gpu_object_attach() calls done after virtio_gpu_object_create() are not needed any more. The fence support for the create ioctl becomes a bit more tricky though. The code moved into virtio_gpu_object_create() too. We first submit the (fenced) virtio_gpu_cmd_create_resource() command, then initialize the ttm object, and finally attach just created object to the fence for the command in case it didn't finish yet. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Noralf Trønnes <noralf@tronnes.org> Link: http://patchwork.freedesktop.org/patch/msgid/20190318113332.10900-6-kraxel@redhat.com
This commit is contained in:
@@ -54,8 +54,8 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
|
||||
&virtio_gpu_map->offset);
|
||||
}
|
||||
|
||||
static int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
|
||||
struct list_head *head)
|
||||
int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct ttm_operation_ctx ctx = { false, false };
|
||||
struct ttm_validate_buffer *buf;
|
||||
@@ -79,7 +79,7 @@ static int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_gpu_unref_list(struct list_head *head)
|
||||
void virtio_gpu_unref_list(struct list_head *head)
|
||||
{
|
||||
struct ttm_validate_buffer *buf;
|
||||
struct ttm_buffer_object *bo;
|
||||
@@ -275,14 +275,11 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
struct drm_virtgpu_resource_create *rc = data;
|
||||
struct virtio_gpu_fence *fence;
|
||||
int ret;
|
||||
struct virtio_gpu_object *qobj;
|
||||
struct drm_gem_object *obj;
|
||||
uint32_t handle = 0;
|
||||
struct list_head validate_list;
|
||||
struct ttm_validate_buffer mainbuf;
|
||||
struct virtio_gpu_fence *fence = NULL;
|
||||
struct ww_acquire_ctx ticket;
|
||||
struct virtio_gpu_object_params params = { 0 };
|
||||
|
||||
if (vgdev->has_virgl_3d == false) {
|
||||
@@ -298,14 +295,12 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&validate_list);
|
||||
memset(&mainbuf, 0, sizeof(struct ttm_validate_buffer));
|
||||
|
||||
params.format = rc->format;
|
||||
params.width = rc->width;
|
||||
params.height = rc->height;
|
||||
params.size = rc->size;
|
||||
if (vgdev->has_virgl_3d) {
|
||||
params.virgl = true;
|
||||
params.target = rc->target;
|
||||
params.bind = rc->bind;
|
||||
params.depth = rc->depth;
|
||||
@@ -318,72 +313,25 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
|
||||
if (params.size == 0)
|
||||
params.size = PAGE_SIZE;
|
||||
|
||||
qobj = virtio_gpu_alloc_object(dev, ¶ms);
|
||||
fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!fence)
|
||||
return -ENOMEM;
|
||||
qobj = virtio_gpu_alloc_object(dev, ¶ms, fence);
|
||||
dma_fence_put(&fence->f);
|
||||
if (IS_ERR(qobj))
|
||||
return PTR_ERR(qobj);
|
||||
obj = &qobj->gem_base;
|
||||
|
||||
if (!vgdev->has_virgl_3d) {
|
||||
virtio_gpu_cmd_create_resource(vgdev, qobj, ¶ms);
|
||||
|
||||
ret = virtio_gpu_object_attach(vgdev, qobj, NULL);
|
||||
} else {
|
||||
/* use a gem reference since unref list undoes them */
|
||||
drm_gem_object_get(&qobj->gem_base);
|
||||
mainbuf.bo = &qobj->tbo;
|
||||
list_add(&mainbuf.head, &validate_list);
|
||||
|
||||
ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
|
||||
if (ret) {
|
||||
DRM_DEBUG("failed to validate\n");
|
||||
goto fail_unref;
|
||||
}
|
||||
|
||||
fence = virtio_gpu_fence_alloc(vgdev);
|
||||
if (!fence) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_backoff;
|
||||
}
|
||||
|
||||
virtio_gpu_cmd_resource_create_3d(vgdev, qobj, ¶ms);
|
||||
ret = virtio_gpu_object_attach(vgdev, qobj, fence);
|
||||
if (ret) {
|
||||
dma_fence_put(&fence->f);
|
||||
goto fail_backoff;
|
||||
}
|
||||
ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
|
||||
}
|
||||
|
||||
ret = drm_gem_handle_create(file_priv, obj, &handle);
|
||||
if (ret) {
|
||||
|
||||
drm_gem_object_release(obj);
|
||||
if (vgdev->has_virgl_3d) {
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
dma_fence_put(&fence->f);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
|
||||
rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
|
||||
rc->bo_handle = handle;
|
||||
|
||||
if (vgdev->has_virgl_3d) {
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
dma_fence_put(&fence->f);
|
||||
}
|
||||
return 0;
|
||||
fail_backoff:
|
||||
ttm_eu_backoff_reservation(&ticket, &validate_list);
|
||||
fail_unref:
|
||||
if (vgdev->has_virgl_3d) {
|
||||
virtio_gpu_unref_list(&validate_list);
|
||||
dma_fence_put(&fence->f);
|
||||
}
|
||||
//fail_obj:
|
||||
// drm_gem_object_handle_unreference_unlocked(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
|
||||
|
Reference in New Issue
Block a user