summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorXianzhong <xianzhong.li@nxp.com>2018-06-06 02:41:49 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitd08b3bb5d4ab61333a23175bd4f6137a2f0502f0 (patch)
tree90820ea3ffdacb1946d6eb995d94d8fe41339972 /drivers
parenta2c2681f886402764bef0c0632821e350952252d (diff)
MGS-4095 gpu: fix m845s system hang for suspend/resume
cherry-pick one patch to fix m845s suspend/resume hang: 6.2.4.p2-0018-BUG-19216-BUG-19230-CL151956-fix-synchronization-bet BUG#19216 BUG#19230 CL151956 fix synchronization between isr and clock state,fix kernel panic issue in bug #19216, #19230. CL151956 Continue refine ISR and PM logic Signed-off-by: Xianzhong <xianzhong.li@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c138
1 files changed, 90 insertions, 48 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 4b0a2ff50ce2..88cf582bffe6 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
@@ -1684,40 +1684,53 @@ gckOS_ReadRegisterEx(
OUT gctUINT32 * Data
)
{
- unsigned long flags;
+ if (in_irq())
+ {
+ spin_lock(&Os->registerAccessLock);
+
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock(&Os->registerAccessLock);
- spin_lock_irqsave(&Os->registerAccessLock, flags);
+ /*
+ * Read register when power off:
+ * 1. In shared IRQ, read register may be called and that's not our irq.
+ */
+ return gcvSTATUS_GENERIC_IO;
+ }
- if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock(&Os->registerAccessLock);
+ }
+ else
{
- spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ unsigned long flags;
- /*
- * Read register when power off:
- * 1. In shared IRQ, read register may be called and that's not our irq.
- * 2. In non-irq context, register access should not be called,
- * otherwise it's driver bug.
- */
- if (!in_irq())
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
{
- gcmkPRINT("[galcore]: %s(%d) GPU[%d] external clock off",
- __func__, __LINE__, Core);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+
+ /*
+ * Read register when power off:
+ * 2. In non-irq context, register access should not be called,
+ * otherwise it's driver bug.
+ */
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
}
- return gcvSTATUS_GENERIC_IO;
- }
-
- *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
- spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
#if gcdDUMP_AHB_ACCESS
- if (!in_irq())
- {
/* Dangerous to print in interrupt context, skip. */
gcmkPRINT("@[RD %d] %08x %08x", Core, Address, *Data);
- }
#endif
+ }
/* Success. */
return gcvSTATUS_OK;
@@ -1762,32 +1775,51 @@ gckOS_WriteRegisterEx(
IN gctUINT32 Data
)
{
- unsigned long flags;
+ if (in_irq())
+ {
+ spin_lock(&Os->registerAccessLock);
- spin_lock_irqsave(&Os->registerAccessLock, flags);
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock(&Os->registerAccessLock);
- if (unlikely(Os->clockStates[Core] == gcvFALSE))
- {
- spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
- gcmkPRINT("[galcore]: %s(%d) GPU[%d] external clock off",
- __func__, __LINE__, Core);
+ /* Driver bug: register write when clock off. */
+ gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
+ }
- /* Driver bug: register write when clock off. */
- gcmkBUG_ON(1);
- return gcvSTATUS_GENERIC_IO;
+ writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock(&Os->registerAccessLock);
}
+ else
+ {
+ unsigned long flags;
- writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
- spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ if (unlikely(Os->clockStates[Core] == gcvFALSE))
+ {
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+
+ printk(KERN_ERR "[galcore]: %s(%d) GPU[%d] external clock off",
+ __func__, __LINE__, Core);
+
+ /* Driver bug: register write when clock off. */
+ gcmkBUG_ON(1);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
#if gcdDUMP_AHB_ACCESS
- if (!in_irq())
- {
/* Dangerous to print in interrupt context, skip. */
gcmkPRINT("@[WR %d] %08x %08x", Core, Address, Data);
- }
#endif
+ }
/* Success. */
return gcvSTATUS_OK;
@@ -5385,18 +5417,6 @@ gckOS_SetGPUPower(
clockChange = (Clock != Os->clockStates[Core]);
- if (clockChange)
- {
- unsigned long flags;
-
- spin_lock_irqsave(&Os->registerAccessLock, flags);
-
- /* Record clock states, ahead. */
- Os->clockStates[Core] = Clock;
-
- spin_unlock_irqrestore(&Os->registerAccessLock, flags);
- }
-
if (powerChange && (Power == gcvTRUE))
{
if (platform && platform->ops->setPower)
@@ -5409,10 +5429,32 @@ gckOS_SetGPUPower(
if (clockChange)
{
+ unsigned long flags;
+
+ if (!Clock)
+ {
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ /* Record clock off, ahead. */
+ Os->clockStates[Core] = gcvFALSE;
+
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ }
+
if (platform && platform->ops->setClock)
{
gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
}
+
+ if (Clock)
+ {
+ spin_lock_irqsave(&Os->registerAccessLock, flags);
+
+ /* Record clock on, behind. */
+ Os->clockStates[Core] = gcvTRUE;
+
+ spin_unlock_irqrestore(&Os->registerAccessLock, flags);
+ }
}
if (powerChange && (Power == gcvFALSE))