From 65e208cf8947171abf70e09ac08cb0e749f9e296 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Tue, 22 Jun 2021 18:45:43 +0530 Subject: [PATCH] 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 --- drivers/gpu/msm/kgsl.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 120fcdc5950a..f68815f3cf1a 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -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;