mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 16:50:10 +01:00
etnaviv: drm: defer destruction of softpin BOs
When destroying a BO with a userspace managed address and thus freeing the VMA space, we need to make sure that the BO isn't in use by any active submit anymore, as the kernel will rightfully reject the next submit that re-uses the still active VMA. Keep the BO alive as long as it isn't fully idle to prevent the VMA being reused prematurely. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Tested-by: Guido Günther <agx@sigxcpu.org> Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14159>
This commit is contained in:
parent
98a2049c08
commit
d799a4be27
3 changed files with 52 additions and 2 deletions
|
|
@ -51,7 +51,7 @@ int etna_bo_is_idle(struct etna_bo *bo)
|
|||
}
|
||||
|
||||
/* Called under etna_drm_table_lock */
|
||||
void etna_bo_free(struct etna_bo *bo)
|
||||
static void _etna_bo_free(struct etna_bo *bo)
|
||||
{
|
||||
DEBUG_BO("Del bo:", bo);
|
||||
VG_BO_FREE(bo);
|
||||
|
|
@ -79,6 +79,51 @@ void etna_bo_free(struct etna_bo *bo)
|
|||
free(bo);
|
||||
}
|
||||
|
||||
void etna_bo_kill_zombies(struct etna_device *dev)
|
||||
{
|
||||
simple_mtx_assert_locked(&etna_drm_table_lock);
|
||||
|
||||
list_for_each_entry_safe(struct etna_bo, bo, &dev->zombie_list, list) {
|
||||
VG_BO_OBTAIN(bo);
|
||||
list_del(&bo->list);
|
||||
_etna_bo_free(bo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void etna_bo_cleanup_zombies(struct etna_device *dev)
|
||||
{
|
||||
simple_mtx_assert_locked(&etna_drm_table_lock);
|
||||
|
||||
list_for_each_entry_safe(struct etna_bo, bo, &dev->zombie_list, list) {
|
||||
/* Stop once we reach a busy BO - all others past this point were
|
||||
* freed more recently so are likely also busy.
|
||||
*/
|
||||
if (!etna_bo_is_idle(bo))
|
||||
break;
|
||||
|
||||
VG_BO_OBTAIN(bo);
|
||||
list_del(&bo->list);
|
||||
_etna_bo_free(bo);
|
||||
}
|
||||
}
|
||||
|
||||
void etna_bo_free(struct etna_bo *bo) {
|
||||
struct etna_device *dev = bo->dev;
|
||||
|
||||
/* If the BO has a userspace managed address we don't free it immediately,
|
||||
* but keep it on a deferred destroy list until all submits with the buffer
|
||||
* have finished, at which point we can reuse the VMA space.
|
||||
*/
|
||||
if (dev->use_softpin) {
|
||||
etna_bo_cleanup_zombies(dev);
|
||||
VG_BO_RELEASE(bo);
|
||||
list_addtail(&bo->list, &dev->zombie_list);
|
||||
} else {
|
||||
_etna_bo_free(bo);
|
||||
}
|
||||
}
|
||||
|
||||
/* lookup a buffer from it's handle, call w/ etna_drm_table_lock held: */
|
||||
static struct etna_bo *lookup_bo(void *tbl, uint32_t handle)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ out:
|
|||
if (!ret && req.value != ~0ULL) {
|
||||
const uint64_t _4GB = 1ull << 32;
|
||||
|
||||
list_inithead(&dev->zombie_list);
|
||||
util_vma_heap_init(&dev->address_space, req.value, _4GB - req.value);
|
||||
dev->use_softpin = 1;
|
||||
}
|
||||
|
|
@ -105,8 +106,10 @@ static void etna_device_del_impl(struct etna_device *dev)
|
|||
{
|
||||
etna_bo_cache_cleanup(&dev->bo_cache, 0);
|
||||
|
||||
if (dev->use_softpin)
|
||||
if (dev->use_softpin) {
|
||||
etna_bo_kill_zombies(dev);
|
||||
util_vma_heap_finish(&dev->address_space);
|
||||
}
|
||||
|
||||
_mesa_hash_table_destroy(dev->handle_table, NULL);
|
||||
_mesa_hash_table_destroy(dev->name_table, NULL);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ struct etna_device {
|
|||
void *handle_table, *name_table;
|
||||
|
||||
struct etna_bo_cache bo_cache;
|
||||
struct list_head zombie_list;
|
||||
|
||||
int use_softpin;
|
||||
struct util_vma_heap address_space;
|
||||
|
|
@ -89,6 +90,7 @@ struct etna_device {
|
|||
};
|
||||
|
||||
void etna_bo_free(struct etna_bo *bo);
|
||||
void etna_bo_kill_zombies(struct etna_device *dev);
|
||||
|
||||
void etna_bo_cache_init(struct etna_bo_cache *cache);
|
||||
void etna_bo_cache_cleanup(struct etna_bo_cache *cache, time_t time);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue