Merge "msm: kgsl: Use worker to put refcount on mem entry"

This commit is contained in:
qctecmdr 2021-08-22 23:06:38 -07:00 • committed by Gerrit - the friendly Code Review server
commit c984db7626
3 changed files with 28 additions and 10 deletions

View file

@ -248,6 +248,13 @@ static void _deferred_put(struct work_struct *work)
kgsl_mem_entry_put(entry);
}
/* 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);
}
static struct kgsl_mem_entry *kgsl_mem_entry_create(void)
{
struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@ -2336,8 +2343,7 @@ static bool gpuobj_free_fence_func(void *priv)
entry->memdesc.gpuaddr, entry->memdesc.size,
entry->memdesc.flags);
INIT_WORK(&entry->work, _deferred_put);
queue_work(kgsl_driver.mem_workqueue, &entry->work);
kgsl_mem_entry_put_deferred(entry);
return true;
}

View file

@ -561,6 +561,13 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry)
kref_put(&entry->refcount, kgsl_mem_entry_destroy);
}
/**
* 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
*/
void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry);
/*
* kgsl_addr_range_overlap() - Checks if 2 ranges overlap
* @gpuaddr1: Start of first address range

View file

@ -136,7 +136,18 @@ imported_mem_show(struct kgsl_process_private *priv,
}
}
kgsl_mem_entry_put(entry);
/*
* If refcount on mem entry is the last refcount, we will
* call kgsl_mem_entry_destroy and detach it from process
* list. When there is no refcount on the process private,
* we will call kgsl_destroy_process_private to do cleanup.
* During cleanup, we will try to remove the same sysfs
* node which is in use by the current thread and this
* situation will end up in a deadloack.
* To avoid this situation, use a worker to put the refcount
* on mem entry.
*/
kgsl_mem_entry_put_deferred(entry);
spin_lock(&priv->mem_lock);
}
spin_unlock(&priv->mem_lock);
@ -227,12 +238,6 @@ static ssize_t memtype_sysfs_show(struct kobject *kobj,
u64 size = 0;
int id = 0;
/*
* sysfs_remove_file waits for reads to complete before the node is
* deleted and process private is freed only once kobj is released.
* This implies that priv will not be freed until this function
* completes, and no further locking is needed.
*/
priv = container_of(kobj, struct kgsl_process_private, kobj_memtype);
memtype = container_of(attr, struct kgsl_memtype, attr);
@ -253,7 +258,7 @@ static ssize_t memtype_sysfs_show(struct kobject *kobj,
if (type == memtype->type)
size += memdesc->size;
kgsl_mem_entry_put(entry);
kgsl_mem_entry_put_deferred(entry);
spin_lock(&priv->mem_lock);
}
spin_unlock(&priv->mem_lock);