@@ -754,33 +754,21 @@ static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
qemu_bh_schedule(g->cursor_bh);
}
-static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+static void virtio_gpu_process_cmdq(VirtIOGPU *g)
{
- VirtIOGPU *g = VIRTIO_GPU(vdev);
struct virtio_gpu_ctrl_command *cmd;
- if (!virtio_queue_ready(vq)) {
- return;
- }
-
-#ifdef CONFIG_VIRGL
- if (!g->renderer_inited && g->use_virgl_renderer) {
- virtio_gpu_virgl_init(g);
- g->renderer_inited = true;
- }
-#endif
-
- cmd = g_new(struct virtio_gpu_ctrl_command, 1);
- while (virtqueue_pop(vq, &cmd->elem)) {
- cmd->vq = vq;
- cmd->error = 0;
- cmd->finished = false;
- if (virtio_gpu_stats_enabled(g->conf)) {
- g->stats.requests++;
- }
+ while (!QTAILQ_EMPTY(&g->cmdq)) {
+ cmd = QTAILQ_FIRST(&g->cmdq);
+ /* process command */
VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd,
g, cmd);
+ QTAILQ_REMOVE(&g->cmdq, cmd, next);
+ if (virtio_gpu_stats_enabled(g->conf)) {
+ g->stats.requests++;
+ }
+
if (!cmd->finished) {
QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
g->inflight++;
@@ -790,11 +778,41 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
}
fprintf(stderr, "inflight: %3d (+)\r", g->inflight);
}
- cmd = g_new(struct virtio_gpu_ctrl_command, 1);
+ } else {
+ g_free(cmd);
}
}
+}
+
+static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOGPU *g = VIRTIO_GPU(vdev);
+ struct virtio_gpu_ctrl_command *cmd;
+
+ if (!virtio_queue_ready(vq)) {
+ return;
+ }
+
+#ifdef CONFIG_VIRGL
+ if (!g->renderer_inited && g->use_virgl_renderer) {
+ virtio_gpu_virgl_init(g);
+ g->renderer_inited = true;
+ }
+#endif
+
+ cmd = g_new(struct virtio_gpu_ctrl_command, 1);
+ while (virtqueue_pop(vq, &cmd->elem)) {
+ cmd->vq = vq;
+ cmd->error = 0;
+ cmd->finished = false;
+ cmd->waiting = false;
+ QTAILQ_INSERT_TAIL(&g->cmdq, cmd, next);
+ cmd = g_new(struct virtio_gpu_ctrl_command, 1);
+ }
g_free(cmd);
+ virtio_gpu_process_cmdq(g);
+
#ifdef CONFIG_VIRGL
if (g->use_virgl_renderer) {
virtio_gpu_virgl_fence_poll(g);
@@ -920,6 +938,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
QTAILQ_INIT(&g->reslist);
+ QTAILQ_INIT(&g->cmdq);
QTAILQ_INIT(&g->fenceq);
g->enabled_output_bitmask = 1;
@@ -94,6 +94,7 @@ typedef struct VirtIOGPU {
DeviceState *qdev;
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
+ QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUT];
We'll go take out the commands we receive out of the virt queue and put them into a linked list, to decouple virtio queue handling from actual command processing. Also move cmd processing to new virtio_gpu_handle_ctrl func, so we can easily kick it from different places. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- hw/display/virtio-gpu.c | 63 +++++++++++++++++++++++++++--------------- include/hw/virtio/virtio-gpu.h | 1 + 2 files changed, 42 insertions(+), 22 deletions(-)