gfx: pvr: make sure power is on during SGX reset
authorImre Deak <imre.deak@intel.com>
Fri, 18 Nov 2011 14:38:01 +0000 (16:38 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:28:39 +0000 (12:28 +0300)
There is a race where after calling the SGX power-on function, it's possible
that the device will be powered-off through another IOCTL or and SGX
interrupt, before we get to perform the actual reset operation. To prevent
this, keep the power-lock for the duration of the reset.

Note that the current PVR API for powering on/off the devices is suboptimal.
Powering on a device requires acquiring the 'power lock', which will be
re-tried for a given amount of time, after which the driver will give up.
Instead of this we should have a refcount based solution and get rid of
the above timeout mechanism.

Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/staging/mrst/pvr/pvr_debug_core.c
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
drivers/staging/mrst/pvr/services4/srvkm/devices/sgx/sgxinit.c

index 004e36a..511fdf0 100644 (file)
@@ -101,12 +101,13 @@ int sgx_trigger_reset(PVRSRV_DEVICE_NODE *dev_node)
 
        err = PVRSRVSetDevicePowerStateKM(dev_node->sDevId.ui32DeviceIndex,
                                          PVRSRV_DEV_POWER_STATE_ON,
-                                         KERNEL_ID, IMG_FALSE);
+                                         KERNEL_ID, IMG_TRUE);
        if (err != PVRSRV_OK)
                return -EIO;
 
-       HWRecoveryResetSGX(dev_node, 0, KERNEL_ID);
+       HWRecoveryResetSGXNoLock(dev_node);
 
+       PVRSRVPowerUnlock(KERNEL_ID);
        /* power down if no activity */
        SGXTestActivePowerEvent(dev_node, KERNEL_ID);
 
index be6ca26..ad205f0 100644 (file)
@@ -319,6 +319,8 @@ typedef struct _PVRSRV_SGX_CCB_INFO_
 
 PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
 
+IMG_VOID HWRecoveryResetSGXNoLock(PVRSRV_DEVICE_NODE *psDeviceNode);
+
 IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE *psDeviceNode,
                             IMG_UINT32 ui32Component,
                             IMG_UINT32 ui32CallerID);
index 6fd2431..1fc54d5 100644 (file)
@@ -1039,28 +1039,12 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_DEVICE_NODE *dev_node, IMG_BOOL bDumpSG
 }
 
 
-IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
-                                                        IMG_UINT32             ui32Component,
-                                                        IMG_UINT32                     ui32CallerID)
+IMG_VOID HWRecoveryResetSGXNoLock(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        PVRSRV_ERROR            eError;
        PVRSRV_SGXDEV_INFO      *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
        SGXMKIF_HOST_CTL        *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
 
-       PVR_UNREFERENCED_PARAMETER(ui32Component);
-
-       
-
-       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
-       if(eError != PVRSRV_OK)
-       {
-               
-
-
-               PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
-               return;
-       }
-
        psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
 
        PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
@@ -1087,17 +1071,33 @@ IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
        
        PDUMPRESUME();
 
+}
+
+IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE *psDeviceNode,
+                           IMG_UINT32 ui32Component,
+                           IMG_UINT32 ui32CallerID)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_SGXDEV_INFO      *sgx_info;
+
+       PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+       sgx_info = psDeviceNode->pvDevice;
+       eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+       if (eError != PVRSRV_OK) {
+               pr_warn("pvr: %s: power transition in progress", __func__);
+
+               return;
+       }
+
+       HWRecoveryResetSGXNoLock(psDeviceNode);
+
        PVRSRVPowerUnlock(ui32CallerID);
 
-       
        SGXScheduleProcessQueuesKM(psDeviceNode);
-
-       
-       
        PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
 }
 
-
 #if defined(SUPPORT_HW_RECOVERY)
 IMG_VOID SGXOSTimer(IMG_VOID *pvData)
 {