diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_3d.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_display.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_drv.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_dumb.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_fb.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_gem.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_hw.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/virgl/virgl_ioctl.c | 86 |
8 files changed, 150 insertions, 74 deletions
diff --git a/drivers/gpu/drm/virgl/virgl_3d.c b/drivers/gpu/drm/virgl/virgl_3d.c index d585ab480036..342c2f4c2274 100644 --- a/drivers/gpu/drm/virgl/virgl_3d.c +++ b/drivers/gpu/drm/virgl/virgl_3d.c @@ -543,7 +543,7 @@ int virgl_execbuffer(struct drm_device *dev, //printk("user cmd size %d\n", user_cmd.command_size); - ret = virgl_gem_object_create(qdev, execbuffer->size + 4, + ret = virgl_gem_object_create(qdev, execbuffer->size, 0, 0, false, true, &gobj); @@ -566,8 +566,7 @@ int virgl_execbuffer(struct drm_device *dev, if (ret) goto out_unresv; - *(uint32_t *)optr = vfpriv->ctx_id; - if (DRM_COPY_FROM_USER(optr + 4, (void *)(unsigned long)execbuffer->command, + if (DRM_COPY_FROM_USER(optr, (void *)(unsigned long)execbuffer->command, execbuffer->size)) { ret = -EFAULT; goto out_kunmap; @@ -584,8 +583,8 @@ int virgl_execbuffer(struct drm_device *dev, goto out_unresv; cmd_p->type = VIRGL_CMD_SUBMIT; - cmd_p->u.cmd_submit.size = execbuffer->size + 4; - + cmd_p->u.cmd_submit.size = execbuffer->size; + cmd_p->u.cmd_submit.ctx_id = vfpriv->ctx_id; cmd_p->u.cmd_submit.phy_addr = 0; ret = virgl_fence_emit(qdev, cmd_p, &fence); @@ -778,6 +777,7 @@ int virgl_3d_set_front(struct virgl_device *qdev, cmd_p->u.set_scanout.box.y = y; cmd_p->u.set_scanout.box.w = width; cmd_p->u.set_scanout.box.h = height; + cmd_p->u.set_scanout.ctx_id = 0; virgl_queue_cmd_buf(qdev, vbuf); return 0; } @@ -798,6 +798,7 @@ int virgl_3d_dirty_front(struct virgl_device *qdev, cmd_p->u.flush_buffer.box.y = y; cmd_p->u.flush_buffer.box.w = width; cmd_p->u.flush_buffer.box.h = height; + cmd_p->u.flush_buffer.ctx_id = 0; virgl_queue_cmd_buf(qdev, vbuf); return 0; } @@ -907,3 +908,39 @@ int virgl_context_destroy(struct virgl_device *qdev, uint32_t id) virgl_ctx_id_put(qdev, id); return 0; } + +int virgl_context_bind_resource(struct virgl_device *qdev, uint32_t ctx_id, + uint32_t res_handle) +{ + struct virgl_command *cmd_p; + struct virgl_vbuffer *vbuf; + + cmd_p = virgl_alloc_cmd(qdev, NULL, false, NULL, 0, &vbuf); + if (IS_ERR(cmd_p)) + return PTR_ERR(cmd_p); + + cmd_p->type = VIRGL_CMD_ATTACH_RES_CTX; + cmd_p->u.res_ctx.res_handle = res_handle; + cmd_p->u.res_ctx.ctx_id = ctx_id; + virgl_queue_cmd_buf(qdev, vbuf); + + return 0; +} + +int virgl_context_unbind_resource(struct virgl_device *qdev, uint32_t ctx_id, + uint32_t res_handle) +{ + struct virgl_command *cmd_p; + struct virgl_vbuffer *vbuf; + + cmd_p = virgl_alloc_cmd(qdev, NULL, false, NULL, 0, &vbuf); + if (IS_ERR(cmd_p)) + return PTR_ERR(cmd_p); + + cmd_p->type = VIRGL_CMD_DETACH_RES_CTX; + cmd_p->u.res_ctx.res_handle = res_handle; + cmd_p->u.res_ctx.ctx_id = ctx_id; + virgl_queue_cmd_buf(qdev, vbuf); + + return 0; +} diff --git a/drivers/gpu/drm/virgl/virgl_display.c b/drivers/gpu/drm/virgl/virgl_display.c index 408e3dff52a0..ea24b5d24223 100644 --- a/drivers/gpu/drm/virgl/virgl_display.c +++ b/drivers/gpu/drm/virgl/virgl_display.c @@ -131,7 +131,7 @@ static int virgl_crtc_cursor_set(struct drm_crtc *crtc, cmd_p->type = VIRGL_TRANSFER_PUT; cmd_p->u.transfer_put.res_handle = qobj->res_handle; - + cmd_p->u.transfer_put.ctx_id = 0; cmd_p->u.transfer_put.dst_box.x = 0; cmd_p->u.transfer_put.dst_box.y = 0; cmd_p->u.transfer_put.dst_box.z = 0; @@ -202,18 +202,15 @@ int virgl_framebuffer_init(struct drm_device *dev, struct virgl_framebuffer *qfb, struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj, - uint32_t res_handle) + struct drm_gem_object *obj) { int ret; - + struct virgl_bo *bo; qfb->obj = obj; - if (obj) { - struct virgl_bo *bo; - bo = gem_to_virgl_bo(obj); - qfb->res_3d_handle = bo->res_handle; - } else - qfb->res_3d_handle = res_handle; + + bo = gem_to_virgl_bo(obj); + qfb->res_3d_handle = bo->res_handle; + ret = drm_framebuffer_init(dev, &qfb->base, &virgl_fb_funcs); if (ret) { qfb->obj = NULL; @@ -483,19 +480,17 @@ virgl_user_framebuffer_create(struct drm_device *dev, struct virgl_framebuffer *virgl_fb; struct virgl_device *qdev = dev->dev_private; int ret; - int handle = 0; /* lookup object associated with res handle */ - handle = mode_cmd->handles[0]; - - if (handle & (1 << 31)) - obj = drm_gem_object_lookup(dev, file_priv, handle & ~(1 << 31)); + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) + return PTR_ERR(-EINVAL); virgl_fb = kzalloc(sizeof(*virgl_fb), GFP_KERNEL); if (virgl_fb == NULL) - return NULL; + return PTR_ERR(-ENOMEM); - ret = virgl_framebuffer_init(dev, virgl_fb, mode_cmd, obj, handle); + ret = virgl_framebuffer_init(dev, virgl_fb, mode_cmd, obj); if (ret) { kfree(virgl_fb); if (obj) diff --git a/drivers/gpu/drm/virgl/virgl_drv.h b/drivers/gpu/drm/virgl/virgl_drv.h index 5a9deccd19f8..230ddabe2237 100644 --- a/drivers/gpu/drm/virgl/virgl_drv.h +++ b/drivers/gpu/drm/virgl/virgl_drv.h @@ -251,9 +251,9 @@ int virgl_create_3d_fb_res(struct virgl_device *qdev, int width, int height, uin /* virgl_display.c */ int virgl_framebuffer_init(struct drm_device *dev, - struct virgl_framebuffer *rfb, - struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj, uint32_t res_handle); + struct virgl_framebuffer *rfb, + struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); /* virgl_gem.c */ int virgl_gem_init(struct virgl_device *qdev); @@ -334,7 +334,10 @@ int virgl_3d_surface_dirty(struct virgl_framebuffer *qfb, struct drm_clip_rect * unsigned num_clips); int virgl_context_create(struct virgl_device *qdev, uint32_t *id); int virgl_context_destroy(struct virgl_device *qdev, uint32_t id); - +int virgl_context_bind_resource(struct virgl_device *qdev, uint32_t ctx_id, + uint32_t res_handle); +int virgl_context_unbind_resource(struct virgl_device *qdev, uint32_t ctx_id, + uint32_t res_handle); struct virgl_command *virgl_alloc_cmd_buf(struct virgl_device *qdev, struct virgl_bo *qobj, bool inout, diff --git a/drivers/gpu/drm/virgl/virgl_dumb.c b/drivers/gpu/drm/virgl/virgl_dumb.c index 3c02cccac38f..54c423ae7c98 100644 --- a/drivers/gpu/drm/virgl/virgl_dumb.c +++ b/drivers/gpu/drm/virgl/virgl_dumb.c @@ -53,7 +53,7 @@ int virgl_mode_dumb_create(struct drm_file *file_priv, return r; args->pitch = pitch; - args->handle = handle | (1 << 31); + args->handle = handle; return 0; } @@ -61,7 +61,7 @@ int virgl_mode_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle) { - return drm_gem_handle_delete(file_priv, (handle & ~(1<<31))); + return drm_gem_handle_delete(file_priv, handle); } int virgl_mode_dumb_mmap(struct drm_file *file_priv, @@ -72,7 +72,7 @@ int virgl_mode_dumb_mmap(struct drm_file *file_priv, struct virgl_bo *qobj; BUG_ON(!offset_p); - gobj = drm_gem_object_lookup(dev, file_priv, handle & ~(1<<31)); + gobj = drm_gem_object_lookup(dev, file_priv, handle); if (gobj == NULL) return -ENOENT; qobj = gem_to_virgl_bo(gobj); diff --git a/drivers/gpu/drm/virgl/virgl_fb.c b/drivers/gpu/drm/virgl/virgl_fb.c index e577c5f28244..66e95418fa63 100644 --- a/drivers/gpu/drm/virgl/virgl_fb.c +++ b/drivers/gpu/drm/virgl/virgl_fb.c @@ -356,7 +356,7 @@ static int virglfb_create(struct virgl_fbdev *qfbdev, if (ret) { goto out_unref; } - virgl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, 0); + virgl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj); fb = &qfbdev->qfb.base; diff --git a/drivers/gpu/drm/virgl/virgl_gem.c b/drivers/gpu/drm/virgl/virgl_gem.c index a399d9b5dfe9..04a5e0e9c942 100644 --- a/drivers/gpu/drm/virgl/virgl_gem.c +++ b/drivers/gpu/drm/virgl/virgl_gem.c @@ -125,14 +125,38 @@ void virgl_gem_object_unpin(struct drm_gem_object *obj) } } -int virgl_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) +int virgl_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file) { - return 0; + struct virgl_device *qdev = (struct virgl_device *)obj->dev->dev_private; + struct virgl_fpriv *vfpriv = file->driver_priv; + struct virgl_bo *qobj = gem_to_virgl_bo(obj); + int r; + + r = virgl_bo_reserve(qobj, false); + if (r) + return r; + + r = virgl_context_bind_resource(qdev, vfpriv->ctx_id, qobj->res_handle); + virgl_bo_unreserve(qobj); + return r; } void virgl_gem_object_close(struct drm_gem_object *obj, - struct drm_file *file_priv) + struct drm_file *file) { + struct virgl_device *qdev = (struct virgl_device *)obj->dev->dev_private; + struct virgl_fpriv *vfpriv = file->driver_priv; + struct virgl_bo *qobj = gem_to_virgl_bo(obj); + int r; + + r = virgl_bo_reserve(qobj, false); + if (r) + return r; + + r = virgl_context_unbind_resource(qdev, vfpriv->ctx_id, qobj->res_handle); + virgl_bo_unreserve(qobj); + return r; } int virgl_gem_init(struct virgl_device *qdev) diff --git a/drivers/gpu/drm/virgl/virgl_hw.h b/drivers/gpu/drm/virgl/virgl_hw.h index 8d0f86746507..348b859590a0 100644 --- a/drivers/gpu/drm/virgl/virgl_hw.h +++ b/drivers/gpu/drm/virgl/virgl_hw.h @@ -23,6 +23,8 @@ enum virgl_cmd_type { VIRGL_SET_SCANOUT, VIRGL_FLUSH_BUFFER, VIRGL_RESOURCE_UNREF, + VIRGL_CMD_ATTACH_RES_CTX, + VIRGL_CMD_DETACH_RES_CTX, }; /* put a box of data from a BO into a tex/buffer resource */ @@ -32,6 +34,7 @@ struct virgl_transfer_put { struct virgl_box dst_box; /* dst box */ uint32_t dst_level; uint32_t src_stride; + uint32_t ctx_id; }; struct virgl_transfer_get { @@ -40,15 +43,18 @@ struct virgl_transfer_get { struct virgl_box box; int level; uint32_t dx, dy; + uint32_t ctx_id; }; struct virgl_flush_buffer { uint32_t res_handle; + uint32_t ctx_id; struct virgl_box box; }; struct virgl_set_scanout { uint32_t res_handle; + uint32_t ctx_id; struct virgl_box box; }; @@ -73,6 +79,7 @@ struct virgl_resource_unref { struct virgl_cmd_submit { uint64_t phy_addr; uint32_t size; + uint32_t ctx_id; }; struct virgl_cmd_context { @@ -80,6 +87,11 @@ struct virgl_cmd_context { uint32_t pad; }; +struct virgl_cmd_resource_context { + uint32_t res_handle; + uint32_t ctx_id; +}; + #define VIRGL_COMMAND_EMIT_FENCE (1 << 0) struct virgl_command { @@ -95,6 +107,7 @@ struct virgl_command { struct virgl_set_scanout set_scanout; struct virgl_flush_buffer flush_buffer; struct virgl_resource_unref res_unref; + struct virgl_cmd_resource_context res_ctx; } u; }; diff --git a/drivers/gpu/drm/virgl/virgl_ioctl.c b/drivers/gpu/drm/virgl/virgl_ioctl.c index 14d092f68f06..f40a6e886e34 100644 --- a/drivers/gpu/drm/virgl/virgl_ioctl.c +++ b/drivers/gpu/drm/virgl/virgl_ioctl.c @@ -95,16 +95,27 @@ static int virgl_resource_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct virgl_device *qdev = dev->dev_private; - struct drm_virgl_3d_resource_create *rc = data; + struct drm_virgl_resource_create *rc = data; struct virgl_command *cmd_p; struct virgl_vbuffer *vbuf; int ret; uint32_t res_id; + struct virgl_bo *qobj; + uint32_t handle; ret = virgl_resource_id_get(qdev, &res_id); - if (ret) + if (ret) return ret; + ret = virgl_gem_object_create_with_handle(qdev, file_priv, + 0, + rc->size, + &qobj, &handle); + if (ret) { + virgl_resource_id_put(qdev, res_id); + return ret; + } + cmd_p = virgl_alloc_cmd(qdev, NULL, false, NULL, 0, &vbuf); memset(cmd_p, 0, sizeof(*cmd_p)); cmd_p->type = VIRGL_CMD_CREATE_RESOURCE; @@ -121,7 +132,29 @@ static int virgl_resource_create_ioctl(struct drm_device *dev, void *data, virgl_queue_cmd_buf(qdev, vbuf); - rc->res_handle = res_id; + qobj->res_handle = res_id; + rc->res_handle = res_id; /* similiar to a VM address */ + rc->bo_handle = handle; + return 0; +} + +static int virgl_resource_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct virgl_device *qdev = dev->dev_private; + struct drm_virgl_resource_info *ri = data; + struct drm_gem_object *gobj = NULL; + struct virgl_bo *qobj = NULL; + + gobj = drm_gem_object_lookup(dev, file_priv, ri->bo_handle); + if (gobj == NULL) + return -ENOENT; + + qobj = gem_to_virgl_bo(gobj); + + ri->size = qobj->gem_base.size; + ri->res_handle = qobj->res_handle; + drm_gem_object_unreference_unlocked(gobj); return 0; } @@ -138,22 +171,14 @@ int virgl_resource_unref(struct virgl_device *qdev, uint32_t res_handle) virgl_queue_cmd_buf(qdev, vbuf); virgl_resource_id_put(qdev, res_handle); -} - -static int virgl_resource_unref_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct virgl_device *qdev = dev->dev_private; - struct drm_virgl_3d_resource_unref *ru = data; - - virgl_resource_unref(qdev, ru->res_handle); return 0; } - + static int virgl_transfer_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct virgl_device *qdev = dev->dev_private; + struct virgl_fpriv *vfpriv = file->driver_priv; struct drm_virgl_3d_transfer_get *args = data; struct virgl_command *cmd_p; struct virgl_vbuffer *vbuf; @@ -183,11 +208,11 @@ static int virgl_transfer_get_ioctl(struct drm_device *dev, void *data, cmd_p->type = VIRGL_TRANSFER_GET; - cmd_p->u.transfer_get.res_handle = args->res_handle; + cmd_p->u.transfer_get.res_handle = qobj->res_handle; convert_to_hw_box(&cmd_p->u.transfer_get.box, &args->box); cmd_p->u.transfer_get.level = args->level; cmd_p->u.transfer_get.data = offset; - + cmd_p->u.transfer_get.ctx_id = vfpriv->ctx_id; ret = virgl_fence_emit(qdev, cmd_p, &fence); virgl_queue_cmd_buf(qdev, vbuf); @@ -205,6 +230,7 @@ static int virgl_transfer_put_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct virgl_device *qdev = dev->dev_private; + struct virgl_fpriv *vfpriv = file->driver_priv; struct drm_virgl_3d_transfer_put *args = data; struct virgl_command *cmd_p; struct virgl_vbuffer *vbuf; @@ -238,12 +264,12 @@ static int virgl_transfer_put_ioctl(struct drm_device *dev, void *data, cmd_p = virgl_alloc_cmd(qdev, qobj, false, &offset, max_size, &vbuf); memset(cmd_p, 0, sizeof(*cmd_p)); cmd_p->type = VIRGL_TRANSFER_PUT; - cmd_p->u.transfer_put.res_handle = args->res_handle; + cmd_p->u.transfer_put.res_handle = qobj->res_handle; convert_to_hw_box(&cmd_p->u.transfer_put.dst_box, &args->dst_box); cmd_p->u.transfer_put.dst_level = args->dst_level; cmd_p->u.transfer_put.src_stride = args->src_stride; cmd_p->u.transfer_put.data = offset; - + cmd_p->u.transfer_put.ctx_id = vfpriv->ctx_id; ret = virgl_fence_emit(qdev, cmd_p, &fence); virgl_queue_cmd_buf(qdev, vbuf); @@ -257,7 +283,7 @@ out_unres: } static int virgl_wait_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) + struct drm_file *file) { struct drm_virgl_3d_wait *args = data; struct drm_gem_object *gobj = NULL; @@ -279,25 +305,6 @@ static int virgl_wait_ioctl(struct drm_device *dev, void *data, return ret; } -static int virgl_cursor_link_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_virgl_cursor_link *args = data; - struct drm_gem_object *gobj = NULL; - struct virgl_bo *qobj = NULL; - - gobj = drm_gem_object_lookup(dev, file, args->bo_handle); - if (gobj == NULL) - return -ENOENT; - - qobj = gem_to_virgl_bo(gobj); - - qobj->res_handle = args->res_handle; - drm_gem_object_unreference_unlocked(gobj); - - return 0; -} - struct drm_ioctl_desc virgl_ioctls[] = { DRM_IOCTL_DEF_DRV(VIRGL_ALLOC, virgl_alloc_ioctl, DRM_AUTH|DRM_UNLOCKED), @@ -310,17 +317,14 @@ struct drm_ioctl_desc virgl_ioctls[] = { DRM_IOCTL_DEF_DRV(VIRGL_RESOURCE_CREATE, virgl_resource_create_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(VIRGL_RESOURCE_INFO, virgl_resource_info_ioctl, DRM_AUTH|DRM_UNLOCKED), /* make transfer async to the main ring? - no sure, can we thread these in the underlying GL */ DRM_IOCTL_DEF_DRV(VIRGL_TRANSFER_GET, virgl_transfer_get_ioctl, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(VIRGL_TRANSFER_PUT, virgl_transfer_put_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(VIRGL_RESOURCE_UNREF, virgl_resource_unref_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(VIRGL_WAIT, virgl_wait_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(VIRGL_CURSOR_LINK, virgl_cursor_link_ioctl, DRM_AUTH|DRM_UNLOCKED), - }; int virgl_max_ioctls = DRM_ARRAY_SIZE(virgl_ioctls); |