diff options
author | Xianzhong <b07117@freescale.com> | 2014-03-31 16:20:02 +0800 |
---|---|---|
committer | Richard Liu <r66033@freescale.com> | 2014-05-15 15:07:53 +0800 |
commit | 720361618607db2ebb5fd18a212665867b240c20 (patch) | |
tree | cbcb2f64df8eab1aad07bd9fec2f14238288b352 | |
parent | ecd7caaa5ec4328f324decde008bacfc93099bdc (diff) |
ENGR00306397 [#1118] use BUG_ON to check if GPU clock is off
Access GPU register will cause system hang(bus lock-up) without log when clock is off,
GPU kernel BUG_ON is added to check if GPU clock is off when read & write GPU registers,
GPU clock issue can be easily identified with the detailed kernel panic log as below:
kernel BUG at drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c:2423!
Unable to handle kernel NULL pointer dereference at virtual address 0000000
...
[<c0050008>] (__bug+0x1c/0x28) from [<c046bb3c>] (gckOS_ReadRegisterEx+0xbc/0xdc)
[<c046bb3c>] (gckOS_ReadRegisterEx+0xbc/0xdc) from [<c047eab4>] (gckHARDWARE_QueryIdle+0x4c/0xbc)
[<c047eab4>] (gckHARDWARE_QueryIdle+0x4c/0xbc) from [<c0475e0c>] (_TryToIdleGPU+0x70/0x12c)
Mutex protection is not necessary for interrupt handling, because GPU clock is only turned off
by interrupt worker thread during clock gating.
Date: Apr 11, 2014
Signed-off-by: Xianzhong <b07117@freescale.com>
Acked-by: Jason Liu
-rw-r--r-- | drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c index 91e58f0a91b9..35d479f7290c 100644 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c @@ -211,6 +211,9 @@ struct _gckOS /* workqueue for os timer. */ struct workqueue_struct * workqueue; + + int gpu_clk_on[3]; + struct mutex gpu_clk_mutex; }; typedef struct _gcsSIGNAL * gcsSIGNAL_PTR; @@ -1111,6 +1114,8 @@ gckOS_Construct( gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); } + mutex_init(&os->gpu_clk_mutex); + /* Return pointer to the gckOS object. */ *Os = os; @@ -2410,7 +2415,17 @@ gckOS_ReadRegisterEx( gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]); gcmkVERIFY_ARGUMENT(Data != gcvNULL); + if(Address != 0x10) mutex_lock(&Os->gpu_clk_mutex); + BUG_ON(!Os->gpu_clk_on[Core]); + + if(Address) + { + gctUINT32 AQHiClockControl = readl((gctUINT8 *)Os->device->registerBases[Core]); + BUG_ON((AQHiClockControl & 0x3) == 0x3); + } + *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address); + if(Address != 0x10) mutex_unlock(&Os->gpu_clk_mutex); /* Success. */ gcmkFOOTER_ARG("*Data=0x%08x", *Data); @@ -2460,7 +2475,17 @@ gckOS_WriteRegisterEx( gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]); + mutex_lock(&Os->gpu_clk_mutex); + BUG_ON(!Os->gpu_clk_on[Core]); + + if(Address) + { + gctUINT32 AQHiClockControl = readl((gctUINT8 *)Os->device->registerBases[Core]); + BUG_ON((AQHiClockControl & 0x3) == 0x3); + } + writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address); + mutex_unlock(&Os->gpu_clk_mutex); /* Success. */ gcmkFOOTER_NO(); @@ -6983,6 +7008,7 @@ gckOS_SetGPUPower( #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) if (Clock == gcvTRUE) { if (oldClockState == gcvFALSE) { + mutex_lock(&Os->gpu_clk_mutex); switch (Core) { case gcvCORE_MAJOR: clk_enable(clk_3dcore); @@ -7000,9 +7026,12 @@ gckOS_SetGPUPower( default: break; } + Os->gpu_clk_on[Core] = 1; + mutex_unlock(&Os->gpu_clk_mutex); } } else { if (oldClockState == gcvTRUE) { + mutex_lock(&Os->gpu_clk_mutex); switch (Core) { case gcvCORE_MAJOR: if (cpu_is_mx6q()) @@ -7020,11 +7049,14 @@ gckOS_SetGPUPower( default: break; } + Os->gpu_clk_on[Core] = 0; + mutex_unlock(&Os->gpu_clk_mutex); } } #else if (Clock == gcvTRUE) { if (oldClockState == gcvFALSE) { + mutex_lock(&Os->gpu_clk_mutex); switch (Core) { case gcvCORE_MAJOR: clk_prepare(clk_3dcore); @@ -7049,9 +7081,12 @@ gckOS_SetGPUPower( default: break; } + Os->gpu_clk_on[Core] = 1; + mutex_unlock(&Os->gpu_clk_mutex); } } else { if (oldClockState == gcvTRUE) { + mutex_lock(&Os->gpu_clk_mutex); switch (Core) { case gcvCORE_MAJOR: clk_disable(clk_3dshader); @@ -7076,6 +7111,8 @@ gckOS_SetGPUPower( default: break; } + Os->gpu_clk_on[Core] = 0; + mutex_unlock(&Os->gpu_clk_mutex); } } #endif |