Skip to content

Commit 7d2d6d0

Browse files
committed
drm/panfrost: Fix a deadlock between the shrinker and madvise path
panfrost_ioctl_madvise() and panfrost_gem_purge() acquire the mappings and shmem locks in different orders, thus leading to a potential the mappings lock first. Fixes: bdefca2 ("drm/panfrost: Add the panfrost_gem_mapping concept") Cc: <stable@vger.kernel.org> Cc: Christian Hewitt <christianshewitt@gmail.com> Reported-by: Christian Hewitt <christianshewitt@gmail.com> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201101174016.839110-1-boris.brezillon@collabora.com
1 parent dcda7c2 commit 7d2d6d0

3 files changed

Lines changed: 13 additions & 7 deletions

File tree

drivers/gpu/drm/panfrost/panfrost_gem.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,12 @@ void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping)
105105
kref_put(&mapping->refcount, panfrost_gem_mapping_release);
106106
}
107107

108-
void panfrost_gem_teardown_mappings(struct panfrost_gem_object *bo)
108+
void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo)
109109
{
110110
struct panfrost_gem_mapping *mapping;
111111

112-
mutex_lock(&bo->mappings.lock);
113112
list_for_each_entry(mapping, &bo->mappings.list, node)
114113
panfrost_gem_teardown_mapping(mapping);
115-
mutex_unlock(&bo->mappings.lock);
116114
}
117115

118116
int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)

drivers/gpu/drm/panfrost/panfrost_gem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct panfrost_gem_mapping *
8282
panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
8383
struct panfrost_file_priv *priv);
8484
void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping);
85-
void panfrost_gem_teardown_mappings(struct panfrost_gem_object *bo);
85+
void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo);
8686

8787
void panfrost_gem_shrinker_init(struct drm_device *dev);
8888
void panfrost_gem_shrinker_cleanup(struct drm_device *dev);

drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,26 @@ static bool panfrost_gem_purge(struct drm_gem_object *obj)
4040
{
4141
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
4242
struct panfrost_gem_object *bo = to_panfrost_bo(obj);
43+
bool ret = false;
4344

4445
if (atomic_read(&bo->gpu_usecount))
4546
return false;
4647

47-
if (!mutex_trylock(&shmem->pages_lock))
48+
if (!mutex_trylock(&bo->mappings.lock))
4849
return false;
4950

50-
panfrost_gem_teardown_mappings(bo);
51+
if (!mutex_trylock(&shmem->pages_lock))
52+
goto unlock_mappings;
53+
54+
panfrost_gem_teardown_mappings_locked(bo);
5155
drm_gem_shmem_purge_locked(obj);
56+
ret = true;
5257

5358
mutex_unlock(&shmem->pages_lock);
54-
return true;
59+
60+
unlock_mappings:
61+
mutex_unlock(&bo->mappings.lock);
62+
return ret;
5563
}
5664

5765
static unsigned long

0 commit comments

Comments
 (0)