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);