freedreno/drm: Split out bo->finalize()
The complexity around batching up handle closing is simply to allow the virtgpu to back up ccmd's to the host (because virtio/virtgpu is pretty inefficient when it comes to lots of small msgs to the host, and it is common that when we are deleting BOs, we delete a lot of them at the same time. But that will make the locking fix in the next commit impossible (without nested locks). So let's flip this around and do the step that virtgpu wants to batch up first, before we get into closing GEM handles, etc. Signed-off-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20918>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
||||
/**
|
||||
|
@@ -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: */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user