msm: kgsl: Retry process private open in a special failure case

Currently, process private open/kgsl_open fails in case same pid
previous process private refcount is zero but destroy didn't
complete yet. In this failure case, as we are sure that destroy
is triggered and just pending to finish, retry process private
open again after some delay to ensure process private open is
successful.

Change-Id: I7cd8a2b7d64d9472121ffa8633d0621923f5ec89
Signed-off-by: Deepak Kumar <dkumar@codeaurora.org>
This commit is contained in:
Deepak Kumar 2021-06-22 18:45:43 +05:30
commit 65e208cf89

View file

@ -6,6 +6,7 @@
#include <uapi/linux/sched/types.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dma-buf.h>
#include <linux/fdtable.h>
#include <linux/io.h>
@ -933,9 +934,15 @@ 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)) {
private = ERR_PTR(-EINVAL);
}
if (!kgsl_process_private_get(private))
/*
* This will happen only if refcount is zero
* i.e. destroy is triggered but didn't complete
* yet. Return -EEXIST to indicate caller that
* destroy is pending to allow caller to take
* appropriate action.
*/
private = ERR_PTR(-EEXIST);
/*
* We need to hold only one reference to the PID for
* each process struct to avoid overflowing the
@ -1043,8 +1050,7 @@ static void kgsl_process_private_close(struct kgsl_device_private *dev_priv,
kgsl_process_private_put(private);
}
static struct kgsl_process_private *kgsl_process_private_open(
static struct kgsl_process_private *_process_private_open(
struct kgsl_device *device)
{
struct kgsl_process_private *private;
@ -1062,6 +1068,27 @@ done:
return private;
}
static struct kgsl_process_private *kgsl_process_private_open(
struct kgsl_device *device)
{
struct kgsl_process_private *private;
int i;
private = _process_private_open(device);
/*
* If we get error and error is -EEXIST that means previous process
* private destroy is triggered but didn't complete. Retry creating
* process private after sometime to allow previous destroy to complete.
*/
for (i = 0; (PTR_ERR_OR_ZERO(private) == -EEXIST) && (i < 5); i++) {
usleep_range(10, 100);
private = _process_private_open(device);
}
return private;
}
int kgsl_gpu_frame_count(pid_t pid, u64 *frame_count)
{
struct kgsl_process_private *p;