diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index 58da00a39ef..d8b07baf377 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -298,6 +298,20 @@ fd_bo_ref(struct fd_bo *bo) static uint32_t bo_del(struct fd_bo *bo); static void close_handles(struct fd_device *dev, uint32_t *handles, unsigned cnt); +static void +bo_finalize(struct fd_bo *bo) +{ + if (bo->funcs->finalize) + bo->funcs->finalize(bo); +} + +static void +dev_flush(struct fd_device *dev) +{ + if (dev->funcs->flush) + dev->funcs->flush(dev); +} + static bool try_recycle(struct fd_bo *bo) { @@ -327,6 +341,9 @@ fd_bo_del(struct fd_bo *bo) struct fd_device *dev = bo->dev; + bo_finalize(bo); + dev_flush(dev); + uint32_t handle = bo_del(bo); if (handle) close_handles(dev, &handle, 1); @@ -349,9 +366,14 @@ fd_bo_del_array(struct fd_bo **bos, int count) for (int i = 0; i < count; i++) { if (!unref(&bos[i]->refcnt) || try_recycle(bos[i])) { bos[i--] = bos[--count]; + } else { + /* We are going to delete this one, so finalize it first: */ + bo_finalize(bos[i]); } } + dev_flush(dev); + /* * Second pass, delete all of the objects remaining after first pass. */ @@ -387,6 +409,12 @@ fd_bo_del_list_nocache(struct list_head *list) uint32_t handles[64]; unsigned cnt = 0; + foreach_bo (bo, list) { + bo_finalize(bo); + } + + dev_flush(dev); + foreach_bo_safe (bo, list) { assert(bo->refcnt == 0); if (cnt == ARRAY_SIZE(handles)) { @@ -439,6 +467,8 @@ fd_bo_fini_common(struct fd_bo *bo) _mesa_hash_table_remove_key(dev->name_table, &bo->name); simple_mtx_unlock(&table_lock); } + + free(bo); } /** diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index 6c4a473d01c..e36a097f6e9 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -411,6 +411,19 @@ struct fd_bo_funcs { int (*madvise)(struct fd_bo *bo, int willneed); uint64_t (*iova)(struct fd_bo *bo); void (*set_name)(struct fd_bo *bo, const char *fmt, va_list ap); + + /** + * Optional hook that is called before ->destroy(). In the case of + * batch deletes (such as BO cache cleanup or cleaning up a submit) + * the ->finalize() hook will be called for all of the BOs being + * destroyed followed by dev->flush() and then bo->destroy(). This + * allows the backend to batch up processing. (Ie. this is for + * virtio backend to batch ccmds to the host) + * + * In all cases, dev->flush() will happen after bo->finalize() and + * bo->destroy(). + */ + void (*finalize)(struct fd_bo *bo); void (*destroy)(struct fd_bo *bo); /** diff --git a/src/freedreno/drm/msm/msm_bo.c b/src/freedreno/drm/msm/msm_bo.c index e649c369e44..4f9f4826bb8 100644 --- a/src/freedreno/drm/msm/msm_bo.c +++ b/src/freedreno/drm/msm/msm_bo.c @@ -136,21 +136,13 @@ msm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) drmCommandWrite(bo->dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req)); } -static void -msm_bo_destroy(struct fd_bo *bo) -{ - struct msm_bo *msm_bo = to_msm_bo(bo); - fd_bo_fini_common(bo); - free(msm_bo); -} - static const struct fd_bo_funcs funcs = { .offset = msm_bo_offset, .cpu_prep = msm_bo_cpu_prep, .madvise = msm_bo_madvise, .iova = msm_bo_iova, .set_name = msm_bo_set_name, - .destroy = msm_bo_destroy, + .destroy = fd_bo_fini_common, }; /* allocate a buffer handle: */ diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c index c46df75d4d2..9c071a482ea 100644 --- a/src/freedreno/drm/virtio/virtio_bo.c +++ b/src/freedreno/drm/virtio/virtio_bo.c @@ -267,20 +267,14 @@ set_iova(struct fd_bo *bo, uint64_t iova) } static void -virtio_bo_destroy(struct fd_bo *bo) +virtio_bo_finalize(struct fd_bo *bo) { - struct virtio_bo *virtio_bo = to_virtio_bo(bo); - /* Release iova by setting to zero: */ if (bo->iova) { set_iova(bo, 0); virtio_dev_free_iova(bo->dev, bo->iova, bo->size); } - - fd_bo_fini_common(bo); - - free(virtio_bo); } static const struct fd_bo_funcs funcs = { @@ -291,7 +285,8 @@ static const struct fd_bo_funcs funcs = { .set_name = virtio_bo_set_name, .upload = virtio_bo_upload, .prefer_upload = virtio_bo_prefer_upload, - .destroy = virtio_bo_destroy, + .finalize = virtio_bo_finalize, + .destroy = fd_bo_fini_common, }; static struct fd_bo * @@ -358,7 +353,8 @@ virtio_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) return bo; fail: - virtio_bo_destroy(bo); + virtio_bo_finalize(bo); + fd_bo_fini_common(bo); return NULL; }