diff --git a/.pick_status.json b/.pick_status.json index 774670e039c..196691780ff 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -625,7 +625,7 @@ "description": "etnaviv: drm: fix BO refcount race", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": null }, diff --git a/src/etnaviv/drm/etnaviv_bo.c b/src/etnaviv/drm/etnaviv_bo.c index 0ec64b780f5..7fde304ed3b 100644 --- a/src/etnaviv/drm/etnaviv_bo.c +++ b/src/etnaviv/drm/etnaviv_bo.c @@ -257,11 +257,15 @@ void etna_bo_del(struct etna_bo *bo) struct etna_device *dev = bo->dev; - if (!p_atomic_dec_zero(&bo->refcnt)) - return; - pthread_mutex_lock(&etna_drm_table_lock); + /* Must test under table lock to avoid racing with the from_dmabuf/name + * paths, which rely on the BO refcount to be stable over the lookup, so + * they can grab a reference when the BO is found in the hash. + */ + if (!p_atomic_dec_zero(&bo->refcnt)) + goto out; + if (bo->reuse && (etna_bo_cache_free(&dev->bo_cache, bo) == 0)) goto out;