IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CallerID) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; #if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK) if (!psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0)) { psDevInfo->bSGXIdle = IMG_TRUE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } else if (psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0)) { psDevInfo->bSGXIdle = IMG_FALSE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } #endif if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) && ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0)) { psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; PDUMPSUSPEND(); #if defined(SYS_CUSTOM_POWERDOWN) eError = SysPowerDownMISR(psDeviceNode, ui32CallerID); #else eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_OFF, ui32CallerID, IMG_FALSE); if (eError == PVRSRV_OK) { SGXPostActivePowerEvent(psDeviceNode, ui32CallerID); } #endif if (eError == PVRSRV_ERROR_RETRY) { psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; eError = PVRSRV_OK; } PDUMPRESUME(); } if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError)); } }
IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32CallerID) { PVRSRV_ERROR eError = PVRSRV_OK; PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice; SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl; #if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK) if (!psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0)) { psDevInfo->bSGXIdle = IMG_TRUE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } else if (psDevInfo->bSGXIdle && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0)) { psDevInfo->bSGXIdle = IMG_FALSE; SysSGXIdleTransition(psDevInfo->bSGXIdle); } #endif /** * Quickly check (without lock) if there is an APM event we should handle. * This check fails most of the time so we don't want to incur lock overhead. * Check the flags in the reverse order that microkernel clears them to prevent * us from seeing an inconsistent state. */ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0) && ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0)) { eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE); if (eError == PVRSRV_ERROR_RETRY) return; if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SGXTestActivePowerEvent failed to acquire lock - " "ui32CallerID:%d eError:%u", ui32CallerID, eError)); return; } /** * Check again (with lock) if APM event has been cleared or handled. A race * condition may allow multiple threads to pass the quick check. */ if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) || ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0)) { PVRSRVPowerUnlock(ui32CallerID); return; } psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER; PDUMPSUSPEND(); #if defined(SYS_CUSTOM_POWERDOWN) eError = SysPowerDownMISR(psDeviceNode, ui32CallerID); #else eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_OFF); if (eError == PVRSRV_OK) { SGXPostActivePowerEvent(psDeviceNode, ui32CallerID); } #endif PVRSRVPowerUnlock(ui32CallerID); PDUMPRESUME(); } if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError)); } }