/**********************************************************************
*
* Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
- *
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful but, except
- * as otherwise stated in writing, without any warranty; without even the
- * implied warranty of merchantability or fitness for a particular purpose.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
* See the GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ *
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Contact Information:
* Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
*
******************************************************************************/
#include <stddef.h>
-#include <linux/spinlock.h>
+
#include <linux/workqueue.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
#include "sgxdefs.h"
#include "sgxmmu.h"
#include "sgxconfig.h"
#include "sysconfig.h"
#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "resman.h"
+#include "bridged_support.h"
-#include "pdump_km.h"
+#include "pvr_pdump.h"
#include "ra.h"
#include "mmu.h"
+#include "mm.h"
#include "handle.h"
#include "perproc.h"
#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+#ifdef CONFIG_DEBUG_FS
+#include "pvr_debugfs.h"
+#endif
-IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData);
-
-IMG_UINT32 gui32EventStatusServicesByISR = 0;
-
-IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO * psDevInfo, IMG_UINT32 ui32PDUMPFlags);
-
-static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
- IMG_BOOL bHardwareRecovery);
-PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+static IMG_BOOL SGX_ISRHandler(void *pvData);
-typedef enum _PVR_DEVICE_POWER_STATE_ {
- PVR_DEVICE_POWER_STATE_ON = 0,
- PVR_DEVICE_POWER_STATE_IDLE = 1,
- PVR_DEVICE_POWER_STATE_OFF = 2,
+static u32 gui32EventStatusServicesByISR;
- PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff
-} PVR_DEVICE_POWER_STATE, *PPVR_DEVICE_POWER_STATE;
+static enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
-static PVR_DEVICE_POWER_STATE MapDevicePowerState(PVR_POWER_STATE ePowerState)
+static void SGXCommandComplete(struct PVRSRV_DEVICE_NODE *psDeviceNode)
{
- PVR_DEVICE_POWER_STATE eDevicePowerState;
+ BUG_ON(in_irq());
- switch (ePowerState) {
- case PVRSRV_POWER_STATE_D0:
- {
- eDevicePowerState = PVR_DEVICE_POWER_STATE_ON;
- break;
- }
- case PVRSRV_POWER_STATE_D3:
- {
- eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF;
- break;
- }
- default:
- {
- PVR_DPF((PVR_DBG_ERROR,
- "MapDevicePowerState: Invalid state: %ld",
- ePowerState));
- eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32;
- PVR_ASSERT(eDevicePowerState !=
- PVR_DEVICE_POWER_STATE_FORCE_I32);
- }
- }
-
- return eDevicePowerState;
-}
-
-static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE * psDeviceNode)
-{
- SGXScheduleProcessQueues(psDeviceNode);
+ SGXScheduleProcessQueuesKM(psDeviceNode);
}
-static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO * psDevInfo)
+static u32 DeinitDevInfo(struct PVRSRV_SGXDEV_INFO *psDevInfo)
{
- if (psDevInfo->psKernelCCBInfo != IMG_NULL) {
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO),
- psDevInfo->psKernelCCBInfo, IMG_NULL);
- }
+ if (psDevInfo->psKernelCCBInfo != NULL)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGX_CCB_INFO),
+ psDevInfo->psKernelCCBInfo, NULL);
return PVRSRV_OK;
}
-static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA * psPerProc,
- PVRSRV_DEVICE_NODE * psDeviceNode,
- SGX_BRIDGE_INIT_INFO * psInitInfo)
+static enum PVRSRV_ERROR InitDevInfo(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct SGX_BRIDGE_INIT_INFO *psInitInfo)
{
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
- PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ enum PVRSRV_ERROR eError;
- PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL;
+ struct PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = NULL;
PVR_UNREFERENCED_PARAMETER(psPerProc);
psDevInfo->sScripts = psInitInfo->sScripts;
psDevInfo->psKernelCCBMemInfo =
- (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBMemInfo;
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
psDevInfo->psKernelCCB =
- (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->
- pvLinAddrKM;
+ (struct PVRSRV_SGX_KERNEL_CCB *)psDevInfo->psKernelCCBMemInfo->
+ pvLinAddrKM;
psDevInfo->psKernelCCBCtlMemInfo =
- (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBCtlMemInfo;
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
psDevInfo->psKernelCCBCtl =
- (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->
- pvLinAddrKM;
+ (struct PVRSRV_SGX_CCB_CTL *)psDevInfo->psKernelCCBCtlMemInfo->
+ pvLinAddrKM;
psDevInfo->psKernelCCBEventKickerMemInfo =
- (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelCCBEventKickerMemInfo;
+ (struct PVRSRV_KERNEL_MEM_INFO *)
+ psInitInfo->hKernelCCBEventKickerMemInfo;
psDevInfo->pui32KernelCCBEventKicker =
- (IMG_UINT32 *) psDevInfo->psKernelCCBEventKickerMemInfo->
- pvLinAddrKM;
+ (u32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
psDevInfo->psKernelSGXHostCtlMemInfo =
- (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelSGXHostCtlMemInfo;
- psDevInfo->psSGXHostCtl =
- (PVRSRV_SGX_HOST_CTL *) psDevInfo->psKernelSGXHostCtlMemInfo->
- pvLinAddrKM;
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
+ hKernelSGXHostCtlMemInfo;
+ psDevInfo->psSGXHostCtl = (struct SGXMKIF_HOST_CTL __force __iomem *)
+ psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXTA3DCtlMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
+ hKernelSGXTA3DCtlMemInfo;
+
+ psDevInfo->psKernelSGXMiscMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
psDevInfo->psKernelHWPerfCBMemInfo =
- (PVRSRV_KERNEL_MEM_INFO *) psInitInfo->hKernelHWPerfCBMemInfo;
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+ psDevInfo->psKernelEDMStatusBufferMemInfo =
+ psInitInfo->hKernelEDMStatusBufferMemInfo;
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(PVRSRV_SGX_CCB_INFO),
- (IMG_VOID **) & psKernelCCBInfo, 0);
+ sizeof(struct PVRSRV_SGX_CCB_INFO),
+ (void **)&psKernelCCBInfo, NULL);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory"));
+ PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory");
goto failed_allockernelccb;
}
- OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+ OSMemSet(psKernelCCBInfo, 0, sizeof(struct PVRSRV_SGX_CCB_INFO));
psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
psKernelCCBInfo->pui32WriteOffset =
- &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+ &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
psKernelCCBInfo->pui32ReadOffset =
- &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+ &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
- psDevInfo->ui32TAKickAddress = psInitInfo->ui32TAKickAddress;
+ psDevInfo->ui32HostKickAddress = psInitInfo->ui32HostKickAddress;
- psDevInfo->ui32VideoHandlerAddress =
- psInitInfo->ui32VideoHandlerAddress;
+ psDevInfo->ui32GetMiscInfoAddress = psInitInfo->ui32GetMiscInfoAddress;
psDevInfo->bForcePTOff = IMG_FALSE;
psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
- psDevInfo->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl;
- psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2;
+ psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
sizeof(psDevInfo->asSGXDevData));
+ psDevInfo->state_buf_ofs = psInitInfo->state_buf_ofs;
+
return PVRSRV_OK;
failed_allockernelccb:
return eError;
}
-static IMG_VOID SGXGetTimingInfo(PVRSRV_DEVICE_NODE * psDeviceNode)
-{
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- SGX_TIMING_INFORMATION sSGXTimingInfo = { 0 };
- IMG_UINT32 ui32ActivePowManSampleRate;
- SGX_TIMING_INFORMATION *psSGXTimingInfo;
-
- psSGXTimingInfo = &sSGXTimingInfo;
- SysGetSGXTimingInformation(psSGXTimingInfo);
-
- {
- PVRSRV_ERROR eError;
- IMG_UINT32 ui32OlduKernelFreq;
-
- if (psDevInfo->hTimer != IMG_NULL) {
- ui32OlduKernelFreq =
- psDevInfo->ui32CoreClockSpeed /
- psDevInfo->ui32uKernelTimerClock;
- if (ui32OlduKernelFreq !=
- psSGXTimingInfo->ui32uKernelFreq) {
- eError = OSRemoveTimer(psDevInfo->hTimer);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXGetTimingInfo: Failed to remove timer"));
- }
- psDevInfo->hTimer = IMG_NULL;
- }
- }
- if (psDevInfo->hTimer == IMG_NULL) {
-
- psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
- 1000 * 50 /
- psSGXTimingInfo->
- ui32uKernelFreq);
- if (psDevInfo->hTimer == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXGetTimingInfo : Failed to register timer callback function"));
- }
- }
-
- psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
- psSGXTimingInfo->ui32uKernelFreq /
- psSGXTimingInfo->ui32HWRecoveryFreq;
- }
-
- psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
- psDevInfo->ui32uKernelTimerClock =
- psSGXTimingInfo->ui32CoreClockSpeed /
- psSGXTimingInfo->ui32uKernelFreq;
-
- ui32ActivePowManSampleRate =
- psSGXTimingInfo->ui32uKernelFreq *
- psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
- ui32ActivePowManSampleRate += 1;
- psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate =
- ui32ActivePowManSampleRate;
-}
-
-static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo,
- IMG_BOOL bStartOSTimer)
-{
- IMG_UINT32 ui32RegVal;
-
-
- ui32RegVal =
- EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
- PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
- PDUMP_FLAGS_CONTINUOUS);
-
- if (bStartOSTimer) {
- PVRSRV_ERROR eError;
- eError = OSEnableTimer(psDevInfo->hTimer);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXStartTimer : Failed to enable host timer"));
- }
- }
-}
-
-static PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
- PVR_DEVICE_POWER_STATE eNewPowerState,
- PVR_DEVICE_POWER_STATE eCurrentPowerState)
-{
- if ((eNewPowerState != eCurrentPowerState) &&
- (eNewPowerState != PVR_DEVICE_POWER_STATE_ON)) {
- PVRSRV_ERROR eError;
- PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
- IMG_UINT32 ui32PowManRequest, ui32PowManComplete;
-
- eError = OSDisableTimer(psDevInfo->hTimer);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Failed to disable timer"));
- return eError;
- }
-
- if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
- ui32PowManRequest =
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST;
- ui32PowManComplete =
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
- PDUMPCOMMENT
- ("TA/3D CCB Control - SGX power off request");
- } else {
- ui32PowManRequest = PVRSRV_USSE_EDM_POWMAN_IDLE_REQUEST;
- ui32PowManComplete =
- PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
- PDUMPCOMMENT("TA/3D CCB Control - SGX idle request");
- }
-
- psSGXHostCtl->ui32PowManFlags |= ui32PowManRequest;
-#if defined(PDUMP)
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
- sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
-
- if (PollForValueKM(&psSGXHostCtl->ui32PowManFlags,
- ui32PowManComplete,
- ui32PowManComplete,
- MAX_HW_TIME_US / WAIT_TRY_COUNT,
- WAIT_TRY_COUNT) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Wait for SGX ukernel power transition failed."));
- }
-
-#if defined(PDUMP)
- PDUMPCOMMENT
- ("TA/3D CCB Control - Wait for power event on uKernel.");
- PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
- ui32PowManComplete, ui32PowManComplete,
- PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
- MAKEUNIQUETAG(psDevInfo->
- psKernelSGXHostCtlMemInfo));
-#endif
-
-
- {
- if (PollForValueKM
- ((IMG_UINT32 *) psDevInfo->pvRegsBaseKM +
- (EUR_CR_CLKGATESTATUS >> 2), 0,
- psDevInfo->ui32ClkGateStatusMask,
- MAX_HW_TIME_US / WAIT_TRY_COUNT,
- WAIT_TRY_COUNT) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Wait for SGX clock gating failed."));
- }
-
- PDUMPCOMMENT("Wait for SGX clock gating.");
- PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0,
- psDevInfo->ui32ClkGateStatusMask);
- }
-
- if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
- eError = SGXDeinitialise(psDevInfo);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: SGXDeinitialise failed: %lu",
- eError));
- return eError;
- }
- }
- }
-
- return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
- PVR_DEVICE_POWER_STATE eNewPowerState,
- PVR_DEVICE_POWER_STATE eCurrentPowerState)
-{
- if ((eNewPowerState != eCurrentPowerState) &&
- (eCurrentPowerState != PVR_DEVICE_POWER_STATE_ON)) {
- PVRSRV_ERROR eError;
- PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
-
- psSGXHostCtl->ui32PowManFlags = 0;
- PDUMPCOMMENT("TA/3D CCB Control - Reset Power Manager flags");
-#if defined(PDUMP)
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
- sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
-
- if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) {
-
- SGXGetTimingInfo(psDeviceNode);
-
- eError = SGXInitialise(psDevInfo, IMG_FALSE);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPostPowerState: SGXInitialise failed"));
- return eError;
- }
- }
- }
-
- return PVRSRV_OK;
-}
-
-PVRSRV_ERROR SGXPrePowerStateExt(IMG_HANDLE hDevHandle,
- PVR_POWER_STATE eNewPowerState,
- PVR_POWER_STATE eCurrentPowerState)
-{
- PVR_DEVICE_POWER_STATE eNewDevicePowerState =
- MapDevicePowerState(eNewPowerState);
- PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
- MapDevicePowerState(eCurrentPowerState);
-
- return SGXPrePowerState(hDevHandle, eNewDevicePowerState,
- eCurrentDevicePowerState);
-}
-
-PVRSRV_ERROR SGXPostPowerStateExt(IMG_HANDLE hDevHandle,
- PVR_POWER_STATE eNewPowerState,
- PVR_POWER_STATE eCurrentPowerState)
-{
- PVRSRV_ERROR eError;
- PVR_DEVICE_POWER_STATE eNewDevicePowerState =
- MapDevicePowerState(eNewPowerState);
- PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
- MapDevicePowerState(eCurrentPowerState);
-
- eError =
- SGXPostPowerState(hDevHandle, eNewDevicePowerState,
- eCurrentDevicePowerState);
- if (eError != PVRSRV_OK) {
- return eError;
- }
-
- PVR_DPF((PVR_DBG_WARNING,
- "SGXPostPowerState : SGX Power Transition from %d to %d OK",
- eCurrentPowerState, eNewPowerState));
-
- return eError;
-}
-
-static PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
- IMG_BOOL bIdleDevice,
- PVR_POWER_STATE eCurrentPowerState)
+static enum PVRSRV_ERROR SGXRunScript(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ union SGX_INIT_COMMAND *psScript,
+ u32 ui32NumInitCommands)
{
- PVRSRV_ERROR eError;
- PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-
- PVR_UNREFERENCED_PARAMETER(psDevInfo);
-
- if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
- if (bIdleDevice) {
-
- eError =
- SGXPrePowerState(hDevHandle,
- PVR_DEVICE_POWER_STATE_IDLE,
- PVR_DEVICE_POWER_STATE_ON);
-
- if (eError != PVRSRV_OK) {
- return eError;
- }
- }
- }
-
- PVR_DPF((PVR_DBG_MESSAGE,
- "SGXPreClockSpeedChange: SGX clock speed was %luHz",
- psDevInfo->ui32CoreClockSpeed));
-
- return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
- IMG_BOOL bIdleDevice,
- PVR_POWER_STATE eCurrentPowerState)
-{
- PVRSRV_ERROR eError = PVRSRV_OK;
- PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
-
- PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
-
- if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
- SGXGetTimingInfo(psDeviceNode);
- if (bIdleDevice) {
- eError =
- SGXPostPowerState(hDevHandle,
- PVR_DEVICE_POWER_STATE_ON,
- PVR_DEVICE_POWER_STATE_IDLE);
-
- if (eError != PVRSRV_OK) {
- return eError;
- }
- }
- SGXStartTimer(psDevInfo, IMG_TRUE);
- }
-
- PVR_DPF((PVR_DBG_MESSAGE,
- "SGXPostClockSpeedChange: SGX clock speed changed from %luHz to %luHz",
- ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
-
- return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO * psDevInfo,
- SGX_INIT_COMMAND * psScript,
- IMG_UINT32 ui32NumInitCommands)
-{
- IMG_UINT32 ui32PC;
- SGX_INIT_COMMAND *psComm;
+ u32 ui32PC;
+ union SGX_INIT_COMMAND *psComm;
for (ui32PC = 0, psComm = psScript;
ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
default:
{
- PVR_DPF((PVR_DBG_ERROR,
- "SGXRunScript: PC %d: Illegal command: %d",
- ui32PC, psComm->eOp));
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXRunScript: PC %d: Illegal command: %d",
+ ui32PC, psComm->eOp);
return PVRSRV_ERROR_GENERIC;
}
}
}
- return PVRSRV_ERROR_GENERIC;;
+ return PVRSRV_ERROR_GENERIC;
}
-static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
+enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bHardwareRecovery)
{
- PVRSRV_ERROR eError;
- IMG_UINT32 ui32ReadOffset, ui32WriteOffset;
+ enum PVRSRV_ERROR eError;
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL,
- psDevInfo->ui32ClkGateCtl);
- PDUMPREGWITHFLAGS(EUR_CR_CLKGATECTL, psDevInfo->ui32ClkGateCtl,
- PDUMP_FLAGS_CONTINUOUS);
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX initialisation script part 1\n");
+ eError =
+ SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1,
+ SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXInitialise: SGXRunScript (part 1) failed (%d)",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "End of SGX initialisation script part 1\n");
SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
*psDevInfo->pui32KernelCCBEventKicker = 0;
#if defined(PDUMP)
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
sizeof(*psDevInfo->pui32KernelCCBEventKicker),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
#endif
- psDevInfo->psSGXHostCtl->sTAHWPBDesc.uiAddr = 0;
- psDevInfo->psSGXHostCtl->s3DHWPBDesc.uiAddr = 0;
-#if defined(PDUMP)
- PDUMPCOMMENT(" CCB Control - Reset HW PBDesc records");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, sTAHWPBDesc),
- sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, s3DHWPBDesc),
- sizeof(IMG_DEV_VIRTADDR), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
-
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX initialisation script part 2\n");
eError =
- SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommands,
+ SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2,
SGX_MAX_INIT_COMMANDS);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXInitialise: SGXRunScript failed (%d)", eError));
- return (PVRSRV_ERROR_GENERIC);
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXInitialise: SGXRunScript (part 2) failed (%d)",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
}
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "End of SGX initialisation script part 2\n");
- SGXStartTimer(psDevInfo, !bHardwareRecovery);
+ SGXStartTimer(psDevInfo, (IMG_BOOL)!bHardwareRecovery);
if (bHardwareRecovery) {
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
- if (PollForValueKM
- ((volatile IMG_UINT32 *)(&psSGXHostCtl->
- ui32InterruptClearFlags), 0,
+ if (PollForValueKM(&psSGXHostCtl->ui32InterruptClearFlags, 0,
PVRSRV_USSE_EDM_INTERRUPT_HWR,
MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXInitialise: Wait for uKernel HW Recovery failed"));
+ PVR_DPF(PVR_DBG_ERROR, "SGXInitialise: "
+ "Wait for uKernel HW Recovery failed");
+ PVR_DBG_BREAK;
return PVRSRV_ERROR_RETRY;
}
}
- for (ui32ReadOffset = psDevInfo->psKernelCCBCtl->ui32ReadOffset,
- ui32WriteOffset = psDevInfo->psKernelCCBCtl->ui32WriteOffset;
- ui32ReadOffset != ui32WriteOffset;
- ui32ReadOffset = (ui32ReadOffset + 1) & 0xFF) {
- *psDevInfo->pui32KernelCCBEventKicker =
- (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_KICK,
- EUR_CR_EVENT_KICK_NOW_MASK);
- }
+ PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset ==
+ psDevInfo->psKernelCCBCtl->ui32WriteOffset);
return PVRSRV_OK;
}
-PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie)
{
- PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
- PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
+ hDevCookie;
+ enum PVRSRV_ERROR eError;
- if (psDevInfo->pvRegsBaseKM == IMG_NULL) {
+ if (psDevInfo->pvRegsBaseKM == NULL)
return PVRSRV_OK;
- }
- eError =
- SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
SGX_MAX_DEINIT_COMMANDS);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXDeinitialise: SGXRunScript failed (%d)", eError));
- return (PVRSRV_ERROR_GENERIC);
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXDeinitialise: SGXRunScript failed (%d)", eError);
+ return PVRSRV_ERROR_GENERIC;
}
return PVRSRV_OK;
}
-static PVRSRV_ERROR DevInitSGXPart1(IMG_VOID * pvDeviceNode)
+static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
{
- PVRSRV_SGXDEV_INFO *psDevInfo;
- IMG_HANDLE hKernelDevMemContext;
- IMG_DEV_PHYADDR sPDDevPAddr;
- IMG_UINT32 i;
- PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvDeviceNode;
- DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ void *hKernelDevMemContext;
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ u32 i;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = (struct PVRSRV_DEVICE_NODE *)
+ pvDeviceNode;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
- IMG_HANDLE hDevInfoOSMemHandle = (IMG_HANDLE) IMG_NULL;
- PVRSRV_ERROR eError;
+ enum PVRSRV_ERROR eError;
PDUMPCOMMENT("SGX Initialisation Part 1");
PDUMPCOMMENT("SGX Core Version Information: %s",
SGX_CORE_FRIENDLY_NAME);
-#ifdef SGX_CORE_REV
- PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
-#else
- PDUMPCOMMENT("SGX Core Revision Information: head rtl");
-#endif
-
- if (OSAllocPages
- (PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS |
- PVRSRV_HAP_CACHED, sizeof(PVRSRV_SGXDEV_INFO),
- (IMG_VOID **) & psDevInfo, &hDevInfoOSMemHandle) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
- return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ PDUMPCOMMENT("SGX Core Revision Information: multi rev support");
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGXDEV_INFO),
+ (void **)&psDevInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGXPart1 : Failed to alloc memory for DevInfo");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
}
- OSMemSet(psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+ OSMemSet(psDevInfo, 0, sizeof(struct PVRSRV_SGXDEV_INFO));
psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
- psDeviceNode->pvDevice = (IMG_PVOID) psDevInfo;
- psDeviceNode->hDeviceOSMemHandle = hDevInfoOSMemHandle;
+ psDeviceNode->pvDevice = (void *) psDevInfo;
- psDevInfo->pvDeviceMemoryHeap = (IMG_VOID *) psDeviceMemoryHeap;
+ psDevInfo->pvDeviceMemoryHeap = (void *) psDeviceMemoryHeap;
- hKernelDevMemContext = BM_CreateContext(psDeviceNode,
- &sPDDevPAddr,
- IMG_NULL, IMG_NULL);
+ hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
+ NULL, NULL);
+ if (!hKernelDevMemContext)
+ goto err1;
psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
- IMG_HANDLE hDevMemHeap;
+ void *hDevMemHeap;
switch (psDeviceMemoryHeap[i].DevMemHeapType) {
case DEVICE_MEMORY_HEAP_KERNEL:
BM_CreateHeap(hKernelDevMemContext,
&psDeviceMemoryHeap[i]);
+ if (!hDevMemHeap)
+ goto err2;
+
psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
break;
}
eError = MMU_BIFResetPDAlloc(psDevInfo);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGX : Failed to alloc memory for BIF reset"));
- return PVRSRV_ERROR_GENERIC;
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGX : Failed to alloc memory for BIF reset");
+ goto err2;
}
return PVRSRV_OK;
+err2:
+ while (i) {
+ int type;
+
+ i--;
+ type = psDeviceMemoryHeap[i].DevMemHeapType;
+ if (type != DEVICE_MEMORY_HEAP_KERNEL &&
+ type != DEVICE_MEMORY_HEAP_SHARED &&
+ type != DEVICE_MEMORY_HEAP_SHARED_EXPORTED)
+ continue;
+ BM_DestroyHeap(psDeviceMemoryHeap[i].hDevMemHeap);
+ }
+ BM_DestroyContext(hKernelDevMemContext);
+err1:
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
+
+ return PVRSRV_ERROR_GENERIC;
}
-IMG_EXPORT
- PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
- SGX_BRIDGE_INFO_FOR_SRVINIT *
- psInitInfo)
+enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
+ struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
{
- PVRSRV_DEVICE_NODE *psDeviceNode;
- PVRSRV_SGXDEV_INFO *psDevInfo;
- PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ enum PVRSRV_ERROR eError;
PDUMPCOMMENT("SGXGetInfoForSrvinit");
- psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevHandle;
- psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
eError =
PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)",
- eError));
+ PVR_DPF(PVR_DBG_ERROR, "SGXGetInfoForSrvinit: "
+ "PVRSRVGetDeviceMemHeapsKM failed (%d)",
+ eError);
return PVRSRV_ERROR_GENERIC;
}
return eError;
}
-IMG_EXPORT
- PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA * psPerProc,
- IMG_HANDLE hDevHandle,
- SGX_BRIDGE_INIT_INFO * psInitInfo)
+enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevHandle,
+ struct SGX_BRIDGE_INIT_INFO *psInitInfo)
{
- PVRSRV_DEVICE_NODE *psDeviceNode;
- PVRSRV_SGXDEV_INFO *psDevInfo;
- PVRSRV_ERROR eError;
- SGX_DEVICE_MAP *psSGXDeviceMap;
- PVR_POWER_STATE eDefaultPowerState;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ enum PVRSRV_ERROR eError;
+ struct SGX_DEVICE_MAP *psSGXDeviceMap;
+ enum PVR_POWER_STATE eDefaultPowerState;
+ u32 l;
PDUMPCOMMENT("SGX Initialisation Part 2");
- psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevHandle;
- psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart2KM: Failed to load EDM program"));
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "Failed to load EDM program");
goto failed_init_dev_info;
}
eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
- (IMG_VOID **) & psSGXDeviceMap);
+ (void **) &psSGXDeviceMap);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart2KM: Failed to get device memory map!"));
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "Failed to get device memory map!");
return PVRSRV_ERROR_INIT_FAILURE;
}
if (psSGXDeviceMap->pvRegsCpuVBase) {
psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
} else {
-
psDevInfo->pvRegsBaseKM =
OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
psSGXDeviceMap->ui32RegsSize,
PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
- IMG_NULL);
+ NULL);
if (!psDevInfo->pvRegsBaseKM) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart2KM: Failed to map in regs\n"));
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGXPart2KM: Failed to map in regs\n");
return PVRSRV_ERROR_BAD_MAPPING;
}
}
psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
-
-
psDeviceNode->pvISRData = psDeviceNode;
PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
-
-
- psDevInfo->psSGXHostCtl->ui32PowManFlags |=
- PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ pvr_dev_lock();
+ l = readl(&psDevInfo->psSGXHostCtl->ui32PowerStatus);
+ l |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ writel(l, &psDevInfo->psSGXHostCtl->ui32PowerStatus);
+ pvr_dev_unlock();
eDefaultPowerState = PVRSRV_POWER_STATE_D3;
+
eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
SGXPrePowerStateExt,
SGXPostPowerStateExt,
SGXPreClockSpeedChange,
SGXPostClockSpeedChange,
- (IMG_HANDLE) psDeviceNode,
+ (void *) psDeviceNode,
PVRSRV_POWER_STATE_D3,
eDefaultPowerState);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart2KM: failed to register device with power manager"));
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "failed to register device with power manager");
return eError;
}
- OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
- OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+ OSMemSet(psDevInfo->psKernelCCB, 0,
+ sizeof(struct PVRSRV_SGX_KERNEL_CCB));
+ OSMemSet(psDevInfo->psKernelCCBCtl, 0,
+ sizeof(struct PVRSRV_SGX_CCB_CTL));
OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
sizeof(*psDevInfo->pui32KernelCCBEventKicker));
- PDUMPCOMMENT("Kernel CCB");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0,
- sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
+ PDUMPCOMMENT("Initialise Kernel CCB");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBMemInfo, 0,
+ sizeof(struct PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
- PDUMPCOMMENT("Kernel CCB Control");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
- sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
+ PDUMPCOMMENT("Initialise Kernel CCB Control");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
+ sizeof(struct PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
- PDUMPCOMMENT("Kernel CCB Event Kicker");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
sizeof(*psDevInfo->pui32KernelCCBEventKicker),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ psDevInfo->hTimer = SGXOSTimerInit(psDeviceNode);
+ if (!psDevInfo->hTimer)
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM : "
+ "Failed to initialize HW recovery timer");
+
return PVRSRV_OK;
failed_init_dev_info:
return eError;
}
-static PVRSRV_ERROR DevDeInitSGX(IMG_VOID * pvDeviceNode)
+static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
{
- PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvDeviceNode;
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
- IMG_HANDLE hDevInfoOSMemHandle = psDeviceNode->hDeviceOSMemHandle;
- PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
- IMG_UINT32 ui32Heap;
- DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
- SGX_DEVICE_MAP *psSGXDeviceMap;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode =
+ (struct PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ enum PVRSRV_ERROR eError;
+ u32 ui32Heap;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ struct SGX_DEVICE_MAP *psSGXDeviceMap;
if (!psDevInfo) {
-
- PVR_DPF((PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo"));
+ PVR_DPF(PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo");
return PVRSRV_OK;
}
if (psDevInfo->hTimer) {
- eError = OSRemoveTimer(psDevInfo->hTimer);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevDeInitSGX: Failed to remove timer"));
- return eError;
- }
- psDevInfo->hTimer = IMG_NULL;
+ SGXOSTimerCancel(psDevInfo->hTimer);
+ SGXOSTimerDeInit(psDevInfo->hTimer);
+ psDevInfo->hTimer = NULL;
}
MMU_BIFResetPDFree(psDevInfo);
psDeviceMemoryHeap =
- (DEVICE_MEMORY_HEAP_INFO *) psDevInfo->pvDeviceMemoryHeap;
+ (struct DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
for (ui32Heap = 0;
ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
ui32Heap++) {
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
- IMG_NULL) {
+ NULL)
BM_DestroyHeap(psDeviceMemoryHeap
[ui32Heap].hDevMemHeap);
- }
break;
}
}
}
- eError =
- BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext,
- IMG_NULL);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevDeInitSGX : Failed to destroy kernel context"));
- return eError;
- }
+ if (!pvr_put_ctx(psDeviceNode->sDevMemoryInfo.pBMKernelContext))
+ pr_err("%s: kernel context still in use, can't free it",
+ __func__);
- eError =
- PVRSRVRemovePowerDevice(((PVRSRV_DEVICE_NODE *) pvDeviceNode)->
- sDevId.ui32DeviceIndex);
- if (eError != PVRSRV_OK) {
+ eError = PVRSRVRemovePowerDevice(
+ ((struct PVRSRV_DEVICE_NODE *)pvDeviceNode)->
+ sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
return eError;
- }
eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
- (IMG_VOID **) & psSGXDeviceMap);
+ (void **)&psSGXDeviceMap);
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevDeInitSGX: Failed to get device memory map!"));
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevDeInitSGX: Failed to get device memory map!");
return eError;
}
- if (!psSGXDeviceMap->pvRegsCpuVBase) {
-
- if (psDevInfo->pvRegsBaseKM != IMG_NULL) {
+ if (!psSGXDeviceMap->pvRegsCpuVBase)
+ if (psDevInfo->pvRegsBaseKM != NULL)
OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
psDevInfo->ui32RegSize,
PVRSRV_HAP_KERNEL_ONLY |
- PVRSRV_HAP_UNCACHED, IMG_NULL);
- }
- }
+ PVRSRV_HAP_UNCACHED,
+ NULL);
- OSFreePages(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_HAP_MULTI_PROCESS,
- sizeof(PVRSRV_SGXDEV_INFO), psDevInfo, hDevInfoOSMemHandle);
- psDeviceNode->pvDevice = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
- if (psDeviceMemoryHeap != IMG_NULL) {
+ psDeviceNode->pvDevice = NULL;
+ if (psDeviceMemoryHeap != NULL)
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
- sizeof(DEVICE_MEMORY_HEAP_INFO) *
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
psDeviceNode->sDevMemoryInfo.ui32HeapCount,
- psDeviceMemoryHeap, 0);
- }
+ psDeviceMemoryHeap, NULL);
return PVRSRV_OK;
}
-static
-IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE * psDeviceNode,
- IMG_UINT32 ui32Component, IMG_UINT32 ui32CallerID)
+static struct PVRSRV_PER_PROCESS_DATA *find_cur_proc_data(
+ struct PVRSRV_DEVICE_NODE *dev)
{
- PVRSRV_ERROR eError;
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
+ struct PVRSRV_SGXDEV_INFO *dev_info = dev->pvDevice;
+ u32 page_dir = readl(dev_info->pvRegsBaseKM +
+ EUR_CR_BIF_DIR_LIST_BASE0);
+ struct BM_CONTEXT *bm_ctx;
+ struct RESMAN_CONTEXT *res_ctx = NULL;
+ struct PVRSRV_PER_PROCESS_DATA *proc_data = NULL;
- PVR_UNREFERENCED_PARAMETER(ui32Component);
+ bm_ctx = bm_find_context(dev->sDevMemoryInfo.pBMContext, page_dir);
+ if (bm_ctx)
+ res_ctx = pvr_get_resman_ctx(bm_ctx);
- eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
- if (eError != PVRSRV_OK) {
+ if (res_ctx)
+ proc_data = pvr_get_proc_by_ctx(res_ctx);
- PVR_DPF((PVR_DBG_WARNING,
- "HWRecoveryResetSGX: Power transition in progress"));
+ return proc_data;
+}
+
+static void pr_err_process_info(struct PVRSRV_PER_PROCESS_DATA *proc)
+{
+ struct task_struct *tsk;
+ int pid;
+
+ if (!proc)
return;
- }
- psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+ pid = proc->ui32PID;
+ rcu_read_lock();
+ tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
+ pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
+ rcu_read_unlock();
+}
+
+static void pr_err_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ pr_err("EVENT_STATUS = 0x%08X\n"
+ "EVENT_STATUS2 = 0x%08X\n"
+ "BIF_CTRL = 0x%08X\n"
+ "BIF_INT_STAT = 0x%08X\n"
+ "BIF_MEM_REQ_STAT = 0x%08X\n"
+ "BIF_FAULT = 0x%08X\n"
+ "CLKGATECTL = 0x%08X\n",
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS2),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_CTRL),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_INT_STAT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_FAULT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
+}
+
+/* Should be called with pvr_lock held */
+void
+HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode, const char *caller)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ struct PVRSRV_PER_PROCESS_DATA *proc;
+ u32 l;
+ int max_retries = 10;
+
+ BUG_ON(!pvr_is_locked());
+
+ l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+ l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+ writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
- pr_err("HWRecoveryResetSGX: SGX Hardware Recovery triggered\n");
+ pr_err("SGX Hardware Recovery triggered (from %s)\n", caller);
+
+ proc = find_cur_proc_data(psDeviceNode);
+
+ pr_err_process_info(proc);
+ pr_err_sgx_registers(psDevInfo);
+
+#ifdef CONFIG_DEBUG_FS
+ pvr_hwrec_dump(proc, psDevInfo);
+#endif
PDUMPSUSPEND();
do {
eError = SGXInitialise(psDevInfo, IMG_TRUE);
- }
- while (eError == PVRSRV_ERROR_RETRY);
+ if (eError != PVRSRV_ERROR_RETRY)
+ break;
+ } while (max_retries--);
+
if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "HWRecoveryResetSGX: SGXInitialise failed (%d)",
- eError));
+ pr_err("%s: recovery failed (%d). Disabling the driver",
+ __func__, eError);
+ pvr_disable();
+
+ PDUMPRESUME();
+
+ return;
}
PDUMPRESUME();
- PVRSRVPowerUnlock(ui32CallerID);
-
SGXScheduleProcessQueues(psDeviceNode);
- PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
-}
-
-static struct workdata {
- PVRSRV_DEVICE_NODE *psDeviceNode;
- IMG_UINT32 ui32Component;
- IMG_UINT32 ui32CallerID;
-} gHWRecoveryParams;
-
-static void HWRecoveryWrapper(struct work_struct *work)
-{
- HWRecoveryResetSGX(gHWRecoveryParams.psDeviceNode,
- gHWRecoveryParams.ui32Component,
- gHWRecoveryParams.ui32CallerID);
+ PVRSRVProcessQueues(IMG_TRUE);
}
-DECLARE_WORK(gWork, HWRecoveryWrapper);
+static unsigned long sgx_reset_forced;
-IMG_VOID SGXOSTimer(IMG_VOID * pvData)
+static void SGXOSTimer(struct work_struct *work)
{
- PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- static IMG_UINT32 ui32EDMTasks = 0;
- static IMG_UINT32 ui32LockupCounter = 0;
- static IMG_UINT32 ui32NumResets = 0;
- IMG_UINT32 ui32CurrentEDMTasks;
+ struct timer_work_data *data = container_of(work,
+ struct timer_work_data,
+ work.work);
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = data->psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ static u32 ui32EDMTasks;
+ static u32 ui32LockupCounter;
+ static u32 ui32NumResets;
+ u32 ui32CurrentEDMTasks;
IMG_BOOL bLockup = IMG_FALSE;
IMG_BOOL bPoweredDown;
+ pvr_lock();
+
+ if (!data->armed || pvr_is_disabled()) {
+ pvr_unlock();
+ return;
+ }
+
psDevInfo->ui32TimeStamp++;
- bPoweredDown = (IMG_BOOL) ! SGXIsDevicePowered(psDeviceNode);
+#if defined(NO_HARDWARE)
+ bPoweredDown = IMG_TRUE;
+#else
+ bPoweredDown = (IMG_BOOL) !SGXIsDevicePowered(psDeviceNode);
+#endif
if (bPoweredDown) {
ui32LockupCounter = 0;
} else {
-
- ui32CurrentEDMTasks =
- OSReadHWReg(psDevInfo->pvRegsBaseKM,
- psDevInfo->ui32EDMTaskReg0);
- if (psDevInfo->ui32EDMTaskReg1 != 0) {
+ pvr_dev_lock();
+ ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32EDMTaskReg0);
+ if (psDevInfo->ui32EDMTaskReg1 != 0)
ui32CurrentEDMTasks ^=
OSReadHWReg(psDevInfo->pvRegsBaseKM,
psDevInfo->ui32EDMTaskReg1);
- }
if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
(psDevInfo->ui32NumResets == ui32NumResets)) {
ui32LockupCounter++;
if (ui32LockupCounter == 3) {
ui32LockupCounter = 0;
- PVR_DPF((PVR_DBG_ERROR,
- "SGXOSTimer() detected SGX lockup (0x%x tasks)",
- ui32EDMTasks));
+ PVR_DPF(PVR_DBG_ERROR, "SGXOSTimer() "
+ "detected SGX lockup (0x%x tasks)",
+ ui32EDMTasks);
bLockup = IMG_TRUE;
}
ui32EDMTasks = ui32CurrentEDMTasks;
ui32NumResets = psDevInfo->ui32NumResets;
}
+ pvr_dev_unlock();
}
+ bLockup |= cmpxchg(&sgx_reset_forced, 1, 0);
+
if (bLockup) {
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
-
- psSGXHostCtl->ui32HostDetectedLockups++;
-
- /*
- * schedule HWRecoveryResetSGX from a work
- * in the shared queue
- */
- gHWRecoveryParams.psDeviceNode = psDeviceNode;
- gHWRecoveryParams.ui32Component = 0;
- gHWRecoveryParams.ui32CallerID = TIMER_ID;
- schedule_work(&gWork);
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l;
+
+ pvr_dev_lock();
+ l = readl(&psSGXHostCtl->ui32HostDetectedLockups);
+ l++;
+ writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
+
+ HWRecoveryResetSGX(psDeviceNode, __func__);
+ pvr_dev_unlock();
}
+
+ queue_delayed_work(data->work_queue, &data->work,
+ msecs_to_jiffies(data->interval));
+
+ pvr_unlock();
}
+struct timer_work_data *
+SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct timer_work_data *data;
+
+ data = kzalloc(sizeof(struct timer_work_data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ data->work_queue = create_workqueue("SGXOSTimer");
+ if (!data->work_queue) {
+ kfree(data);
+ return NULL;
+ }
+
+ data->interval = 150;
+ data->psDeviceNode = psDeviceNode;
+ INIT_DELAYED_WORK(&data->work, SGXOSTimer);
+
+ return data;
+}
-IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData)
+void SGXOSTimerDeInit(struct timer_work_data *data)
+{
+ data->armed = false;
+ destroy_workqueue(data->work_queue);
+ kfree(data);
+}
+
+enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data)
+{
+ if (!data)
+ return PVRSRV_ERROR_GENERIC;
+
+ if (queue_delayed_work(data->work_queue, &data->work,
+ msecs_to_jiffies(data->interval))) {
+ data->armed = true;
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data)
+{
+ if (!data)
+ return PVRSRV_ERROR_GENERIC;
+
+ data->armed = false;
+ cancel_delayed_work(&data->work);
+
+ return PVRSRV_OK;
+}
+
+int sgx_force_reset(void)
+{
+ return !cmpxchg(&sgx_reset_forced, 0, 1);
+}
+
+static IMG_BOOL SGX_ISRHandler(void *pvData)
{
IMG_BOOL bInterruptProcessed = IMG_FALSE;
{
- IMG_UINT32 ui32EventStatus, ui32EventEnable;
- IMG_UINT32 ui32EventClear = 0;
- PVRSRV_DEVICE_NODE *psDeviceNode;
- PVRSRV_SGXDEV_INFO *psDevInfo;
-
- if (pvData == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGX_ISRHandler: Invalid params\n"));
+ u32 ui32EventStatus, ui32EventEnable;
+ u32 ui32EventClear = 0;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ if (pvData == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGX_ISRHandler: Invalid params\n");
return bInterruptProcessed;
}
- psDeviceNode = (PVRSRV_DEVICE_NODE *) pvData;
- psDevInfo = (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)pvData;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
ui32EventStatus =
OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
- ui32EventEnable =
- OSReadHWReg(psDevInfo->pvRegsBaseKM,
- EUR_CR_EVENT_HOST_ENABLE);
+ ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_EVENT_HOST_ENABLE);
gui32EventStatusServicesByISR = ui32EventStatus;
ui32EventStatus &= ui32EventEnable;
- if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK) {
+ if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
- }
if (ui32EventClear) {
bInterruptProcessed = IMG_TRUE;
return bInterruptProcessed;
}
-IMG_VOID SGX_MISRHandler(IMG_VOID * pvData)
+static void SGX_MISRHandler(void *pvData)
{
- PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *) pvData;
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- (PVRSRV_SGX_HOST_CTL *) psDevInfo->psSGXHostCtl;
-
- if ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)
- && !(psSGXHostCtl->
- ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR)) {
- HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
- }
- SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+ struct PVRSRV_DEVICE_NODE *psDeviceNode =
+ (struct PVRSRV_DEVICE_NODE *)pvData;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l1, l2;
+ int dev_idx;
+ enum PVRSRV_ERROR err;
+
+ dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ pvr_dev_lock();
+
+ err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0);
+ BUG_ON(err != PVRSRV_OK);
+
+ l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
+ l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+
+ if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
+ !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
+ HWRecoveryResetSGX(psDeviceNode, __func__);
+
+ if (psDeviceNode->bReProcessDeviceCommandComplete)
+ SGXScheduleProcessQueues(psDeviceNode);
+
+ SGXTestActivePowerEvent(psDeviceNode);
+
+ pvr_dev_unlock();
}
-PVRSRV_ERROR SGXRegisterDevice(PVRSRV_DEVICE_NODE * psDeviceNode)
+enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
{
- DEVICE_MEMORY_INFO *psDevMemoryInfo;
- DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
psDeviceNode->pfnInitDevice = DevInitSGXPart1;
psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
+ psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
+
psDeviceNode->pfnMMUInitialise = MMU_Initialise;
psDeviceNode->pfnMMUFinalise = MMU_Finalise;
psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
-
psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
- psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_ADDRESS_SPACE_SIZE;
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 =
+ SGX_FEATURE_ADDRESS_SPACE_SIZE;
psDevMemoryInfo->ui32Flags = 0;
-
psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
-
psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
- psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_MAPPING_HEAP_ID;
+ psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_HEAP_ID;
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(DEVICE_MEMORY_HEAP_INFO) *
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
psDevMemoryInfo->ui32HeapCount,
- (IMG_VOID **) & psDevMemoryInfo->psDeviceMemoryHeap,
- 0) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
- return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ (void **) &psDevMemoryInfo->psDeviceMemoryHeap,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXRegisterDevice : "
+ "Failed to alloc memory for "
+ "struct DEVICE_MEMORY_HEAP_INFO");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
}
OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
- sizeof(DEVICE_MEMORY_HEAP_INFO) *
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
psDevMemoryInfo->ui32HeapCount);
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
SGX_KERNEL_CODE_HEAP_SIZE;
psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
- PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
- | PVRSRV_HAP_MULTI_PROCESS;
- psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel";
- psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName = "Kernel BS";
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel Code";
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName =
+ "Kernel Code BS";
psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapID =
- HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VIDEO_CODE_HEAP_ID);
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
- SGX_VIDEO_CODE_HEAP_BASE;
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32HeapSize =
- SGX_VIDEO_CODE_HEAP_SIZE;
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].ui32Attribs =
- PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
- PVRSRV_HAP_KERNEL_ONLY;
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszName = "Video";
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].pszBSName = "Video BS";
- psDeviceMemoryHeap[SGX_VIDEO_CODE_HEAP_ID].DevMemHeapType =
- DEVICE_MEMORY_HEAP_SHARED;
-
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapID =
- HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_VIDEO_DATA_HEAP_ID);
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
- SGX_KERNEL_VIDEO_DATA_HEAP_BASE;
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32HeapSize =
- SGX_KERNEL_VIDEO_DATA_HEAP_SIZE;
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].ui32Attribs =
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_KERNEL_DATA_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapSize =
+ SGX_KERNEL_DATA_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32Attribs =
PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
PVRSRV_HAP_MULTI_PROCESS;
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszName =
- "KernelVideoData";
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].pszBSName =
- "KernelVideoData BS";
- psDeviceMemoryHeap[SGX_KERNEL_VIDEO_DATA_HEAP_ID].DevMemHeapType =
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszName = "KernelData";
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszBSName = "KernelData BS";
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_PERCONTEXT;
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapID =
- HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
- SGX_GENERAL_MAPPING_HEAP_BASE;
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32HeapSize =
- SGX_GENERAL_MAPPING_HEAP_SIZE;
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].ui32Attribs =
- PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszName =
- "GeneralMapping";
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].pszBSName =
- "GeneralMapping BS";
-
- psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].DevMemHeapType =
- DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].ui32HeapID =
- HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_FB_MAPPING_HEAP_ID);
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
- SGX_FB_MAPPING_HEAP_BASE;
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].ui32HeapSize =
- SGX_FB_MAPPING_HEAP_SIZE;
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].ui32Attribs =
- PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].pszName =
- "FramebufferMapping";
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].pszBSName =
- "FramebufferMapping BS";
-
- psDeviceMemoryHeap[SGX_FB_MAPPING_HEAP_ID].DevMemHeapType =
- DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapID =
- HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_ALT_MAPPING_HEAP_ID);
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
- SGX_ALT_MAPPING_HEAP_BASE;
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapSize =
- SGX_ALT_MAPPING_HEAP_SIZE;
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32Attribs =
- PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszName = "AltMapping";
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszBSName = "AltMapping BS";
-
- psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].DevMemHeapType =
- DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
return PVRSRV_OK;
}
-IMG_EXPORT
- PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
- PVR3DIF4_CLIENT_INFO * psClientInfo)
+enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
+ struct SGX_CLIENT_INFO *psClientInfo)
{
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) ((PVRSRV_DEVICE_NODE *) hDevCookie)->
- pvDevice;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)
+ ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
psDevInfo->ui32ClientRefCount++;
#ifdef PDUMP
- if (psDevInfo->ui32ClientRefCount == 1) {
+ if (psDevInfo->ui32ClientRefCount == 1)
psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
- }
#endif
-
psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
return PVRSRV_OK;
}
-IMG_EXPORT
- PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO * psDevInfo,
- SGX_MISC_INFO * psMiscInfo)
+enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ enum PVRSRV_ERROR eError;
+#if !defined(NO_HARDWARE)
+ u32 opts;
+ u32 opt_mismatch;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+#endif
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXDevInitCompatCheck: Device not of type SGX");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit;
+ }
+ psDevInfo = psDeviceNode->pvDevice;
+ psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+#if !defined(NO_HARDWARE)
+
+ eError = SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ pr_err("pvr: unable to validate device DDK version\n");
+ goto exit;
+ }
+ psSGXFeatures =
+ &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->pvLinAddrKM))->
+ sSGXFeatures;
+ if ((psSGXFeatures->ui32DDKVersion !=
+ ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH)) ||
+ (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD)) {
+ pr_err("pvr: incompatible driver DDK revision (%d)"
+ "/device DDK revision (%d).\n",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ goto exit;
+ } else {
+ PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
+ "driver DDK (%ld) and device DDK (%ld) match",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
+ }
+
+ opts = psSGXFeatures->ui32BuildOptions;
+ opt_mismatch = opts ^ SGX_BUILD_OPTIONS;
+ /* we support the ABIs both with and without EDM tracing option */
+ opt_mismatch &= ~PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET;
+ if (opt_mismatch) {
+ if (SGX_BUILD_OPTIONS & opt_mismatch)
+ pr_err("pvr: mismatch in driver and microkernel build "
+ "options; extra options present in driver: "
+ "(0x%x)", SGX_BUILD_OPTIONS & opt_mismatch);
+
+ if (opts & opt_mismatch)
+ pr_err("pvr: Mismatch in driver and microkernel build "
+ "options; extra options present in "
+ "microkernel: (0x%x)", opts & opt_mismatch);
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto exit;
+ } else {
+ PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
+ "Driver and microkernel build options match.");
+ }
+
+#endif
+ eError = PVRSRV_OK;
+exit:
+ return eError;
+}
+
+static
+enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError;
+ struct SGXMKIF_COMMAND sCommandData;
+ struct PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+
+ if (!psMemInfo->pvLinAddrKM) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXGetMiscInfoKM: Invalid address.");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+ psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
+
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+ OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+
+ mb();
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_COMMAND_REQUEST_SGXMISCINFO,
+ &sCommandData, KERNEL_ID, 0);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.");
+ return eError;
+ }
+
+#if !defined(NO_HARDWARE)
+ {
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if ((psSGXMiscInfoInt->
+ ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) !=
+ 0) {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout)
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct SGX_MISC_INFO *psMiscInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode)
{
switch (psMiscInfo->eRequest) {
case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
psDevInfo->ui32CoreClockSpeed;
return PVRSRV_OK;
}
+
+ case SGX_MISC_INFO_REQUEST_SGXREV:
+ {
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+
+ SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
+ psSGXFeatures =
+ &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->
+ pvLinAddrKM))->sSGXFeatures;
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
+ "Core 0x%lx, sw ID 0x%lx, "
+ "sw Rev 0x%lx\n",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreIdSW,
+ psSGXFeatures->ui32CoreRevSW);
+ PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
+ "DDK version 0x%lx, DDK build 0x%lx\n",
+ psSGXFeatures->ui32DDKVersion,
+ psSGXFeatures->ui32DDKBuild);
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+ {
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ psSGXFeatures = &((struct PVRSRV_SGX_MISCINFO_INFO *)(
+ psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
+
+ psSGXFeatures->ui32DDKVersion =
+ (PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) | PVRVERSION_BRANCH;
+ psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+ {
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned ui32MatchingFlags;
+
+ if ((psMiscInfo->uData.ui32NewHWPerfStatus &
+ ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON |
+ PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pvr_dev_lock();
+ ui32MatchingFlags = readl(&psDevInfo->
+ psSGXHostCtl->ui32HWPerfFlags);
+ ui32MatchingFlags &=
+ psMiscInfo->uData.ui32NewHWPerfStatus;
+ if ((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON)
+ == 0UL) {
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
+ }
+ if ((ui32MatchingFlags &
+ PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL) {
+ psHWPerfCB->ui32OrdinalMK_EXECUTION =
+ 0xffffffffUL;
+ }
+
+
+ writel(psMiscInfo->uData.ui32NewHWPerfStatus,
+ &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX ukernel HWPerf status %u\n",
+ readl(&psDevInfo->psSGXHostCtl->
+ ui32HWPerfFlags));
+ PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL,
+ ui32HWPerfFlags),
+ sizeof(psDevInfo->psSGXHostCtl->
+ ui32HWPerfFlags),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->
+ psKernelSGXHostCtlMemInfo));
+#endif
+
+ return PVRSRV_OK;
+ }
case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
{
- psDevInfo->psSGXHostCtl->ui32HWPerfFlags |=
- PVRSRV_SGX_HWPERF_ON;
+
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ u32 l;
+
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
+
+ pvr_dev_lock();;
+ l = readl(&psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ l |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
+ writel(l, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
{
- psDevInfo->psSGXHostCtl->ui32HWPerfFlags &=
- ~PVRSRV_SGX_HWPERF_ON;
+ pvr_dev_lock();
+ writel(0, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
{
- SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
+ struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
&psMiscInfo->uData.sRetrieveCB;
- PVRSRV_SGX_HWPERF_CB *psHWPerfCB =
- (PVRSRV_SGX_HWPERF_CB *) psDevInfo->
- psKernelHWPerfCBMemInfo->pvLinAddrKM;
- IMG_UINT i = 0;
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned i;
- for (;
+ for (i = 0;
psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
&& i < psRetrieve->ui32ArraySize; i++) {
- PVRSRV_SGX_HWPERF_CBDATA *psData =
+ struct SGXMKIF_HWPERF_CB_ENTRY *psData =
&psHWPerfCB->psHWPerfCBData[psHWPerfCB->
ui32Roff];
- OSMemCopy(&psRetrieve->psHWPerfData[i], psData,
- sizeof(PVRSRV_SGX_HWPERF_CBDATA));
+
+ psRetrieve->psHWPerfData[i].ui32FrameNo =
+ psData->ui32FrameNo;
+ psRetrieve->psHWPerfData[i].ui32Type =
+ (psData->ui32Type &
+ PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
+ psRetrieve->psHWPerfData[i].ui32StartTime =
+ psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32StartTimeWraps =
+ psData->ui32TimeWraps;
+ psRetrieve->psHWPerfData[i].ui32EndTime =
+ psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32EndTimeWraps =
+ psData->ui32TimeWraps;
psRetrieve->psHWPerfData[i].ui32ClockSpeed =
psDevInfo->ui32CoreClockSpeed;
psRetrieve->psHWPerfData[i].ui32TimeMax =
psDevInfo->ui32uKernelTimerClock;
psHWPerfCB->ui32Roff =
- (psHWPerfCB->ui32Roff +
- 1) & (PVRSRV_SGX_HWPERF_CBSIZE - 1);
+ (psHWPerfCB->ui32Roff + 1) &
+ (SGXMKIF_HWPERF_CB_SIZE - 1);
}
psRetrieve->ui32DataCount = i;
psRetrieve->ui32Time = OSClockus();
}
default:
{
-
return PVRSRV_ERROR_INVALID_PARAMS;
}
}
}
-IMG_EXPORT
- PVRSRV_ERROR SGXReadDiffCountersKM(IMG_HANDLE hDevHandle,
- IMG_UINT32 ui32Reg,
- IMG_UINT32 * pui32Old,
- IMG_BOOL bNew,
- IMG_UINT32 ui32New,
- IMG_UINT32 ui32NewReset,
- IMG_UINT32 ui32CountersReg,
- IMG_UINT32 * pui32Time,
- IMG_BOOL * pbActive,
- PVRSRV_SGXDEV_DIFF_INFO * psDiffs)
+
+
+static bool sgxps_active;
+static unsigned long sgxps_timeout;
+
+IMG_BOOL isSGXPerfServerActive(void)
+{
+ if (!sgxps_active)
+ return 0;
+
+ if (time_before_eq((unsigned long)OSClockus(), sgxps_timeout))
+ return 1;
+
+ sgxps_active = false;
+ PVR_DPF(DBGPRIV_WARNING, "pvr: perf server inactive\n");
+
+ return 0;
+}
+
+
+void SGXPerfServerMonitor(u32 u32TimeStamp)
{
- PVRSRV_ERROR eError;
- SYS_DATA *psSysData;
- PVRSRV_POWER_DEV *psPowerDevice;
+ if (!sgxps_active) {
+ PVR_DPF(DBGPRIV_WARNING, "pvr: perf server active\n");
+ sgxps_active = true;
+ }
+
+ /* turn off after 1 second of inactivity */
+ sgxps_timeout = u32TimeStamp + 1000000;
+}
+
+
+enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
+ u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
+ u32 ui32NewReset, u32 ui32CountersReg,
+ u32 *pui32Time, IMG_BOOL *pbActive,
+ struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
IMG_BOOL bPowered = IMG_FALSE;
- PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- if (bNew) {
+ if (bNew)
psDevInfo->ui32HWGroupRequested = ui32New;
- }
psDevInfo->ui32HWReset |= ui32NewReset;
- eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
- if (eError != PVRSRV_OK) {
- return eError;
- }
-
- SysAcquireData(&psSysData);
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
psPowerDevice = psSysData->psPowerDeviceList;
while (psPowerDevice) {
if (psPowerDevice->ui32DeviceIndex ==
psDeviceNode->sDevId.ui32DeviceIndex) {
bPowered =
- (IMG_BOOL) (psPowerDevice->eCurrentPowerState ==
+ (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
PVRSRV_POWER_STATE_D0);
break;
}
*pbActive = bPowered;
+ pvr_dev_lock();
+
{
- PVRSRV_SGXDEV_DIFF_INFO sNew, *psPrev = &psDevInfo->sDiffInfo;
- IMG_UINT32 i;
+ struct PVRSRV_SGXDEV_DIFF_INFO sNew,
+ *psPrev = &psDevInfo->sDiffInfo;
+ u32 i;
sNew.ui32Time[0] = OSClockus();
-
*pui32Time = sNew.ui32Time[0];
-
if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
+ SGXPerfServerMonitor(*pui32Time);
+
*pui32Old =
OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
}
if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
-
if (psDevInfo->ui32HWReset != 0) {
OSWriteHWReg(psDevInfo->pvRegsBaseKM,
ui32Reg,
psDevInfo->ui32HWReset);
psDevInfo->ui32HWReset = 0;
}
-
OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
psDevInfo->ui32HWGroupRequested);
}
sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
- sNew.ui32Time[1] =
- psDevInfo->psSGXHostCtl->ui32TimeWraps;
+ sNew.ui32Time[1] = readl(
+ &psDevInfo->psSGXHostCtl->ui32TimeWraps);
for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
psDiffs->aui32Counters[i] =
*psPrev = sNew;
} else {
-
- for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+ for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
psDiffs->aui32Counters[i] = 0;
- }
psDiffs->ui32Marker[0] = 0;
psDiffs->ui32Marker[1] = 0;
}
}
- PVRSRVPowerUnlock(KERNEL_ID);
+ SGXTestActivePowerEvent(psDeviceNode);
+
+ pvr_dev_unlock();
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
+ struct PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
+ u32 *pui32DataCount, u32 *pui32ClockSpeed,
+ u32 *pui32HostTimeStamp)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+ i++) {
+ struct SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry =
+ &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+ psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+ psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+ psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
+ psClientHWPerfEntry[i].ui32Clocksx16 =
+ SGXConvertTimeStamp(psDevInfo, psMKPerfEntry->ui32TimeWraps,
+ psMKPerfEntry->ui32Time);
+ OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
+ &psMKPerfEntry->ui32Counters[0],
+ sizeof(psMKPerfEntry->ui32Counters));
+
+ psHWPerfCB->ui32Roff =
+ (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
- SGXTestActivePowerEvent(psDeviceNode, KERNEL_ID);
+ *pui32DataCount = i;
+ *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ *pui32HostTimeStamp = OSClockus();
return eError;
}