Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff332e83 authored by Pankaj Gupta's avatar Pankaj Gupta
Browse files

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: default avatarPankaj Gupta <gpankaj@codeaurora.org>
parent 8e924318
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -239,22 +239,30 @@ 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);
}

/* Use a worker to put the refcount on mem entry */
void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry)
static void kgsl_mem_entry_destroy_deferred(struct kref *kref)
{
	INIT_WORK(&entry->work, _deferred_put);
	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);
}

void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry)
{
	if (entry)
		kref_put(&entry->refcount, kgsl_mem_entry_destroy_deferred);
}

static struct kgsl_mem_entry *kgsl_mem_entry_create(void)
{
	struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+6 −3
Original line number Diff line number Diff line
@@ -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);