summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXianzhong <b07117@freescale.com>2014-03-31 16:20:02 +0800
committerRichard Liu <r66033@freescale.com>2014-05-15 15:07:53 +0800
commit720361618607db2ebb5fd18a212665867b240c20 (patch)
treecbcb2f64df8eab1aad07bd9fec2f14238288b352
parentecd7caaa5ec4328f324decde008bacfc93099bdc (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.c37
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