diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index fa63709e37c..78285108d5a 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -150,8 +150,7 @@ _fd_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) struct fd_bo * fd_bo_new_ring(struct fd_device *dev, uint32_t size) { - uint32_t flags = FD_BO_GPUREADONLY | FD_BO_CACHED_COHERENT; - struct fd_bo *bo = bo_new(dev, size, flags, &dev->ring_cache); + struct fd_bo *bo = bo_new(dev, size, RING_FLAGS, &dev->ring_cache); if (bo) { bo->bo_reuse = RING_CACHE; bo->reloc_flags |= FD_RELOC_DUMP; diff --git a/src/freedreno/drm/freedreno_drmif.h b/src/freedreno/drm/freedreno_drmif.h index 616b5b29d3a..d4dd3f64a05 100644 --- a/src/freedreno/drm/freedreno_drmif.h +++ b/src/freedreno/drm/freedreno_drmif.h @@ -108,8 +108,9 @@ struct fd_fence { /* Hint that the bo will be exported/shared: */ #define FD_BO_SHARED BITSET_BIT(5) -/* backend private bo flags: */ +/* internal bo flags: */ #define _FD_BO_VIRTIO_SHM BITSET_BIT(6) +#define _FD_BO_RING BITSET_BIT(7) /* bo access flags: (keep aligned to MSM_PREP_x) */ #define FD_BO_PREP_READ BITSET_BIT(0) diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index a5184dc22cc..827ed1c3d27 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -54,6 +54,7 @@ extern simple_mtx_t table_lock; #define SUBALLOC_SIZE (32 * 1024) +#define RING_FLAGS (FD_BO_GPUREADONLY | FD_BO_CACHED_COHERENT | _FD_BO_RING) /* * Stupid/simple growable array implementation: diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c index 7636f3948d1..52a1f016ff3 100644 --- a/src/freedreno/drm/virtio/virtio_bo.c +++ b/src/freedreno/drm/virtio/virtio_bo.c @@ -372,8 +372,8 @@ fail: } /* allocate a buffer object: */ -struct fd_bo * -virtio_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) +static struct fd_bo * +virtio_bo_new_impl(struct fd_device *dev, uint32_t size, uint32_t flags) { struct virtio_device *virtio_dev = to_virtio_device(dev); struct drm_virtgpu_resource_create_blob args = { @@ -449,3 +449,38 @@ fail: } return NULL; } + +struct fd_bo * +virtio_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) +{ + struct fd_bo *bo = virtio_bo_new_impl(dev, size, flags); + + if (bo && (flags == RING_FLAGS) && (size == SUBALLOC_SIZE)) { + struct virtio_device *virtio_dev = to_virtio_device(dev); + + /* + * Swap the bo with an earlier pre-allocated one, since we know + * this one will be immediately mmap'd and want to avoid the + * latency hit of waiting for the host to catch up. + */ + simple_mtx_lock(&virtio_dev->eb_lock); + list_addtail(&bo->list, &virtio_dev->prealloc_list); + bo = list_first_entry(&virtio_dev->prealloc_list, struct fd_bo, list); + list_delinit(&bo->list); + simple_mtx_unlock(&virtio_dev->eb_lock); + } + + return bo; +} + +void virtio_bo_setup_prealloc(struct fd_device *dev) +{ + struct virtio_device *virtio_dev = to_virtio_device(dev); + + for (int i = 0; i < 16; i++) { + struct fd_bo *bo = virtio_bo_new_impl(dev, SUBALLOC_SIZE, RING_FLAGS); + if (!bo) + break; + list_addtail(&bo->list, &virtio_dev->prealloc_list); + } +} diff --git a/src/freedreno/drm/virtio/virtio_device.c b/src/freedreno/drm/virtio/virtio_device.c index 8a09e36cb29..333565016dd 100644 --- a/src/freedreno/drm/virtio/virtio_device.c +++ b/src/freedreno/drm/virtio/virtio_device.c @@ -204,6 +204,8 @@ virtio_device_new(int fd, drmVersionPtr version) set_debuginfo(dev); + list_inithead(&virtio_dev->prealloc_list); + util_vma_heap_init(&virtio_dev->address_space, caps.u.msm.va_start, caps.u.msm.va_size); diff --git a/src/freedreno/drm/virtio/virtio_pipe.c b/src/freedreno/drm/virtio/virtio_pipe.c index bb54442cbfb..f109cfb57d2 100644 --- a/src/freedreno/drm/virtio/virtio_pipe.c +++ b/src/freedreno/drm/virtio/virtio_pipe.c @@ -220,6 +220,8 @@ init_shmem(struct fd_device *dev) uint32_t offset = virtio_dev->shmem->rsp_mem_offset; virtio_dev->rsp_mem_len = fd_bo_size(virtio_dev->shmem_bo) - offset; virtio_dev->rsp_mem = &((uint8_t *)virtio_dev->shmem)[offset]; + + virtio_bo_setup_prealloc(dev); } simple_mtx_unlock(&virtio_dev->rsp_lock); diff --git a/src/freedreno/drm/virtio/virtio_priv.h b/src/freedreno/drm/virtio/virtio_priv.h index c210a2b05b7..d453d15c26c 100644 --- a/src/freedreno/drm/virtio/virtio_priv.h +++ b/src/freedreno/drm/virtio/virtio_priv.h @@ -81,6 +81,11 @@ struct virtio_device { struct util_vma_heap address_space; simple_mtx_t address_space_lock; + /** + * Pre-allocated cmdstream buffers to avoid stalling on mmap. + */ + struct list_head prealloc_list; + uint32_t reqbuf_len; uint32_t reqbuf_cnt; uint8_t reqbuf[0x4000]; @@ -182,6 +187,7 @@ FD_DEFINE_CAST(fd_bo, virtio_bo); struct fd_bo *virtio_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags); struct fd_bo *virtio_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle); +void virtio_bo_setup_prealloc(struct fd_device *dev); /* * Internal helpers: