MGS-6197 [#imx-2532] GPU crash when changing gpu_govern mode
authorNicușor Cîțu <nicusor.citu@nxp.com>
Wed, 21 Apr 2021 07:54:20 +0000 (10:54 +0300)
committerNicușor Cîțu <nicusor.citu@nxp.com>
Wed, 12 May 2021 11:27:24 +0000 (14:27 +0300)
The suspend will acquire the global semaphore, and a later gcvPOWER_ON_AUTO
determined by a new commit will wait for global semaphore until a GPU resume
(power ON) release the global semaphore, then the gcvPOWER_ON_AUTO will
continue to run. But during the stress test, the sequence might change.
For example:
1. GPU goes to suspend; if a new commit comes then gcvPOWER_ON_AUTO will
wait for global semaphore.
2. GPU goes to resume, a global power ON will release the global semaphore,
gcvPOWER_ON_AUTO acquire the global semaphore successfully but will release
it by itself because gcvPOWER_ON_AUTO is not a global state and it won't
occupy a global semaphore.
3. The next GPU suspend will also acquire the global semaphore successfully.
As the GPU suspend and gcvPOWER_ON_AUTO are in two threads, there is a certain
probability that suspend is executed first, then gcvPOWER_ON_AUTO, so that the
later GPU stall (from suspend) will occur at the same time with new
commit abd will cause the GPU hang.

Suggested-by: Zhe Pan <Zhe.Pan@verisilicon.com>
Signed-off-by: Nicușor Cîțu <nicusor.citu@nxp.com>
drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx.c

index cc2b368..1d7cbe8 100644 (file)
@@ -555,6 +555,7 @@ static ssize_t gpu_govern_store(struct device_driver *dev, const char *buf, size
     int core = gcvCORE_MAJOR;
     int i;
     gckGALDEVICE device = platform_get_drvdata(pdevice);
+    gctBOOL mutex_acquired = gcvFALSE;
     gctBOOL sem_acquired = gcvFALSE;
     gceSTATUS status;
 
@@ -576,9 +577,13 @@ static ssize_t gpu_govern_store(struct device_driver *dev, const char *buf, size
         return count;
     }
 
+    /* Get the device commit mutex. */
+    gcmkONERROR(gckOS_AcquireMutex(device->os, device->device->commitMutex,
+            gcvINFINITE));
+    mutex_acquired = gcvTRUE;
+
     /* Acquire the suspend semaphore. */
     gcmkONERROR(gckOS_AcquireSemaphore(device->os, device->suspendSemaphore));
-
     sem_acquired = gcvTRUE;
 
     /* Suspend the GPU. */
@@ -618,6 +623,13 @@ OnError:
                 device->suspendSemaphore));
     }
 
+    /* Release the commit mutex. */
+    if (mutex_acquired)
+    {
+        gcmkVERIFY_OK(gckOS_ReleaseMutex(device->os,
+                device->device->commitMutex));
+    }
+
     return count;
 }