drm/panfrost: Make sure MMU context lifetime is not bound to panfrost_priv
commit 7fdc48cc63a30fa3480d18bdd8c5fff2b9b15212 upstream.
Jobs can be in-flight when the file descriptor is closed (either because
the process did not terminate properly, or because it didn't wait for
all GPU jobs to be finished), and apparently panfrost_job_close() does
not cancel already running jobs. Let's refcount the MMU context object
so it's lifetime is no longer bound to the FD lifetime and running jobs
can finish properly without generating spurious page faults.
Reported-by: Icecream95 <ixn@keemail.me>
Fixes: 7282f7645d
("drm/panfrost: Implement per FD address spaces")
Cc: <stable@vger.kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210621133907.1683899-2-boris.brezillon@collabora.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
bb693c114e
commit
c29485e34e
@@ -60,7 +60,7 @@ panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
|
||||
|
||||
mutex_lock(&bo->mappings.lock);
|
||||
list_for_each_entry(iter, &bo->mappings.list, node) {
|
||||
if (iter->mmu == &priv->mmu) {
|
||||
if (iter->mmu == priv->mmu) {
|
||||
kref_get(&iter->refcount);
|
||||
mapping = iter;
|
||||
break;
|
||||
@@ -74,16 +74,13 @@ panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
|
||||
static void
|
||||
panfrost_gem_teardown_mapping(struct panfrost_gem_mapping *mapping)
|
||||
{
|
||||
struct panfrost_file_priv *priv;
|
||||
|
||||
if (mapping->active)
|
||||
panfrost_mmu_unmap(mapping);
|
||||
|
||||
priv = container_of(mapping->mmu, struct panfrost_file_priv, mmu);
|
||||
spin_lock(&priv->mm_lock);
|
||||
spin_lock(&mapping->mmu->mm_lock);
|
||||
if (drm_mm_node_allocated(&mapping->mmnode))
|
||||
drm_mm_remove_node(&mapping->mmnode);
|
||||
spin_unlock(&priv->mm_lock);
|
||||
spin_unlock(&mapping->mmu->mm_lock);
|
||||
}
|
||||
|
||||
static void panfrost_gem_mapping_release(struct kref *kref)
|
||||
@@ -94,6 +91,7 @@ static void panfrost_gem_mapping_release(struct kref *kref)
|
||||
|
||||
panfrost_gem_teardown_mapping(mapping);
|
||||
drm_gem_object_put(&mapping->obj->base.base);
|
||||
panfrost_mmu_ctx_put(mapping->mmu);
|
||||
kfree(mapping);
|
||||
}
|
||||
|
||||
@@ -143,11 +141,11 @@ int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
|
||||
else
|
||||
align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0;
|
||||
|
||||
mapping->mmu = &priv->mmu;
|
||||
spin_lock(&priv->mm_lock);
|
||||
ret = drm_mm_insert_node_generic(&priv->mm, &mapping->mmnode,
|
||||
mapping->mmu = panfrost_mmu_ctx_get(priv->mmu);
|
||||
spin_lock(&mapping->mmu->mm_lock);
|
||||
ret = drm_mm_insert_node_generic(&mapping->mmu->mm, &mapping->mmnode,
|
||||
size >> PAGE_SHIFT, align, color, 0);
|
||||
spin_unlock(&priv->mm_lock);
|
||||
spin_unlock(&mapping->mmu->mm_lock);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@@ -176,7 +174,7 @@ void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
|
||||
|
||||
mutex_lock(&bo->mappings.lock);
|
||||
list_for_each_entry(iter, &bo->mappings.list, node) {
|
||||
if (iter->mmu == &priv->mmu) {
|
||||
if (iter->mmu == priv->mmu) {
|
||||
mapping = iter;
|
||||
list_del(&iter->node);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user