diff options
author | Xianzhong <xianzhong.li@nxp.com> | 2018-06-06 02:41:49 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | d08b3bb5d4ab61333a23175bd4f6137a2f0502f0 (patch) | |
tree | 90820ea3ffdacb1946d6eb995d94d8fe41339972 /drivers | |
parent | a2c2681f886402764bef0c0632821e350952252d (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.c | 138 |
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)) |