Allow virtio_gpu_virgl_unmap_resource_blob() to be invoked while async unmapping is in progress. Do it in preparation to improvement of virtio-gpu resetting that will require this change.
Suggested-by: Akihiko Odaki <[email protected]> Signed-off-by: Dmitry Osipenko <[email protected]> --- hw/display/trace-events | 2 +- hw/display/virtio-gpu-virgl.c | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/hw/display/trace-events b/hw/display/trace-events index e323a82cff24..4bfc457fbac1 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -39,7 +39,7 @@ virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d" virtio_gpu_cmd_res_create_blob(uint32_t res, uint64_t size) "res 0x%x, size %" PRId64 virtio_gpu_cmd_res_map_blob(uint32_t res, void *vmr, void *mr) "res 0x%x, vmr %p, mr %p" -virtio_gpu_cmd_res_unmap_blob(uint32_t res, void *mr, bool finish_unmapping) "res 0x%x, mr %p, finish_unmapping %d" +virtio_gpu_cmd_res_unmap_blob(uint32_t res, void *mr, int mapping_state) "res 0x%x, mr %p, mapping_state %d" virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x" virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x" virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x" diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 6a2aac0b6e5c..342e93728df0 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -68,10 +68,16 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie) #endif #if VIRGL_VERSION_MAJOR >= 1 +enum virtio_gpu_virgl_hostmem_region_mapping_state { + VIRTIO_GPU_MR_MAPPED, + VIRTIO_GPU_MR_UNMAP_STARTED, + VIRTIO_GPU_MR_UNMAP_COMPLETED, +}; + struct virtio_gpu_virgl_hostmem_region { MemoryRegion mr; struct VirtIOGPU *g; - bool finish_unmapping; + enum virtio_gpu_virgl_hostmem_region_mapping_state mapping_state; }; static struct virtio_gpu_virgl_hostmem_region * @@ -95,7 +101,7 @@ static void virtio_gpu_virgl_hostmem_region_free(void *obj) VirtIOGPUGL *gl; vmr = to_hostmem_region(mr); - vmr->finish_unmapping = true; + vmr->mapping_state = VIRTIO_GPU_MR_UNMAP_COMPLETED; b = VIRTIO_GPU_BASE(vmr->g); b->renderer_blocked--; @@ -135,6 +141,7 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g, vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1); vmr->g = g; + vmr->mapping_state = VIRTIO_GPU_MR_MAPPED; mr = &vmr->mr; memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data); @@ -171,7 +178,8 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g, vmr = to_hostmem_region(res->mr); - trace_virtio_gpu_cmd_res_unmap_blob(res->base.resource_id, mr, vmr->finish_unmapping); + trace_virtio_gpu_cmd_res_unmap_blob(res->base.resource_id, mr, + vmr->mapping_state); /* * Perform async unmapping in 3 steps: @@ -182,7 +190,8 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g, * asynchronously by virtio_gpu_virgl_hostmem_region_free(). * 3. Finish the unmapping with final virgl_renderer_resource_unmap(). */ - if (vmr->finish_unmapping) { + switch (vmr->mapping_state) { + case VIRTIO_GPU_MR_UNMAP_COMPLETED: res->mr = NULL; g_free(vmr); @@ -193,15 +202,24 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g, __func__, strerror(-ret)); return ret; } - } else { + break; + + case VIRTIO_GPU_MR_MAPPED: *cmd_suspended = true; /* render will be unblocked once MR is freed */ b->renderer_blocked++; + vmr->mapping_state = VIRTIO_GPU_MR_UNMAP_STARTED; + /* memory region owns self res->mr object and frees it by itself */ memory_region_del_subregion(&b->hostmem, mr); object_unparent(OBJECT(mr)); + break; + + case VIRTIO_GPU_MR_UNMAP_STARTED: + *cmd_suspended = true; + break; } return 0; -- 2.52.0
