While SGX_MISRHandler is scheduled another code path of the driver
(IOCTL, SGXOSTimer) can race with it and turn the power off before
it starts to execute.
When this happens we get the following oops backtrace:
HWRecoveryResetSGX: SGX Hardware Recovery triggered
Unhandled fault: external abort on non-linefetch (0x1008)
PC is at HWRecoveryResetSGX+0x74/0x1b8 [pvrsrvkm]
LR is at preempt_schedule+0x44/0x54
(HWRecoveryResetSGX+0x0/0x1b8) from (SGX_MISRHandler+0x5c/0x60)
(SGX_MISRHandler+0x0/0x60) from (PVRSRVMISR+0x44/0xa0)
r5:
bf0a29cc r4:
dfbbbcc0
(PVRSRVMISR+0x0/0xa0) from (MISRWrapper+0x14/0x18)
r5:
00000002 r4:
00000000
(MISRWrapper+0x0/0x18) from (worker_thread+0x1d0/0x2cc)
(worker_thread+0x0/0x2cc) from (kthread+0x88/0x90)
(kthread+0x0/0x90) from (do_exit+0x0/0x680)
Signed-off-by: Imre Deak <imre.deak@nokia.com>
struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
psDevInfo->psSGXHostCtl;
u32 l1, l2;
+ int dev_idx;
+ enum PVRSRV_ERROR err;
+
+ /*
+ * Yet again we have to cope with the caller ID argument, which
+ * determines whether the power lock is properly locked or just
+ * trylock'd. If trylock fails we just get back here with an error
+ * so we need a proper lock. Actually trylock should never fail
+ * either because of the next assumption.
+ * The code afterwards depends on noone turning off the power and
+ * also the power lock to be released, so ask for the lock to be
+ * released when returning from the function.
+ */
+ dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
+ err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0,
+ ISR_ID, IMG_FALSE);
+ BUG_ON(err != PVRSRV_OK);
l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);