diff options
Diffstat (limited to 'drivers/gpu/drm/virtio')
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_display.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_drv.h | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_fence.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_ioctl.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_plane.c | 112 | ||||
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_vq.c | 42 |
8 files changed, 129 insertions, 93 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index e622485ae826..0966208ec30d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -43,6 +43,9 @@ #define XRES_MAX 8192 #define YRES_MAX 8192 +#define drm_connector_to_virtio_gpu_output(x) \ + container_of(x, struct virtio_gpu_output, conn) + static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = drm_crtc_cleanup, @@ -59,7 +62,7 @@ static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { .dirty = drm_atomic_helper_dirtyfb, }; -int +static int virtio_gpu_framebuffer_init(struct drm_device *dev, struct virtio_gpu_framebuffer *vgfb, const struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 8dee698c90ff..8cf27af3ad53 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -137,7 +137,7 @@ static void virtio_gpu_remove(struct virtio_device *vdev) drm_dev_unregister(dev); virtio_gpu_deinit(dev); - drm_put_dev(dev); + drm_dev_put(dev); } static void virtio_gpu_config_changed(struct virtio_device *vdev) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 0b56ba005e25..7e69c06e168e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -38,6 +38,7 @@ #include <drm/drm_gem_shmem_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_probe_helper.h> +#include <drm/virtgpu_drm.h> #define DRIVER_NAME "virtio_gpu" #define DRIVER_DESC "virtio GPU" @@ -102,8 +103,6 @@ struct virtio_gpu_fence { struct virtio_gpu_fence_driver *drv; struct list_head node; }; -#define to_virtio_fence(x) \ - container_of(x, struct virtio_gpu_fence, f) struct virtio_gpu_vbuffer { char *buf; @@ -134,10 +133,6 @@ struct virtio_gpu_output { }; #define drm_crtc_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, crtc) -#define drm_connector_to_virtio_gpu_output(x) \ - container_of(x, struct virtio_gpu_output, conn) -#define drm_encoder_to_virtio_gpu_output(x) \ - container_of(x, struct virtio_gpu_output, enc) struct virtio_gpu_framebuffer { struct drm_framebuffer base; @@ -182,6 +177,9 @@ struct virtio_gpu_device { struct kmem_cache *vbufs; bool vqs_ready; + bool disable_notify; + bool pending_notify; + struct ida resource_ida; wait_queue_head_t resp_wq; @@ -312,13 +310,13 @@ void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev, void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, uint32_t ctx_id, uint64_t offset, uint32_t level, - struct virtio_gpu_box *box, + struct drm_virtgpu_3d_box *box, struct virtio_gpu_object_array *objs, struct virtio_gpu_fence *fence); void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, uint32_t ctx_id, uint64_t offset, uint32_t level, - struct virtio_gpu_box *box, + struct drm_virtgpu_3d_box *box, struct virtio_gpu_object_array *objs, struct virtio_gpu_fence *fence); void @@ -334,11 +332,10 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work); void virtio_gpu_dequeue_cursor_func(struct work_struct *work); void virtio_gpu_dequeue_fence_func(struct work_struct *work); +void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev); +void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev); + /* virtio_gpu_display.c */ -int virtio_gpu_framebuffer_init(struct drm_device *dev, - struct virtio_gpu_framebuffer *vgfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev); @@ -349,7 +346,6 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, int index); /* virtio_gpu_fence.c */ -bool virtio_fence_signaled(struct dma_fence *f); struct virtio_gpu_fence *virtio_gpu_fence_alloc( struct virtio_gpu_device *vgdev); void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, @@ -365,18 +361,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_params *params, struct virtio_gpu_object **bo_ptr, struct virtio_gpu_fence *fence); - /* virtgpu_prime.c */ struct drm_gem_object *virtgpu_gem_prime_import_sg_table( struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); -static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo) -{ - return drm_vma_node_offset_addr(&bo->base.base.vma_node); -} - -/* virgl debufs */ +/* virgl debugfs */ int virtio_gpu_debugfs_init(struct drm_minor *minor); #endif diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index a4b9881ca1d3..5b2a4146c5bd 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -27,6 +27,9 @@ #include "virtgpu_drv.h" +#define to_virtio_fence(x) \ + container_of(x, struct virtio_gpu_fence, f) + static const char *virtio_get_driver_name(struct dma_fence *f) { return "virtio_gpu"; @@ -37,7 +40,7 @@ static const char *virtio_get_timeline_name(struct dma_fence *f) return "controlq"; } -bool virtio_fence_signaled(struct dma_fence *f) +static bool virtio_fence_signaled(struct dma_fence *f) { struct virtio_gpu_fence *fence = to_virtio_fence(f); diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 4c1f579edfb3..0a2b62279647 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -96,14 +96,12 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, uint32_t handle, uint64_t *offset_p) { struct drm_gem_object *gobj; - struct virtio_gpu_object *obj; BUG_ON(!offset_p); gobj = drm_gem_object_lookup(file_priv, handle); if (gobj == NULL) return -ENOENT; - obj = gem_to_virtio_gpu_obj(gobj); - *offset_p = virtio_gpu_object_mmap_offset(obj); + *offset_p = drm_vma_node_offset_addr(&gobj->vma_node); drm_gem_object_put_unlocked(gobj); return 0; } diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 9af1ec62434f..205ec4abae2b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -33,17 +33,6 @@ #include "virtgpu_drv.h" -static void convert_to_hw_box(struct virtio_gpu_box *dst, - const struct drm_virtgpu_3d_box *src) -{ - dst->x = cpu_to_le32(src->x); - dst->y = cpu_to_le32(src->y); - dst->z = cpu_to_le32(src->z); - dst->w = cpu_to_le32(src->w); - dst->h = cpu_to_le32(src->h); - dst->d = cpu_to_le32(src->d); -} - static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -304,7 +293,6 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, struct virtio_gpu_fence *fence; int ret; u32 offset = args->offset; - struct virtio_gpu_box box; if (vgdev->has_virgl_3d == false) return -ENOSYS; @@ -317,8 +305,6 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, if (ret != 0) goto err_put_free; - convert_to_hw_box(&box, &args->box); - fence = virtio_gpu_fence_alloc(vgdev); if (!fence) { ret = -ENOMEM; @@ -326,7 +312,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, } virtio_gpu_cmd_transfer_from_host_3d (vgdev, vfpriv->ctx_id, offset, args->level, - &box, objs, fence); + &args->box, objs, fence); dma_fence_put(&fence->f); return 0; @@ -345,7 +331,6 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, struct drm_virtgpu_3d_transfer_to_host *args = data; struct virtio_gpu_object_array *objs; struct virtio_gpu_fence *fence; - struct virtio_gpu_box box; int ret; u32 offset = args->offset; @@ -353,11 +338,10 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, if (objs == NULL) return -ENOENT; - convert_to_hw_box(&box, &args->box); if (!vgdev->has_virgl_3d) { virtio_gpu_cmd_transfer_to_host_2d (vgdev, offset, - box.w, box.h, box.x, box.y, + args->box.w, args->box.h, args->box.x, args->box.y, objs, NULL); } else { ret = virtio_gpu_array_lock_resv(objs); @@ -372,7 +356,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, virtio_gpu_cmd_transfer_to_host_3d (vgdev, vfpriv ? vfpriv->ctx_id : 0, offset, - args->level, &box, objs, fence); + args->level, &args->box, objs, fence); dma_fence_put(&fence->f); } return 0; diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 1635a9ff4794..d1c3f5fbfee4 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -24,6 +24,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> @@ -88,7 +89,7 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, struct drm_crtc_state *crtc_state; int ret; - if (!state->fb || !state->crtc) + if (!state->fb || WARN_ON(!state->crtc)) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); @@ -102,15 +103,37 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, return ret; } +static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, + struct drm_plane_state *state, + struct drm_rect *rect) +{ + struct virtio_gpu_object *bo = + gem_to_virtio_gpu_obj(state->fb->obj[0]); + struct virtio_gpu_object_array *objs; + uint32_t w = rect->x2 - rect->x1; + uint32_t h = rect->y2 - rect->y1; + uint32_t x = rect->x1; + uint32_t y = rect->y1; + uint32_t off = x * state->fb->format->cpp[0] + + y * state->fb->pitches[0]; + + objs = virtio_gpu_array_alloc(1); + if (!objs) + return; + virtio_gpu_array_add_obj(objs, &bo->base.base); + + virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y, + objs, NULL); +} + static void virtio_gpu_primary_plane_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct drm_device *dev = plane->dev; struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_output *output = NULL; - struct virtio_gpu_framebuffer *vgfb; struct virtio_gpu_object *bo; - uint32_t handle; + struct drm_rect rect; if (plane->state->crtc) output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); @@ -119,47 +142,52 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, if (WARN_ON(!output)) return; - if (plane->state->fb && output->enabled) { - vgfb = to_virtio_gpu_framebuffer(plane->state->fb); - bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); - handle = bo->hw_res_handle; - if (bo->dumb) { - struct virtio_gpu_object_array *objs; - - objs = virtio_gpu_array_alloc(1); - if (!objs) - return; - virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]); - virtio_gpu_cmd_transfer_to_host_2d - (vgdev, 0, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->src_x >> 16, - plane->state->src_y >> 16, - objs, NULL); - } - } else { - handle = 0; + if (!plane->state->fb || !output->enabled) { + DRM_DEBUG("nofb\n"); + virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + 0, 0); + return; } - DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", handle, - plane->state->crtc_w, plane->state->crtc_h, - plane->state->crtc_x, plane->state->crtc_y, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->src_x >> 16, - plane->state->src_y >> 16); - virtio_gpu_cmd_set_scanout(vgdev, output->index, handle, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->src_x >> 16, - plane->state->src_y >> 16); - if (handle) - virtio_gpu_cmd_resource_flush(vgdev, handle, - plane->state->src_x >> 16, - plane->state->src_y >> 16, - plane->state->src_w >> 16, - plane->state->src_h >> 16); + if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect)) + return; + + virtio_gpu_disable_notify(vgdev); + + bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); + if (bo->dumb) + virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect); + + if (plane->state->fb != old_state->fb || + plane->state->src_w != old_state->src_w || + plane->state->src_h != old_state->src_h || + plane->state->src_x != old_state->src_x || + plane->state->src_y != old_state->src_y) { + DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", + bo->hw_res_handle, + plane->state->crtc_w, plane->state->crtc_h, + plane->state->crtc_x, plane->state->crtc_y, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16); + virtio_gpu_cmd_set_scanout(vgdev, output->index, + bo->hw_res_handle, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16); + } + + virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, + rect.x1, + rect.y1, + rect.x2 - rect.x1, + rect.y2 - rect.y1); + + virtio_gpu_enable_notify(vgdev); } static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane, diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 74ad3bc3ebe8..5914e79d3429 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -40,6 +40,17 @@ + MAX_INLINE_CMD_SIZE \ + MAX_INLINE_RESP_SIZE) +static void convert_to_hw_box(struct virtio_gpu_box *dst, + const struct drm_virtgpu_3d_box *src) +{ + dst->x = cpu_to_le32(src->x); + dst->y = cpu_to_le32(src->y); + dst->z = cpu_to_le32(src->z); + dst->w = cpu_to_le32(src->w); + dst->h = cpu_to_le32(src->h); + dst->d = cpu_to_le32(src->d); +} + void virtio_gpu_ctrl_ack(struct virtqueue *vq) { struct drm_device *dev = vq->vdev->priv; @@ -393,8 +404,12 @@ again: } notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout); spin_unlock(&vgdev->ctrlq.qlock); - if (notify) - virtqueue_notify(vgdev->ctrlq.vq); + if (notify) { + if (vgdev->disable_notify) + vgdev->pending_notify = true; + else + virtqueue_notify(vgdev->ctrlq.vq); + } if (sgt) { sg_free_table(sgt); @@ -402,6 +417,21 @@ again: } } +void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev) +{ + vgdev->disable_notify = true; +} + +void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev) +{ + vgdev->disable_notify = false; + + if (!vgdev->pending_notify) + return; + vgdev->pending_notify = false; + virtqueue_notify(vgdev->ctrlq.vq); +} + static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev, struct virtio_gpu_vbuffer *vbuf) { @@ -965,7 +995,7 @@ virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev, void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, uint32_t ctx_id, uint64_t offset, uint32_t level, - struct virtio_gpu_box *box, + struct drm_virtgpu_3d_box *box, struct virtio_gpu_object_array *objs, struct virtio_gpu_fence *fence) { @@ -987,7 +1017,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D); cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); - cmd_p->box = *box; + convert_to_hw_box(&cmd_p->box, box); cmd_p->offset = cpu_to_le64(offset); cmd_p->level = cpu_to_le32(level); @@ -997,7 +1027,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, uint32_t ctx_id, uint64_t offset, uint32_t level, - struct virtio_gpu_box *box, + struct drm_virtgpu_3d_box *box, struct virtio_gpu_object_array *objs, struct virtio_gpu_fence *fence) { @@ -1013,7 +1043,7 @@ void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D); cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id); cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); - cmd_p->box = *box; + convert_to_hw_box(&cmd_p->box, box); cmd_p->offset = cpu_to_le64(offset); cmd_p->level = cpu_to_le32(level); |