Merge "msm: kgsl: Keep private intact until last refcount is put"

This commit is contained in:
qctecmdr 2021-06-21 21:13:26 -07:00 • committed by Gerrit - the friendly Code Review server
commit 3b7468e324
2 changed files with 34 additions and 44 deletions

View file

@ -869,11 +869,25 @@ static void kgsl_destroy_process_private(struct kref *kref)
struct kgsl_process_private *private = container_of(kref,
struct kgsl_process_private, refcount);
mutex_lock(&kgsl_driver.process_mutex);
debugfs_remove_recursive(private->debug_root);
kgsl_process_uninit_sysfs(private);
/* When using global pagetables, do not detach global pagetable */
if (private->pagetable->name != KGSL_MMU_GLOBAL_PT)
kgsl_mmu_detach_pagetable(private->pagetable);
/* Remove the process struct from the master list */
write_lock(&kgsl_driver.proclist_lock);
list_del(&private->list);
write_unlock(&kgsl_driver.proclist_lock);
mutex_unlock(&kgsl_driver.process_mutex);
put_pid(private->pid);
idr_destroy(&private->mem_idr);
idr_destroy(&private->syncsource_idr);
/* When using global pagetables, do not detach global pagetable */
/* When using global pagetables, do not put global pagetable */
if (private->pagetable->name != KGSL_MMU_GLOBAL_PT)
kgsl_mmu_putpagetable(private->pagetable);
@ -962,8 +976,15 @@ static struct kgsl_process_private *kgsl_process_private_new(
kfree(private);
private = ERR_PTR(err);
return private;
}
kgsl_process_init_sysfs(device, private);
kgsl_process_init_debugfs(private);
write_lock(&kgsl_driver.proclist_lock);
list_add(&private->list, &kgsl_driver.process_list);
write_unlock(&kgsl_driver.proclist_lock);
return private;
}
@ -1008,8 +1029,8 @@ static void kgsl_process_private_close(struct kgsl_device_private *dev_priv,
}
/*
* If this is the last file on the process take down the debug
* directories and garbage collect any outstanding resources
* If this is the last file on the process garbage collect
* any outstanding resources
*/
process_release_memory(private);
@ -1017,18 +1038,6 @@ static void kgsl_process_private_close(struct kgsl_device_private *dev_priv,
/* Release all syncsource objects from process private */
kgsl_syncsource_process_release_syncsources(private);
debugfs_remove_recursive(private->debug_root);
kgsl_process_uninit_sysfs(private);
/* When using global pagetables, do not detach global pagetable */
if (private->pagetable->name != KGSL_MMU_GLOBAL_PT)
kgsl_mmu_detach_pagetable(private->pagetable);
/* Remove the process struct from the master list */
write_lock(&kgsl_driver.proclist_lock);
list_del(&private->list);
write_unlock(&kgsl_driver.proclist_lock);
mutex_unlock(&kgsl_driver.process_mutex);
kgsl_process_private_put(private);
@ -1046,19 +1055,7 @@ static struct kgsl_process_private *kgsl_process_private_open(
if (IS_ERR(private))
goto done;
/*
* If this is a new process create the debug directories and add it to
* the process list
*/
if (private->fd_count++ == 0) {
kgsl_process_init_sysfs(device, private);
kgsl_process_init_debugfs(private);
write_lock(&kgsl_driver.proclist_lock);
list_add(&private->list, &kgsl_driver.process_list);
write_unlock(&kgsl_driver.proclist_lock);
}
private->fd_count++;
done:
mutex_unlock(&kgsl_driver.process_mutex);

View file

@ -202,10 +202,10 @@ static ssize_t mem_entry_sysfs_show(struct kobject *kobj,
ssize_t ret;
/*
* kgsl_process_init_sysfs takes a refcount to the process_private,
* which is put when the kobj is released. This implies that priv will
* not be freed until this function completes, and no further locking
* is needed.
* 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 = kobj ? container_of(kobj, struct kgsl_process_private, kobj) :
NULL;
@ -228,10 +228,10 @@ static ssize_t memtype_sysfs_show(struct kobject *kobj,
int id = 0;
/*
* kgsl_process_init_sysfs takes a refcount to the process_private,
* which is put when the kobj is released. This implies that priv will
* not be freed until this function completes, and no further locking
* is needed.
* 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);
@ -261,13 +261,9 @@ static ssize_t memtype_sysfs_show(struct kobject *kobj,
return scnprintf(buf, PAGE_SIZE, "%llu\n", size);
}
/* Dummy release function - we have nothing to do here */
static void mem_entry_release(struct kobject *kobj)
{
struct kgsl_process_private *priv;
priv = container_of(kobj, struct kgsl_process_private, kobj);
/* Put the refcount we got in kgsl_process_init_sysfs */
kgsl_process_private_put(priv);
}
static const struct sysfs_ops mem_entry_sysfs_ops = {
@ -329,9 +325,6 @@ void kgsl_process_init_sysfs(struct kgsl_device *device,
{
int i;
/* Keep private valid until the sysfs enries are removed. */
kgsl_process_private_get(private);
if (kobject_init_and_add(&private->kobj, &ktype_mem_entry,
kgsl_driver.prockobj, "%d", pid_nr(private->pid))) {
dev_err(device->dev, "Unable to add sysfs for process %d\n",