msm: kgsl: Avoid global process lock for close

Currently, resources for processes are freed within global
process lock. This can block resources of multiple other
processes. Ideally, there is no global resource that is being
protected. Introduce a process private level lock to protect
the private information.

Change-Id: Ib28da1e346269eaa0a638b32ebc7471ff676afb0
Signed-off-by: Kamal Agrawal <quic_kamaagra@quicinc.com>
This commit is contained in:
Kamal Agrawal 2021-12-20 22:33:52 +05:30 committed by Gerrit - the friendly Code Review server
parent 6c9426c7dc
commit 5af7b2f049
2 changed files with 18 additions and 11 deletions

24
kgsl.c
View File

@ -963,7 +963,7 @@ static struct kgsl_process_private *kgsl_process_private_new(
/* Search in the process list */
list_for_each_entry(private, &kgsl_driver.process_list, list) {
if (private->pid == cur_pid) {
if (!kgsl_process_private_get(private))
if (!kgsl_process_private_get(private)) {
/*
* This will happen only if refcount is zero
* i.e. destroy is triggered but didn't complete
@ -972,6 +972,12 @@ static struct kgsl_process_private *kgsl_process_private_new(
* appropriate action.
*/
private = ERR_PTR(-EEXIST);
} else {
mutex_lock(&private->private_mutex);
private->fd_count++;
mutex_unlock(&private->private_mutex);
}
/*
* We need to hold only one reference to the PID for
* each process struct to avoid overflowing the
@ -991,12 +997,14 @@ static struct kgsl_process_private *kgsl_process_private_new(
kref_init(&private->refcount);
private->fd_count = 1;
private->pid = cur_pid;
get_task_comm(private->comm, current->group_leader);
spin_lock_init(&private->mem_lock);
spin_lock_init(&private->syncsource_lock);
spin_lock_init(&private->ctxt_count_lock);
mutex_init(&private->private_mutex);
idr_init(&private->mem_idr);
idr_init(&private->syncsource_idr);
@ -1058,10 +1066,10 @@ static void process_release_memory(struct kgsl_process_private *private)
static void kgsl_process_private_close(struct kgsl_device_private *dev_priv,
struct kgsl_process_private *private)
{
mutex_lock(&kgsl_driver.process_mutex);
mutex_lock(&private->private_mutex);
if (--private->fd_count > 0) {
mutex_unlock(&kgsl_driver.process_mutex);
mutex_unlock(&private->private_mutex);
kgsl_process_private_put(private);
return;
}
@ -1075,7 +1083,7 @@ 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);
mutex_unlock(&kgsl_driver.process_mutex);
mutex_unlock(&private->private_mutex);
kgsl_process_private_put(private);
}
@ -1087,14 +1095,8 @@ static struct kgsl_process_private *_process_private_open(
mutex_lock(&kgsl_driver.process_mutex);
private = kgsl_process_private_new(device);
if (IS_ERR(private))
goto done;
private->fd_count++;
done:
mutex_unlock(&kgsl_driver.process_mutex);
return private;
}

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __KGSL_DEVICE_H
#define __KGSL_DEVICE_H
@ -489,6 +490,10 @@ struct kgsl_process_private {
* process
*/
struct kobject kobj_memtype;
/**
* @private_mutex: Mutex lock to protect kgsl_process_private
*/
struct mutex private_mutex;
};
struct kgsl_device_private {