From ff332e83f2c88f3e6cef14e3653b7eff0b7b74da Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Mon, 30 Aug 2021 12:51:32 +0530 Subject: [PATCH] msm: kgsl: Fix list corruption in worker initialization of mem_entry While deferring mem_entry_put, we are doing INIT_WORK for entry. When mem_entry_put get called again for the same entry before execution of previous work finishes, there is a chance of corruption in the list and cause a crash. Update kgsl_mem_entry_put_deferred to put refcount on mem entry and trigger deferred mem entry destroy only when refcount on entry is the last refcount. Change-Id: I2a8533fd26e776d49ab128bdb484053ce3bc82dc Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/kgsl.c | 20 ++++++++++++++------ drivers/gpu/msm/kgsl.h | 9 ++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f1e978020213..4b0e1d13fa78 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -239,20 +239,28 @@ const char *kgsl_context_type(int type) return "ANY"; } -/* Scheduled by kgsl_mem_entry_put_deferred() */ -static void _deferred_put(struct work_struct *work) +/* Scheduled by kgsl_mem_entry_destroy_deferred() */ +static void _deferred_destroy(struct work_struct *work) { struct kgsl_mem_entry *entry = container_of(work, struct kgsl_mem_entry, work); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_destroy(&entry->refcount); +} + +static void kgsl_mem_entry_destroy_deferred(struct kref *kref) +{ + struct kgsl_mem_entry *entry = + container_of(kref, struct kgsl_mem_entry, refcount); + + INIT_WORK(&entry->work, _deferred_destroy); + queue_work(kgsl_driver.mem_workqueue, &entry->work); } -/* Use a worker to put the refcount on mem entry */ void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry) { - INIT_WORK(&entry->work, _deferred_put); - queue_work(kgsl_driver.mem_workqueue, &entry->work); + if (entry) + kref_put(&entry->refcount, kgsl_mem_entry_destroy_deferred); } static struct kgsl_mem_entry *kgsl_mem_entry_create(void) diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 85d67d0dc2bb..69fdf288fa68 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -562,9 +562,12 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) } /** - * kgsl_mem_entry_put_deferred() - use a worker to put the refcount - * on mem entry from a sysfs handler or debugfs handler. - * @entry - The memory entry + * kgsl_mem_entry_put_deferred() - Puts refcount and triggers deferred + * mem_entry destroy when refcount is the last refcount. + * @entry: memory entry to be put. + * + * Use this to put a memory entry when we don't want to block + * the caller while destroying memory entry. */ void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry);